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