geom_subr.c revision 124883
1/*- 2 * Copyright (c) 2002 Poul-Henning Kamp 3 * Copyright (c) 2002 Networks Associates Technology, Inc. 4 * All rights reserved. 5 * 6 * This software was developed for the FreeBSD Project by Poul-Henning Kamp 7 * and NAI Labs, the Security Research Division of Network Associates, Inc. 8 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 9 * DARPA CHATS research program. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. The names of the authors may not be used to endorse or promote 20 * products derived from this software without specific prior written 21 * permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include <sys/cdefs.h> 37__FBSDID("$FreeBSD: head/sys/geom/geom_subr.c 124883 2004-01-23 21:02:49Z phk $"); 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/devicestat.h> 42#include <sys/kernel.h> 43#include <sys/malloc.h> 44#include <sys/bio.h> 45#include <sys/sysctl.h> 46#include <sys/proc.h> 47#include <sys/kthread.h> 48#include <sys/lock.h> 49#include <sys/mutex.h> 50#include <sys/errno.h> 51#include <sys/sbuf.h> 52#include <geom/geom.h> 53#include <geom/geom_int.h> 54#include <machine/stdarg.h> 55 56struct class_list_head g_classes = LIST_HEAD_INITIALIZER(g_classes); 57static struct g_tailq_head geoms = TAILQ_HEAD_INITIALIZER(geoms); 58char *g_wait_event, *g_wait_up, *g_wait_down, *g_wait_sim; 59 60static int g_valid_obj(void const *ptr); 61 62struct g_hh00 { 63 struct g_class *mp; 64 int error; 65}; 66 67/* 68 * This event offers a new class a chance to taste all preexisting providers. 69 */ 70static void 71g_load_class(void *arg, int flag) 72{ 73 struct g_hh00 *hh; 74 struct g_class *mp2, *mp; 75 struct g_geom *gp; 76 struct g_provider *pp; 77 78 g_topology_assert(); 79 if (flag == EV_CANCEL) /* XXX: can't happen ? */ 80 return; 81 if (g_shutdown) 82 return; 83 84 hh = arg; 85 mp = hh->mp; 86 g_free(hh); 87 g_trace(G_T_TOPOLOGY, "g_load_class(%s)", mp->name); 88 KASSERT(mp->name != NULL && *mp->name != '\0', 89 ("GEOM class has no name")); 90 LIST_FOREACH(mp2, &g_classes, class) { 91 KASSERT(mp2 != mp, 92 ("The GEOM class %s already loaded", mp2->name)); 93 KASSERT(strcmp(mp2->name, mp->name) != 0, 94 ("A GEOM class named %s is already loaded", mp2->name)); 95 } 96 97 LIST_INIT(&mp->geom); 98 LIST_INSERT_HEAD(&g_classes, mp, class); 99 if (mp->init != NULL) 100 mp->init(mp); 101 if (mp->taste == NULL) 102 return; 103 LIST_FOREACH(mp2, &g_classes, class) { 104 if (mp == mp2) 105 continue; 106 LIST_FOREACH(gp, &mp2->geom, geom) { 107 LIST_FOREACH(pp, &gp->provider, provider) { 108 mp->taste(mp, pp, 0); 109 g_topology_assert(); 110 } 111 } 112 } 113} 114 115static void 116g_unload_class(void *arg, int flag) 117{ 118 struct g_hh00 *hh; 119 struct g_class *mp; 120 struct g_geom *gp; 121 struct g_provider *pp; 122 struct g_consumer *cp; 123 int error; 124 125 g_topology_assert(); 126 hh = arg; 127 mp = hh->mp; 128 g_trace(G_T_TOPOLOGY, "g_unload_class(%s)", mp->name); 129 if (mp->destroy_geom == NULL) { 130 hh->error = EOPNOTSUPP; 131 return; 132 } 133 134 /* We refuse to unload if anything is open */ 135 LIST_FOREACH(gp, &mp->geom, geom) { 136 LIST_FOREACH(pp, &gp->provider, provider) 137 if (pp->acr || pp->acw || pp->ace) { 138 hh->error = EBUSY; 139 return; 140 } 141 LIST_FOREACH(cp, &gp->consumer, consumer) 142 if (cp->acr || cp->acw || cp->ace) { 143 hh->error = EBUSY; 144 return; 145 } 146 } 147 148 /* Bar new entries */ 149 mp->taste = NULL; 150 mp->config = NULL; 151 152 error = 0; 153 LIST_FOREACH(gp, &mp->geom, geom) { 154 error = mp->destroy_geom(NULL, mp, gp); 155 if (error != 0) 156 break; 157 } 158 if (error == 0) { 159 if (mp->fini != NULL) 160 mp->fini(mp); 161 LIST_REMOVE(mp, class); 162 } 163 hh->error = error; 164 return; 165} 166 167int 168g_modevent(module_t mod, int type, void *data) 169{ 170 struct g_hh00 *hh; 171 int error; 172 static int g_ignition; 173 174 if (!g_ignition) { 175 g_ignition++; 176 g_init(); 177 } 178 hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO); 179 hh->mp = data; 180 error = EOPNOTSUPP; 181 switch (type) { 182 case MOD_LOAD: 183 g_trace(G_T_TOPOLOGY, "g_modevent(%s, LOAD)", hh->mp->name); 184 g_post_event(g_load_class, hh, M_WAITOK, NULL); 185 error = 0; 186 break; 187 case MOD_UNLOAD: 188 g_trace(G_T_TOPOLOGY, "g_modevent(%s, UNLOAD)", hh->mp->name); 189 error = g_waitfor_event(g_unload_class, hh, M_WAITOK, NULL); 190 if (error == 0) 191 error = hh->error; 192 if (error == 0) { 193 g_waitidle(); 194 KASSERT(LIST_EMPTY(&hh->mp->geom), 195 ("Unloaded class (%s) still has geom", hh->mp->name)); 196 } 197 g_free(hh); 198 break; 199 default: 200 g_free(hh); 201 break; 202 } 203 return (error); 204} 205 206struct g_geom * 207g_new_geomf(struct g_class *mp, const char *fmt, ...) 208{ 209 struct g_geom *gp; 210 va_list ap; 211 struct sbuf *sb; 212 213 g_topology_assert(); 214 KASSERT(g_valid_obj(mp), ("g_new_geom_f() on alien class %p", mp)); 215 sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); 216 va_start(ap, fmt); 217 sbuf_vprintf(sb, fmt, ap); 218 va_end(ap); 219 sbuf_finish(sb); 220 gp = g_malloc(sizeof *gp, M_WAITOK | M_ZERO); 221 gp->name = g_malloc(sbuf_len(sb) + 1, M_WAITOK | M_ZERO); 222 gp->class = mp; 223 gp->rank = 1; 224 LIST_INIT(&gp->consumer); 225 LIST_INIT(&gp->provider); 226 LIST_INSERT_HEAD(&mp->geom, gp, geom); 227 TAILQ_INSERT_HEAD(&geoms, gp, geoms); 228 strcpy(gp->name, sbuf_data(sb)); 229 sbuf_delete(sb); 230 return (gp); 231} 232 233void 234g_destroy_geom(struct g_geom *gp) 235{ 236 237 g_trace(G_T_TOPOLOGY, "g_destroy_geom(%p(%s))", gp, gp->name); 238 g_topology_assert(); 239 KASSERT(LIST_EMPTY(&gp->consumer), 240 ("g_destroy_geom(%s) with consumer(s) [%p]", 241 gp->name, LIST_FIRST(&gp->consumer))); 242 KASSERT(LIST_EMPTY(&gp->provider), 243 ("g_destroy_geom(%s) with provider(s) [%p]", 244 gp->name, LIST_FIRST(&gp->provider))); 245 g_cancel_event(gp); 246 LIST_REMOVE(gp, geom); 247 TAILQ_REMOVE(&geoms, gp, geoms); 248 g_free(gp->name); 249 g_free(gp); 250} 251 252/* 253 * This function is called (repeatedly) until has withered away. 254 */ 255void 256g_wither_geom(struct g_geom *gp, int error) 257{ 258 struct g_provider *pp, *pp2; 259 struct g_consumer *cp, *cp2; 260 static int once_is_enough; 261 262 if (once_is_enough) 263 return; 264 once_is_enough = 1; 265 g_trace(G_T_TOPOLOGY, "g_wither_geom(%p(%s))", gp, gp->name); 266 g_topology_assert(); 267 if (!(gp->flags & G_GEOM_WITHER)) { 268 gp->flags |= G_GEOM_WITHER; 269 LIST_FOREACH(pp, &gp->provider, provider) 270 g_orphan_provider(pp, error); 271 } 272 for (pp = LIST_FIRST(&gp->provider); pp != NULL; pp = pp2) { 273 pp2 = LIST_NEXT(pp, provider); 274 if (!LIST_EMPTY(&pp->consumers)) 275 continue; 276 g_destroy_provider(pp); 277 } 278 for (cp = LIST_FIRST(&gp->consumer); cp != NULL; cp = cp2) { 279 cp2 = LIST_NEXT(cp, consumer); 280 if (cp->acr || cp->acw || cp->ace) 281 continue; 282 g_detach(cp); 283 g_destroy_consumer(cp); 284 } 285 if (LIST_EMPTY(&gp->provider) && LIST_EMPTY(&gp->consumer)) 286 g_destroy_geom(gp); 287 once_is_enough = 0; 288} 289 290struct g_consumer * 291g_new_consumer(struct g_geom *gp) 292{ 293 struct g_consumer *cp; 294 295 g_topology_assert(); 296 KASSERT(!(gp->flags & G_GEOM_WITHER), 297 ("g_new_consumer on WITHERing geom(%s) (class %s)", 298 gp->name, gp->class->name)); 299 KASSERT(gp->orphan != NULL, 300 ("g_new_consumer on geom(%s) (class %s) without orphan", 301 gp->name, gp->class->name)); 302 303 cp = g_malloc(sizeof *cp, M_WAITOK | M_ZERO); 304 cp->geom = gp; 305 cp->stat = devstat_new_entry(cp, -1, 0, DEVSTAT_ALL_SUPPORTED, 306 DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX); 307 LIST_INSERT_HEAD(&gp->consumer, cp, consumer); 308 return(cp); 309} 310 311void 312g_destroy_consumer(struct g_consumer *cp) 313{ 314 struct g_geom *gp; 315 316 g_trace(G_T_TOPOLOGY, "g_destroy_consumer(%p)", cp); 317 g_topology_assert(); 318 KASSERT (cp->provider == NULL, ("g_destroy_consumer but attached")); 319 KASSERT (cp->acr == 0, ("g_destroy_consumer with acr")); 320 KASSERT (cp->acw == 0, ("g_destroy_consumer with acw")); 321 KASSERT (cp->ace == 0, ("g_destroy_consumer with ace")); 322 g_cancel_event(cp); 323 gp = cp->geom; 324 LIST_REMOVE(cp, consumer); 325 devstat_remove_entry(cp->stat); 326 g_free(cp); 327 if (gp->flags & G_GEOM_WITHER) 328 g_wither_geom(gp, 0); 329} 330 331static void 332g_new_provider_event(void *arg, int flag) 333{ 334 struct g_class *mp; 335 struct g_provider *pp; 336 struct g_consumer *cp; 337 int i; 338 339 g_topology_assert(); 340 if (flag == EV_CANCEL) 341 return; 342 if (g_shutdown) 343 return; 344 pp = arg; 345 LIST_FOREACH(mp, &g_classes, class) { 346 if (mp->taste == NULL) 347 continue; 348 i = 1; 349 LIST_FOREACH(cp, &pp->consumers, consumers) 350 if (cp->geom->class == mp) 351 i = 0; 352 if (!i) 353 continue; 354 mp->taste(mp, pp, 0); 355 g_topology_assert(); 356 /* 357 * XXX: Bandaid for 5.2-RELEASE 358 * XXX: DO NOT REPLICATE THIS CODE! 359 */ 360 if (!g_valid_obj(pp)) { 361 printf("g_provider %p disappeared while tasting\n", pp); 362 return; 363 } 364 } 365} 366 367 368struct g_provider * 369g_new_providerf(struct g_geom *gp, const char *fmt, ...) 370{ 371 struct g_provider *pp; 372 struct sbuf *sb; 373 va_list ap; 374 375 g_topology_assert(); 376 KASSERT(gp->start != NULL, 377 ("new provider on geom(%s) without ->start (class:%s)", 378 gp->class->name, gp->class->name)); 379 KASSERT(!(gp->flags & G_GEOM_WITHER), 380 ("new provider on WITHERing geom(%s) (class:%s)", 381 gp->class->name, gp->class->name)); 382 sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); 383 va_start(ap, fmt); 384 sbuf_vprintf(sb, fmt, ap); 385 va_end(ap); 386 sbuf_finish(sb); 387 pp = g_malloc(sizeof *pp + sbuf_len(sb) + 1, M_WAITOK | M_ZERO); 388 pp->name = (char *)(pp + 1); 389 strcpy(pp->name, sbuf_data(sb)); 390 sbuf_delete(sb); 391 LIST_INIT(&pp->consumers); 392 pp->error = ENXIO; 393 pp->geom = gp; 394 pp->stat = devstat_new_entry(pp, -1, 0, DEVSTAT_ALL_SUPPORTED, 395 DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX); 396 LIST_INSERT_HEAD(&gp->provider, pp, provider); 397 g_post_event(g_new_provider_event, pp, M_WAITOK, pp, NULL); 398 return (pp); 399} 400 401void 402g_error_provider(struct g_provider *pp, int error) 403{ 404 405 pp->error = error; 406} 407 408struct g_provider * 409g_provider_by_name(char const *arg) 410{ 411 struct g_class *cp; 412 struct g_geom *gp; 413 struct g_provider *pp; 414 415 LIST_FOREACH(cp, &g_classes, class) { 416 LIST_FOREACH(gp, &cp->geom, geom) { 417 LIST_FOREACH(pp, &gp->provider, provider) { 418 if (!strcmp(arg, pp->name)) 419 return (pp); 420 } 421 } 422 } 423 return (NULL); 424} 425 426void 427g_destroy_provider(struct g_provider *pp) 428{ 429 struct g_geom *gp; 430 431 g_topology_assert(); 432 KASSERT(LIST_EMPTY(&pp->consumers), 433 ("g_destroy_provider but attached")); 434 KASSERT (pp->acr == 0, ("g_destroy_provider with acr")); 435 KASSERT (pp->acw == 0, ("g_destroy_provider with acw")); 436 KASSERT (pp->acw == 0, ("g_destroy_provider with ace")); 437 g_cancel_event(pp); 438 LIST_REMOVE(pp, provider); 439 gp = pp->geom; 440 devstat_remove_entry(pp->stat); 441 g_free(pp); 442 if ((gp->flags & G_GEOM_WITHER)) 443 g_wither_geom(gp, 0); 444} 445 446/* 447 * We keep the "geoms" list sorted by topological order (== increasing 448 * numerical rank) at all times. 449 * When an attach is done, the attaching geoms rank is invalidated 450 * and it is moved to the tail of the list. 451 * All geoms later in the sequence has their ranks reevaluated in 452 * sequence. If we cannot assign rank to a geom because it's 453 * prerequisites do not have rank, we move that element to the tail 454 * of the sequence with invalid rank as well. 455 * At some point we encounter our original geom and if we stil fail 456 * to assign it a rank, there must be a loop and we fail back to 457 * g_attach() which detach again and calls redo_rank again 458 * to fix up the damage. 459 * It would be much simpler code wise to do it recursively, but we 460 * can't risk that on the kernel stack. 461 */ 462 463static int 464redo_rank(struct g_geom *gp) 465{ 466 struct g_consumer *cp; 467 struct g_geom *gp1, *gp2; 468 int n, m; 469 470 g_topology_assert(); 471 472 /* Invalidate this geoms rank and move it to the tail */ 473 gp1 = TAILQ_NEXT(gp, geoms); 474 if (gp1 != NULL) { 475 gp->rank = 0; 476 TAILQ_REMOVE(&geoms, gp, geoms); 477 TAILQ_INSERT_TAIL(&geoms, gp, geoms); 478 } else { 479 gp1 = gp; 480 } 481 482 /* re-rank the rest of the sequence */ 483 for (; gp1 != NULL; gp1 = gp2) { 484 gp1->rank = 0; 485 m = 1; 486 LIST_FOREACH(cp, &gp1->consumer, consumer) { 487 if (cp->provider == NULL) 488 continue; 489 n = cp->provider->geom->rank; 490 if (n == 0) { 491 m = 0; 492 break; 493 } else if (n >= m) 494 m = n + 1; 495 } 496 gp1->rank = m; 497 gp2 = TAILQ_NEXT(gp1, geoms); 498 499 /* got a rank, moving on */ 500 if (m != 0) 501 continue; 502 503 /* no rank to original geom means loop */ 504 if (gp == gp1) 505 return (ELOOP); 506 507 /* no rank, put it at the end move on */ 508 TAILQ_REMOVE(&geoms, gp1, geoms); 509 TAILQ_INSERT_TAIL(&geoms, gp1, geoms); 510 } 511 return (0); 512} 513 514int 515g_attach(struct g_consumer *cp, struct g_provider *pp) 516{ 517 int error; 518 519 g_topology_assert(); 520 KASSERT(cp->provider == NULL, ("attach but attached")); 521 cp->provider = pp; 522 LIST_INSERT_HEAD(&pp->consumers, cp, consumers); 523 error = redo_rank(cp->geom); 524 if (error) { 525 LIST_REMOVE(cp, consumers); 526 cp->provider = NULL; 527 redo_rank(cp->geom); 528 } 529 return (error); 530} 531 532void 533g_detach(struct g_consumer *cp) 534{ 535 struct g_provider *pp; 536 537 g_trace(G_T_TOPOLOGY, "g_detach(%p)", cp); 538 KASSERT(cp != (void*)0xd0d0d0d0, ("ARGH!")); 539 g_topology_assert(); 540 KASSERT(cp->provider != NULL, ("detach but not attached")); 541 KASSERT(cp->acr == 0, ("detach but nonzero acr")); 542 KASSERT(cp->acw == 0, ("detach but nonzero acw")); 543 KASSERT(cp->ace == 0, ("detach but nonzero ace")); 544 KASSERT(cp->nstart == cp->nend, 545 ("detach with active requests")); 546 pp = cp->provider; 547 LIST_REMOVE(cp, consumers); 548 cp->provider = NULL; 549 if (pp->geom->flags & G_GEOM_WITHER) 550 g_wither_geom(pp->geom, 0); 551 else if (pp->flags & G_PF_WITHER) 552 g_destroy_provider(pp); 553 redo_rank(cp->geom); 554} 555 556 557/* 558 * g_access_abs() 559 * 560 * Access-check with absolute new values: Just fall through 561 * and use the relative version. 562 */ 563int 564g_access_abs(struct g_consumer *cp, int acr, int acw, int ace) 565{ 566 567 g_topology_assert(); 568 return(g_access_rel(cp, 569 acr - cp->acr, 570 acw - cp->acw, 571 ace - cp->ace)); 572} 573 574/* 575 * g_access_rel() 576 * 577 * Access-check with delta values. The question asked is "can provider 578 * "cp" change the access counters by the relative amounts dc[rwe] ?" 579 */ 580 581int 582g_access_rel(struct g_consumer *cp, int dcr, int dcw, int dce) 583{ 584 struct g_provider *pp; 585 int pr,pw,pe; 586 int error; 587 588 pp = cp->provider; 589 590 g_trace(G_T_ACCESS, "g_access_rel(%p(%s), %d, %d, %d)", 591 cp, pp->name, dcr, dcw, dce); 592 593 g_topology_assert(); 594 KASSERT(cp->provider != NULL, ("access but not attached")); 595 KASSERT(cp->acr + dcr >= 0, ("access resulting in negative acr")); 596 KASSERT(cp->acw + dcw >= 0, ("access resulting in negative acw")); 597 KASSERT(cp->ace + dce >= 0, ("access resulting in negative ace")); 598 KASSERT(dcr != 0 || dcw != 0 || dce != 0, ("NOP access request")); 599 KASSERT(pp->geom->access != NULL, ("NULL geom->access")); 600 601 /* 602 * If our class cares about being spoiled, and we have been, we 603 * are probably just ahead of the event telling us that. Fail 604 * now rather than having to unravel this later. 605 */ 606 if (cp->geom->spoiled != NULL && cp->spoiled) { 607 KASSERT(dcr <= 0, ("spoiled but dcr = %d", dcr)); 608 KASSERT(dcw <= 0, ("spoiled but dce = %d", dcw)); 609 KASSERT(dce <= 0, ("spoiled but dcw = %d", dce)); 610 } 611 612 /* 613 * Figure out what counts the provider would have had, if this 614 * consumer had (r0w0e0) at this time. 615 */ 616 pr = pp->acr - cp->acr; 617 pw = pp->acw - cp->acw; 618 pe = pp->ace - cp->ace; 619 620 g_trace(G_T_ACCESS, 621 "open delta:[r%dw%de%d] old:[r%dw%de%d] provider:[r%dw%de%d] %p(%s)", 622 dcr, dcw, dce, 623 cp->acr, cp->acw, cp->ace, 624 pp->acr, pp->acw, pp->ace, 625 pp, pp->name); 626 627 /* If foot-shooting is enabled, any open on rank#1 is OK */ 628 if ((g_debugflags & 16) && pp->geom->rank == 1) 629 ; 630 /* If we try exclusive but already write: fail */ 631 else if (dce > 0 && pw > 0) 632 return (EPERM); 633 /* If we try write but already exclusive: fail */ 634 else if (dcw > 0 && pe > 0) 635 return (EPERM); 636 /* If we try to open more but provider is error'ed: fail */ 637 else if ((dcr > 0 || dcw > 0 || dce > 0) && pp->error != 0) 638 return (pp->error); 639 640 /* Ok then... */ 641 642 error = pp->geom->access(pp, dcr, dcw, dce); 643 if (!error) { 644 /* 645 * If we open first write, spoil any partner consumers. 646 * If we close last write, trigger re-taste. 647 */ 648 if (pp->acw == 0 && dcw != 0) 649 g_spoil(pp, cp); 650 else if (pp->acw != 0 && pp->acw == -dcw && 651 !(pp->geom->flags & G_GEOM_WITHER)) 652 g_post_event(g_new_provider_event, pp, M_WAITOK, 653 pp, NULL); 654 655 pp->acr += dcr; 656 pp->acw += dcw; 657 pp->ace += dce; 658 cp->acr += dcr; 659 cp->acw += dcw; 660 cp->ace += dce; 661 } 662 return (error); 663} 664 665int 666g_handleattr_int(struct bio *bp, const char *attribute, int val) 667{ 668 669 return (g_handleattr(bp, attribute, &val, sizeof val)); 670} 671 672int 673g_handleattr_off_t(struct bio *bp, const char *attribute, off_t val) 674{ 675 676 return (g_handleattr(bp, attribute, &val, sizeof val)); 677} 678 679int 680g_handleattr(struct bio *bp, const char *attribute, void *val, int len) 681{ 682 int error; 683 684 if (strcmp(bp->bio_attribute, attribute)) 685 return (0); 686 if (bp->bio_length != len) { 687 printf("bio_length %jd len %d -> EFAULT\n", 688 (intmax_t)bp->bio_length, len); 689 error = EFAULT; 690 } else { 691 error = 0; 692 bcopy(val, bp->bio_data, len); 693 bp->bio_completed = len; 694 } 695 g_io_deliver(bp, error); 696 return (1); 697} 698 699int 700g_std_access(struct g_provider *pp __unused, 701 int dr __unused, int dw __unused, int de __unused) 702{ 703 704 return (0); 705} 706 707void 708g_std_done(struct bio *bp) 709{ 710 struct bio *bp2; 711 712 bp2 = bp->bio_parent; 713 if (bp2->bio_error == 0) 714 bp2->bio_error = bp->bio_error; 715 bp2->bio_completed += bp->bio_completed; 716 g_destroy_bio(bp); 717 bp2->bio_inbed++; 718 if (bp2->bio_children == bp2->bio_inbed) 719 g_io_deliver(bp2, bp2->bio_error); 720} 721 722/* XXX: maybe this is only g_slice_spoiled */ 723 724void 725g_std_spoiled(struct g_consumer *cp) 726{ 727 struct g_geom *gp; 728 struct g_provider *pp; 729 730 g_trace(G_T_TOPOLOGY, "g_std_spoiled(%p)", cp); 731 g_topology_assert(); 732 g_detach(cp); 733 gp = cp->geom; 734 LIST_FOREACH(pp, &gp->provider, provider) 735 g_orphan_provider(pp, ENXIO); 736 g_destroy_consumer(cp); 737 if (LIST_EMPTY(&gp->provider) && LIST_EMPTY(&gp->consumer)) 738 g_destroy_geom(gp); 739 else 740 gp->flags |= G_GEOM_WITHER; 741} 742 743/* 744 * Spoiling happens when a provider is opened for writing, but consumers 745 * which are configured by in-band data are attached (slicers for instance). 746 * Since the write might potentially change the in-band data, such consumers 747 * need to re-evaluate their existence after the writing session closes. 748 * We do this by (offering to) tear them down when the open for write happens 749 * in return for a re-taste when it closes again. 750 * Together with the fact that such consumers grab an 'e' bit whenever they 751 * are open, regardless of mode, this ends up DTRT. 752 */ 753 754static void 755g_spoil_event(void *arg, int flag) 756{ 757 struct g_provider *pp; 758 struct g_consumer *cp, *cp2; 759 760 g_topology_assert(); 761 if (flag == EV_CANCEL) 762 return; 763 pp = arg; 764 for (cp = LIST_FIRST(&pp->consumers); cp != NULL; cp = cp2) { 765 cp2 = LIST_NEXT(cp, consumers); 766 if (!cp->spoiled) 767 continue; 768 cp->spoiled = 0; 769 if (cp->geom->spoiled == NULL) 770 continue; 771 cp->geom->spoiled(cp); 772 g_topology_assert(); 773 } 774} 775 776void 777g_spoil(struct g_provider *pp, struct g_consumer *cp) 778{ 779 struct g_consumer *cp2; 780 781 g_topology_assert(); 782 783 LIST_FOREACH(cp2, &pp->consumers, consumers) { 784 if (cp2 == cp) 785 continue; 786/* 787 KASSERT(cp2->acr == 0, ("spoiling cp->acr = %d", cp2->acr)); 788 KASSERT(cp2->acw == 0, ("spoiling cp->acw = %d", cp2->acw)); 789*/ 790 KASSERT(cp2->ace == 0, ("spoiling cp->ace = %d", cp2->ace)); 791 cp2->spoiled++; 792 } 793 g_post_event(g_spoil_event, pp, M_WAITOK, pp, NULL); 794} 795 796int 797g_getattr__(const char *attr, struct g_consumer *cp, void *var, int len) 798{ 799 int error, i; 800 801 i = len; 802 error = g_io_getattr(attr, cp, &i, var); 803 if (error) 804 return (error); 805 if (i != len) 806 return (EINVAL); 807 return (0); 808} 809 810/* 811 * XXX: Bandaid for 5.2. 812 * XXX: DO NOT EVEN THINK ABOUT CALLING THIS FUNCTION! 813 */ 814static int 815g_valid_obj(void const *ptr) 816{ 817 struct g_class *mp; 818 struct g_geom *gp; 819 struct g_consumer *cp; 820 struct g_provider *pp; 821 822 g_topology_assert(); 823 LIST_FOREACH(mp, &g_classes, class) { 824 if (ptr == mp) 825 return (1); 826 LIST_FOREACH(gp, &mp->geom, geom) { 827 if (ptr == gp) 828 return (1); 829 LIST_FOREACH(cp, &gp->consumer, consumer) 830 if (ptr == cp) 831 return (1); 832 LIST_FOREACH(pp, &gp->provider, provider) 833 if (ptr == pp) 834 return (1); 835 } 836 } 837 return(0); 838} 839 840/* 841 * Check if the given pointer is a live object 842 */ 843 844void 845g_sanity(void const *ptr) 846{ 847 struct g_class *mp; 848 struct g_geom *gp; 849 struct g_consumer *cp; 850 struct g_provider *pp; 851 852 if (!(g_debugflags & 0x8)) 853 return; 854 LIST_FOREACH(mp, &g_classes, class) { 855 KASSERT(mp != ptr, ("Ptr is live class")); 856 LIST_FOREACH(gp, &mp->geom, geom) { 857 KASSERT(gp != ptr, ("Ptr is live geom")); 858 KASSERT(gp->name != ptr, ("Ptr is live geom's name")); 859 LIST_FOREACH(cp, &gp->consumer, consumer) { 860 KASSERT(cp != ptr, ("Ptr is live consumer")); 861 } 862 LIST_FOREACH(pp, &gp->provider, provider) { 863 KASSERT(pp != ptr, ("Ptr is live provider")); 864 } 865 } 866 } 867} 868 869