1 /* 2 * To do: 3 * 4 * Don't store drive configuration on the config DB: read each drive's header 5 * to decide where it is. 6 * 7 * Accept any old crap in the config_<foo> functions, and complain when 8 * we try to bring it up. 9 * 10 * When trying to bring volumes up, check that the complete address range 11 * is covered. 12 */ 13 /*- 14 * Copyright (c) 1997, 1998 15 * Nan Yang Computer Services Limited. All rights reserved. 16 * 17 * This software is distributed under the so-called ``Berkeley 18 * License'': 19 * 20 * Redistribution and use in source and binary forms, with or without 21 * modification, are permitted provided that the following conditions 22 * are met: 23 * 1. Redistributions of source code must retain the above copyright 24 * notice, this list of conditions and the following disclaimer. 25 * 2. Redistributions in binary form must reproduce the above copyright 26 * notice, this list of conditions and the following disclaimer in the 27 * documentation and/or other materials provided with the distribution. 28 * 3. All advertising materials mentioning features or use of this software 29 * must display the following acknowledgement: 30 * This product includes software developed by Nan Yang Computer 31 * Services Limited. 32 * 4. Neither the name of the Company nor the names of its contributors 33 * may be used to endorse or promote products derived from this software 34 * without specific prior written permission. 35 * 36 * This software is provided ``as is'', and any express or implied 37 * warranties, including, but not limited to, the implied warranties of 38 * merchantability and fitness for a particular purpose are disclaimed. 39 * In no event shall the company or contributors be liable for any 40 * direct, indirect, incidental, special, exemplary, or consequential 41 * damages (including, but not limited to, procurement of substitute 42 * goods or services; loss of use, data, or profits; or business 43 * interruption) however caused and on any theory of liability, whether 44 * in contract, strict liability, or tort (including negligence or 45 * otherwise) arising in any way out of the use of this software, even if 46 * advised of the possibility of such damage. 47 * 48 * $Id: vinumconfig.c,v 1.30 2000/05/01 09:45:50 grog Exp grog $ 49 * $FreeBSD: src/sys/dev/vinum/vinumconfig.c,v 1.32.2.6 2002/02/03 00:43:35 grog Exp $ 50 */ 51 52 #define STATIC static 53 54 #include <dev/vinum/vinumhdr.h> 55 #include <dev/vinum/request.h> 56 57 #define MAXTOKEN 64 /* maximum number of tokens in a line */ 58 59 /* 60 * We can afford the luxury of global variables here, 61 * since start_config ensures that these functions 62 * are single-threaded. 63 */ 64 65 /* These are indices in vinum_conf of the last-mentioned of each kind of object */ 66 static int current_drive; /* note the last drive we mention, for 67 * some defaults */ 68 static int current_plex; /* and the same for the last plex */ 69 static int current_volume; /* and the last volme */ 70 static struct _ioctl_reply *ioctl_reply; /* struct to return via ioctl */ 71 72 73 /* These values are used by most of these routines, so set them as globals */ 74 static char *token[MAXTOKEN]; /* pointers to individual tokens */ 75 static int tokens; /* number of tokens */ 76 77 #define TOCONS 0x01 78 #define TOTTY 0x02 79 #define TOLOG 0x04 80 81 struct putchar_arg { 82 int flags; 83 struct tty *tty; 84 }; 85 86 #define MSG_MAX 1024 /* maximum length of a formatted message */ 87 /* 88 * Format an error message and return to the user in the reply. 89 * CARE: This routine is designed to be called only from the 90 * configuration routines, so it assumes it's the owner of 91 * the configuration lock, and unlocks it on exit 92 */ 93 void 94 throw_rude_remark(int error, char *msg,...) 95 { 96 int retval; 97 va_list ap; 98 char *text; 99 static int finishing; /* don't recurse */ 100 int was_finishing; 101 102 if ((vinum_conf.flags & VF_LOCKED) == 0) /* bug catcher */ 103 panic ("throw_rude_remark: called without config lock"); 104 va_start(ap, msg); 105 if ((ioctl_reply != NULL) /* we're called from the user */ 106 &&(!(vinum_conf.flags & VF_READING_CONFIG))) { /* and not reading from disk: return msg */ 107 /* 108 * We can't just format to ioctl_reply, since it 109 * may contain our input parameters 110 */ 111 text = Malloc(MSG_MAX); 112 if (text == NULL) { 113 log(LOG_ERR, "vinum: can't allocate error message buffer\n"); 114 printf("vinum: "); 115 vprintf(msg, ap); /* print to the console */ 116 printf("\n"); 117 } else { 118 retval = kvprintf(msg, NULL, (void *) text, 10, ap); 119 text[retval] = '\0'; /* delimit */ 120 strcpy(ioctl_reply->msg, text); 121 ioctl_reply->error = error; /* first byte is the error number */ 122 Free(text); 123 } 124 } else { 125 printf("vinum: "); 126 vprintf(msg, ap); /* print to the console */ 127 printf("\n"); 128 } 129 va_end(ap); 130 131 if (vinum_conf.flags & VF_READING_CONFIG) { /* go through to the bitter end, */ 132 if ((vinum_conf.flags & VF_READING_CONFIG) /* we're reading from disk, */ 133 &&((daemon_options & daemon_noupdate) == 0)) { 134 log(LOG_NOTICE, "Disabling configuration updates\n"); 135 daemon_options |= daemon_noupdate; 136 } 137 return; 138 } 139 /* 140 * We have a problem here: we want to unlock the 141 * configuration, which implies tidying up, but 142 * if we find an error while tidying up, we could 143 * recurse for ever. Use this kludge to only try 144 * once 145 */ 146 was_finishing = finishing; 147 finishing = 1; 148 finish_config(was_finishing); /* unlock anything we may be holding */ 149 finishing = was_finishing; 150 longjmp(command_fail, error); 151 } 152 153 /* 154 * Check a volume to see if the plex is already assigned to it. 155 * Return index in volume->plex, or -1 if not assigned 156 */ 157 int 158 my_plex(int volno, int plexno) 159 { 160 int i; 161 struct volume *vol; 162 163 vol = &VOL[volno]; /* point to volno */ 164 for (i = 0; i < vol->plexes; i++) 165 if (vol->plex[i] == plexno) 166 return i; 167 return -1; /* not found */ 168 } 169 170 /* 171 * Check a plex to see if the subdisk is already assigned to it. 172 * Return index in plex->sd, or -1 if not assigned 173 */ 174 int 175 my_sd(int plexno, int sdno) 176 { 177 int i; 178 struct plex *plex; 179 180 plex = &PLEX[plexno]; 181 for (i = 0; i < plex->subdisks; i++) 182 if (plex->sdnos[i] == sdno) 183 return i; 184 return -1; /* not found */ 185 } 186 187 /* Add plex to the volume if possible */ 188 int 189 give_plex_to_volume(int volno, int plexno) 190 { 191 struct volume *vol; 192 int i; 193 194 /* 195 * It's not an error for the plex to already 196 * belong to the volume, but we need to check a 197 * number of things to make sure it's done right. 198 * Some day. 199 */ 200 if (my_plex(volno, plexno) >= 0) 201 return plexno; /* that's it */ 202 203 vol = &VOL[volno]; /* point to volume */ 204 if (vol->plexes == MAXPLEX) /* all plexes allocated */ 205 throw_rude_remark(ENOSPC, 206 "Too many plexes for volume %s", 207 vol->name); 208 else if ((vol->plexes > 0) /* we have other plexes */ 209 &&((vol->flags & VF_CONFIG_SETUPSTATE) == 0)) /* and we're not setting up state */ 210 invalidate_subdisks(&PLEX[plexno], sd_stale); /* make the subdisks invalid */ 211 vol->plex[vol->plexes] = plexno; /* this one */ 212 vol->plexes++; /* add another plex */ 213 PLEX[plexno].volno = volno; /* note the number of our volume */ 214 215 /* Find out how big our volume is */ 216 for (i = 0; i < vol->plexes; i++) 217 vol->size = max(vol->size, PLEX[vol->plex[i]].length); 218 return vol->plexes - 1; /* and return its index */ 219 } 220 221 /* 222 * Add subdisk to a plex if possible 223 */ 224 int 225 give_sd_to_plex(int plexno, int sdno) 226 { 227 int i; 228 struct plex *plex; 229 struct sd *sd; 230 231 /* 232 * It's not an error for the sd to already 233 * belong to the plex, but we need to check a 234 * number of things to make sure it's done right. 235 * Some day. 236 */ 237 i = my_sd(plexno, sdno); 238 if (i >= 0) /* does it already belong to us? */ 239 return i; /* that's it */ 240 241 plex = &PLEX[plexno]; /* point to the plex */ 242 sd = &SD[sdno]; /* and the subdisk */ 243 244 /* Do we have an offset? Otherwise put it after the last one */ 245 if (sd->plexoffset < 0) { /* no offset specified */ 246 if (plex->subdisks > 0) { 247 struct sd *lastsd = &SD[plex->sdnos[plex->subdisks - 1]]; /* last subdisk */ 248 249 if (plex->organization == plex_concat) /* concat, */ 250 sd->plexoffset = lastsd->sectors + lastsd->plexoffset; /* starts here */ 251 else /* striped, RAID-4 or RAID-5 */ 252 sd->plexoffset = plex->stripesize * plex->subdisks; /* starts here */ 253 } else /* first subdisk */ 254 sd->plexoffset = 0; /* start at the beginning */ 255 } 256 if (plex->subdisks == MAXSD) /* we already have our maximum */ 257 throw_rude_remark(ENOSPC, /* crap out */ 258 "Can't add %s to %s: plex full", 259 sd->name, 260 plex->name); 261 262 plex->subdisks++; /* another entry */ 263 if (plex->subdisks >= plex->subdisks_allocated) /* need more space */ 264 EXPAND(plex->sdnos, int, plex->subdisks_allocated, INITIAL_SUBDISKS_IN_PLEX); 265 266 /* Adjust size of plex and volume. */ 267 if (isparity(plex)) /* RAID-4 or RAID-5 */ 268 plex->length = (plex->subdisks - 1) * sd->sectors; /* size is one disk short */ 269 else 270 plex->length += sd->sectors; /* plex gets this much bigger */ 271 if (plex->volno >= 0) /* we have a volume */ 272 VOL[plex->volno].size = max(VOL[plex->volno].size, plex->length); /* adjust its size */ 273 274 /* 275 * We need to check that the subdisks don't overlap, 276 * but we can't do that until a point where we *must* 277 * know the size of all the subdisks. That's not 278 * here. But we need to sort them by offset 279 */ 280 for (i = 0; i < plex->subdisks - 1; i++) { 281 if (sd->plexoffset < SD[plex->sdnos[i]].plexoffset) { /* it fits before this one */ 282 /* First move any remaining subdisks by one */ 283 int j; 284 285 for (j = plex->subdisks - 1; j > i; j--) /* move up one at a time */ 286 plex->sdnos[j] = plex->sdnos[j - 1]; 287 plex->sdnos[i] = sdno; 288 sd->plexsdno = i; /* note where we are in the subdisk */ 289 return i; 290 } 291 } 292 293 /* 294 * The plex doesn't have any subdisk with a 295 * larger offset. Insert it here. 296 */ 297 plex->sdnos[i] = sdno; 298 sd->plexsdno = i; /* note where we are in the subdisk */ 299 sd->plexno = plex->plexno; /* and who we belong to */ 300 return i; 301 } 302 303 /* 304 * Add a subdisk to drive if possible. The 305 * pointer to the drive must already be stored in 306 * the sd structure, but the drive doesn't know 307 * about the subdisk yet. 308 */ 309 void 310 give_sd_to_drive(int sdno) 311 { 312 struct sd *sd; /* pointer to subdisk */ 313 struct drive *drive; /* and drive */ 314 int fe; /* index in free list */ 315 int sfe; /* and index of subdisk when assigning max */ 316 317 sd = &SD[sdno]; /* point to sd */ 318 drive = &DRIVE[sd->driveno]; /* and drive */ 319 320 if (drive->state != drive_up) { 321 update_sd_state(sdno); /* that crashes the subdisk */ 322 return; 323 } 324 if (drive->flags & VF_HOTSPARE) /* the drive is a hot spare, */ 325 throw_rude_remark(ENOSPC, 326 "Can't place %s on hot spare drive %s", 327 sd->name, 328 drive->label.name); 329 if ((drive->sectors_available == 0) /* no space left */ 330 ||(sd->sectors > drive->sectors_available)) { /* or too big, */ 331 sd->driveoffset = -1; /* don't be confusing */ 332 free_sd(sd->sdno); 333 throw_rude_remark(ENOSPC, "No space for %s on %s", sd->name, drive->label.name); 334 return; /* in case we come back here */ 335 } 336 drive->subdisks_used++; /* one more subdisk */ 337 338 if (sd->sectors == 0) { /* take the largest chunk */ 339 sfe = 0; /* to keep the compiler happy */ 340 for (fe = 0; fe < drive->freelist_entries; fe++) { 341 if (drive->freelist[fe].sectors >= sd->sectors) { /* more space here */ 342 sd->sectors = drive->freelist[fe].sectors; /* take it */ 343 sd->driveoffset = drive->freelist[fe].offset; 344 sfe = fe; /* and note the index for later */ 345 } 346 } 347 if (sd->sectors == 0) { /* no luck, */ 348 sd->driveoffset = -1; /* don't be confusing */ 349 free_sd(sd->sdno); 350 throw_rude_remark(ENOSPC, /* give up */ 351 "No space for %s on %s", 352 sd->name, 353 drive->label.name); 354 } 355 if (sfe < (drive->freelist_entries - 1)) /* not the last one, */ 356 bcopy(&drive->freelist[sfe + 1], 357 &drive->freelist[sfe], 358 (drive->freelist_entries - sfe) * sizeof(struct drive_freelist)); 359 drive->freelist_entries--; /* one less entry */ 360 drive->sectors_available -= sd->sectors; /* and note how much less space we have */ 361 } else if (sd->driveoffset < 0) { /* no offset specified, find one */ 362 for (fe = 0; fe < drive->freelist_entries; fe++) { 363 if (drive->freelist[fe].sectors >= sd->sectors) { /* it'll fit here */ 364 sd->driveoffset = drive->freelist[fe].offset; 365 if (sd->sectors == drive->freelist[fe].sectors) { /* used up the entire entry */ 366 if (fe < (drive->freelist_entries - 1)) /* not the last one, */ 367 bcopy(&drive->freelist[fe + 1], 368 &drive->freelist[fe], 369 (drive->freelist_entries - fe) * sizeof(struct drive_freelist)); 370 drive->freelist_entries--; /* one less entry */ 371 } else { 372 drive->freelist[fe].sectors -= sd->sectors; /* this much less space */ 373 drive->freelist[fe].offset += sd->sectors; /* this much further on */ 374 } 375 drive->sectors_available -= sd->sectors; /* and note how much less space we have */ 376 break; 377 } 378 } 379 if (sd->driveoffset < 0) 380 /* 381 * Didn't find anything. Although the drive has 382 * enough space, it's too fragmented 383 */ 384 { 385 free_sd(sd->sdno); 386 throw_rude_remark(ENOSPC, "No space for %s on %s", sd->name, drive->label.name); 387 } 388 } else { /* specific offset */ 389 /* 390 * For a specific offset to work, the space must be 391 * entirely in a single freelist entry. Look for it. 392 */ 393 u_int64_t sdend = sd->driveoffset + sd->sectors; /* end of our subdisk */ 394 for (fe = 0; fe < drive->freelist_entries; fe++) { 395 u_int64_t dend = drive->freelist[fe].offset + drive->freelist[fe].sectors; /* end of entry */ 396 if (dend >= sdend) { /* fits before here */ 397 if (drive->freelist[fe].offset > sd->driveoffset) { /* starts after the beginning of sd area */ 398 sd->driveoffset = -1; /* don't be confusing */ 399 set_sd_state(sd->sdno, sd_down, setstate_force); 400 throw_rude_remark(ENOSPC, 401 "No space for %s on drive %s at offset %lld", 402 sd->name, 403 drive->label.name, 404 sd->driveoffset); 405 return; 406 } 407 /* 408 * We've found the space, and we can allocate it. 409 * We don't need to say that to the subdisk, which 410 * already knows about it. We need to tell it to 411 * the free list, though. We have four possibilities: 412 * 413 * 1. The subdisk exactly eats up the entry. That's the 414 * same as above. 415 * 2. The subdisk starts at the beginning and leaves space 416 * at the end. 417 * 3. The subdisk starts after the beginning and leaves 418 * space at the end as well: we end up with another 419 * fragment. 420 * 4. The subdisk leaves space at the beginning and finishes 421 * at the end. 422 */ 423 drive->sectors_available -= sd->sectors; /* note how much less space we have */ 424 if (sd->driveoffset == drive->freelist[fe].offset) { /* 1 or 2 */ 425 if (sd->sectors == drive->freelist[fe].sectors) { /* 1: used up the entire entry */ 426 if (fe < (drive->freelist_entries - 1)) /* not the last one, */ 427 bcopy(&drive->freelist[fe + 1], 428 &drive->freelist[fe], 429 (drive->freelist_entries - fe) * sizeof(struct drive_freelist)); 430 drive->freelist_entries--; /* one less entry */ 431 } else { /* 2: space at the end */ 432 drive->freelist[fe].sectors -= sd->sectors; /* this much less space */ 433 drive->freelist[fe].offset += sd->sectors; /* this much further on */ 434 } 435 } else { /* 3 or 4 */ 436 drive->freelist[fe].sectors = sd->driveoffset - drive->freelist[fe].offset; 437 if (dend > sdend) { /* 3: space at the end as well */ 438 if (fe < (drive->freelist_entries - 1)) /* not the last one */ 439 bcopy(&drive->freelist[fe], /* move the rest down */ 440 &drive->freelist[fe + 1], 441 (drive->freelist_entries - fe) * sizeof(struct drive_freelist)); 442 drive->freelist_entries++; /* one less entry */ 443 drive->freelist[fe + 1].offset = sdend; /* second entry starts after sd */ 444 drive->freelist[fe + 1].sectors = dend - sdend; /* and is this long */ 445 } 446 } 447 break; 448 } 449 } 450 } 451 drive->opencount++; /* one more subdisk attached */ 452 } 453 454 /* Get an empty drive entry from the drive table */ 455 int 456 get_empty_drive(void) 457 { 458 int driveno; 459 struct drive *drive; 460 461 /* first see if we have one which has been deallocated */ 462 for (driveno = 0; driveno < vinum_conf.drives_allocated; driveno++) { 463 if (DRIVE[driveno].state == drive_unallocated) /* bingo */ 464 break; 465 } 466 467 if (driveno >= vinum_conf.drives_allocated) /* we've used all our allocation */ 468 EXPAND(DRIVE, struct drive, vinum_conf.drives_allocated, INITIAL_DRIVES); 469 470 /* got a drive entry. Make it pretty */ 471 drive = &DRIVE[driveno]; 472 bzero(drive, sizeof(struct drive)); 473 drive->driveno = driveno; /* put number in structure */ 474 drive->flags |= VF_NEWBORN; /* newly born drive */ 475 strcpy("unknown", drive->devicename); /* and make the name ``unknown'' */ 476 return driveno; /* return the index */ 477 } 478 479 /* 480 * Find the named drive in vinum_conf.drive, return a pointer 481 * return the index in vinum_conf.drive. 482 * Don't mark the drive as allocated (XXX SMP) 483 * If create != 0, create an entry if it doesn't exist 484 */ 485 /* XXX check if we have it open from attach */ 486 int 487 find_drive(const char *name, int create) 488 { 489 int driveno; 490 struct drive *drive; 491 492 if (name != NULL) { 493 for (driveno = 0; driveno < vinum_conf.drives_allocated; driveno++) { 494 drive = &DRIVE[driveno]; /* point to drive */ 495 if ((drive->label.name[0] != '\0') /* it has a name */ 496 &&(strcmp(drive->label.name, name) == 0) /* and it's this one */ 497 &&(drive->state > drive_unallocated)) /* and it's a real one: found */ 498 return driveno; 499 } 500 } 501 /* the drive isn't in the list. Add it if he wants */ 502 if (create == 0) /* don't want to create */ 503 return -1; /* give up */ 504 505 driveno = get_empty_drive(); 506 drive = &DRIVE[driveno]; 507 if (name != NULL) 508 bcopy(name, /* put in its name */ 509 drive->label.name, 510 min(sizeof(drive->label.name), 511 strlen(name))); 512 drive->state = drive_referenced; /* in use, nothing worthwhile there */ 513 return driveno; /* return the index */ 514 } 515 516 /* 517 * Find a drive given its device name. 518 * devname must be valid. 519 * Otherwise the same as find_drive above 520 */ 521 int 522 find_drive_by_dev(const char *devname, int create) 523 { 524 int driveno; 525 struct drive *drive; 526 527 for (driveno = 0; driveno < vinum_conf.drives_allocated; driveno++) { 528 drive = &DRIVE[driveno]; /* point to drive */ 529 if ((strcmp(drive->devicename, devname) == 0) /* it's this device */ 530 &&(drive->state > drive_unallocated)) /* and it's a real one: found */ 531 return driveno; 532 } 533 534 /* the drive isn't in the list. Add it if he wants */ 535 if (create == 0) /* don't want to create */ 536 return -1; /* give up */ 537 538 driveno = get_empty_drive(); 539 drive = &DRIVE[driveno]; 540 bcopy(devname, /* put in its name */ 541 drive->devicename, 542 min(sizeof(drive->devicename), 543 strlen(devname))); 544 drive->state = drive_referenced; /* in use, nothing worthwhile there */ 545 return driveno; /* return the index */ 546 } 547 548 /* Find an empty subdisk in the subdisk table */ 549 int 550 get_empty_sd(void) 551 { 552 int sdno; 553 struct sd *sd; 554 555 /* first see if we have one which has been deallocated */ 556 for (sdno = 0; sdno < vinum_conf.subdisks_allocated; sdno++) { 557 if (SD[sdno].state == sd_unallocated) /* bingo */ 558 break; 559 } 560 if (sdno >= vinum_conf.subdisks_allocated) 561 /* 562 * We've run out of space. sdno is pointing 563 * where we want it, but at the moment we 564 * don't have the space. Get it. 565 */ 566 EXPAND(SD, struct sd, vinum_conf.subdisks_allocated, INITIAL_SUBDISKS); 567 568 /* initialize some things */ 569 sd = &SD[sdno]; /* point to it */ 570 bzero(sd, sizeof(struct sd)); /* initialize */ 571 sd->flags |= VF_NEWBORN; /* newly born subdisk */ 572 sd->plexno = -1; /* no plex */ 573 sd->sectors = -1; /* no space */ 574 sd->driveno = -1; /* no drive */ 575 sd->plexoffset = -1; /* and no offsets */ 576 sd->driveoffset = -1; 577 return sdno; /* return the index */ 578 } 579 580 /* return a drive to the free pool */ 581 void 582 free_drive(struct drive *drive) 583 { 584 if ((drive->state > drive_referenced) /* real drive */ 585 ||(drive->flags & VF_OPEN)) { /* how can it be open without a state? */ 586 LOCKDRIVE(drive); 587 if (drive->flags & VF_OPEN) { /* it's open, */ 588 close_locked_drive(drive); /* close it */ 589 drive->state = drive_down; /* and note the fact */ 590 } 591 if (drive->freelist) 592 Free(drive->freelist); 593 bzero(drive, sizeof(struct drive)); /* this also sets drive_unallocated */ 594 unlockdrive(drive); 595 } 596 } 597 598 /* 599 * Find the named subdisk in vinum_conf.sd. 600 * 601 * If create != 0, create an entry if it doesn't exist 602 * 603 * Return index in vinum_conf.sd 604 */ 605 int 606 find_subdisk(const char *name, int create) 607 { 608 int sdno; 609 struct sd *sd; 610 611 for (sdno = 0; sdno < vinum_conf.subdisks_allocated; sdno++) { 612 if (strcmp(SD[sdno].name, name) == 0) /* found it */ 613 return sdno; 614 } 615 616 /* the subdisk isn't in the list. Add it if he wants */ 617 if (create == 0) /* don't want to create */ 618 return -1; /* give up */ 619 620 /* Allocate one and insert the name */ 621 sdno = get_empty_sd(); 622 sd = &SD[sdno]; 623 bcopy(name, sd->name, min(sizeof(sd->name), strlen(name))); /* put in its name */ 624 return sdno; /* return the pointer */ 625 } 626 627 /* Return space to a drive */ 628 void 629 return_drive_space(int driveno, int64_t offset, int length) 630 { 631 struct drive *drive; 632 int fe; /* free list entry */ 633 u_int64_t sdend; /* end of our subdisk */ 634 u_int64_t dend; /* end of our freelist entry */ 635 636 drive = &DRIVE[driveno]; 637 if (drive->state == drive_up) { 638 sdend = offset + length; /* end of our subdisk */ 639 640 /* Look for where to return the sd address space */ 641 for (fe = 0; 642 (fe < drive->freelist_entries) && (drive->freelist[fe].offset < offset); 643 fe++); 644 /* 645 * Now we are pointing to the last entry, the first 646 * with a higher offset than the subdisk, or both. 647 */ 648 if ((fe > 1) /* not the first entry */ 649 &&((fe == drive->freelist_entries) /* gone past the end */ 650 ||(drive->freelist[fe].offset > offset))) /* or past the block were looking for */ 651 fe--; /* point to the block before */ 652 dend = drive->freelist[fe].offset + drive->freelist[fe].sectors; /* end of the entry */ 653 654 /* 655 * At this point, we are pointing to the correct 656 * place in the free list. A number of possibilities 657 * exist: 658 * 659 * 1. The block to be freed starts at the end of the 660 * block to which we are pointing. This has two 661 * subcases: 662 * 663 * a. The block to be freed ends at the beginning 664 * of the following block. Merge the three 665 * areas into a single block. 666 * 667 * b. The block is shorter than the space between 668 * the current block and the next one. Enlarge 669 * the current block. 670 * 671 * 2. The block to be freed starts after the end 672 * of the block. Again, we have two cases: 673 * 674 * a. It ends before the start of the following block. 675 * Create a new free block. 676 * 677 * b. It ends at the start of the following block. 678 * Enlarge the following block downwards. 679 * 680 * When there is only one free space block, and the 681 * space to be returned is before it, the pointer is 682 * to a non-existent zeroth block. XXX check this 683 */ 684 if (offset == dend) { /* Case 1: it starts at the end of this block */ 685 if ((fe < drive->freelist_entries - 1) /* we're not the last block in the free list */ 686 /* and the subdisk ends at the start of the next block */ 687 &&(sdend == drive->freelist[fe + 1].offset)) { 688 drive->freelist[fe].sectors /* 1a: merge all three blocks */ 689 = drive->freelist[fe + 1].sectors; 690 if (fe < drive->freelist_entries - 2) /* still more blocks after next */ 691 bcopy(&drive->freelist[fe + 2], /* move down one */ 692 &drive->freelist[fe + 1], 693 (drive->freelist_entries - 2 - fe) 694 * sizeof(struct drive_freelist)); 695 drive->freelist_entries--; /* one less entry in the free list */ 696 } else /* 1b: just enlarge this block */ 697 drive->freelist[fe].sectors += length; 698 } else { /* Case 2 */ 699 if (offset > dend) /* it starts after this block */ 700 fe++; /* so look at the next block */ 701 if ((fe < drive->freelist_entries) /* we're not the last block in the free list */ 702 /* and the subdisk ends at the start of this block: case 4 */ 703 &&(sdend == drive->freelist[fe].offset)) { 704 drive->freelist[fe].offset = offset; /* it starts where the sd was */ 705 drive->freelist[fe].sectors += length; /* and it's this much bigger */ 706 } else { /* case 3: non-contiguous */ 707 if (fe < drive->freelist_entries) /* not after the last block, */ 708 bcopy(&drive->freelist[fe], /* move the rest up one entry */ 709 &drive->freelist[fe + 1], 710 (drive->freelist_entries - fe) 711 * sizeof(struct drive_freelist)); 712 drive->freelist_entries++; /* one less entry */ 713 drive->freelist[fe].offset = offset; /* this entry represents the sd */ 714 drive->freelist[fe].sectors = length; 715 } 716 } 717 drive->sectors_available += length; /* the sectors are now available */ 718 } 719 } 720 721 /* 722 * Free an allocated sd entry. 723 * This performs memory management only. remove() 724 * is responsible for checking relationships. 725 */ 726 void 727 free_sd(int sdno) 728 { 729 struct sd *sd; 730 731 sd = &SD[sdno]; 732 if ((sd->driveno >= 0) /* we have a drive, */ 733 &&(sd->sectors > 0)) /* and some space on it */ 734 return_drive_space(sd->driveno, /* return the space */ 735 sd->driveoffset, 736 sd->sectors); 737 if (sd->plexno >= 0) 738 PLEX[sd->plexno].subdisks--; /* one less subdisk */ 739 bzero(sd, sizeof(struct sd)); /* and clear it out */ 740 sd->state = sd_unallocated; 741 vinum_conf.subdisks_used--; /* one less sd */ 742 } 743 744 /* Find an empty plex in the plex table */ 745 int 746 get_empty_plex(void) 747 { 748 int plexno; 749 struct plex *plex; /* if we allocate one */ 750 751 /* first see if we have one which has been deallocated */ 752 for (plexno = 0; plexno < vinum_conf.plexes_allocated; plexno++) { 753 if (PLEX[plexno].state == plex_unallocated) /* bingo */ 754 break; /* and get out of here */ 755 } 756 757 if (plexno >= vinum_conf.plexes_allocated) 758 EXPAND(PLEX, struct plex, vinum_conf.plexes_allocated, INITIAL_PLEXES); 759 760 /* Found a plex. Give it an sd structure */ 761 plex = &PLEX[plexno]; /* this one is ours */ 762 bzero(plex, sizeof(struct plex)); /* polish it up */ 763 plex->sdnos = (int *) Malloc(sizeof(int) * INITIAL_SUBDISKS_IN_PLEX); /* allocate sd table */ 764 CHECKALLOC(plex->sdnos, "vinum: Can't allocate plex subdisk table"); 765 bzero(plex->sdnos, (sizeof(int) * INITIAL_SUBDISKS_IN_PLEX)); /* do we need this? */ 766 plex->flags |= VF_NEWBORN; /* newly born plex */ 767 plex->subdisks = 0; /* no subdisks in use */ 768 plex->subdisks_allocated = INITIAL_SUBDISKS_IN_PLEX; /* and we have space for this many */ 769 plex->organization = plex_disorg; /* and it's not organized */ 770 plex->volno = -1; /* no volume yet */ 771 return plexno; /* return the index */ 772 } 773 774 /* 775 * Find the named plex in vinum_conf.plex 776 * 777 * If create != 0, create an entry if it doesn't exist 778 * return index in vinum_conf.plex 779 */ 780 int 781 find_plex(const char *name, int create) 782 { 783 int plexno; 784 struct plex *plex; 785 786 for (plexno = 0; plexno < vinum_conf.plexes_allocated; plexno++) { 787 if (strcmp(PLEX[plexno].name, name) == 0) /* found it */ 788 return plexno; 789 } 790 791 /* the plex isn't in the list. Add it if he wants */ 792 if (create == 0) /* don't want to create */ 793 return -1; /* give up */ 794 795 /* Allocate one and insert the name */ 796 plexno = get_empty_plex(); 797 plex = &PLEX[plexno]; /* point to it */ 798 bcopy(name, plex->name, min(sizeof(plex->name), strlen(name))); /* put in its name */ 799 return plexno; /* return the pointer */ 800 } 801 802 /* 803 * Free an allocated plex entry 804 * and its associated memory areas 805 */ 806 void 807 free_plex(int plexno) 808 { 809 struct plex *plex; 810 811 plex = &PLEX[plexno]; 812 if (plex->sdnos) 813 Free(plex->sdnos); 814 if (plex->lock) 815 Free(plex->lock); 816 bzero(plex, sizeof(struct plex)); /* and clear it out */ 817 plex->state = plex_unallocated; 818 } 819 820 /* Find an empty volume in the volume table */ 821 int 822 get_empty_volume(void) 823 { 824 int volno; 825 struct volume *vol; 826 int i; 827 828 /* first see if we have one which has been deallocated */ 829 for (volno = 0; volno < vinum_conf.volumes_allocated; volno++) { 830 if (VOL[volno].state == volume_unallocated) /* bingo */ 831 break; 832 } 833 834 if (volno >= vinum_conf.volumes_allocated) 835 EXPAND(VOL, struct volume, vinum_conf.volumes_allocated, INITIAL_VOLUMES); 836 837 /* Now initialize fields */ 838 vol = &VOL[volno]; 839 bzero(vol, sizeof(struct volume)); 840 vol->flags |= VF_NEWBORN | VF_CREATED; /* newly born volume */ 841 vol->preferred_plex = ROUND_ROBIN_READPOL; /* round robin */ 842 for (i = 0; i < MAXPLEX; i++) /* mark the plexes missing */ 843 vol->plex[i] = -1; 844 return volno; /* return the index */ 845 } 846 847 /* 848 * Find the named volume in vinum_conf.volume. 849 * 850 * If create != 0, create an entry if it doesn't exist 851 * return the index in vinum_conf 852 */ 853 int 854 find_volume(const char *name, int create) 855 { 856 int volno; 857 struct volume *vol; 858 859 for (volno = 0; volno < vinum_conf.volumes_allocated; volno++) { 860 if (strcmp(VOL[volno].name, name) == 0) /* found it */ 861 return volno; 862 } 863 864 /* the volume isn't in the list. Add it if he wants */ 865 if (create == 0) /* don't want to create */ 866 return -1; /* give up */ 867 868 /* Allocate one and insert the name */ 869 volno = get_empty_volume(); 870 vol = &VOL[volno]; 871 bcopy(name, vol->name, min(sizeof(vol->name), strlen(name))); /* put in its name */ 872 vol->blocksize = DEV_BSIZE; /* block size of this volume */ 873 return volno; /* return the pointer */ 874 } 875 876 /* 877 * Free an allocated volume entry 878 * and its associated memory areas 879 */ 880 void 881 free_volume(int volno) 882 { 883 struct volume *vol; 884 885 vol = &VOL[volno]; 886 bzero(vol, sizeof(struct volume)); /* and clear it out */ 887 vol->state = volume_unallocated; 888 } 889 890 /* 891 * Handle a drive definition. We store the information in the global variable 892 * drive, so we don't need to allocate. 893 * 894 * If we find an error, print a message and return 895 */ 896 void 897 config_drive(int update) 898 { 899 enum drive_label_info partition_status; /* info about the partition */ 900 int parameter; 901 int driveno; /* index of drive in vinum_conf */ 902 struct drive *drive; /* and pointer to it */ 903 int otherdriveno; /* index of possible second drive */ 904 int sdno; 905 906 if (tokens < 2) /* not enough tokens */ 907 throw_rude_remark(EINVAL, "Drive has no name\n"); 908 driveno = find_drive(token[1], 1); /* allocate a drive to initialize */ 909 drive = &DRIVE[driveno]; /* and get a pointer */ 910 if (update && ((drive->flags & VF_NEWBORN) == 0)) /* this drive exists already */ 911 return; /* don't do anything */ 912 drive->flags &= ~VF_NEWBORN; /* no longer newly born */ 913 914 if (drive->state != drive_referenced) { /* we already know this drive */ 915 /* 916 * XXX Check which definition is more up-to-date. Give 917 * preference for the definition on its own drive. 918 */ 919 return; /* XXX */ 920 } 921 for (parameter = 2; parameter < tokens; parameter++) { /* look at the other tokens */ 922 switch (get_keyword(token[parameter], &keyword_set)) { 923 case kw_device: 924 parameter++; 925 otherdriveno = find_drive_by_dev(token[parameter], 0); /* see if it exists already */ 926 if (otherdriveno >= 0) { /* yup, */ 927 drive->state = drive_unallocated; /* deallocate the drive */ 928 throw_rude_remark(EEXIST, /* and complain */ 929 "Drive %s would have same device as drive %s", 930 token[1], 931 DRIVE[otherdriveno].label.name); 932 } 933 if (drive->devicename[0] == '/') { /* we know this drive... */ 934 if (strcmp(drive->devicename, token[parameter])) /* different name */ 935 close_drive(drive); /* close it if it's open */ 936 else /* no change */ 937 break; 938 } 939 /* open the device and get the configuration */ 940 bcopy(token[parameter], /* insert device information */ 941 drive->devicename, 942 min(sizeof(drive->devicename), 943 strlen(token[parameter]))); 944 partition_status = read_drive_label(drive, 1); 945 switch (partition_status) { 946 case DL_CANT_OPEN: /* not our kind */ 947 close_drive(drive); 948 if (drive->lasterror == EFTYPE) /* wrong kind of partition */ 949 throw_rude_remark(drive->lasterror, 950 "Drive %s has invalid partition type", 951 drive->label.name); 952 else /* I/O error of some kind */ 953 throw_rude_remark(drive->lasterror, 954 "Can't initialize drive %s", 955 drive->label.name); 956 break; 957 958 case DL_WRONG_DRIVE: /* valid drive, not the name we expected */ 959 if (vinum_conf.flags & VF_FORCECONFIG) { /* but we'll accept that */ 960 bcopy(token[1], drive->label.name, sizeof(drive->label.name)); 961 break; 962 } 963 close_drive(drive); 964 /* 965 * There's a potential race condition here: 966 * the rude remark refers to a field in an 967 * unallocated drive, which potentially could 968 * be reused. This works because we're the only 969 * thread accessing the config at the moment. 970 */ 971 drive->state = drive_unallocated; /* throw it away completely */ 972 throw_rude_remark(drive->lasterror, 973 "Incorrect drive name %s specified for drive %s", 974 token[1], 975 drive->label.name); 976 break; 977 978 case DL_DELETED_LABEL: /* it was a drive, but we deleted it */ 979 case DL_NOT_OURS: /* nothing to do with the rest */ 980 case DL_OURS: 981 break; 982 } 983 /* 984 * read_drive_label overwrites the device name. 985 * If we get here, we can have the drive, 986 * so put it back again 987 */ 988 bcopy(token[parameter], 989 drive->devicename, 990 min(sizeof(drive->devicename), 991 strlen(token[parameter]))); 992 break; 993 994 case kw_state: 995 parameter++; /* skip the keyword */ 996 if (vinum_conf.flags & VF_READING_CONFIG) 997 drive->state = DriveState(token[parameter]); /* set the state */ 998 break; 999 1000 case kw_hotspare: /* this drive is a hot spare */ 1001 drive->flags |= VF_HOTSPARE; 1002 break; 1003 1004 default: 1005 close_drive(drive); 1006 throw_rude_remark(EINVAL, 1007 "Drive %s, invalid keyword: %s", 1008 token[1], 1009 token[parameter]); 1010 } 1011 } 1012 1013 if (drive->devicename[0] != '/') { 1014 drive->state = drive_unallocated; /* deallocate the drive */ 1015 throw_rude_remark(EINVAL, "No device name for %s", drive->label.name); 1016 } 1017 vinum_conf.drives_used++; /* passed all hurdles: one more in use */ 1018 /* 1019 * If we're replacing a drive, it could be that 1020 * we already have subdisks referencing this 1021 * drive. Note where they should be and change 1022 * their state to obsolete. 1023 */ 1024 for (sdno = 0; sdno < vinum_conf.subdisks_allocated; sdno++) { 1025 if ((SD[sdno].state > sd_referenced) 1026 && (SD[sdno].driveno == driveno)) { 1027 give_sd_to_drive(sdno); 1028 if (SD[sdno].state > sd_stale) 1029 SD[sdno].state = sd_stale; 1030 } 1031 } 1032 } 1033 1034 /* 1035 * Handle a subdisk definition. We store the information in the global variable 1036 * sd, so we don't need to allocate. 1037 * 1038 * If we find an error, print a message and return 1039 */ 1040 void 1041 config_subdisk(int update) 1042 { 1043 int parameter; 1044 int sdno; /* index of sd in vinum_conf */ 1045 struct sd *sd; /* and pointer to it */ 1046 u_int64_t size; 1047 int detached = 0; /* set to 1 if this is a detached subdisk */ 1048 int sdindex = -1; /* index in plexes subdisk table */ 1049 enum sdstate state = sd_unallocated; /* state to set, if specified */ 1050 int autosize = 0; /* set if we autosize in give_sd_to_drive */ 1051 int namedsdno; /* index of another with this name */ 1052 char partition = 0; /* partition of external subdisk */ 1053 1054 sdno = get_empty_sd(); /* allocate an SD to initialize */ 1055 sd = &SD[sdno]; /* and get a pointer */ 1056 1057 for (parameter = 1; parameter < tokens; parameter++) { /* look at the other tokens */ 1058 switch (get_keyword(token[parameter], &keyword_set)) { 1059 /* 1060 * If we have a 'name' parameter, it must 1061 * come first, because we're too lazy to tidy 1062 * up dangling refs if it comes later. 1063 */ 1064 case kw_name: 1065 namedsdno = find_subdisk(token[++parameter], 0); /* find an existing sd with this name */ 1066 if (namedsdno >= 0) { /* got one */ 1067 if (SD[namedsdno].state == sd_referenced) { /* we've been told about this one */ 1068 if (parameter > 2) 1069 throw_rude_remark(EINVAL, 1070 "sd %s: name parameter must come first\n", /* no go */ 1071 token[parameter]); 1072 else { 1073 int i; 1074 struct plex *plex; /* for tidying up dangling references */ 1075 1076 *sd = SD[namedsdno]; /* copy from the referenced one */ 1077 SD[namedsdno].state = sd_unallocated; /* and deallocate the referenced one */ 1078 plex = &PLEX[sd->plexno]; /* now take a look at our plex */ 1079 for (i = 0; i < plex->subdisks; i++) { /* look for the pointer */ 1080 if (plex->sdnos[i] == namedsdno) /* pointing to the old subdisk */ 1081 plex->sdnos[i] = sdno; /* bend it to point here */ 1082 } 1083 } 1084 } 1085 if (update) /* are we updating? */ 1086 return; /* that's OK, nothing more to do */ 1087 else 1088 throw_rude_remark(EINVAL, "Duplicate subdisk %s", token[parameter]); 1089 } else 1090 bcopy(token[parameter], 1091 sd->name, 1092 min(sizeof(sd->name), strlen(token[parameter]))); 1093 break; 1094 1095 case kw_detached: 1096 detached = 1; 1097 break; 1098 1099 case kw_plexoffset: 1100 size = sizespec(token[++parameter]); 1101 if ((size == -1) /* unallocated */ 1102 &&(vinum_conf.flags & VF_READING_CONFIG)) /* reading from disk */ 1103 break; /* invalid sd; just ignore it */ 1104 if ((size % DEV_BSIZE) != 0) 1105 throw_rude_remark(EINVAL, 1106 "sd %s, bad plex offset alignment: %lld", 1107 sd->name, 1108 (long long) size); 1109 else 1110 sd->plexoffset = size / DEV_BSIZE; 1111 break; 1112 1113 case kw_driveoffset: 1114 size = sizespec(token[++parameter]); 1115 if ((size == -1) /* unallocated */ 1116 &&(vinum_conf.flags & VF_READING_CONFIG)) /* reading from disk */ 1117 break; /* invalid sd; just ignore it */ 1118 if ((size % DEV_BSIZE) != 0) 1119 throw_rude_remark(EINVAL, 1120 "sd %s, bad drive offset alignment: %lld", 1121 sd->name, 1122 (long long) size); 1123 else 1124 sd->driveoffset = size / DEV_BSIZE; 1125 break; 1126 1127 case kw_len: 1128 if (get_keyword(token[++parameter], &keyword_set) == kw_max) /* select maximum size from drive */ 1129 size = 0; /* this is how we say it :-) */ 1130 else 1131 size = sizespec(token[parameter]); 1132 if ((size % DEV_BSIZE) != 0) 1133 throw_rude_remark(EINVAL, "sd %s, length %d not multiple of sector size", sd->name, size); 1134 else 1135 sd->sectors = size / DEV_BSIZE; 1136 /* 1137 * We have a problem with autosizing: we need to 1138 * give the drive to the plex before we give it 1139 * to the drive, in order to be clean if we give 1140 * up in the middle, but at this time the size hasn't 1141 * been set. Note that we have to fix up after 1142 * giving the subdisk to the drive. 1143 */ 1144 if (size == 0) 1145 autosize = 1; /* note that we're autosizing */ 1146 break; 1147 1148 case kw_drive: 1149 sd->driveno = find_drive(token[++parameter], 1); /* insert drive information */ 1150 break; 1151 1152 case kw_plex: 1153 sd->plexno = find_plex(token[++parameter], 1); /* insert plex information */ 1154 break; 1155 1156 /* 1157 * Set the state. We can't do this directly, 1158 * because give_sd_to_plex may change it 1159 */ 1160 case kw_state: 1161 parameter++; /* skip the keyword */ 1162 if (vinum_conf.flags & VF_READING_CONFIG) 1163 state = SdState(token[parameter]); /* set the state */ 1164 break; 1165 1166 case kw_partition: 1167 parameter++; /* skip the keyword */ 1168 if ((strlen(token[parameter]) != 1) 1169 || (token[parameter][0] < 'a') 1170 || (token[parameter][0] > 'h')) 1171 throw_rude_remark(EINVAL, 1172 "%s: invalid partition %c", 1173 sd->name, 1174 token[parameter][0]); 1175 else 1176 partition = token[parameter][0]; 1177 break; 1178 1179 case kw_retryerrors: 1180 sd->flags |= VF_RETRYERRORS; 1181 break; 1182 1183 default: 1184 throw_rude_remark(EINVAL, "%s: invalid keyword: %s", sd->name, token[parameter]); 1185 } 1186 } 1187 1188 /* Check we have a drive name */ 1189 if (sd->driveno < 0) { /* didn't specify a drive */ 1190 sd->driveno = current_drive; /* set to the current drive */ 1191 if (sd->driveno < 0) /* no current drive? */ 1192 throw_rude_remark(EINVAL, "Subdisk %s is not associated with a drive", sd->name); 1193 } 1194 /* 1195 * This is tacky. If something goes wrong 1196 * with the checks, we may end up losing drive 1197 * space. FIXME. 1198 */ 1199 if (autosize != 0) /* need to find a size, */ 1200 give_sd_to_drive(sdno); /* do it before the plex */ 1201 1202 /* Check for a plex name */ 1203 if ((sd->plexno < 0) /* didn't specify a plex */ 1204 &&(!detached)) /* and didn't say not to, */ 1205 sd->plexno = current_plex; /* set to the current plex */ 1206 1207 if (sd->plexno >= 0) 1208 sdindex = give_sd_to_plex(sd->plexno, sdno); /* now tell the plex that it has this sd */ 1209 1210 sd->sdno = sdno; /* point to our entry in the table */ 1211 1212 /* Does the subdisk have a name? If not, give it one */ 1213 if (sd->name[0] == '\0') { /* no name */ 1214 char sdsuffix[8]; /* form sd name suffix here */ 1215 1216 /* Do we have a plex name? */ 1217 if (sdindex >= 0) /* we have a plex */ 1218 strcpy(sd->name, PLEX[sd->plexno].name); /* take it from there */ 1219 else /* no way */ 1220 throw_rude_remark(EINVAL, "Unnamed sd is not associated with a plex"); 1221 sprintf(sdsuffix, ".s%d", sdindex); /* form the suffix */ 1222 strcat(sd->name, sdsuffix); /* and add it to the name */ 1223 } 1224 /* do we have complete info for this subdisk? */ 1225 if (sd->sectors < 0) 1226 throw_rude_remark(EINVAL, "sd %s has no length spec", sd->name); 1227 1228 if (state != sd_unallocated) /* we had a specific state to set */ 1229 sd->state = state; /* do it now */ 1230 else if (sd->state == sd_unallocated) /* no, nothing set yet, */ 1231 sd->state = sd_empty; /* must be empty */ 1232 if (autosize == 0) /* no autoconfig, do the drive now */ 1233 give_sd_to_drive(sdno); 1234 vinum_conf.subdisks_used++; /* one more in use */ 1235 } 1236 1237 /* 1238 * Handle a plex definition. 1239 */ 1240 void 1241 config_plex(int update) 1242 { 1243 int parameter; 1244 int plexno; /* index of plex in vinum_conf */ 1245 struct plex *plex; /* and pointer to it */ 1246 int pindex = MAXPLEX; /* index in volume's plex list */ 1247 int detached = 0; /* don't give it to a volume */ 1248 int namedplexno; 1249 enum plexstate state = plex_init; /* state to set at end */ 1250 1251 current_plex = -1; /* forget the previous plex */ 1252 plexno = get_empty_plex(); /* allocate a plex */ 1253 plex = &PLEX[plexno]; /* and point to it */ 1254 plex->plexno = plexno; /* and back to the config */ 1255 1256 for (parameter = 1; parameter < tokens; parameter++) { /* look at the other tokens */ 1257 switch (get_keyword(token[parameter], &keyword_set)) { 1258 /* 1259 * If we have a 'name' parameter, it must 1260 * come first, because we're too lazy to tidy 1261 * up dangling refs if it comes later. 1262 */ 1263 case kw_name: 1264 namedplexno = find_plex(token[++parameter], 0); /* find an existing plex with this name */ 1265 if (namedplexno >= 0) { /* plex exists already, */ 1266 if (PLEX[namedplexno].state == plex_referenced) { /* we've been told about this one */ 1267 if (parameter > 2) /* we've done other things first, */ 1268 throw_rude_remark(EINVAL, 1269 "plex %s: name parameter must come first\n", /* no go */ 1270 token[parameter]); 1271 else { 1272 int i; 1273 struct volume *vol; /* for tidying up dangling references */ 1274 1275 *plex = PLEX[namedplexno]; /* get the info */ 1276 PLEX[namedplexno].state = plex_unallocated; /* and deallocate the other one */ 1277 vol = &VOL[plex->volno]; /* point to the volume */ 1278 for (i = 0; i < MAXPLEX; i++) { /* for each plex */ 1279 if (vol->plex[i] == namedplexno) 1280 vol->plex[i] = plexno; /* bend the pointer */ 1281 } 1282 } 1283 break; /* use this one */ 1284 } 1285 if (update) /* are we updating? */ 1286 return; /* yes: that's OK, just return */ 1287 else 1288 throw_rude_remark(EINVAL, "Duplicate plex %s", token[parameter]); 1289 } else 1290 bcopy(token[parameter], /* put in the name */ 1291 plex->name, 1292 min(MAXPLEXNAME, strlen(token[parameter]))); 1293 break; 1294 1295 case kw_detached: 1296 detached = 1; 1297 break; 1298 1299 case kw_org: /* plex organization */ 1300 switch (get_keyword(token[++parameter], &keyword_set)) { 1301 case kw_concat: 1302 plex->organization = plex_concat; 1303 break; 1304 1305 case kw_striped: 1306 { 1307 int stripesize = sizespec(token[++parameter]); 1308 1309 plex->organization = plex_striped; 1310 if (stripesize % DEV_BSIZE != 0) /* not a multiple of block size, */ 1311 throw_rude_remark(EINVAL, "plex %s: stripe size %d not a multiple of sector size", 1312 plex->name, 1313 stripesize); 1314 else 1315 plex->stripesize = stripesize / DEV_BSIZE; 1316 break; 1317 } 1318 1319 case kw_raid4: 1320 { 1321 int stripesize = sizespec(token[++parameter]); 1322 1323 plex->organization = plex_raid4; 1324 if (stripesize % DEV_BSIZE != 0) /* not a multiple of block size, */ 1325 throw_rude_remark(EINVAL, "plex %s: stripe size %d not a multiple of sector size", 1326 plex->name, 1327 stripesize); 1328 else 1329 plex->stripesize = stripesize / DEV_BSIZE; 1330 break; 1331 } 1332 1333 case kw_raid5: 1334 { 1335 int stripesize = sizespec(token[++parameter]); 1336 1337 plex->organization = plex_raid5; 1338 if (stripesize % DEV_BSIZE != 0) /* not a multiple of block size, */ 1339 throw_rude_remark(EINVAL, "plex %s: stripe size %d not a multiple of sector size", 1340 plex->name, 1341 stripesize); 1342 else 1343 plex->stripesize = stripesize / DEV_BSIZE; 1344 break; 1345 } 1346 1347 default: 1348 throw_rude_remark(EINVAL, "Invalid plex organization"); 1349 } 1350 if (isstriped(plex) 1351 && (plex->stripesize == 0)) /* didn't specify a valid stripe size */ 1352 throw_rude_remark(EINVAL, "Need a stripe size parameter"); 1353 break; 1354 1355 case kw_volume: 1356 plex->volno = find_volume(token[++parameter], 1); /* insert a pointer to the volume */ 1357 break; 1358 1359 case kw_sd: /* add a subdisk */ 1360 { 1361 int sdno; 1362 1363 sdno = find_subdisk(token[++parameter], 1); /* find a subdisk */ 1364 SD[sdno].plexoffset = sizespec(token[++parameter]); /* get the offset */ 1365 give_sd_to_plex(plexno, sdno); /* and insert it there */ 1366 break; 1367 } 1368 1369 case kw_state: 1370 parameter++; /* skip the keyword */ 1371 if (vinum_conf.flags & VF_READING_CONFIG) 1372 state = PlexState(token[parameter]); /* set the state */ 1373 break; 1374 1375 default: 1376 throw_rude_remark(EINVAL, "plex %s, invalid keyword: %s", 1377 plex->name, 1378 token[parameter]); 1379 } 1380 } 1381 1382 if (plex->organization == plex_disorg) 1383 throw_rude_remark(EINVAL, "No plex organization specified"); 1384 1385 if ((plex->volno < 0) /* we don't have a volume */ 1386 &&(!detached)) /* and we wouldn't object */ 1387 plex->volno = current_volume; 1388 1389 if (plex->volno >= 0) 1390 pindex = give_plex_to_volume(plex->volno, plexno); /* Now tell the volume that it has this plex */ 1391 1392 /* Does the plex have a name? If not, give it one */ 1393 if (plex->name[0] == '\0') { /* no name */ 1394 char plexsuffix[8]; /* form plex name suffix here */ 1395 /* Do we have a volume name? */ 1396 if (plex->volno >= 0) /* we have a volume */ 1397 strcpy(plex->name, /* take it from there */ 1398 VOL[plex->volno].name); 1399 else /* no way */ 1400 throw_rude_remark(EINVAL, "Unnamed plex is not associated with a volume"); 1401 sprintf(plexsuffix, ".p%d", pindex); /* form the suffix */ 1402 strcat(plex->name, plexsuffix); /* and add it to the name */ 1403 } 1404 if (isstriped(plex)) { 1405 plex->lock = (struct rangelock *) 1406 Malloc(PLEX_LOCKS * sizeof(struct rangelock)); 1407 CHECKALLOC(plex->lock, "vinum: Can't allocate lock table\n"); 1408 bzero((char *) plex->lock, PLEX_LOCKS * sizeof(struct rangelock)); 1409 } 1410 /* Note the last plex we configured */ 1411 current_plex = plexno; 1412 plex->state = state; /* set whatever state we chose */ 1413 vinum_conf.plexes_used++; /* one more in use */ 1414 } 1415 1416 /* 1417 * Handle a volume definition. 1418 * If we find an error, print a message, deallocate the nascent volume, and return 1419 */ 1420 void 1421 config_volume(int update) 1422 { 1423 int parameter; 1424 int volno; 1425 struct volume *vol; /* collect volume info here */ 1426 int i; 1427 1428 if (tokens < 2) /* not enough tokens */ 1429 throw_rude_remark(EINVAL, "Volume has no name"); 1430 current_volume = -1; /* forget the previous volume */ 1431 volno = find_volume(token[1], 1); /* allocate a volume to initialize */ 1432 vol = &VOL[volno]; /* and get a pointer */ 1433 if (update && ((vol->flags & VF_CREATED) == 0)) /* this volume exists already */ 1434 return; /* don't do anything */ 1435 vol->flags &= ~VF_CREATED; /* it exists now */ 1436 1437 for (parameter = 2; parameter < tokens; parameter++) { /* look at all tokens */ 1438 switch (get_keyword(token[parameter], &keyword_set)) { 1439 case kw_plex: 1440 { 1441 int plexno; /* index of this plex */ 1442 int myplexno; /* and index if it's already ours */ 1443 1444 plexno = find_plex(token[++parameter], 1); /* find a plex */ 1445 if (plexno < 0) /* couldn't */ 1446 break; /* we've already had an error message */ 1447 myplexno = my_plex(volno, plexno); /* does it already belong to us? */ 1448 if (myplexno > 0) /* yes, shouldn't get it again */ 1449 throw_rude_remark(EINVAL, 1450 "Plex %s already belongs to volume %s", 1451 token[parameter], 1452 vol->name); 1453 else if (++vol->plexes > 8) /* another entry */ 1454 throw_rude_remark(EINVAL, 1455 "Too many plexes for volume %s", 1456 vol->name); 1457 vol->plex[vol->plexes - 1] = plexno; 1458 PLEX[plexno].state = plex_referenced; /* we know something about it */ 1459 PLEX[plexno].volno = volno; /* and this volume references it */ 1460 } 1461 break; 1462 1463 case kw_readpol: 1464 switch (get_keyword(token[++parameter], &keyword_set)) { /* decide what to do */ 1465 case kw_round: 1466 vol->preferred_plex = ROUND_ROBIN_READPOL; /* default */ 1467 break; 1468 1469 case kw_prefer: 1470 { 1471 int myplexno; /* index of this plex */ 1472 1473 myplexno = find_plex(token[++parameter], 1); /* find a plex */ 1474 if (myplexno < 0) /* couldn't */ 1475 break; /* we've already had an error message */ 1476 myplexno = my_plex(volno, myplexno); /* does it already belong to us? */ 1477 if (myplexno > 0) /* yes */ 1478 vol->preferred_plex = myplexno; /* just note the index */ 1479 else if (++vol->plexes > 8) /* another entry */ 1480 throw_rude_remark(EINVAL, "Too many plexes"); 1481 else { /* space for the new plex */ 1482 vol->plex[vol->plexes - 1] = myplexno; /* add it to our list */ 1483 vol->preferred_plex = vol->plexes - 1; /* and note the index */ 1484 } 1485 } 1486 break; 1487 1488 default: 1489 throw_rude_remark(EINVAL, "Invalid read policy"); 1490 } 1491 1492 case kw_setupstate: 1493 vol->flags |= VF_CONFIG_SETUPSTATE; /* set the volume up later on */ 1494 break; 1495 1496 case kw_state: 1497 parameter++; /* skip the keyword */ 1498 if (vinum_conf.flags & VF_READING_CONFIG) 1499 vol->state = VolState(token[parameter]); /* set the state */ 1500 break; 1501 1502 /* 1503 * XXX experimental ideas. These are not 1504 * documented, and will not be until I 1505 * decide they're worth keeping 1506 */ 1507 case kw_writethrough: /* set writethrough mode */ 1508 vol->flags |= VF_WRITETHROUGH; 1509 break; 1510 1511 case kw_writeback: /* set writeback mode */ 1512 vol->flags &= ~VF_WRITETHROUGH; 1513 break; 1514 1515 case kw_raw: 1516 vol->flags |= VF_RAW; /* raw volume (no label) */ 1517 break; 1518 1519 default: 1520 throw_rude_remark(EINVAL, "volume %s, invalid keyword: %s", 1521 vol->name, 1522 token[parameter]); 1523 } 1524 } 1525 current_volume = volno; /* note last referred volume */ 1526 vol->volno = volno; /* also note in volume */ 1527 1528 /* 1529 * Before we can actually use the volume, we need 1530 * a volume label. We could start to fake one here, 1531 * but it will be a lot easier when we have some 1532 * to copy from the drives, so defer it until we 1533 * set up the configuration. XXX 1534 */ 1535 if (vol->state == volume_unallocated) 1536 vol->state = volume_down; /* now ready to bring up at the end */ 1537 1538 /* Find out how big our volume is */ 1539 for (i = 0; i < vol->plexes; i++) 1540 vol->size = max(vol->size, PLEX[vol->plex[i]].length); 1541 vinum_conf.volumes_used++; /* one more in use */ 1542 } 1543 1544 /* 1545 * Parse a config entry. CARE! This destroys the original contents of the 1546 * config entry, which we don't really need after this. More specifically, it 1547 * places \0 characters at the end of each token. 1548 * 1549 * Return 0 if all is well, otherwise EINVAL for invalid keyword, 1550 * or ENOENT if 'read' command doesn't find any drives. 1551 */ 1552 int 1553 parse_config(char *cptr, struct keywordset *keyset, int update) 1554 { 1555 int status; 1556 1557 status = 0; /* until proven otherwise */ 1558 tokens = tokenize(cptr, token); /* chop up into tokens */ 1559 1560 if (tokens <= 0) /* screwed up or empty line */ 1561 return tokens; /* give up */ 1562 1563 if (token[0][0] == '#') /* comment line */ 1564 return 0; 1565 1566 switch (get_keyword(token[0], keyset)) { /* decide what to do */ 1567 case kw_read: /* read config from a specified drive */ 1568 status = vinum_scandisk(&token[1], tokens - 1); /* read the config from disk */ 1569 break; 1570 1571 case kw_drive: 1572 config_drive(update); 1573 break; 1574 1575 case kw_subdisk: 1576 config_subdisk(update); 1577 break; 1578 1579 case kw_plex: 1580 config_plex(update); 1581 break; 1582 1583 case kw_volume: 1584 config_volume(update); 1585 break; 1586 1587 /* Anything else is invalid in this context */ 1588 default: 1589 throw_rude_remark(EINVAL, /* should we die? */ 1590 "Invalid configuration information: %s", 1591 token[0]); 1592 } 1593 return status; 1594 } 1595 1596 /* 1597 * parse a line handed in from userland via ioctl. 1598 * This differs only by the error reporting mechanism: 1599 * we return the error indication in the reply to the 1600 * ioctl, so we need to set a global static pointer in 1601 * this file. This technique works because we have 1602 * ensured that configuration is performed in a single- 1603 * threaded manner 1604 */ 1605 int 1606 parse_user_config(char *cptr, struct keywordset *keyset) 1607 { 1608 int status; 1609 1610 ioctl_reply = (struct _ioctl_reply *) cptr; 1611 status = parse_config(cptr, keyset, 0); 1612 if (status == ENOENT) /* from scandisk, but it can't tell us */ 1613 strcpy(ioctl_reply->msg, "no drives found"); 1614 ioctl_reply = NULL; /* don't do this again */ 1615 return status; 1616 } 1617 1618 /* Remove an object */ 1619 void 1620 remove(struct vinum_ioctl_msg *msg) 1621 { 1622 struct vinum_ioctl_msg message = *msg; /* make a copy to hand on */ 1623 1624 ioctl_reply = (struct _ioctl_reply *) msg; /* reinstate the address to reply to */ 1625 ioctl_reply->error = 0; /* no error, */ 1626 ioctl_reply->msg[0] = '\0'; /* no message */ 1627 1628 switch (message.type) { 1629 case drive_object: 1630 remove_drive_entry(message.index, message.force); 1631 updateconfig(0); 1632 return; 1633 1634 case sd_object: 1635 remove_sd_entry(message.index, message.force, message.recurse); 1636 updateconfig(0); 1637 return; 1638 1639 case plex_object: 1640 remove_plex_entry(message.index, message.force, message.recurse); 1641 updateconfig(0); 1642 return; 1643 1644 case volume_object: 1645 remove_volume_entry(message.index, message.force, message.recurse); 1646 updateconfig(0); 1647 return; 1648 1649 default: 1650 ioctl_reply->error = EINVAL; 1651 strcpy(ioctl_reply->msg, "Invalid object type"); 1652 } 1653 } 1654 1655 /* Remove a drive. */ 1656 void 1657 remove_drive_entry(int driveno, int force) 1658 { 1659 struct drive *drive = &DRIVE[driveno]; 1660 int sdno; 1661 1662 if ((driveno > vinum_conf.drives_allocated) /* not a valid drive */ 1663 ||(drive->state == drive_unallocated)) { /* or nothing there */ 1664 ioctl_reply->error = EINVAL; 1665 strcpy(ioctl_reply->msg, "No such drive"); 1666 } else if (drive->opencount > 0) { /* we have subdisks */ 1667 if (force) { /* do it at any cost */ 1668 for (sdno = 0; sdno < vinum_conf.subdisks_allocated; sdno++) { 1669 if ((SD[sdno].state != sd_unallocated) /* subdisk is allocated */ 1670 &&(SD[sdno].driveno == driveno)) /* and it belongs to this drive */ 1671 remove_sd_entry(sdno, force, 0); 1672 } 1673 remove_drive(driveno); /* now remove it */ 1674 vinum_conf.drives_used--; /* one less drive */ 1675 } else 1676 ioctl_reply->error = EBUSY; /* can't do that */ 1677 } else { 1678 remove_drive(driveno); /* just remove it */ 1679 vinum_conf.drives_used--; /* one less drive */ 1680 } 1681 } 1682 1683 /* remove a subdisk */ 1684 void 1685 remove_sd_entry(int sdno, int force, int recurse) 1686 { 1687 struct sd *sd = &SD[sdno]; 1688 1689 if ((sdno > vinum_conf.subdisks_allocated) /* not a valid sd */ 1690 ||(sd->state == sd_unallocated)) { /* or nothing there */ 1691 ioctl_reply->error = EINVAL; 1692 strcpy(ioctl_reply->msg, "No such subdisk"); 1693 } else if (sd->flags & VF_OPEN) { /* we're open */ 1694 ioctl_reply->error = EBUSY; /* no getting around that */ 1695 return; 1696 } else if (sd->plexno >= 0) { /* we have a plex */ 1697 if (force) { /* do it at any cost */ 1698 struct plex *plex = &PLEX[sd->plexno]; /* point to our plex */ 1699 int mysdno; 1700 1701 for (mysdno = 0; /* look for ourselves */ 1702 mysdno < plex->subdisks && &SD[plex->sdnos[mysdno]] != sd; 1703 mysdno++); 1704 if (mysdno == plex->subdisks) /* didn't find it */ 1705 log(LOG_ERR, 1706 "Error removing subdisk %s: not found in plex %s\n", 1707 SD[mysdno].name, 1708 plex->name); 1709 else { /* remove the subdisk from plex */ 1710 if (mysdno < (plex->subdisks - 1)) /* not the last subdisk */ 1711 bcopy(&plex->sdnos[mysdno + 1], 1712 &plex->sdnos[mysdno], 1713 (plex->subdisks - 1 - mysdno) * sizeof(int)); 1714 plex->subdisks--; 1715 sd->plexno = -1; /* disown the subdisk */ 1716 } 1717 1718 /* 1719 * Removing a subdisk from a striped or 1720 * RAID-4 or RAID-5 plex really tears the 1721 * hell out of the structure, and it needs 1722 * to be reinitialized. 1723 */ 1724 if (plex->organization != plex_concat) /* not concatenated, */ 1725 set_plex_state(plex->plexno, plex_faulty, setstate_force); /* need to reinitialize */ 1726 log(LOG_INFO, "vinum: removing %s\n", sd->name); 1727 free_sd(sdno); 1728 } else 1729 ioctl_reply->error = EBUSY; /* can't do that */ 1730 } else { 1731 log(LOG_INFO, "vinum: removing %s\n", sd->name); 1732 free_sd(sdno); 1733 } 1734 } 1735 1736 /* remove a plex */ 1737 void 1738 remove_plex_entry(int plexno, int force, int recurse) 1739 { 1740 struct plex *plex = &PLEX[plexno]; 1741 int sdno; 1742 1743 if ((plexno > vinum_conf.plexes_allocated) /* not a valid plex */ 1744 ||(plex->state == plex_unallocated)) { /* or nothing there */ 1745 ioctl_reply->error = EINVAL; 1746 strcpy(ioctl_reply->msg, "No such plex"); 1747 } else if (plex->flags & VF_OPEN) { /* we're open */ 1748 ioctl_reply->error = EBUSY; /* no getting around that */ 1749 return; 1750 } 1751 if (plex->subdisks) { 1752 if (force) { /* do it anyway */ 1753 if (recurse) { /* remove all below */ 1754 int sds = plex->subdisks; 1755 for (sdno = 0; sdno < sds; sdno++) 1756 free_sd(plex->sdnos[sdno]); /* free all subdisks */ 1757 } else { /* just tear them out */ 1758 int sds = plex->subdisks; 1759 for (sdno = 0; sdno < sds; sdno++) 1760 SD[plex->sdnos[sdno]].plexno = -1; /* no plex any more */ 1761 } 1762 } else { /* can't do it without force */ 1763 ioctl_reply->error = EBUSY; /* can't do that */ 1764 return; 1765 } 1766 } 1767 if (plex->volno >= 0) { /* we are part of a volume */ 1768 if (force) { /* do it at any cost */ 1769 struct volume *vol = &VOL[plex->volno]; 1770 int myplexno; 1771 1772 for (myplexno = 0; myplexno < vol->plexes; myplexno++) 1773 if (vol->plex[myplexno] == plexno) /* found it */ 1774 break; 1775 if (myplexno == vol->plexes) /* didn't find it. Huh? */ 1776 log(LOG_ERR, 1777 "Error removing plex %s: not found in volume %s\n", 1778 plex->name, 1779 vol->name); 1780 if (myplexno < (vol->plexes - 1)) /* not the last plex in the list */ 1781 bcopy(&vol->plex[myplexno + 1], 1782 &vol->plex[myplexno], 1783 vol->plexes - 1 - myplexno); 1784 vol->plexes--; 1785 } else { 1786 ioctl_reply->error = EBUSY; /* can't do that */ 1787 return; 1788 } 1789 } 1790 log(LOG_INFO, "vinum: removing %s\n", plex->name); 1791 free_plex(plexno); 1792 vinum_conf.plexes_used--; /* one less plex */ 1793 } 1794 1795 /* remove a volume */ 1796 void 1797 remove_volume_entry(int volno, int force, int recurse) 1798 { 1799 struct volume *vol = &VOL[volno]; 1800 int plexno; 1801 1802 if ((volno > vinum_conf.volumes_allocated) /* not a valid volume */ 1803 ||(vol->state == volume_unallocated)) { /* or nothing there */ 1804 ioctl_reply->error = EINVAL; 1805 strcpy(ioctl_reply->msg, "No such volume"); 1806 } else if (vol->flags & VF_OPEN) /* we're open */ 1807 ioctl_reply->error = EBUSY; /* no getting around that */ 1808 else if (vol->plexes) { 1809 if (recurse && force) { /* remove all below */ 1810 int plexes = vol->plexes; 1811 1812 /* for (plexno = plexes - 1; plexno >= 0; plexno--) */ 1813 for (plexno = 0; plexno < plexes; plexno++) 1814 remove_plex_entry(vol->plex[plexno], force, recurse); 1815 log(LOG_INFO, "vinum: removing %s\n", vol->name); 1816 free_volume(volno); 1817 vinum_conf.volumes_used--; /* one less volume */ 1818 } else 1819 ioctl_reply->error = EBUSY; /* can't do that */ 1820 } else { 1821 log(LOG_INFO, "vinum: removing %s\n", vol->name); 1822 free_volume(volno); 1823 vinum_conf.volumes_used--; /* one less volume */ 1824 } 1825 } 1826 1827 /* Currently called only from ioctl */ 1828 void 1829 update_sd_config(int sdno, int diskconfig) 1830 { 1831 if (!diskconfig) 1832 set_sd_state(sdno, sd_up, setstate_configuring); 1833 SD[sdno].flags &= ~VF_NEWBORN; 1834 } 1835 1836 void 1837 update_plex_config(int plexno, int diskconfig) 1838 { 1839 u_int64_t size; 1840 int sdno; 1841 struct plex *plex = &PLEX[plexno]; 1842 enum plexstate state = plex_up; /* state we want the plex in */ 1843 int remainder; /* size of fractional stripe at end */ 1844 int added_plex; /* set if we add a plex to a volume */ 1845 int required_sds; /* number of subdisks we need */ 1846 struct sd *sd; 1847 struct volume *vol; 1848 int data_sds; /* number of sds carrying data */ 1849 1850 if (plex->state < plex_init) /* not a real plex, */ 1851 return; 1852 added_plex = 0; 1853 if (plex->volno >= 0) { /* we have a volume */ 1854 vol = &VOL[plex->volno]; 1855 1856 /* 1857 * If we're newly born, 1858 * and the volume isn't, 1859 * and it has other plexes, 1860 * and we didn't read this mess from disk, 1861 * we were added later. 1862 */ 1863 if ((plex->flags & VF_NEWBORN) 1864 && ((vol->flags & VF_NEWBORN) == 0) 1865 && (vol->plexes > 0) 1866 && (diskconfig == 0)) { 1867 added_plex = 1; 1868 state = plex_down; /* so take ourselves down */ 1869 } 1870 } 1871 /* 1872 * Check that our subdisks make sense. For 1873 * striped, RAID-4 and RAID-5 plexes, we need at 1874 * least two subdisks, and they must all be the 1875 * same size. 1876 */ 1877 if (plex->organization == plex_striped) { 1878 data_sds = plex->subdisks; 1879 required_sds = 2; 1880 } else if (isparity(plex)) { /* RAID 4 or 5 */ 1881 data_sds = plex->subdisks - 1; 1882 required_sds = 3; 1883 } else 1884 required_sds = 0; 1885 if (required_sds > 0) { /* striped, RAID-4 or RAID-5 */ 1886 if (plex->subdisks < required_sds) { 1887 log(LOG_ERR, 1888 "vinum: plex %s does not have at least %d subdisks\n", 1889 plex->name, 1890 required_sds); 1891 state = plex_faulty; 1892 } 1893 /* 1894 * Now see if the plex size is a multiple of 1895 * the stripe size. If not, trim off the end 1896 * of each subdisk and return it to the drive. 1897 */ 1898 if (plex->length > 0) { 1899 if (data_sds > 0) { 1900 if (plex->stripesize > 0) { 1901 remainder = (int) (plex->length /* are we exact? */ 1902 % ((u_int64_t) plex->stripesize * data_sds)); 1903 if (remainder) { /* no */ 1904 log(LOG_INFO, "vinum: removing %d blocks of partial stripe at the end of %s\n", 1905 remainder, 1906 plex->name); 1907 plex->length -= remainder; /* shorten the plex */ 1908 remainder /= data_sds; /* spread the remainder amongst the sds */ 1909 for (sdno = 0; sdno < plex->subdisks; sdno++) { 1910 sd = &SD[plex->sdnos[sdno]]; /* point to the subdisk */ 1911 return_drive_space(sd->driveno, /* return the space */ 1912 sd->driveoffset + sd->sectors - remainder, 1913 remainder); 1914 sd->sectors -= remainder; /* and shorten it */ 1915 } 1916 } 1917 } else /* no data sds, */ 1918 plex->length = 0; /* reset length */ 1919 } 1920 } 1921 } 1922 size = 0; 1923 for (sdno = 0; sdno < plex->subdisks; sdno++) { 1924 sd = &SD[plex->sdnos[sdno]]; 1925 if (isstriped(plex) 1926 && (sdno > 0) 1927 && (sd->sectors != SD[plex->sdnos[sdno - 1]].sectors)) { 1928 log(LOG_ERR, "vinum: %s must have equal sized subdisks\n", plex->name); 1929 state = plex_down; 1930 } 1931 size += sd->sectors; 1932 if (added_plex) /* we were added later */ 1933 sd->state = sd_stale; /* stale until proven otherwise */ 1934 } 1935 1936 if (plex->subdisks) { /* plex has subdisks, calculate size */ 1937 /* 1938 * XXX We shouldn't need to calculate the size any 1939 * more. Check this some time 1940 */ 1941 if (isparity(plex)) 1942 size = size / plex->subdisks * (plex->subdisks - 1); /* less space for RAID-4 and RAID-5 */ 1943 if (plex->length != size) 1944 log(LOG_INFO, 1945 "Correcting length of %s: was %lld, is %lld\n", 1946 plex->name, 1947 (long long) plex->length, 1948 (long long) size); 1949 plex->length = size; 1950 } else { /* no subdisks, */ 1951 plex->length = 0; /* no size */ 1952 state = plex_down; /* take it down */ 1953 } 1954 update_plex_state(plexno); /* set the state */ 1955 plex->flags &= ~VF_NEWBORN; 1956 } 1957 1958 void 1959 update_volume_config(int volno, int diskconfig) 1960 { 1961 struct volume *vol = &VOL[volno]; 1962 struct plex *plex; 1963 int plexno; 1964 1965 if (vol->state != volume_unallocated) 1966 /* 1967 * Recalculate the size of the volume, 1968 * which might change if the original 1969 * plexes were not a multiple of the 1970 * stripe size. 1971 */ 1972 { 1973 vol->size = 0; 1974 for (plexno = 0; plexno < vol->plexes; plexno++) { 1975 plex = &PLEX[vol->plex[plexno]]; 1976 vol->size = max(plex->length, vol->size); /* maximum size */ 1977 plex->volplexno = plexno; /* note it in the plex */ 1978 } 1979 } 1980 vol->flags &= ~VF_NEWBORN; /* no longer newly born */ 1981 } 1982 1983 /* 1984 * Update the global configuration. 1985 * diskconfig is != 0 if we're reading in a config 1986 * from disk. In this case, we don't try to 1987 * bring the devices up, though we will bring 1988 * them down if there's some error which got 1989 * missed when writing to disk. 1990 */ 1991 void 1992 updateconfig(int diskconfig) 1993 { 1994 int plexno; 1995 int volno; 1996 1997 for (plexno = 0; plexno < vinum_conf.plexes_allocated; plexno++) 1998 update_plex_config(plexno, diskconfig); 1999 2000 for (volno = 0; volno < vinum_conf.volumes_allocated; volno++) { 2001 if (VOL[volno].state > volume_uninit) { 2002 VOL[volno].flags &= ~VF_CONFIG_SETUPSTATE; /* no more setupstate */ 2003 update_volume_state(volno); 2004 update_volume_config(volno, diskconfig); 2005 } 2006 } 2007 save_config(); 2008 } 2009 2010 /* 2011 * Start manual changes to the configuration and lock out 2012 * others who may wish to do so. 2013 * XXX why do we need this and lock_config too? 2014 */ 2015 int 2016 start_config(int force) 2017 { 2018 int error; 2019 2020 current_drive = -1; /* note the last drive we mention, for 2021 * some defaults */ 2022 current_plex = -1; /* and the same for the last plex */ 2023 current_volume = -1; /* and the last volume */ 2024 while ((vinum_conf.flags & VF_CONFIGURING) != 0) { 2025 vinum_conf.flags |= VF_WILL_CONFIGURE; 2026 if ((error = tsleep(&vinum_conf, PRIBIO | PCATCH, "vincfg", 0)) != 0) 2027 return error; 2028 } 2029 /* 2030 * We need two flags here: VF_CONFIGURING 2031 * tells other processes to hold off (this 2032 * function), and VF_CONFIG_INCOMPLETE 2033 * tells the state change routines not to 2034 * propagate incrememntal state changes 2035 */ 2036 vinum_conf.flags |= VF_CONFIGURING | VF_CONFIG_INCOMPLETE; 2037 if (force) 2038 vinum_conf.flags |= VF_FORCECONFIG; /* overwrite differently named drives */ 2039 current_drive = -1; /* reset the defaults */ 2040 current_plex = -1; /* and the same for the last plex */ 2041 current_volume = -1; /* and the last volme */ 2042 return 0; 2043 } 2044 2045 /* 2046 * Update the config if update is 1, and unlock 2047 * it. We won't update the configuration if we 2048 * are called in a recursive loop via throw_rude_remark. 2049 */ 2050 void 2051 finish_config(int update) 2052 { 2053 /* we've finished our config */ 2054 vinum_conf.flags &= ~(VF_CONFIG_INCOMPLETE | VF_READING_CONFIG | VF_FORCECONFIG); 2055 if (update) 2056 updateconfig(0); /* so update things */ 2057 else 2058 updateconfig(1); /* do some updates only */ 2059 vinum_conf.flags &= ~VF_CONFIGURING; /* and now other people can take a turn */ 2060 if ((vinum_conf.flags & VF_WILL_CONFIGURE) != 0) { 2061 vinum_conf.flags &= ~VF_WILL_CONFIGURE; 2062 wakeup_one(&vinum_conf); 2063 } 2064 } 2065 /* Local Variables: */ 2066 /* fill-column: 50 */ 2067 /* End: */ 2068