1 /*- 2 * SPDX-License-Identifier: BSD-4-Clause 3 * 4 * Copyright (c) 2004, 2007 Lukas Ertl 5 * Copyright (c) 2007, 2009 Ulf Lilleengen 6 * Copyright (c) 1997, 1998, 1999 7 * Nan Yang Computer Services Limited. All rights reserved. 8 * 9 * Parts written by Greg Lehey 10 * 11 * This software is distributed under the so-called ``Berkeley 12 * License'': 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. All advertising materials mentioning features or use of this software 23 * must display the following acknowledgement: 24 * This product includes software developed by Nan Yang Computer 25 * Services Limited. 26 * 4. Neither the name of the Company nor the names of its contributors 27 * may be used to endorse or promote products derived from this software 28 * without specific prior written permission. 29 * 30 * This software is provided ``as is'', and any express or implied 31 * warranties, including, but not limited to, the implied warranties of 32 * merchantability and fitness for a particular purpose are disclaimed. 33 * In no event shall the company or contributors be liable for any 34 * direct, indirect, incidental, special, exemplary, or consequential 35 * damages (including, but not limited to, procurement of substitute 36 * goods or services; loss of use, data, or profits; or business 37 * interruption) however caused and on any theory of liability, whether 38 * in contract, strict liability, or tort (including negligence or 39 * otherwise) arising in any way out of the use of this software, even if 40 * advised of the possibility of such damage. 41 * 42 */ 43 44 #include <sys/cdefs.h> 45 __FBSDID("$FreeBSD$"); 46 47 #include <sys/param.h> 48 #include <sys/malloc.h> 49 #include <sys/sbuf.h> 50 #include <sys/systm.h> 51 52 #include <geom/geom.h> 53 #include <geom/vinum/geom_vinum_var.h> 54 #include <geom/vinum/geom_vinum.h> 55 #include <geom/vinum/geom_vinum_share.h> 56 57 int gv_drive_is_newer(struct gv_softc *, struct gv_drive *); 58 static off_t gv_plex_smallest_sd(struct gv_plex *); 59 60 void 61 gv_parse_config(struct gv_softc *sc, char *buf, struct gv_drive *d) 62 { 63 char *aptr, *bptr, *cptr; 64 struct gv_volume *v, *v2; 65 struct gv_plex *p, *p2; 66 struct gv_sd *s, *s2; 67 int error, is_newer, tokens; 68 char *token[GV_MAXARGS]; 69 70 is_newer = gv_drive_is_newer(sc, d); 71 72 /* Until the end of the string *buf. */ 73 for (aptr = buf; *aptr != '\0'; aptr = bptr) { 74 bptr = aptr; 75 cptr = aptr; 76 77 /* Separate input lines. */ 78 while (*bptr != '\n') 79 bptr++; 80 *bptr = '\0'; 81 bptr++; 82 83 tokens = gv_tokenize(cptr, token, GV_MAXARGS); 84 85 if (tokens <= 0) 86 continue; 87 88 if (!strcmp(token[0], "volume")) { 89 v = gv_new_volume(tokens, token); 90 if (v == NULL) { 91 G_VINUM_DEBUG(0, "config parse failed volume"); 92 break; 93 } 94 95 v2 = gv_find_vol(sc, v->name); 96 if (v2 != NULL) { 97 if (is_newer) { 98 v2->state = v->state; 99 G_VINUM_DEBUG(2, "newer volume found!"); 100 } 101 g_free(v); 102 continue; 103 } 104 105 gv_create_volume(sc, v); 106 107 } else if (!strcmp(token[0], "plex")) { 108 p = gv_new_plex(tokens, token); 109 if (p == NULL) { 110 G_VINUM_DEBUG(0, "config parse failed plex"); 111 break; 112 } 113 114 p2 = gv_find_plex(sc, p->name); 115 if (p2 != NULL) { 116 /* XXX */ 117 if (is_newer) { 118 p2->state = p->state; 119 G_VINUM_DEBUG(2, "newer plex found!"); 120 } 121 g_free(p); 122 continue; 123 } 124 125 error = gv_create_plex(sc, p); 126 if (error) 127 continue; 128 /* 129 * These flags were set in gv_create_plex() and are not 130 * needed here (on-disk config parsing). 131 */ 132 p->flags &= ~GV_PLEX_ADDED; 133 134 } else if (!strcmp(token[0], "sd")) { 135 s = gv_new_sd(tokens, token); 136 137 if (s == NULL) { 138 G_VINUM_DEBUG(0, "config parse failed subdisk"); 139 break; 140 } 141 142 s2 = gv_find_sd(sc, s->name); 143 if (s2 != NULL) { 144 /* XXX */ 145 if (is_newer) { 146 s2->state = s->state; 147 G_VINUM_DEBUG(2, "newer subdisk found!"); 148 } 149 g_free(s); 150 continue; 151 } 152 153 /* 154 * Signal that this subdisk was tasted, and could 155 * possibly reference a drive that isn't in our config 156 * yet. 157 */ 158 s->flags |= GV_SD_TASTED; 159 160 if (s->state == GV_SD_UP) 161 s->flags |= GV_SD_CANGOUP; 162 163 error = gv_create_sd(sc, s); 164 if (error) 165 continue; 166 167 /* 168 * This flag was set in gv_create_sd() and is not 169 * needed here (on-disk config parsing). 170 */ 171 s->flags &= ~GV_SD_NEWBORN; 172 s->flags &= ~GV_SD_GROW; 173 } 174 } 175 } 176 177 /* 178 * Format the vinum configuration properly. If ondisk is non-zero then the 179 * configuration is intended to be written to disk later. 180 */ 181 void 182 gv_format_config(struct gv_softc *sc, struct sbuf *sb, int ondisk, char *prefix) 183 { 184 struct gv_drive *d; 185 struct gv_sd *s; 186 struct gv_plex *p; 187 struct gv_volume *v; 188 189 /* 190 * We don't need the drive configuration if we're not writing the 191 * config to disk. 192 */ 193 if (!ondisk) { 194 LIST_FOREACH(d, &sc->drives, drive) { 195 sbuf_printf(sb, "%sdrive %s device /dev/%s\n", prefix, 196 d->name, d->device); 197 } 198 } 199 200 LIST_FOREACH(v, &sc->volumes, volume) { 201 if (!ondisk) 202 sbuf_printf(sb, "%s", prefix); 203 sbuf_printf(sb, "volume %s", v->name); 204 if (ondisk) 205 sbuf_printf(sb, " state %s", gv_volstate(v->state)); 206 sbuf_printf(sb, "\n"); 207 } 208 209 LIST_FOREACH(p, &sc->plexes, plex) { 210 if (!ondisk) 211 sbuf_printf(sb, "%s", prefix); 212 sbuf_printf(sb, "plex name %s org %s ", p->name, 213 gv_plexorg(p->org)); 214 if (gv_is_striped(p)) 215 sbuf_printf(sb, "%ds ", p->stripesize / 512); 216 if (p->vol_sc != NULL) 217 sbuf_printf(sb, "vol %s", p->volume); 218 if (ondisk) 219 sbuf_printf(sb, " state %s", gv_plexstate(p->state)); 220 sbuf_printf(sb, "\n"); 221 } 222 223 LIST_FOREACH(s, &sc->subdisks, sd) { 224 if (!ondisk) 225 sbuf_printf(sb, "%s", prefix); 226 sbuf_printf(sb, "sd name %s drive %s len %jds driveoffset " 227 "%jds", s->name, s->drive, s->size / 512, 228 s->drive_offset / 512); 229 if (s->plex_sc != NULL) { 230 sbuf_printf(sb, " plex %s plexoffset %jds", s->plex, 231 s->plex_offset / 512); 232 } 233 if (ondisk) 234 sbuf_printf(sb, " state %s", gv_sdstate(s->state)); 235 sbuf_printf(sb, "\n"); 236 } 237 } 238 239 static off_t 240 gv_plex_smallest_sd(struct gv_plex *p) 241 { 242 struct gv_sd *s; 243 off_t smallest; 244 245 KASSERT(p != NULL, ("gv_plex_smallest_sd: NULL p")); 246 247 s = LIST_FIRST(&p->subdisks); 248 if (s == NULL) 249 return (-1); 250 smallest = s->size; 251 LIST_FOREACH(s, &p->subdisks, in_plex) { 252 if (s->size < smallest) 253 smallest = s->size; 254 } 255 return (smallest); 256 } 257 258 /* Walk over plexes in a volume and count how many are down. */ 259 int 260 gv_plexdown(struct gv_volume *v) 261 { 262 int plexdown; 263 struct gv_plex *p; 264 265 KASSERT(v != NULL, ("gv_plexdown: NULL v")); 266 267 plexdown = 0; 268 269 LIST_FOREACH(p, &v->plexes, plex) { 270 if (p->state == GV_PLEX_DOWN) 271 plexdown++; 272 } 273 return (plexdown); 274 } 275 276 int 277 gv_sd_to_plex(struct gv_sd *s, struct gv_plex *p) 278 { 279 struct gv_sd *s2; 280 off_t psizeorig, remainder, smallest; 281 282 /* If this subdisk was already given to this plex, do nothing. */ 283 if (s->plex_sc == p) 284 return (0); 285 286 /* Check correct size of this subdisk. */ 287 s2 = LIST_FIRST(&p->subdisks); 288 /* Adjust the subdisk-size if necessary. */ 289 if (s2 != NULL && gv_is_striped(p)) { 290 /* First adjust to the stripesize. */ 291 remainder = s->size % p->stripesize; 292 293 if (remainder) { 294 G_VINUM_DEBUG(1, "size of sd %s is not a " 295 "multiple of plex stripesize, taking off " 296 "%jd bytes", s->name, 297 (intmax_t)remainder); 298 gv_adjust_freespace(s, remainder); 299 } 300 301 smallest = gv_plex_smallest_sd(p); 302 /* Then take off extra if other subdisks are smaller. */ 303 remainder = s->size - smallest; 304 305 /* 306 * Don't allow a remainder below zero for running plexes, it's too 307 * painful, and if someone were to accidentally do this, the 308 * resulting array might be smaller than the original... not god 309 */ 310 if (remainder < 0) { 311 if (!(p->flags & GV_PLEX_NEWBORN)) { 312 G_VINUM_DEBUG(0, "sd %s too small for plex %s!", 313 s->name, p->name); 314 return (GV_ERR_BADSIZE); 315 } 316 /* Adjust other subdisks. */ 317 LIST_FOREACH(s2, &p->subdisks, in_plex) { 318 G_VINUM_DEBUG(1, "size of sd %s is to big, " 319 "taking off %jd bytes", s->name, 320 (intmax_t)remainder); 321 gv_adjust_freespace(s2, (remainder * -1)); 322 } 323 } else if (remainder > 0) { 324 G_VINUM_DEBUG(1, "size of sd %s is to big, " 325 "taking off %jd bytes", s->name, 326 (intmax_t)remainder); 327 gv_adjust_freespace(s, remainder); 328 } 329 } 330 331 /* Find the correct plex offset for this subdisk, if needed. */ 332 if (s->plex_offset == -1) { 333 /* 334 * First set it to 0 to catch the case where we had a detached 335 * subdisk that didn't get any good offset. 336 */ 337 s->plex_offset = 0; 338 if (p->sdcount) { 339 LIST_FOREACH(s2, &p->subdisks, in_plex) { 340 if (gv_is_striped(p)) 341 s->plex_offset = p->sdcount * 342 p->stripesize; 343 else 344 s->plex_offset = s2->plex_offset + 345 s2->size; 346 } 347 } 348 } 349 350 /* There are no subdisks for this plex yet, just insert it. */ 351 if (LIST_EMPTY(&p->subdisks)) { 352 LIST_INSERT_HEAD(&p->subdisks, s, in_plex); 353 354 /* Insert in correct order, depending on plex_offset. */ 355 } else { 356 LIST_FOREACH(s2, &p->subdisks, in_plex) { 357 if (s->plex_offset < s2->plex_offset) { 358 LIST_INSERT_BEFORE(s2, s, in_plex); 359 break; 360 } else if (LIST_NEXT(s2, in_plex) == NULL) { 361 LIST_INSERT_AFTER(s2, s, in_plex); 362 break; 363 } 364 } 365 } 366 367 s->plex_sc = p; 368 /* Adjust the size of our plex. We check if the plex misses a subdisk, 369 * so we don't make the plex smaller than it actually should be. 370 */ 371 psizeorig = p->size; 372 p->size = gv_plex_size(p); 373 /* Make sure the size is not changed. */ 374 if (p->sddetached > 0) { 375 if (p->size < psizeorig) { 376 p->size = psizeorig; 377 /* We make sure wee need another subdisk. */ 378 if (p->sddetached == 1) 379 p->sddetached++; 380 } 381 p->sddetached--; 382 } else { 383 if ((p->org == GV_PLEX_RAID5 || 384 p->org == GV_PLEX_STRIPED) && 385 !(p->flags & GV_PLEX_NEWBORN) && 386 p->state == GV_PLEX_UP) { 387 s->flags |= GV_SD_GROW; 388 } 389 p->sdcount++; 390 } 391 392 return (0); 393 } 394 395 void 396 gv_update_vol_size(struct gv_volume *v, off_t size) 397 { 398 if (v == NULL) 399 return; 400 if (v->provider != NULL) { 401 g_topology_lock(); 402 v->provider->mediasize = size; 403 g_topology_unlock(); 404 } 405 v->size = size; 406 } 407 408 /* Return how many subdisks that constitute the original plex. */ 409 int 410 gv_sdcount(struct gv_plex *p, int growing) 411 { 412 struct gv_sd *s; 413 int sdcount; 414 415 sdcount = p->sdcount; 416 if (growing) { 417 LIST_FOREACH(s, &p->subdisks, in_plex) { 418 if (s->flags & GV_SD_GROW) 419 sdcount--; 420 } 421 } 422 423 return (sdcount); 424 } 425 426 /* Calculates the plex size. */ 427 off_t 428 gv_plex_size(struct gv_plex *p) 429 { 430 struct gv_sd *s; 431 off_t size; 432 int sdcount; 433 434 KASSERT(p != NULL, ("gv_plex_size: NULL p")); 435 436 /* Adjust the size of our plex. */ 437 size = 0; 438 sdcount = gv_sdcount(p, 1); 439 switch (p->org) { 440 case GV_PLEX_CONCAT: 441 LIST_FOREACH(s, &p->subdisks, in_plex) 442 size += s->size; 443 break; 444 case GV_PLEX_STRIPED: 445 s = LIST_FIRST(&p->subdisks); 446 size = ((s != NULL) ? (sdcount * s->size) : 0); 447 break; 448 case GV_PLEX_RAID5: 449 s = LIST_FIRST(&p->subdisks); 450 size = ((s != NULL) ? ((sdcount - 1) * s->size) : 0); 451 break; 452 } 453 454 return (size); 455 } 456 457 /* Returns the size of a volume. */ 458 off_t 459 gv_vol_size(struct gv_volume *v) 460 { 461 struct gv_plex *p; 462 off_t minplexsize; 463 464 KASSERT(v != NULL, ("gv_vol_size: NULL v")); 465 466 p = LIST_FIRST(&v->plexes); 467 if (p == NULL) 468 return (0); 469 470 minplexsize = p->size; 471 LIST_FOREACH(p, &v->plexes, in_volume) { 472 if (p->size < minplexsize) { 473 minplexsize = p->size; 474 } 475 } 476 return (minplexsize); 477 } 478 479 void 480 gv_update_plex_config(struct gv_plex *p) 481 { 482 struct gv_sd *s, *s2; 483 off_t remainder; 484 int required_sds, state; 485 486 KASSERT(p != NULL, ("gv_update_plex_config: NULL p")); 487 488 /* The plex was added to an already running volume. */ 489 if (p->flags & GV_PLEX_ADDED) 490 gv_set_plex_state(p, GV_PLEX_DOWN, GV_SETSTATE_FORCE); 491 492 switch (p->org) { 493 case GV_PLEX_STRIPED: 494 required_sds = 2; 495 break; 496 case GV_PLEX_RAID5: 497 required_sds = 3; 498 break; 499 case GV_PLEX_CONCAT: 500 default: 501 required_sds = 0; 502 break; 503 } 504 505 if (required_sds) { 506 if (p->sdcount < required_sds) { 507 gv_set_plex_state(p, GV_PLEX_DOWN, GV_SETSTATE_FORCE); 508 } 509 510 /* 511 * The subdisks in striped plexes must all have the same size. 512 */ 513 s = LIST_FIRST(&p->subdisks); 514 LIST_FOREACH(s2, &p->subdisks, in_plex) { 515 if (s->size != s2->size) { 516 G_VINUM_DEBUG(0, "subdisk size mismatch %s" 517 "(%jd) <> %s (%jd)", s->name, s->size, 518 s2->name, s2->size); 519 gv_set_plex_state(p, GV_PLEX_DOWN, 520 GV_SETSTATE_FORCE); 521 } 522 } 523 524 LIST_FOREACH(s, &p->subdisks, in_plex) { 525 /* Trim subdisk sizes to match the stripe size. */ 526 remainder = s->size % p->stripesize; 527 if (remainder) { 528 G_VINUM_DEBUG(1, "size of sd %s is not a " 529 "multiple of plex stripesize, taking off " 530 "%jd bytes", s->name, (intmax_t)remainder); 531 gv_adjust_freespace(s, remainder); 532 } 533 } 534 } 535 536 p->size = gv_plex_size(p); 537 if (p->sdcount == 0) 538 gv_set_plex_state(p, GV_PLEX_DOWN, GV_SETSTATE_FORCE); 539 else if (p->org == GV_PLEX_RAID5 && p->flags & GV_PLEX_NEWBORN) { 540 LIST_FOREACH(s, &p->subdisks, in_plex) 541 gv_set_sd_state(s, GV_SD_UP, GV_SETSTATE_FORCE); 542 /* If added to a volume, we want the plex to be down. */ 543 state = (p->flags & GV_PLEX_ADDED) ? GV_PLEX_DOWN : GV_PLEX_UP; 544 gv_set_plex_state(p, state, GV_SETSTATE_FORCE); 545 p->flags &= ~GV_PLEX_ADDED; 546 } else if (p->flags & GV_PLEX_ADDED) { 547 LIST_FOREACH(s, &p->subdisks, in_plex) 548 gv_set_sd_state(s, GV_SD_STALE, GV_SETSTATE_FORCE); 549 gv_set_plex_state(p, GV_PLEX_DOWN, GV_SETSTATE_FORCE); 550 p->flags &= ~GV_PLEX_ADDED; 551 } else if (p->state == GV_PLEX_UP) { 552 LIST_FOREACH(s, &p->subdisks, in_plex) { 553 if (s->flags & GV_SD_GROW) { 554 gv_set_plex_state(p, GV_PLEX_GROWABLE, 555 GV_SETSTATE_FORCE); 556 break; 557 } 558 } 559 } 560 /* Our plex is grown up now. */ 561 p->flags &= ~GV_PLEX_NEWBORN; 562 } 563 564 /* 565 * Give a subdisk to a drive, check and adjust several parameters, adjust 566 * freelist. 567 */ 568 int 569 gv_sd_to_drive(struct gv_sd *s, struct gv_drive *d) 570 { 571 struct gv_sd *s2; 572 struct gv_freelist *fl, *fl2; 573 off_t tmp; 574 int i; 575 576 fl2 = NULL; 577 578 /* Shortcut for "referenced" drives. */ 579 if (d->flags & GV_DRIVE_REFERENCED) { 580 s->drive_sc = d; 581 return (0); 582 } 583 584 /* Check if this subdisk was already given to this drive. */ 585 if (s->drive_sc != NULL) { 586 if (s->drive_sc == d) { 587 if (!(s->flags & GV_SD_TASTED)) { 588 return (0); 589 } 590 } else { 591 G_VINUM_DEBUG(0, "error giving subdisk '%s' to '%s' " 592 "(already on '%s')", s->name, d->name, 593 s->drive_sc->name); 594 return (GV_ERR_ISATTACHED); 595 } 596 } 597 598 /* Preliminary checks. */ 599 if ((s->size > d->avail) || (d->freelist_entries == 0)) { 600 G_VINUM_DEBUG(0, "not enough space on '%s' for '%s'", d->name, 601 s->name); 602 return (GV_ERR_NOSPACE); 603 } 604 605 /* If no size was given for this subdisk, try to auto-size it... */ 606 if (s->size == -1) { 607 /* Find the largest available slot. */ 608 LIST_FOREACH(fl, &d->freelist, freelist) { 609 if (fl->size < s->size) 610 continue; 611 s->size = fl->size; 612 s->drive_offset = fl->offset; 613 fl2 = fl; 614 } 615 616 /* No good slot found? */ 617 if (s->size == -1) { 618 G_VINUM_DEBUG(0, "unable to autosize '%s' on '%s'", 619 s->name, d->name); 620 return (GV_ERR_BADSIZE); 621 } 622 623 /* 624 * ... or check if we have a free slot that's large enough for the 625 * given size. 626 */ 627 } else { 628 i = 0; 629 LIST_FOREACH(fl, &d->freelist, freelist) { 630 if (fl->size < s->size) 631 continue; 632 /* Assign drive offset, if not given. */ 633 if (s->drive_offset == -1) 634 s->drive_offset = fl->offset; 635 fl2 = fl; 636 i++; 637 break; 638 } 639 640 /* Couldn't find a good free slot. */ 641 if (i == 0) { 642 G_VINUM_DEBUG(0, "free slots to small for '%s' on '%s'", 643 s->name, d->name); 644 return (GV_ERR_NOSPACE); 645 } 646 } 647 648 /* No drive offset given, try to calculate it. */ 649 if (s->drive_offset == -1) { 650 651 /* Add offsets and sizes from other subdisks on this drive. */ 652 LIST_FOREACH(s2, &d->subdisks, from_drive) { 653 s->drive_offset = s2->drive_offset + s2->size; 654 } 655 656 /* 657 * If there are no other subdisks yet, then set the default 658 * offset to GV_DATA_START. 659 */ 660 if (s->drive_offset == -1) 661 s->drive_offset = GV_DATA_START; 662 663 /* Check if we have a free slot at the given drive offset. */ 664 } else { 665 i = 0; 666 LIST_FOREACH(fl, &d->freelist, freelist) { 667 /* Yes, this subdisk fits. */ 668 if ((fl->offset <= s->drive_offset) && 669 (fl->offset + fl->size >= 670 s->drive_offset + s->size)) { 671 i++; 672 fl2 = fl; 673 break; 674 } 675 } 676 677 /* Couldn't find a good free slot. */ 678 if (i == 0) { 679 G_VINUM_DEBUG(0, "given drive_offset for '%s' won't fit " 680 "on '%s'", s->name, d->name); 681 return (GV_ERR_NOSPACE); 682 } 683 } 684 685 /* 686 * Now that all parameters are checked and set up, we can give the 687 * subdisk to the drive and adjust the freelist. 688 */ 689 690 /* First, adjust the freelist. */ 691 LIST_FOREACH(fl, &d->freelist, freelist) { 692 /* Look for the free slot that we have found before. */ 693 if (fl != fl2) 694 continue; 695 696 /* The subdisk starts at the beginning of the free slot. */ 697 if (fl->offset == s->drive_offset) { 698 fl->offset += s->size; 699 fl->size -= s->size; 700 701 /* The subdisk uses the whole slot, so remove it. */ 702 if (fl->size == 0) { 703 d->freelist_entries--; 704 LIST_REMOVE(fl, freelist); 705 } 706 /* 707 * The subdisk does not start at the beginning of the free 708 * slot. 709 */ 710 } else { 711 tmp = fl->offset + fl->size; 712 fl->size = s->drive_offset - fl->offset; 713 714 /* 715 * The subdisk didn't use the complete rest of the free 716 * slot, so we need to split it. 717 */ 718 if (s->drive_offset + s->size != tmp) { 719 fl2 = g_malloc(sizeof(*fl2), M_WAITOK | M_ZERO); 720 fl2->offset = s->drive_offset + s->size; 721 fl2->size = tmp - fl2->offset; 722 LIST_INSERT_AFTER(fl, fl2, freelist); 723 d->freelist_entries++; 724 } 725 } 726 break; 727 } 728 729 /* 730 * This is the first subdisk on this drive, just insert it into the 731 * list. 732 */ 733 if (LIST_EMPTY(&d->subdisks)) { 734 LIST_INSERT_HEAD(&d->subdisks, s, from_drive); 735 736 /* There are other subdisks, so insert this one in correct order. */ 737 } else { 738 LIST_FOREACH(s2, &d->subdisks, from_drive) { 739 if (s->drive_offset < s2->drive_offset) { 740 LIST_INSERT_BEFORE(s2, s, from_drive); 741 break; 742 } else if (LIST_NEXT(s2, from_drive) == NULL) { 743 LIST_INSERT_AFTER(s2, s, from_drive); 744 break; 745 } 746 } 747 } 748 749 d->sdcount++; 750 d->avail -= s->size; 751 752 s->flags &= ~GV_SD_TASTED; 753 754 /* Link back from the subdisk to this drive. */ 755 s->drive_sc = d; 756 757 return (0); 758 } 759 760 void 761 gv_free_sd(struct gv_sd *s) 762 { 763 struct gv_drive *d; 764 struct gv_freelist *fl, *fl2; 765 766 KASSERT(s != NULL, ("gv_free_sd: NULL s")); 767 768 d = s->drive_sc; 769 if (d == NULL) 770 return; 771 772 /* 773 * First, find the free slot that's immediately before or after this 774 * subdisk. 775 */ 776 fl = NULL; 777 LIST_FOREACH(fl, &d->freelist, freelist) { 778 if (fl->offset == s->drive_offset + s->size) 779 break; 780 if (fl->offset + fl->size == s->drive_offset) 781 break; 782 } 783 784 /* If there is no free slot behind this subdisk, so create one. */ 785 if (fl == NULL) { 786 787 fl = g_malloc(sizeof(*fl), M_WAITOK | M_ZERO); 788 fl->size = s->size; 789 fl->offset = s->drive_offset; 790 791 if (d->freelist_entries == 0) { 792 LIST_INSERT_HEAD(&d->freelist, fl, freelist); 793 } else { 794 LIST_FOREACH(fl2, &d->freelist, freelist) { 795 if (fl->offset < fl2->offset) { 796 LIST_INSERT_BEFORE(fl2, fl, freelist); 797 break; 798 } else if (LIST_NEXT(fl2, freelist) == NULL) { 799 LIST_INSERT_AFTER(fl2, fl, freelist); 800 break; 801 } 802 } 803 } 804 805 d->freelist_entries++; 806 807 /* Expand the free slot we just found. */ 808 } else { 809 fl->size += s->size; 810 if (fl->offset > s->drive_offset) 811 fl->offset = s->drive_offset; 812 } 813 814 d->avail += s->size; 815 d->sdcount--; 816 } 817 818 void 819 gv_adjust_freespace(struct gv_sd *s, off_t remainder) 820 { 821 struct gv_drive *d; 822 struct gv_freelist *fl, *fl2; 823 824 KASSERT(s != NULL, ("gv_adjust_freespace: NULL s")); 825 d = s->drive_sc; 826 KASSERT(d != NULL, ("gv_adjust_freespace: NULL d")); 827 828 /* First, find the free slot that's immediately after this subdisk. */ 829 fl = NULL; 830 LIST_FOREACH(fl, &d->freelist, freelist) { 831 if (fl->offset == s->drive_offset + s->size) 832 break; 833 } 834 835 /* If there is no free slot behind this subdisk, so create one. */ 836 if (fl == NULL) { 837 838 fl = g_malloc(sizeof(*fl), M_WAITOK | M_ZERO); 839 fl->size = remainder; 840 fl->offset = s->drive_offset + s->size - remainder; 841 842 if (d->freelist_entries == 0) { 843 LIST_INSERT_HEAD(&d->freelist, fl, freelist); 844 } else { 845 LIST_FOREACH(fl2, &d->freelist, freelist) { 846 if (fl->offset < fl2->offset) { 847 LIST_INSERT_BEFORE(fl2, fl, freelist); 848 break; 849 } else if (LIST_NEXT(fl2, freelist) == NULL) { 850 LIST_INSERT_AFTER(fl2, fl, freelist); 851 break; 852 } 853 } 854 } 855 856 d->freelist_entries++; 857 858 /* Expand the free slot we just found. */ 859 } else { 860 fl->offset -= remainder; 861 fl->size += remainder; 862 } 863 864 s->size -= remainder; 865 d->avail += remainder; 866 } 867 868 /* Check if the given plex is a striped one. */ 869 int 870 gv_is_striped(struct gv_plex *p) 871 { 872 KASSERT(p != NULL, ("gv_is_striped: NULL p")); 873 switch(p->org) { 874 case GV_PLEX_STRIPED: 875 case GV_PLEX_RAID5: 876 return (1); 877 default: 878 return (0); 879 } 880 } 881 882 /* Find a volume by name. */ 883 struct gv_volume * 884 gv_find_vol(struct gv_softc *sc, char *name) 885 { 886 struct gv_volume *v; 887 888 LIST_FOREACH(v, &sc->volumes, volume) { 889 if (!strncmp(v->name, name, GV_MAXVOLNAME)) 890 return (v); 891 } 892 893 return (NULL); 894 } 895 896 /* Find a plex by name. */ 897 struct gv_plex * 898 gv_find_plex(struct gv_softc *sc, char *name) 899 { 900 struct gv_plex *p; 901 902 LIST_FOREACH(p, &sc->plexes, plex) { 903 if (!strncmp(p->name, name, GV_MAXPLEXNAME)) 904 return (p); 905 } 906 907 return (NULL); 908 } 909 910 /* Find a subdisk by name. */ 911 struct gv_sd * 912 gv_find_sd(struct gv_softc *sc, char *name) 913 { 914 struct gv_sd *s; 915 916 LIST_FOREACH(s, &sc->subdisks, sd) { 917 if (!strncmp(s->name, name, GV_MAXSDNAME)) 918 return (s); 919 } 920 921 return (NULL); 922 } 923 924 /* Find a drive by name. */ 925 struct gv_drive * 926 gv_find_drive(struct gv_softc *sc, char *name) 927 { 928 struct gv_drive *d; 929 930 LIST_FOREACH(d, &sc->drives, drive) { 931 if (!strncmp(d->name, name, GV_MAXDRIVENAME)) 932 return (d); 933 } 934 935 return (NULL); 936 } 937 938 /* Find a drive given a device. */ 939 struct gv_drive * 940 gv_find_drive_device(struct gv_softc *sc, char *device) 941 { 942 struct gv_drive *d; 943 944 LIST_FOREACH(d, &sc->drives, drive) { 945 if(!strcmp(d->device, device)) 946 return (d); 947 } 948 949 return (NULL); 950 } 951 952 /* Check if any consumer of the given geom is open. */ 953 int 954 gv_consumer_is_open(struct g_consumer *cp) 955 { 956 if (cp == NULL) 957 return (0); 958 959 if (cp->acr || cp->acw || cp->ace) 960 return (1); 961 962 return (0); 963 } 964 965 int 966 gv_provider_is_open(struct g_provider *pp) 967 { 968 if (pp == NULL) 969 return (0); 970 971 if (pp->acr || pp->acw || pp->ace) 972 return (1); 973 974 return (0); 975 } 976 977 /* 978 * Compare the modification dates of the drives. 979 * Return 1 if a > b, 0 otherwise. 980 */ 981 int 982 gv_drive_is_newer(struct gv_softc *sc, struct gv_drive *d) 983 { 984 struct gv_drive *d2; 985 struct timeval *a, *b; 986 987 KASSERT(!LIST_EMPTY(&sc->drives), 988 ("gv_is_drive_newer: empty drive list")); 989 990 a = &d->hdr->label.last_update; 991 LIST_FOREACH(d2, &sc->drives, drive) { 992 if ((d == d2) || (d2->state != GV_DRIVE_UP) || 993 (d2->hdr == NULL)) 994 continue; 995 b = &d2->hdr->label.last_update; 996 if (timevalcmp(a, b, >)) 997 return (1); 998 } 999 1000 return (0); 1001 } 1002 1003 /* Return the type of object identified by string 'name'. */ 1004 int 1005 gv_object_type(struct gv_softc *sc, char *name) 1006 { 1007 struct gv_drive *d; 1008 struct gv_plex *p; 1009 struct gv_sd *s; 1010 struct gv_volume *v; 1011 1012 LIST_FOREACH(v, &sc->volumes, volume) { 1013 if (!strncmp(v->name, name, GV_MAXVOLNAME)) 1014 return (GV_TYPE_VOL); 1015 } 1016 1017 LIST_FOREACH(p, &sc->plexes, plex) { 1018 if (!strncmp(p->name, name, GV_MAXPLEXNAME)) 1019 return (GV_TYPE_PLEX); 1020 } 1021 1022 LIST_FOREACH(s, &sc->subdisks, sd) { 1023 if (!strncmp(s->name, name, GV_MAXSDNAME)) 1024 return (GV_TYPE_SD); 1025 } 1026 1027 LIST_FOREACH(d, &sc->drives, drive) { 1028 if (!strncmp(d->name, name, GV_MAXDRIVENAME)) 1029 return (GV_TYPE_DRIVE); 1030 } 1031 1032 return (GV_ERR_NOTFOUND); 1033 } 1034 1035 void 1036 gv_setup_objects(struct gv_softc *sc) 1037 { 1038 struct g_provider *pp; 1039 struct gv_volume *v; 1040 struct gv_plex *p; 1041 struct gv_sd *s; 1042 struct gv_drive *d; 1043 1044 LIST_FOREACH(s, &sc->subdisks, sd) { 1045 d = gv_find_drive(sc, s->drive); 1046 if (d != NULL) 1047 gv_sd_to_drive(s, d); 1048 p = gv_find_plex(sc, s->plex); 1049 if (p != NULL) 1050 gv_sd_to_plex(s, p); 1051 gv_update_sd_state(s); 1052 } 1053 1054 LIST_FOREACH(p, &sc->plexes, plex) { 1055 gv_update_plex_config(p); 1056 v = gv_find_vol(sc, p->volume); 1057 if (v != NULL && p->vol_sc != v) { 1058 p->vol_sc = v; 1059 v->plexcount++; 1060 LIST_INSERT_HEAD(&v->plexes, p, in_volume); 1061 } 1062 gv_update_plex_config(p); 1063 } 1064 1065 LIST_FOREACH(v, &sc->volumes, volume) { 1066 v->size = gv_vol_size(v); 1067 if (v->provider == NULL) { 1068 g_topology_lock(); 1069 pp = g_new_providerf(sc->geom, "gvinum/%s", v->name); 1070 pp->mediasize = v->size; 1071 pp->sectorsize = 512; /* XXX */ 1072 g_error_provider(pp, 0); 1073 v->provider = pp; 1074 pp->private = v; 1075 g_topology_unlock(); 1076 } else if (v->provider->mediasize != v->size) { 1077 g_topology_lock(); 1078 v->provider->mediasize = v->size; 1079 g_topology_unlock(); 1080 } 1081 v->flags &= ~GV_VOL_NEWBORN; 1082 gv_update_vol_state(v); 1083 } 1084 } 1085 1086 void 1087 gv_cleanup(struct gv_softc *sc) 1088 { 1089 struct gv_volume *v, *v2; 1090 struct gv_plex *p, *p2; 1091 struct gv_sd *s, *s2; 1092 struct gv_drive *d, *d2; 1093 struct gv_freelist *fl, *fl2; 1094 1095 mtx_lock(&sc->config_mtx); 1096 LIST_FOREACH_SAFE(v, &sc->volumes, volume, v2) { 1097 LIST_REMOVE(v, volume); 1098 g_free(v->wqueue); 1099 g_free(v); 1100 } 1101 LIST_FOREACH_SAFE(p, &sc->plexes, plex, p2) { 1102 LIST_REMOVE(p, plex); 1103 g_free(p->bqueue); 1104 g_free(p->rqueue); 1105 g_free(p->wqueue); 1106 g_free(p); 1107 } 1108 LIST_FOREACH_SAFE(s, &sc->subdisks, sd, s2) { 1109 LIST_REMOVE(s, sd); 1110 g_free(s); 1111 } 1112 LIST_FOREACH_SAFE(d, &sc->drives, drive, d2) { 1113 LIST_FOREACH_SAFE(fl, &d->freelist, freelist, fl2) { 1114 LIST_REMOVE(fl, freelist); 1115 g_free(fl); 1116 } 1117 LIST_REMOVE(d, drive); 1118 g_free(d->hdr); 1119 g_free(d); 1120 } 1121 mtx_destroy(&sc->config_mtx); 1122 } 1123 1124 /* General 'attach' routine. */ 1125 int 1126 gv_attach_plex(struct gv_plex *p, struct gv_volume *v, int rename) 1127 { 1128 struct gv_sd *s; 1129 struct gv_softc *sc; 1130 1131 g_topology_assert(); 1132 1133 sc = p->vinumconf; 1134 KASSERT(sc != NULL, ("NULL sc")); 1135 1136 if (p->vol_sc != NULL) { 1137 G_VINUM_DEBUG(1, "unable to attach %s: already attached to %s", 1138 p->name, p->volume); 1139 return (GV_ERR_ISATTACHED); 1140 } 1141 1142 /* Stale all subdisks of this plex. */ 1143 LIST_FOREACH(s, &p->subdisks, in_plex) { 1144 if (s->state != GV_SD_STALE) 1145 gv_set_sd_state(s, GV_SD_STALE, GV_SETSTATE_FORCE); 1146 } 1147 /* Attach to volume. Make sure volume is not up and running. */ 1148 if (gv_provider_is_open(v->provider)) { 1149 G_VINUM_DEBUG(1, "unable to attach %s: volume %s is busy", 1150 p->name, v->name); 1151 return (GV_ERR_ISBUSY); 1152 } 1153 p->vol_sc = v; 1154 strlcpy(p->volume, v->name, sizeof(p->volume)); 1155 v->plexcount++; 1156 if (rename) { 1157 snprintf(p->name, sizeof(p->name), "%s.p%d", v->name, 1158 v->plexcount); 1159 } 1160 LIST_INSERT_HEAD(&v->plexes, p, in_volume); 1161 1162 /* Get plex up again. */ 1163 gv_update_vol_size(v, gv_vol_size(v)); 1164 gv_set_plex_state(p, GV_PLEX_UP, 0); 1165 gv_save_config(p->vinumconf); 1166 return (0); 1167 } 1168 1169 int 1170 gv_attach_sd(struct gv_sd *s, struct gv_plex *p, off_t offset, int rename) 1171 { 1172 struct gv_sd *s2; 1173 int error, sdcount; 1174 1175 g_topology_assert(); 1176 1177 /* If subdisk is attached, don't do it. */ 1178 if (s->plex_sc != NULL) { 1179 G_VINUM_DEBUG(1, "unable to attach %s: already attached to %s", 1180 s->name, s->plex); 1181 return (GV_ERR_ISATTACHED); 1182 } 1183 1184 gv_set_sd_state(s, GV_SD_STALE, GV_SETSTATE_FORCE); 1185 /* First check that this subdisk has a correct offset. If none other 1186 * starts at the same, and it's correct module stripesize, it is */ 1187 if (offset != -1 && offset % p->stripesize != 0) 1188 return (GV_ERR_BADOFFSET); 1189 LIST_FOREACH(s2, &p->subdisks, in_plex) { 1190 if (s2->plex_offset == offset) 1191 return (GV_ERR_BADOFFSET); 1192 } 1193 1194 /* Attach the subdisk to the plex at given offset. */ 1195 s->plex_offset = offset; 1196 strlcpy(s->plex, p->name, sizeof(s->plex)); 1197 1198 sdcount = p->sdcount; 1199 error = gv_sd_to_plex(s, p); 1200 if (error) 1201 return (error); 1202 gv_update_plex_config(p); 1203 1204 if (rename) { 1205 snprintf(s->name, sizeof(s->name), "%s.s%d", s->plex, 1206 p->sdcount); 1207 } 1208 if (p->vol_sc != NULL) 1209 gv_update_vol_size(p->vol_sc, gv_vol_size(p->vol_sc)); 1210 gv_save_config(p->vinumconf); 1211 /* We don't update the subdisk state since the user might have to 1212 * initiate a rebuild/sync first. */ 1213 return (0); 1214 } 1215 1216 /* Detach a plex from a volume. */ 1217 int 1218 gv_detach_plex(struct gv_plex *p, int flags) 1219 { 1220 struct gv_volume *v; 1221 1222 g_topology_assert(); 1223 v = p->vol_sc; 1224 1225 if (v == NULL) { 1226 G_VINUM_DEBUG(1, "unable to detach %s: already detached", 1227 p->name); 1228 return (0); /* Not an error. */ 1229 } 1230 1231 /* 1232 * Only proceed if forced or volume inactive. 1233 */ 1234 if (!(flags & GV_FLAG_F) && (gv_provider_is_open(v->provider) || 1235 p->state == GV_PLEX_UP)) { 1236 G_VINUM_DEBUG(1, "unable to detach %s: volume %s is busy", 1237 p->name, p->volume); 1238 return (GV_ERR_ISBUSY); 1239 } 1240 v->plexcount--; 1241 /* Make sure someone don't read us when gone. */ 1242 v->last_read_plex = NULL; 1243 LIST_REMOVE(p, in_volume); 1244 p->vol_sc = NULL; 1245 memset(p->volume, 0, GV_MAXVOLNAME); 1246 gv_update_vol_size(v, gv_vol_size(v)); 1247 gv_save_config(p->vinumconf); 1248 return (0); 1249 } 1250 1251 /* Detach a subdisk from a plex. */ 1252 int 1253 gv_detach_sd(struct gv_sd *s, int flags) 1254 { 1255 struct gv_plex *p; 1256 1257 g_topology_assert(); 1258 p = s->plex_sc; 1259 1260 if (p == NULL) { 1261 G_VINUM_DEBUG(1, "unable to detach %s: already detached", 1262 s->name); 1263 return (0); /* Not an error. */ 1264 } 1265 1266 /* 1267 * Don't proceed if we're not forcing, and the plex is up, or degraded 1268 * with this subdisk up. 1269 */ 1270 if (!(flags & GV_FLAG_F) && ((p->state > GV_PLEX_DEGRADED) || 1271 ((p->state == GV_PLEX_DEGRADED) && (s->state == GV_SD_UP)))) { 1272 G_VINUM_DEBUG(1, "unable to detach %s: plex %s is busy", 1273 s->name, s->plex); 1274 return (GV_ERR_ISBUSY); 1275 } 1276 1277 LIST_REMOVE(s, in_plex); 1278 s->plex_sc = NULL; 1279 memset(s->plex, 0, GV_MAXPLEXNAME); 1280 p->sddetached++; 1281 gv_save_config(s->vinumconf); 1282 return (0); 1283 } 1284