geom_subr.c revision 188054
1177633Sdfr/*- 2177633Sdfr * Copyright (c) 2002 Poul-Henning Kamp 3261046Smav * Copyright (c) 2002 Networks Associates Technology, Inc. 4261046Smav * All rights reserved. 5261046Smav * 6261046Smav * This software was developed for the FreeBSD Project by Poul-Henning Kamp 7261046Smav * and NAI Labs, the Security Research Division of Network Associates, Inc. 8261046Smav * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 9261046Smav * DARPA CHATS research program. 10261046Smav * 11261046Smav * Redistribution and use in source and binary forms, with or without 12261046Smav * modification, are permitted provided that the following conditions 13261046Smav * are met: 14261046Smav * 1. Redistributions of source code must retain the above copyright 15261046Smav * notice, this list of conditions and the following disclaimer. 16261046Smav * 2. Redistributions in binary form must reproduce the above copyright 17177633Sdfr * notice, this list of conditions and the following disclaimer in the 18261046Smav * documentation and/or other materials provided with the distribution. 19261046Smav * 3. The names of the authors may not be used to endorse or promote 20261046Smav * products derived from this software without specific prior written 21261046Smav * permission. 22261046Smav * 23261046Smav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24261046Smav * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25261046Smav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26261046Smav * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 27261046Smav * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28261046Smav * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29177633Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30177633Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31177633Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32177633Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33177633Sdfr * SUCH DAMAGE. 34177633Sdfr */ 35177633Sdfr 36177633Sdfr#include <sys/cdefs.h> 37177633Sdfr__FBSDID("$FreeBSD: head/sys/geom/geom_subr.c 188054 2009-02-03 07:07:13Z marcel $"); 38177633Sdfr 39177633Sdfr#include "opt_ddb.h" 40177633Sdfr 41177633Sdfr#include <sys/param.h> 42177633Sdfr#include <sys/systm.h> 43177633Sdfr#include <sys/devicestat.h> 44177633Sdfr#include <sys/kernel.h> 45177633Sdfr#include <sys/malloc.h> 46177633Sdfr#include <sys/bio.h> 47180025Sdfr#include <sys/sysctl.h> 48177633Sdfr#include <sys/proc.h> 49177633Sdfr#include <sys/kthread.h> 50177633Sdfr#include <sys/lock.h> 51177633Sdfr#include <sys/mutex.h> 52177633Sdfr#include <sys/errno.h> 53177633Sdfr#include <sys/sbuf.h> 54177633Sdfr#include <geom/geom.h> 55177633Sdfr#include <geom/geom_int.h> 56177633Sdfr#include <machine/stdarg.h> 57177633Sdfr 58177633Sdfr#ifdef DDB 59196503Szec#include <ddb/ddb.h> 60196503Szec#endif 61177633Sdfr 62177685Sdfrstruct class_list_head g_classes = LIST_HEAD_INITIALIZER(g_classes); 63177633Sdfrstatic struct g_tailq_head geoms = TAILQ_HEAD_INITIALIZER(geoms); 64177633Sdfrchar *g_wait_event, *g_wait_up, *g_wait_down, *g_wait_sim; 65177633Sdfr 66177633Sdfrstruct g_hh00 { 67177633Sdfr struct g_class *mp; 68177633Sdfr int error; 69177633Sdfr int post; 70177633Sdfr}; 71177633Sdfr 72177633Sdfr/* 73177633Sdfr * This event offers a new class a chance to taste all preexisting providers. 74177633Sdfr */ 75180025Sdfrstatic void 76184588Sdfrg_load_class(void *arg, int flag) 77177633Sdfr{ 78177633Sdfr struct g_hh00 *hh; 79177633Sdfr struct g_class *mp2, *mp; 80177633Sdfr struct g_geom *gp; 81184588Sdfr struct g_provider *pp; 82177633Sdfr 83193272Sjhb g_topology_assert(); 84177633Sdfr if (flag == EV_CANCEL) /* XXX: can't happen ? */ 85177633Sdfr return; 86177633Sdfr if (g_shutdown) 87177633Sdfr return; 88177633Sdfr 89177633Sdfr hh = arg; 90184588Sdfr mp = hh->mp; 91177633Sdfr hh->error = 0; 92177633Sdfr if (hh->post) { 93177633Sdfr g_free(hh); 94177633Sdfr hh = NULL; 95177633Sdfr } 96180025Sdfr g_trace(G_T_TOPOLOGY, "g_load_class(%s)", mp->name); 97180025Sdfr KASSERT(mp->name != NULL && *mp->name != '\0', 98180025Sdfr ("GEOM class has no name")); 99177633Sdfr LIST_FOREACH(mp2, &g_classes, class) { 100177633Sdfr if (mp2 == mp) { 101177633Sdfr printf("The GEOM class %s is already loaded.\n", 102180025Sdfr mp2->name); 103177633Sdfr if (hh != NULL) 104177633Sdfr hh->error = EEXIST; 105177633Sdfr return; 106184588Sdfr } else if (strcmp(mp2->name, mp->name) == 0) { 107177633Sdfr printf("A GEOM class %s is already loaded.\n", 108177633Sdfr mp2->name); 109177633Sdfr if (hh != NULL) 110177633Sdfr hh->error = EEXIST; 111177633Sdfr return; 112177633Sdfr } 113177633Sdfr } 114193272Sjhb 115177633Sdfr LIST_INIT(&mp->geom); 116177633Sdfr LIST_INSERT_HEAD(&g_classes, mp, class); 117177633Sdfr if (mp->init != NULL) 118177633Sdfr mp->init(mp); 119177633Sdfr if (mp->taste == NULL) 120177633Sdfr return; 121177633Sdfr LIST_FOREACH(mp2, &g_classes, class) { 122177633Sdfr if (mp == mp2) 123177633Sdfr continue; 124177633Sdfr LIST_FOREACH(gp, &mp2->geom, geom) { 125193437Srmacklem LIST_FOREACH(pp, &gp->provider, provider) { 126177633Sdfr mp->taste(mp, pp, 0); 127177633Sdfr g_topology_assert(); 128193437Srmacklem } 129193437Srmacklem } 130177633Sdfr } 131177633Sdfr} 132177633Sdfr 133177633Sdfrstatic void 134180025Sdfrg_unload_class(void *arg, int flag) 135184588Sdfr{ 136184588Sdfr struct g_hh00 *hh; 137177633Sdfr struct g_class *mp; 138177633Sdfr struct g_geom *gp; 139177633Sdfr struct g_provider *pp; 140177633Sdfr struct g_consumer *cp; 141177633Sdfr int error; 142177633Sdfr 143177633Sdfr g_topology_assert(); 144177633Sdfr hh = arg; 145177633Sdfr mp = hh->mp; 146177633Sdfr G_VALID_CLASS(mp); 147177633Sdfr g_trace(G_T_TOPOLOGY, "g_unload_class(%s)", mp->name); 148177633Sdfr 149177633Sdfr /* 150177633Sdfr * We allow unloading if we have no geoms, or a class 151177633Sdfr * method we can use to get rid of them. 152177633Sdfr */ 153177633Sdfr if (!LIST_EMPTY(&mp->geom) && mp->destroy_geom == NULL) { 154184588Sdfr hh->error = EOPNOTSUPP; 155184588Sdfr return; 156184588Sdfr } 157177633Sdfr 158177633Sdfr /* We refuse to unload if anything is open */ 159184588Sdfr LIST_FOREACH(gp, &mp->geom, geom) { 160184588Sdfr LIST_FOREACH(pp, &gp->provider, provider) 161184588Sdfr if (pp->acr || pp->acw || pp->ace) { 162177633Sdfr hh->error = EBUSY; 163177633Sdfr return; 164177633Sdfr } 165177633Sdfr LIST_FOREACH(cp, &gp->consumer, consumer) 166177633Sdfr if (cp->acr || cp->acw || cp->ace) { 167177633Sdfr hh->error = EBUSY; 168177633Sdfr return; 169177633Sdfr } 170177633Sdfr } 171177633Sdfr 172177633Sdfr /* Bar new entries */ 173177633Sdfr mp->taste = NULL; 174177633Sdfr mp->config = NULL; 175177633Sdfr 176177633Sdfr error = 0; 177177633Sdfr for (;;) { 178177633Sdfr gp = LIST_FIRST(&mp->geom); 179177633Sdfr if (gp == NULL) 180177633Sdfr break; 181177633Sdfr error = mp->destroy_geom(NULL, mp, gp); 182177633Sdfr if (error != 0) 183177633Sdfr break; 184177633Sdfr } 185177633Sdfr if (error == 0) { 186177633Sdfr if (mp->fini != NULL) 187177633Sdfr mp->fini(mp); 188193272Sjhb LIST_REMOVE(mp, class); 189177633Sdfr } 190177633Sdfr hh->error = error; 191177633Sdfr return; 192177633Sdfr} 193213756Srmacklem 194177633Sdfrint 195177633Sdfrg_modevent(module_t mod, int type, void *data) 196177633Sdfr{ 197177633Sdfr struct g_hh00 *hh; 198177633Sdfr int error; 199177633Sdfr static int g_ignition; 200177633Sdfr struct g_class *mp; 201177633Sdfr 202177633Sdfr mp = data; 203177633Sdfr if (mp->version != G_VERSION) { 204177633Sdfr printf("GEOM class %s has Wrong version %x\n", 205177633Sdfr mp->name, mp->version); 206177633Sdfr return (EINVAL); 207177633Sdfr } 208177633Sdfr if (!g_ignition) { 209177633Sdfr g_ignition++; 210177633Sdfr g_init(); 211177633Sdfr } 212177633Sdfr hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO); 213177633Sdfr hh->mp = data; 214177633Sdfr error = EOPNOTSUPP; 215177633Sdfr switch (type) { 216177633Sdfr case MOD_LOAD: 217177633Sdfr g_trace(G_T_TOPOLOGY, "g_modevent(%s, LOAD)", hh->mp->name); 218177633Sdfr /* 219177633Sdfr * Once the system is not cold, MOD_LOAD calls will be 220177633Sdfr * from the userland and the g_event thread will be able 221177633Sdfr * to acknowledge their completion. 222177633Sdfr */ 223177633Sdfr if (cold) { 224177633Sdfr hh->post = 1; 225180025Sdfr error = g_post_event(g_load_class, hh, M_WAITOK, NULL); 226180025Sdfr } else { 227184588Sdfr error = g_waitfor_event(g_load_class, hh, M_WAITOK, 228177633Sdfr NULL); 229177633Sdfr if (error == 0) 230177633Sdfr error = hh->error; 231180025Sdfr g_free(hh); 232177633Sdfr } 233177633Sdfr break; 234177633Sdfr case MOD_UNLOAD: 235177633Sdfr g_trace(G_T_TOPOLOGY, "g_modevent(%s, UNLOAD)", hh->mp->name); 236177633Sdfr error = g_waitfor_event(g_unload_class, hh, M_WAITOK, NULL); 237177633Sdfr if (error == 0) 238177633Sdfr error = hh->error; 239177633Sdfr if (error == 0) { 240177633Sdfr KASSERT(LIST_EMPTY(&hh->mp->geom), 241177633Sdfr ("Unloaded class (%s) still has geom", hh->mp->name)); 242184588Sdfr } 243184588Sdfr g_free(hh); 244184588Sdfr break; 245177633Sdfr default: 246177633Sdfr g_free(hh); 247177633Sdfr break; 248177633Sdfr } 249177633Sdfr return (error); 250177633Sdfr} 251177633Sdfr 252177633Sdfrstatic void 253177633Sdfrg_retaste_event(void *arg, int flag) 254177633Sdfr{ 255177633Sdfr struct g_class *cp, *mp; 256201758Smbr struct g_geom *gp, *gp2; 257177633Sdfr struct g_hh00 *hh; 258177633Sdfr struct g_provider *pp; 259177633Sdfr 260177633Sdfr g_topology_assert(); 261177633Sdfr if (flag == EV_CANCEL) /* XXX: can't happen ? */ 262177633Sdfr return; 263177633Sdfr if (g_shutdown) 264177633Sdfr return; 265213756Srmacklem 266213756Srmacklem hh = arg; 267213756Srmacklem mp = hh->mp; 268213756Srmacklem hh->error = 0; 269213756Srmacklem if (hh->post) { 270213756Srmacklem g_free(hh); 271177633Sdfr hh = NULL; 272193272Sjhb } 273177633Sdfr g_trace(G_T_TOPOLOGY, "g_retaste(%s)", mp->name); 274177633Sdfr 275193272Sjhb LIST_FOREACH(cp, &g_classes, class) { 276193272Sjhb LIST_FOREACH(gp, &cp->geom, geom) { 277177633Sdfr LIST_FOREACH(pp, &gp->provider, provider) { 278177633Sdfr if (pp->acr || pp->acw || pp->ace) 279177633Sdfr continue; 280177633Sdfr LIST_FOREACH(gp2, &mp->geom, geom) { 281193272Sjhb if (!strcmp(pp->name, gp2->name)) 282177633Sdfr break; 283177633Sdfr } 284177633Sdfr if (gp2 != NULL) 285177633Sdfr g_wither_geom(gp2, ENXIO); 286177633Sdfr mp->taste(mp, pp, 0); 287177633Sdfr g_topology_assert(); 288177633Sdfr } 289177633Sdfr } 290193272Sjhb } 291177633Sdfr} 292193272Sjhb 293193272Sjhbint 294177633Sdfrg_retaste(struct g_class *mp) 295177633Sdfr{ 296177633Sdfr struct g_hh00 *hh; 297177633Sdfr int error; 298177633Sdfr 299177633Sdfr if (mp->taste == NULL) 300177633Sdfr return (EINVAL); 301177633Sdfr 302193437Srmacklem hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO); 303177633Sdfr hh->mp = mp; 304193272Sjhb 305177633Sdfr if (cold) { 306177633Sdfr hh->post = 1; 307177633Sdfr error = g_post_event(g_retaste_event, hh, M_WAITOK, NULL); 308180025Sdfr } else { 309177633Sdfr error = g_waitfor_event(g_retaste_event, hh, M_WAITOK, NULL); 310177633Sdfr if (error == 0) 311177633Sdfr error = hh->error; 312177633Sdfr g_free(hh); 313177633Sdfr } 314177633Sdfr 315177633Sdfr return (error); 316177633Sdfr} 317177633Sdfr 318177633Sdfrstruct g_geom * 319177633Sdfrg_new_geomf(struct g_class *mp, const char *fmt, ...) 320177633Sdfr{ 321177633Sdfr struct g_geom *gp; 322177633Sdfr va_list ap; 323177633Sdfr struct sbuf *sb; 324177633Sdfr 325177633Sdfr g_topology_assert(); 326180025Sdfr G_VALID_CLASS(mp); 327180025Sdfr sb = sbuf_new_auto(); 328177633Sdfr va_start(ap, fmt); 329184588Sdfr sbuf_vprintf(sb, fmt, ap); 330184588Sdfr va_end(ap); 331177633Sdfr sbuf_finish(sb); 332177633Sdfr gp = g_malloc(sizeof *gp, M_WAITOK | M_ZERO); 333177633Sdfr gp->name = g_malloc(sbuf_len(sb) + 1, M_WAITOK | M_ZERO); 334193272Sjhb gp->class = mp; 335184588Sdfr gp->rank = 1; 336180025Sdfr LIST_INIT(&gp->consumer); 337184588Sdfr LIST_INIT(&gp->provider); 338184588Sdfr LIST_INSERT_HEAD(&mp->geom, gp, geom); 339177633Sdfr TAILQ_INSERT_HEAD(&geoms, gp, geoms); 340177633Sdfr strcpy(gp->name, sbuf_data(sb)); 341177633Sdfr sbuf_delete(sb); 342180025Sdfr /* Fill in defaults from class */ 343177633Sdfr gp->start = mp->start; 344180025Sdfr gp->spoiled = mp->spoiled; 345180025Sdfr gp->dumpconf = mp->dumpconf; 346180025Sdfr gp->access = mp->access; 347184588Sdfr gp->orphan = mp->orphan; 348177633Sdfr gp->ioctl = mp->ioctl; 349177633Sdfr return (gp); 350184588Sdfr} 351184588Sdfr 352180025Sdfrvoid 353177633Sdfrg_destroy_geom(struct g_geom *gp) 354177633Sdfr{ 355193272Sjhb 356180025Sdfr g_topology_assert(); 357180025Sdfr G_VALID_GEOM(gp); 358177633Sdfr g_trace(G_T_TOPOLOGY, "g_destroy_geom(%p(%s))", gp, gp->name); 359177633Sdfr KASSERT(LIST_EMPTY(&gp->consumer), 360184588Sdfr ("g_destroy_geom(%s) with consumer(s) [%p]", 361180025Sdfr gp->name, LIST_FIRST(&gp->consumer))); 362180025Sdfr KASSERT(LIST_EMPTY(&gp->provider), 363180025Sdfr ("g_destroy_geom(%s) with provider(s) [%p]", 364180025Sdfr gp->name, LIST_FIRST(&gp->provider))); 365180025Sdfr g_cancel_event(gp); 366177633Sdfr LIST_REMOVE(gp, geom); 367184588Sdfr TAILQ_REMOVE(&geoms, gp, geoms); 368180025Sdfr g_free(gp->name); 369184588Sdfr g_free(gp); 370184588Sdfr} 371180025Sdfr 372184588Sdfr/* 373184588Sdfr * This function is called (repeatedly) until the geom has withered away. 374180025Sdfr */ 375180025Sdfrvoid 376180025Sdfrg_wither_geom(struct g_geom *gp, int error) 377180025Sdfr{ 378180025Sdfr struct g_provider *pp; 379177633Sdfr 380180025Sdfr g_topology_assert(); 381177633Sdfr G_VALID_GEOM(gp); 382180025Sdfr g_trace(G_T_TOPOLOGY, "g_wither_geom(%p(%s))", gp, gp->name); 383177633Sdfr if (!(gp->flags & G_GEOM_WITHER)) { 384180025Sdfr gp->flags |= G_GEOM_WITHER; 385180025Sdfr LIST_FOREACH(pp, &gp->provider, provider) 386180025Sdfr if (!(pp->flags & G_PF_ORPHAN)) 387180025Sdfr g_orphan_provider(pp, error); 388177633Sdfr } 389177633Sdfr g_do_wither(); 390177633Sdfr} 391177633Sdfr 392177633Sdfr/* 393177633Sdfr * Convenience function to destroy a particular provider. 394177633Sdfr */ 395184588Sdfrvoid 396184588Sdfrg_wither_provider(struct g_provider *pp, int error) 397177633Sdfr{ 398177633Sdfr 399177633Sdfr pp->flags |= G_PF_WITHER; 400177633Sdfr if (!(pp->flags & G_PF_ORPHAN)) 401177633Sdfr g_orphan_provider(pp, error); 402177633Sdfr} 403177633Sdfr 404177633Sdfr/* 405177633Sdfr * This function is called (repeatedly) until the has withered away. 406177633Sdfr */ 407177633Sdfrvoid 408180025Sdfrg_wither_geom_close(struct g_geom *gp, int error) 409180025Sdfr{ 410184588Sdfr struct g_consumer *cp; 411184588Sdfr 412184588Sdfr g_topology_assert(); 413184588Sdfr G_VALID_GEOM(gp); 414184588Sdfr g_trace(G_T_TOPOLOGY, "g_wither_geom_close(%p(%s))", gp, gp->name); 415184588Sdfr LIST_FOREACH(cp, &gp->consumer, consumer) 416184588Sdfr if (cp->acr || cp->acw || cp->ace) 417184588Sdfr g_access(cp, -cp->acr, -cp->acw, -cp->ace); 418184588Sdfr g_wither_geom(gp, error); 419177633Sdfr} 420180025Sdfr 421177633Sdfr/* 422177633Sdfr * This function is called (repeatedly) until we cant wash away more 423177633Sdfr * withered bits at present. Return value contains two bits. Bit 0 424177633Sdfr * set means "withering stuff we can't wash now", bit 1 means "call 425177633Sdfr * me again, there may be stuff I didn't get the first time around. 426177633Sdfr */ 427177633Sdfrint 428177633Sdfrg_wither_washer() 429177633Sdfr{ 430177633Sdfr struct g_class *mp; 431248195Sglebius struct g_geom *gp, *gp2; 432184588Sdfr struct g_provider *pp, *pp2; 433184588Sdfr struct g_consumer *cp, *cp2; 434184588Sdfr int result; 435177633Sdfr 436177633Sdfr result = 0; 437177633Sdfr g_topology_assert(); 438177633Sdfr LIST_FOREACH(mp, &g_classes, class) { 439177633Sdfr LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) { 440177633Sdfr LIST_FOREACH_SAFE(pp, &gp->provider, provider, pp2) { 441177633Sdfr if (!(pp->flags & G_PF_WITHER)) 442177633Sdfr continue; 443184588Sdfr if (LIST_EMPTY(&pp->consumers)) 444177633Sdfr g_destroy_provider(pp); 445177633Sdfr else 446177633Sdfr result |= 1; 447184588Sdfr } 448184588Sdfr if (!(gp->flags & G_GEOM_WITHER)) 449184588Sdfr continue; 450177633Sdfr LIST_FOREACH_SAFE(pp, &gp->provider, provider, pp2) { 451177633Sdfr if (LIST_EMPTY(&pp->consumers)) 452177633Sdfr g_destroy_provider(pp); 453184588Sdfr else 454177633Sdfr result |= 1; 455180025Sdfr } 456177633Sdfr LIST_FOREACH_SAFE(cp, &gp->consumer, consumer, cp2) { 457184588Sdfr if (cp->acr || cp->acw || cp->ace) { 458184588Sdfr result |= 1; 459184588Sdfr continue; 460184588Sdfr } 461184588Sdfr if (cp->provider != NULL) 462184588Sdfr g_detach(cp); 463184588Sdfr g_destroy_consumer(cp); 464184588Sdfr result |= 2; 465184588Sdfr } 466184588Sdfr if (LIST_EMPTY(&gp->provider) && 467225234Sart LIST_EMPTY(&gp->consumer)) 468225234Sart g_destroy_geom(gp); 469225234Sart else 470225234Sart result |= 1; 471184588Sdfr } 472184588Sdfr } 473184588Sdfr return (result); 474184588Sdfr} 475184588Sdfr 476180025Sdfrstruct g_consumer * 477177633Sdfrg_new_consumer(struct g_geom *gp) 478177633Sdfr{ 479177633Sdfr struct g_consumer *cp; 480177633Sdfr 481177633Sdfr g_topology_assert(); 482177633Sdfr G_VALID_GEOM(gp); 483177633Sdfr KASSERT(!(gp->flags & G_GEOM_WITHER), 484177633Sdfr ("g_new_consumer on WITHERing geom(%s) (class %s)", 485177633Sdfr gp->name, gp->class->name)); 486177633Sdfr KASSERT(gp->orphan != NULL, 487177633Sdfr ("g_new_consumer on geom(%s) (class %s) without orphan", 488177633Sdfr gp->name, gp->class->name)); 489177633Sdfr 490184588Sdfr cp = g_malloc(sizeof *cp, M_WAITOK | M_ZERO); 491184588Sdfr cp->geom = gp; 492184588Sdfr cp->stat = devstat_new_entry(cp, -1, 0, DEVSTAT_ALL_SUPPORTED, 493184588Sdfr DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX); 494184588Sdfr LIST_INSERT_HEAD(&gp->consumer, cp, consumer); 495177633Sdfr return(cp); 496177633Sdfr} 497177633Sdfr 498180025Sdfrvoid 499184588Sdfrg_destroy_consumer(struct g_consumer *cp) 500184588Sdfr{ 501184588Sdfr struct g_geom *gp; 502184588Sdfr 503184588Sdfr g_topology_assert(); 504184588Sdfr G_VALID_CONSUMER(cp); 505184588Sdfr g_trace(G_T_TOPOLOGY, "g_destroy_consumer(%p)", cp); 506177633Sdfr KASSERT (cp->provider == NULL, ("g_destroy_consumer but attached")); 507177633Sdfr KASSERT (cp->acr == 0, ("g_destroy_consumer with acr")); 508177633Sdfr KASSERT (cp->acw == 0, ("g_destroy_consumer with acw")); 509177633Sdfr KASSERT (cp->ace == 0, ("g_destroy_consumer with ace")); 510177633Sdfr g_cancel_event(cp); 511180025Sdfr gp = cp->geom; 512177633Sdfr LIST_REMOVE(cp, consumer); 513180025Sdfr devstat_remove_entry(cp->stat); 514180025Sdfr g_free(cp); 515184588Sdfr if (gp->flags & G_GEOM_WITHER) 516184588Sdfr g_do_wither(); 517184588Sdfr} 518184588Sdfr 519184588Sdfrstatic void 520184588Sdfrg_new_provider_event(void *arg, int flag) 521184588Sdfr{ 522177633Sdfr struct g_class *mp; 523177633Sdfr struct g_provider *pp; 524180025Sdfr struct g_consumer *cp; 525180025Sdfr int i; 526184588Sdfr 527184588Sdfr g_topology_assert(); 528184588Sdfr if (flag == EV_CANCEL) 529184588Sdfr return; 530184588Sdfr if (g_shutdown) 531177633Sdfr return; 532177633Sdfr pp = arg; 533177633Sdfr G_VALID_PROVIDER(pp); 534177633Sdfr KASSERT(!(pp->flags & G_PF_WITHER), 535177633Sdfr ("g_new_provider_event but withered")); 536177633Sdfr LIST_FOREACH(mp, &g_classes, class) { 537180025Sdfr if (mp->taste == NULL) 538180025Sdfr continue; 539184588Sdfr i = 1; 540184588Sdfr LIST_FOREACH(cp, &pp->consumers, consumers) 541184588Sdfr if (cp->geom->class == mp) 542184588Sdfr i = 0; 543184588Sdfr if (!i) 544184588Sdfr continue; 545177633Sdfr mp->taste(mp, pp, 0); 546177633Sdfr g_topology_assert(); 547177633Sdfr } 548177633Sdfr} 549177633Sdfr 550177633Sdfr 551180025Sdfrstruct g_provider * 552177633Sdfrg_new_providerf(struct g_geom *gp, const char *fmt, ...) 553180025Sdfr{ 554180025Sdfr struct g_provider *pp; 555180025Sdfr struct sbuf *sb; 556180025Sdfr va_list ap; 557180025Sdfr 558195245Srmacklem g_topology_assert(); 559180025Sdfr G_VALID_GEOM(gp); 560195245Srmacklem KASSERT(gp->access != NULL, 561195245Srmacklem ("new provider on geom(%s) without ->access (class %s)", 562180025Sdfr gp->name, gp->class->name)); 563180025Sdfr KASSERT(gp->start != NULL, 564195245Srmacklem ("new provider on geom(%s) without ->start (class %s)", 565177633Sdfr gp->name, gp->class->name)); 566180025Sdfr KASSERT(!(gp->flags & G_GEOM_WITHER), 567177633Sdfr ("new provider on WITHERing geom(%s) (class %s)", 568177633Sdfr gp->name, gp->class->name)); 569180025Sdfr sb = sbuf_new_auto(); 570184588Sdfr va_start(ap, fmt); 571184588Sdfr sbuf_vprintf(sb, fmt, ap); 572184588Sdfr va_end(ap); 573184588Sdfr sbuf_finish(sb); 574184588Sdfr pp = g_malloc(sizeof *pp + sbuf_len(sb) + 1, M_WAITOK | M_ZERO); 575177633Sdfr pp->name = (char *)(pp + 1); 576177633Sdfr strcpy(pp->name, sbuf_data(sb)); 577177633Sdfr sbuf_delete(sb); 578177633Sdfr LIST_INIT(&pp->consumers); 579177633Sdfr pp->error = ENXIO; 580177633Sdfr pp->geom = gp; 581177633Sdfr pp->stat = devstat_new_entry(pp, -1, 0, DEVSTAT_ALL_SUPPORTED, 582180025Sdfr DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX); 583184588Sdfr LIST_INSERT_HEAD(&gp->provider, pp, provider); 584184588Sdfr g_post_event(g_new_provider_event, pp, M_WAITOK, pp, gp, NULL); 585177633Sdfr return (pp); 586177633Sdfr} 587184588Sdfr 588184588Sdfrvoid 589184588Sdfrg_error_provider(struct g_provider *pp, int error) 590184588Sdfr{ 591184588Sdfr 592184588Sdfr /* G_VALID_PROVIDER(pp); We may not have g_topology */ 593184588Sdfr pp->error = error; 594184588Sdfr} 595184588Sdfr 596184588Sdfrstruct g_provider * 597184588Sdfrg_provider_by_name(char const *arg) 598184588Sdfr{ 599184588Sdfr struct g_class *cp; 600184588Sdfr struct g_geom *gp; 601184588Sdfr struct g_provider *pp; 602184588Sdfr 603184588Sdfr LIST_FOREACH(cp, &g_classes, class) { 604184588Sdfr LIST_FOREACH(gp, &cp->geom, geom) { 605184588Sdfr LIST_FOREACH(pp, &gp->provider, provider) { 606184588Sdfr if (!strcmp(arg, pp->name)) 607184588Sdfr return (pp); 608184588Sdfr } 609184588Sdfr } 610184588Sdfr } 611184588Sdfr return (NULL); 612184588Sdfr} 613184588Sdfr 614184588Sdfrvoid 615184588Sdfrg_destroy_provider(struct g_provider *pp) 616184588Sdfr{ 617184588Sdfr struct g_geom *gp; 618184588Sdfr 619184588Sdfr g_topology_assert(); 620184588Sdfr G_VALID_PROVIDER(pp); 621184588Sdfr KASSERT(LIST_EMPTY(&pp->consumers), 622184588Sdfr ("g_destroy_provider but attached")); 623184588Sdfr KASSERT (pp->acr == 0, ("g_destroy_provider with acr")); 624184588Sdfr KASSERT (pp->acw == 0, ("g_destroy_provider with acw")); 625184588Sdfr KASSERT (pp->ace == 0, ("g_destroy_provider with ace")); 626184588Sdfr g_cancel_event(pp); 627184588Sdfr LIST_REMOVE(pp, provider); 628184588Sdfr gp = pp->geom; 629177633Sdfr devstat_remove_entry(pp->stat); 630177633Sdfr g_free(pp); 631177633Sdfr if ((gp->flags & G_GEOM_WITHER)) 632177633Sdfr g_do_wither(); 633177633Sdfr} 634177633Sdfr 635177633Sdfr/* 636177633Sdfr * We keep the "geoms" list sorted by topological order (== increasing 637177633Sdfr * numerical rank) at all times. 638184588Sdfr * When an attach is done, the attaching geoms rank is invalidated 639225234Sart * and it is moved to the tail of the list. 640184588Sdfr * All geoms later in the sequence has their ranks reevaluated in 641177633Sdfr * sequence. If we cannot assign rank to a geom because it's 642184588Sdfr * prerequisites do not have rank, we move that element to the tail 643177633Sdfr * of the sequence with invalid rank as well. 644177633Sdfr * At some point we encounter our original geom and if we stil fail 645177633Sdfr * to assign it a rank, there must be a loop and we fail back to 646180025Sdfr * g_attach() which detach again and calls redo_rank again 647177633Sdfr * to fix up the damage. 648177633Sdfr * It would be much simpler code wise to do it recursively, but we 649180025Sdfr * can't risk that on the kernel stack. 650184588Sdfr */ 651184588Sdfr 652177633Sdfrstatic int 653177633Sdfrredo_rank(struct g_geom *gp) 654177633Sdfr{ 655177633Sdfr struct g_consumer *cp; 656180025Sdfr struct g_geom *gp1, *gp2; 657184588Sdfr int n, m; 658184588Sdfr 659184588Sdfr g_topology_assert(); 660180025Sdfr G_VALID_GEOM(gp); 661180025Sdfr 662180025Sdfr /* Invalidate this geoms rank and move it to the tail */ 663180025Sdfr gp1 = TAILQ_NEXT(gp, geoms); 664180025Sdfr if (gp1 != NULL) { 665180025Sdfr gp->rank = 0; 666180025Sdfr TAILQ_REMOVE(&geoms, gp, geoms); 667180025Sdfr TAILQ_INSERT_TAIL(&geoms, gp, geoms); 668180025Sdfr } else { 669180025Sdfr gp1 = gp; 670184588Sdfr } 671184588Sdfr 672184588Sdfr /* re-rank the rest of the sequence */ 673180025Sdfr for (; gp1 != NULL; gp1 = gp2) { 674180025Sdfr gp1->rank = 0; 675180025Sdfr m = 1; 676177633Sdfr LIST_FOREACH(cp, &gp1->consumer, consumer) { 677180025Sdfr if (cp->provider == NULL) 678180025Sdfr continue; 679180025Sdfr n = cp->provider->geom->rank; 680177633Sdfr if (n == 0) { 681177633Sdfr m = 0; 682255284Srmacklem break; 683180025Sdfr } else if (n >= m) 684177633Sdfr m = n + 1; 685177633Sdfr } 686177633Sdfr gp1->rank = m; 687177633Sdfr gp2 = TAILQ_NEXT(gp1, geoms); 688177633Sdfr 689177633Sdfr /* got a rank, moving on */ 690177633Sdfr if (m != 0) 691177633Sdfr continue; 692177633Sdfr 693180025Sdfr /* no rank to original geom means loop */ 694180025Sdfr if (gp == gp1) 695180025Sdfr return (ELOOP); 696180025Sdfr 697177633Sdfr /* no rank, put it at the end move on */ 698180025Sdfr TAILQ_REMOVE(&geoms, gp1, geoms); 699177633Sdfr TAILQ_INSERT_TAIL(&geoms, gp1, geoms); 700177633Sdfr } 701177633Sdfr return (0); 702184588Sdfr} 703184588Sdfr 704177633Sdfrint 705184588Sdfrg_attach(struct g_consumer *cp, struct g_provider *pp) 706177633Sdfr{ 707184588Sdfr int error; 708184588Sdfr 709184588Sdfr g_topology_assert(); 710184588Sdfr G_VALID_CONSUMER(cp); 711184588Sdfr G_VALID_PROVIDER(pp); 712184588Sdfr KASSERT(cp->provider == NULL, ("attach but attached")); 713184588Sdfr cp->provider = pp; 714184588Sdfr LIST_INSERT_HEAD(&pp->consumers, cp, consumers); 715184588Sdfr error = redo_rank(cp->geom); 716184588Sdfr if (error) { 717184588Sdfr LIST_REMOVE(cp, consumers); 718184588Sdfr cp->provider = NULL; 719184588Sdfr redo_rank(cp->geom); 720184588Sdfr } 721184588Sdfr return (error); 722184588Sdfr} 723184588Sdfr 724184588Sdfrvoid 725184588Sdfrg_detach(struct g_consumer *cp) 726184588Sdfr{ 727184588Sdfr struct g_provider *pp; 728184588Sdfr 729184588Sdfr g_topology_assert(); 730184588Sdfr G_VALID_CONSUMER(cp); 731184588Sdfr g_trace(G_T_TOPOLOGY, "g_detach(%p)", cp); 732184588Sdfr KASSERT(cp->provider != NULL, ("detach but not attached")); 733184588Sdfr KASSERT(cp->acr == 0, ("detach but nonzero acr")); 734255284Srmacklem KASSERT(cp->acw == 0, ("detach but nonzero acw")); 735184588Sdfr KASSERT(cp->ace == 0, ("detach but nonzero ace")); 736184588Sdfr KASSERT(cp->nstart == cp->nend, 737184588Sdfr ("detach with active requests")); 738184588Sdfr pp = cp->provider; 739184588Sdfr LIST_REMOVE(cp, consumers); 740184588Sdfr cp->provider = NULL; 741184588Sdfr if (pp->geom->flags & G_GEOM_WITHER) 742177633Sdfr g_do_wither(); 743177633Sdfr else if (pp->flags & G_PF_WITHER) 744177633Sdfr g_do_wither(); 745177633Sdfr redo_rank(cp->geom); 746177633Sdfr} 747177633Sdfr 748184588Sdfr/* 749177633Sdfr * g_access() 750177633Sdfr * 751184588Sdfr * Access-check with delta values. The question asked is "can provider 752177633Sdfr * "cp" change the access counters by the relative amounts dc[rwe] ?" 753184588Sdfr */ 754184588Sdfr 755177633Sdfrint 756177633Sdfrg_access(struct g_consumer *cp, int dcr, int dcw, int dce) 757177633Sdfr{ 758177633Sdfr struct g_provider *pp; 759177633Sdfr int pr,pw,pe; 760184588Sdfr int error; 761177633Sdfr 762177633Sdfr g_topology_assert(); 763184588Sdfr G_VALID_CONSUMER(cp); 764184588Sdfr pp = cp->provider; 765177633Sdfr KASSERT(pp != NULL, ("access but not attached")); 766177633Sdfr G_VALID_PROVIDER(pp); 767177633Sdfr 768177633Sdfr g_trace(G_T_ACCESS, "g_access(%p(%s), %d, %d, %d)", 769177633Sdfr cp, pp->name, dcr, dcw, dce); 770180025Sdfr 771180025Sdfr KASSERT(cp->acr + dcr >= 0, ("access resulting in negative acr")); 772177633Sdfr KASSERT(cp->acw + dcw >= 0, ("access resulting in negative acw")); 773180025Sdfr KASSERT(cp->ace + dce >= 0, ("access resulting in negative ace")); 774180025Sdfr KASSERT(dcr != 0 || dcw != 0 || dce != 0, ("NOP access request")); 775180025Sdfr KASSERT(pp->geom->access != NULL, ("NULL geom->access")); 776180025Sdfr 777177633Sdfr /* 778180025Sdfr * If our class cares about being spoiled, and we have been, we 779184588Sdfr * are probably just ahead of the event telling us that. Fail 780184588Sdfr * now rather than having to unravel this later. 781184588Sdfr */ 782180025Sdfr if (cp->geom->spoiled != NULL && cp->spoiled && 783180025Sdfr (dcr > 0 || dcw > 0 || dce > 0)) 784184588Sdfr return (ENXIO); 785177633Sdfr 786177633Sdfr /* 787177633Sdfr * Figure out what counts the provider would have had, if this 788177633Sdfr * consumer had (r0w0e0) at this time. 789177633Sdfr */ 790177633Sdfr pr = pp->acr - cp->acr; 791177633Sdfr pw = pp->acw - cp->acw; 792177633Sdfr pe = pp->ace - cp->ace; 793177633Sdfr 794177633Sdfr g_trace(G_T_ACCESS, 795177633Sdfr "open delta:[r%dw%de%d] old:[r%dw%de%d] provider:[r%dw%de%d] %p(%s)", 796177633Sdfr dcr, dcw, dce, 797177633Sdfr cp->acr, cp->acw, cp->ace, 798177633Sdfr pp->acr, pp->acw, pp->ace, 799177633Sdfr pp, pp->name); 800177633Sdfr 801177633Sdfr /* If foot-shooting is enabled, any open on rank#1 is OK */ 802177633Sdfr if ((g_debugflags & 16) && pp->geom->rank == 1) 803177633Sdfr ; 804177633Sdfr /* If we try exclusive but already write: fail */ 805177633Sdfr else if (dce > 0 && pw > 0) 806177633Sdfr return (EPERM); 807177633Sdfr /* If we try write but already exclusive: fail */ 808177633Sdfr else if (dcw > 0 && pe > 0) 809177633Sdfr return (EPERM); 810177633Sdfr /* If we try to open more but provider is error'ed: fail */ 811177633Sdfr else if ((dcr > 0 || dcw > 0 || dce > 0) && pp->error != 0) 812177633Sdfr return (pp->error); 813177633Sdfr 814177633Sdfr /* Ok then... */ 815177633Sdfr 816177633Sdfr error = pp->geom->access(pp, dcr, dcw, dce); 817193272Sjhb KASSERT(dcr > 0 || dcw > 0 || dce > 0 || error == 0, 818177633Sdfr ("Geom provider %s::%s failed closing ->access()", 819177633Sdfr pp->geom->class->name, pp->name)); 820193272Sjhb if (!error) { 821177633Sdfr /* 822177633Sdfr * If we open first write, spoil any partner consumers. 823177633Sdfr * If we close last write and provider is not errored, 824177633Sdfr * trigger re-taste. 825177633Sdfr */ 826177633Sdfr if (pp->acw == 0 && dcw != 0) 827177633Sdfr g_spoil(pp, cp); 828177633Sdfr else if (pp->acw != 0 && pp->acw == -dcw && pp->error == 0 && 829177633Sdfr !(pp->geom->flags & G_GEOM_WITHER)) 830177633Sdfr g_post_event(g_new_provider_event, pp, M_WAITOK, 831177633Sdfr pp, NULL); 832177633Sdfr 833177633Sdfr pp->acr += dcr; 834177633Sdfr pp->acw += dcw; 835177633Sdfr pp->ace += dce; 836177633Sdfr cp->acr += dcr; 837177633Sdfr cp->acw += dcw; 838177633Sdfr cp->ace += dce; 839177633Sdfr if (pp->acr != 0 || pp->acw != 0 || pp->ace != 0) 840177633Sdfr KASSERT(pp->sectorsize > 0, 841177633Sdfr ("Provider %s lacks sectorsize", pp->name)); 842177633Sdfr } 843177633Sdfr return (error); 844177633Sdfr} 845177633Sdfr 846177633Sdfrint 847177633Sdfrg_handleattr_int(struct bio *bp, const char *attribute, int val) 848177633Sdfr{ 849177633Sdfr 850177633Sdfr return (g_handleattr(bp, attribute, &val, sizeof val)); 851177633Sdfr} 852177633Sdfr 853177633Sdfrint 854177633Sdfrg_handleattr_off_t(struct bio *bp, const char *attribute, off_t val) 855177633Sdfr{ 856177633Sdfr 857177633Sdfr return (g_handleattr(bp, attribute, &val, sizeof val)); 858177633Sdfr} 859177633Sdfr 860177633Sdfrint 861177633Sdfrg_handleattr_str(struct bio *bp, const char *attribute, const char *str) 862177633Sdfr{ 863177633Sdfr 864177633Sdfr return (g_handleattr(bp, attribute, str, 0)); 865177633Sdfr} 866177633Sdfr 867177633Sdfrint 868177633Sdfrg_handleattr(struct bio *bp, const char *attribute, const void *val, int len) 869177633Sdfr{ 870177633Sdfr int error = 0; 871177633Sdfr 872177633Sdfr if (strcmp(bp->bio_attribute, attribute)) 873177633Sdfr return (0); 874177633Sdfr if (len == 0) { 875177633Sdfr bzero(bp->bio_data, bp->bio_length); 876177633Sdfr if (strlcpy(bp->bio_data, val, bp->bio_length) >= 877177633Sdfr bp->bio_length) { 878177633Sdfr printf("%s: %s bio_length %jd len %zu -> EFAULT\n", 879177633Sdfr __func__, bp->bio_to->name, 880177633Sdfr (intmax_t)bp->bio_length, strlen(val)); 881177633Sdfr error = EFAULT; 882177633Sdfr } 883177633Sdfr } else if (bp->bio_length == len) { 884177633Sdfr bcopy(val, bp->bio_data, len); 885177633Sdfr } else { 886177633Sdfr printf("%s: %s bio_length %jd len %d -> EFAULT\n", __func__, 887177633Sdfr bp->bio_to->name, (intmax_t)bp->bio_length, len); 888177633Sdfr error = EFAULT; 889177633Sdfr } 890177633Sdfr if (error == 0) 891177633Sdfr bp->bio_completed = bp->bio_length; 892177633Sdfr g_io_deliver(bp, error); 893177633Sdfr return (1); 894177633Sdfr} 895177633Sdfr 896177633Sdfrint 897177633Sdfrg_std_access(struct g_provider *pp, 898177633Sdfr int dr __unused, int dw __unused, int de __unused) 899177633Sdfr{ 900177633Sdfr 901177633Sdfr g_topology_assert(); 902177633Sdfr G_VALID_PROVIDER(pp); 903177633Sdfr return (0); 904177633Sdfr} 905177633Sdfr 906177633Sdfrvoid 907177633Sdfrg_std_done(struct bio *bp) 908177633Sdfr{ 909177633Sdfr struct bio *bp2; 910177633Sdfr 911177633Sdfr bp2 = bp->bio_parent; 912177633Sdfr if (bp2->bio_error == 0) 913177633Sdfr bp2->bio_error = bp->bio_error; 914177633Sdfr bp2->bio_completed += bp->bio_completed; 915177633Sdfr g_destroy_bio(bp); 916177633Sdfr bp2->bio_inbed++; 917177633Sdfr if (bp2->bio_children == bp2->bio_inbed) 918177633Sdfr g_io_deliver(bp2, bp2->bio_error); 919177633Sdfr} 920177633Sdfr 921184588Sdfr/* XXX: maybe this is only g_slice_spoiled */ 922177633Sdfr 923177633Sdfrvoid 924177633Sdfrg_std_spoiled(struct g_consumer *cp) 925177633Sdfr{ 926177633Sdfr struct g_geom *gp; 927177633Sdfr struct g_provider *pp; 928177633Sdfr 929177633Sdfr g_topology_assert(); 930177633Sdfr G_VALID_CONSUMER(cp); 931177633Sdfr g_trace(G_T_TOPOLOGY, "g_std_spoiled(%p)", cp); 932177633Sdfr g_detach(cp); 933177633Sdfr gp = cp->geom; 934177633Sdfr LIST_FOREACH(pp, &gp->provider, provider) 935177633Sdfr g_orphan_provider(pp, ENXIO); 936177633Sdfr g_destroy_consumer(cp); 937177633Sdfr if (LIST_EMPTY(&gp->provider) && LIST_EMPTY(&gp->consumer)) 938177633Sdfr g_destroy_geom(gp); 939177633Sdfr else 940177633Sdfr gp->flags |= G_GEOM_WITHER; 941177633Sdfr} 942177633Sdfr 943177633Sdfr/* 944177633Sdfr * Spoiling happens when a provider is opened for writing, but consumers 945177633Sdfr * which are configured by in-band data are attached (slicers for instance). 946177633Sdfr * Since the write might potentially change the in-band data, such consumers 947184588Sdfr * need to re-evaluate their existence after the writing session closes. 948177633Sdfr * We do this by (offering to) tear them down when the open for write happens 949177633Sdfr * in return for a re-taste when it closes again. 950193272Sjhb * Together with the fact that such consumers grab an 'e' bit whenever they 951180025Sdfr * are open, regardless of mode, this ends up DTRT. 952177633Sdfr */ 953193272Sjhb 954180025Sdfrstatic void 955177633Sdfrg_spoil_event(void *arg, int flag) 956184588Sdfr{ 957184588Sdfr struct g_provider *pp; 958184588Sdfr struct g_consumer *cp, *cp2; 959184588Sdfr 960184588Sdfr g_topology_assert(); 961184588Sdfr if (flag == EV_CANCEL) 962184588Sdfr return; 963184588Sdfr pp = arg; 964184588Sdfr G_VALID_PROVIDER(pp); 965184588Sdfr for (cp = LIST_FIRST(&pp->consumers); cp != NULL; cp = cp2) { 966184588Sdfr cp2 = LIST_NEXT(cp, consumers); 967184588Sdfr if (!cp->spoiled) 968184588Sdfr continue; 969180025Sdfr cp->spoiled = 0; 970180025Sdfr if (cp->geom->spoiled == NULL) 971180025Sdfr continue; 972180025Sdfr cp->geom->spoiled(cp); 973180025Sdfr g_topology_assert(); 974180025Sdfr } 975180025Sdfr} 976180025Sdfr 977180025Sdfrvoid 978180025Sdfrg_spoil(struct g_provider *pp, struct g_consumer *cp) 979180025Sdfr{ 980180025Sdfr struct g_consumer *cp2; 981180025Sdfr 982180025Sdfr g_topology_assert(); 983180025Sdfr G_VALID_PROVIDER(pp); 984180025Sdfr G_VALID_CONSUMER(cp); 985184588Sdfr 986184588Sdfr LIST_FOREACH(cp2, &pp->consumers, consumers) { 987184588Sdfr if (cp2 == cp) 988184588Sdfr continue; 989184588Sdfr/* 990184588Sdfr KASSERT(cp2->acr == 0, ("spoiling cp->acr = %d", cp2->acr)); 991184588Sdfr KASSERT(cp2->acw == 0, ("spoiling cp->acw = %d", cp2->acw)); 992184588Sdfr*/ 993184588Sdfr KASSERT(cp2->ace == 0, ("spoiling cp->ace = %d", cp2->ace)); 994184588Sdfr cp2->spoiled++; 995184588Sdfr } 996193272Sjhb g_post_event(g_spoil_event, pp, M_WAITOK, pp, NULL); 997184588Sdfr} 998184588Sdfr 999184588Sdfrint 1000193272Sjhbg_getattr__(const char *attr, struct g_consumer *cp, void *var, int len) 1001184588Sdfr{ 1002184588Sdfr int error, i; 1003227059Srmacklem 1004184588Sdfr i = len; 1005184588Sdfr error = g_io_getattr(attr, cp, &i, var); 1006177633Sdfr if (error) 1007177633Sdfr return (error); 1008193437Srmacklem if (i != len) 1009193272Sjhb return (EINVAL); 1010193437Srmacklem return (0); 1011177633Sdfr} 1012193437Srmacklem 1013177633Sdfr#if defined(DIAGNOSTIC) || defined(DDB) 1014177633Sdfr/* 1015177633Sdfr * This function walks (topologically unsafely) the mesh and return a 1016177633Sdfr * non-zero integer if it finds the argument pointer is an object. 1017227059Srmacklem * The return value indicates which type of object it is belived to be. 1018177633Sdfr * If topology is not locked, this function is potentially dangerous, 1019177633Sdfr * but since it is for debugging purposes and can be useful for instance 1020177633Sdfr * from DDB, we do not assert topology lock is held. 1021180025Sdfr */ 1022177633Sdfrint 1023177633Sdfrg_valid_obj(void const *ptr) 1024177633Sdfr{ 1025177633Sdfr struct g_class *mp; 1026177633Sdfr struct g_geom *gp; 1027177633Sdfr struct g_consumer *cp; 1028177633Sdfr struct g_provider *pp; 1029177633Sdfr 1030177633Sdfr LIST_FOREACH(mp, &g_classes, class) { 1031177633Sdfr if (ptr == mp) 1032177633Sdfr return (1); 1033177633Sdfr LIST_FOREACH(gp, &mp->geom, geom) { 1034177633Sdfr if (ptr == gp) 1035177633Sdfr return (2); 1036177633Sdfr LIST_FOREACH(cp, &gp->consumer, consumer) 1037177633Sdfr if (ptr == cp) 1038177633Sdfr return (3); 1039177633Sdfr LIST_FOREACH(pp, &gp->provider, provider) 1040177633Sdfr if (ptr == pp) 1041177633Sdfr return (4); 1042177633Sdfr } 1043177633Sdfr } 1044177633Sdfr return(0); 1045177633Sdfr} 1046177633Sdfr#endif 1047193272Sjhb 1048177633Sdfr#ifdef DDB 1049177633Sdfr 1050177633Sdfr#define gprintf(...) do { \ 1051177633Sdfr printf("%*s", indent, ""); \ 1052177633Sdfr printf(__VA_ARGS__); \ 1053177633Sdfr} while (0) 1054177633Sdfr#define gprintln(...) do { \ 1055177633Sdfr gprintf(__VA_ARGS__); \ 1056177633Sdfr printf("\n"); \ 1057177633Sdfr} while (0) 1058193437Srmacklem 1059177633Sdfr#define ADDFLAG(obj, flag, sflag) do { \ 1060177633Sdfr if ((obj)->flags & (flag)) { \ 1061177633Sdfr if (comma) \ 1062193272Sjhb strlcat(str, ",", size); \ 1063177633Sdfr strlcat(str, (sflag), size); \ 1064177633Sdfr comma = 1; \ 1065177633Sdfr } \ 1066177633Sdfr} while (0) 1067177633Sdfr 1068177633Sdfrstatic char * 1069193272Sjhbprovider_flags_to_string(struct g_provider *pp, char *str, size_t size) 1070177633Sdfr{ 1071177633Sdfr int comma = 0; 1072177633Sdfr 1073177633Sdfr bzero(str, size); 1074177633Sdfr if (pp->flags == 0) { 1075177633Sdfr strlcpy(str, "NONE", size); 1076177633Sdfr return (str); 1077177633Sdfr } 1078177633Sdfr ADDFLAG(pp, G_PF_CANDELETE, "G_PF_CANDELETE"); 1079177633Sdfr ADDFLAG(pp, G_PF_WITHER, "G_PF_WITHER"); 1080177633Sdfr ADDFLAG(pp, G_PF_ORPHAN, "G_PF_ORPHAN"); 1081180025Sdfr return (str); 1082177633Sdfr} 1083177633Sdfr 1084177633Sdfrstatic char * 1085177633Sdfrgeom_flags_to_string(struct g_geom *gp, char *str, size_t size) 1086177633Sdfr{ 1087177633Sdfr int comma = 0; 1088177633Sdfr 1089177633Sdfr bzero(str, size); 1090177633Sdfr if (gp->flags == 0) { 1091177633Sdfr strlcpy(str, "NONE", size); 1092220585Srmacklem return (str); 1093180025Sdfr } 1094180025Sdfr ADDFLAG(gp, G_GEOM_WITHER, "G_GEOM_WITHER"); 1095180025Sdfr return (str); 1096220585Srmacklem} 1097180025Sdfrstatic void 1098220585Srmacklemdb_show_geom_consumer(int indent, struct g_consumer *cp) 1099180025Sdfr{ 1100217242Srmacklem 1101217242Srmacklem if (indent == 0) { 1102177633Sdfr gprintln("consumer: %p", cp); 1103177633Sdfr gprintln(" class: %s (%p)", cp->geom->class->name, 1104177633Sdfr cp->geom->class); 1105177633Sdfr gprintln(" geom: %s (%p)", cp->geom->name, cp->geom); 1106177633Sdfr if (cp->provider == NULL) 1107177633Sdfr gprintln(" provider: none"); 1108177633Sdfr else { 1109177633Sdfr gprintln(" provider: %s (%p)", cp->provider->name, 1110177633Sdfr cp->provider); 1111180025Sdfr } 1112177633Sdfr gprintln(" access: r%dw%de%d", cp->acr, cp->acw, cp->ace); 1113180025Sdfr gprintln(" spoiled: %d", cp->spoiled); 1114180025Sdfr gprintln(" nstart: %u", cp->nstart); 1115180025Sdfr gprintln(" nend: %u", cp->nend); 1116180025Sdfr } else { 1117177633Sdfr gprintf("consumer: %p (%s), access=r%dw%de%d", cp, 1118177633Sdfr cp->provider != NULL ? cp->provider->name : "none", 1119177633Sdfr cp->acr, cp->acw, cp->ace); 1120177633Sdfr if (cp->spoiled) 1121177633Sdfr printf(", spoiled=%d", cp->spoiled); 1122177633Sdfr printf("\n"); 1123177633Sdfr } 1124177633Sdfr} 1125177633Sdfr 1126177633Sdfrstatic void 1127177633Sdfrdb_show_geom_provider(int indent, struct g_provider *pp) 1128177633Sdfr{ 1129177633Sdfr struct g_consumer *cp; 1130177633Sdfr char flags[64]; 1131177633Sdfr 1132177633Sdfr if (indent == 0) { 1133177633Sdfr gprintln("provider: %s (%p)", pp->name, pp); 1134177633Sdfr gprintln(" class: %s (%p)", pp->geom->class->name, 1135193437Srmacklem pp->geom->class); 1136193437Srmacklem gprintln(" geom: %s (%p)", pp->geom->name, pp->geom); 1137193437Srmacklem gprintln(" mediasize: %jd", (intmax_t)pp->mediasize); 1138193437Srmacklem gprintln(" sectorsize: %u", pp->sectorsize); 1139193437Srmacklem gprintln(" stripesize: %u", pp->stripesize); 1140193272Sjhb gprintln(" stripeoffset: %u", pp->stripeoffset); 1141177633Sdfr gprintln(" access: r%dw%de%d", pp->acr, pp->acw, 1142177633Sdfr pp->ace); 1143193437Srmacklem gprintln(" flags: %s (0x%04x)", 1144193437Srmacklem provider_flags_to_string(pp, flags, sizeof(flags)), 1145193437Srmacklem pp->flags); 1146193437Srmacklem gprintln(" error: %d", pp->error); 1147193437Srmacklem gprintln(" nstart: %u", pp->nstart); 1148193437Srmacklem gprintln(" nend: %u", pp->nend); 1149193437Srmacklem if (LIST_EMPTY(&pp->consumers)) 1150193437Srmacklem gprintln(" consumers: none"); 1151193437Srmacklem } else { 1152193437Srmacklem gprintf("provider: %s (%p), access=r%dw%de%d", 1153193437Srmacklem pp->name, pp, pp->acr, pp->acw, pp->ace); 1154193437Srmacklem if (pp->flags != 0) { 1155193437Srmacklem printf(", flags=%s (0x%04x)", 1156 provider_flags_to_string(pp, flags, sizeof(flags)), 1157 pp->flags); 1158 } 1159 printf("\n"); 1160 } 1161 if (!LIST_EMPTY(&pp->consumers)) { 1162 LIST_FOREACH(cp, &pp->consumers, consumers) { 1163 db_show_geom_consumer(indent + 2, cp); 1164 if (db_pager_quit) 1165 break; 1166 } 1167 } 1168} 1169 1170static void 1171db_show_geom_geom(int indent, struct g_geom *gp) 1172{ 1173 struct g_provider *pp; 1174 struct g_consumer *cp; 1175 char flags[64]; 1176 1177 if (indent == 0) { 1178 gprintln("geom: %s (%p)", gp->name, gp); 1179 gprintln(" class: %s (%p)", gp->class->name, gp->class); 1180 gprintln(" flags: %s (0x%04x)", 1181 geom_flags_to_string(gp, flags, sizeof(flags)), gp->flags); 1182 gprintln(" rank: %d", gp->rank); 1183 if (LIST_EMPTY(&gp->provider)) 1184 gprintln(" providers: none"); 1185 if (LIST_EMPTY(&gp->consumer)) 1186 gprintln(" consumers: none"); 1187 } else { 1188 gprintf("geom: %s (%p), rank=%d", gp->name, gp, gp->rank); 1189 if (gp->flags != 0) { 1190 printf(", flags=%s (0x%04x)", 1191 geom_flags_to_string(gp, flags, sizeof(flags)), 1192 gp->flags); 1193 } 1194 printf("\n"); 1195 } 1196 if (!LIST_EMPTY(&gp->provider)) { 1197 LIST_FOREACH(pp, &gp->provider, provider) { 1198 db_show_geom_provider(indent + 2, pp); 1199 if (db_pager_quit) 1200 break; 1201 } 1202 } 1203 if (!LIST_EMPTY(&gp->consumer)) { 1204 LIST_FOREACH(cp, &gp->consumer, consumer) { 1205 db_show_geom_consumer(indent + 2, cp); 1206 if (db_pager_quit) 1207 break; 1208 } 1209 } 1210} 1211 1212static void 1213db_show_geom_class(struct g_class *mp) 1214{ 1215 struct g_geom *gp; 1216 1217 printf("class: %s (%p)\n", mp->name, mp); 1218 LIST_FOREACH(gp, &mp->geom, geom) { 1219 db_show_geom_geom(2, gp); 1220 if (db_pager_quit) 1221 break; 1222 } 1223} 1224 1225/* 1226 * Print the GEOM topology or the given object. 1227 */ 1228DB_SHOW_COMMAND(geom, db_show_geom) 1229{ 1230 struct g_class *mp; 1231 1232 if (!have_addr) { 1233 /* No address given, print the entire topology. */ 1234 LIST_FOREACH(mp, &g_classes, class) { 1235 db_show_geom_class(mp); 1236 printf("\n"); 1237 if (db_pager_quit) 1238 break; 1239 } 1240 } else { 1241 switch (g_valid_obj((void *)addr)) { 1242 case 1: 1243 db_show_geom_class((struct g_class *)addr); 1244 break; 1245 case 2: 1246 db_show_geom_geom(0, (struct g_geom *)addr); 1247 break; 1248 case 3: 1249 db_show_geom_consumer(0, (struct g_consumer *)addr); 1250 break; 1251 case 4: 1252 db_show_geom_provider(0, (struct g_provider *)addr); 1253 break; 1254 default: 1255 printf("Not a GEOM object.\n"); 1256 break; 1257 } 1258 } 1259} 1260 1261#undef gprintf 1262#undef gprintln 1263#undef ADDFLAG 1264 1265#endif /* DDB */ 1266