geom_subr.c revision 192803
1182007Sroberto/*- 2132451Sroberto * Copyright (c) 2002 Poul-Henning Kamp 354359Sroberto * Copyright (c) 2002 Networks Associates Technology, Inc. 4182007Sroberto * All rights reserved. 5182007Sroberto * 654359Sroberto * This software was developed for the FreeBSD Project by Poul-Henning Kamp 754359Sroberto * and NAI Labs, the Security Research Division of Network Associates, Inc. 854359Sroberto * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 954359Sroberto * DARPA CHATS research program. 1054359Sroberto * 1154359Sroberto * Redistribution and use in source and binary forms, with or without 1254359Sroberto * modification, are permitted provided that the following conditions 1354359Sroberto * are met: 1454359Sroberto * 1. Redistributions of source code must retain the above copyright 15106163Sroberto * notice, this list of conditions and the following disclaimer. 16106163Sroberto * 2. Redistributions in binary form must reproduce the above copyright 17182007Sroberto * notice, this list of conditions and the following disclaimer in the 1854359Sroberto * documentation and/or other materials provided with the distribution. 1954359Sroberto * 3. The names of the authors may not be used to endorse or promote 2054359Sroberto * products derived from this software without specific prior written 2154359Sroberto * permission. 2254359Sroberto * 2354359Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2454359Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25132451Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2654359Sroberto * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 27132451Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28132451Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29132451Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3082498Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31132451Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3254359Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3354359Sroberto * SUCH DAMAGE. 3454359Sroberto */ 3554359Sroberto 3654359Sroberto#include <sys/cdefs.h> 3754359Sroberto__FBSDID("$FreeBSD: head/sys/geom/geom_subr.c 192803 2009-05-26 10:03:44Z lulf $"); 3854359Sroberto 3954359Sroberto#include "opt_ddb.h" 40182007Sroberto 41182007Sroberto#include <sys/param.h> 42182007Sroberto#include <sys/systm.h> 43182007Sroberto#include <sys/devicestat.h> 44182007Sroberto#include <sys/kernel.h> 45182007Sroberto#include <sys/malloc.h> 46182007Sroberto#include <sys/bio.h> 47182007Sroberto#include <sys/sysctl.h> 48182007Sroberto#include <sys/proc.h> 49182007Sroberto#include <sys/kthread.h> 50182007Sroberto#include <sys/lock.h> 51182007Sroberto#include <sys/mutex.h> 52182007Sroberto#include <sys/errno.h> 53182007Sroberto#include <sys/sbuf.h> 54182007Sroberto#include <geom/geom.h> 55182007Sroberto#include <geom/geom_int.h> 56182007Sroberto#include <machine/stdarg.h> 57182007Sroberto 58182007Sroberto#ifdef DDB 59182007Sroberto#include <ddb/ddb.h> 60182007Sroberto#endif 61182007Sroberto 62182007Srobertostruct class_list_head g_classes = LIST_HEAD_INITIALIZER(g_classes); 63182007Srobertostatic struct g_tailq_head geoms = TAILQ_HEAD_INITIALIZER(geoms); 64182007Srobertochar *g_wait_event, *g_wait_up, *g_wait_down, *g_wait_sim; 65182007Sroberto 66182007Srobertostruct g_hh00 { 67182007Sroberto struct g_class *mp; 68182007Sroberto int error; 69182007Sroberto int post; 70182007Sroberto}; 71182007Sroberto 72182007Sroberto/* 73182007Sroberto * This event offers a new class a chance to taste all preexisting providers. 74182007Sroberto */ 75182007Srobertostatic void 76182007Srobertog_load_class(void *arg, int flag) 77182007Sroberto{ 78182007Sroberto struct g_hh00 *hh; 79182007Sroberto struct g_class *mp2, *mp; 80182007Sroberto struct g_geom *gp; 81182007Sroberto struct g_provider *pp; 82182007Sroberto 83182007Sroberto g_topology_assert(); 84182007Sroberto if (flag == EV_CANCEL) /* XXX: can't happen ? */ 85182007Sroberto return; 86182007Sroberto if (g_shutdown) 87182007Sroberto return; 88182007Sroberto 89182007Sroberto hh = arg; 90182007Sroberto mp = hh->mp; 91182007Sroberto hh->error = 0; 92182007Sroberto if (hh->post) { 93182007Sroberto g_free(hh); 94182007Sroberto hh = NULL; 95182007Sroberto } 96182007Sroberto g_trace(G_T_TOPOLOGY, "g_load_class(%s)", mp->name); 97182007Sroberto KASSERT(mp->name != NULL && *mp->name != '\0', 98182007Sroberto ("GEOM class has no name")); 99182007Sroberto LIST_FOREACH(mp2, &g_classes, class) { 100182007Sroberto if (mp2 == mp) { 101182007Sroberto printf("The GEOM class %s is already loaded.\n", 102182007Sroberto mp2->name); 103182007Sroberto if (hh != NULL) 104182007Sroberto hh->error = EEXIST; 105132451Sroberto return; 106132451Sroberto } else if (strcmp(mp2->name, mp->name) == 0) { 107132451Sroberto printf("A GEOM class %s is already loaded.\n", 10854359Sroberto mp2->name); 109182007Sroberto if (hh != NULL) 110132451Sroberto hh->error = EEXIST; 111132451Sroberto return; 112132451Sroberto } 113132451Sroberto } 11454359Sroberto 115182007Sroberto LIST_INIT(&mp->geom); 11654359Sroberto LIST_INSERT_HEAD(&g_classes, mp, class); 117132451Sroberto if (mp->init != NULL) 11854359Sroberto mp->init(mp); 11954359Sroberto if (mp->taste == NULL) 12054359Sroberto return; 12154359Sroberto LIST_FOREACH(mp2, &g_classes, class) { 122132451Sroberto if (mp == mp2) 123182007Sroberto continue; 124182007Sroberto LIST_FOREACH(gp, &mp2->geom, geom) { 125182007Sroberto LIST_FOREACH(pp, &gp->provider, provider) { 126182007Sroberto mp->taste(mp, pp, 0); 127132451Sroberto g_topology_assert(); 12854359Sroberto } 129132451Sroberto } 13056746Sroberto } 131182007Sroberto} 132132451Sroberto 133132451Srobertostatic void 134132451Srobertog_unload_class(void *arg, int flag) 13582498Sroberto{ 13682498Sroberto struct g_hh00 *hh; 137132451Sroberto struct g_class *mp; 138106163Sroberto struct g_geom *gp; 139182007Sroberto struct g_provider *pp; 140182007Sroberto struct g_consumer *cp; 141132451Sroberto int error; 142182007Sroberto 143182007Sroberto g_topology_assert(); 144132451Sroberto hh = arg; 145132451Sroberto mp = hh->mp; 14682498Sroberto G_VALID_CLASS(mp); 147132451Sroberto g_trace(G_T_TOPOLOGY, "g_unload_class(%s)", mp->name); 14854359Sroberto 149132451Sroberto /* 150182007Sroberto * We allow unloading if we have no geoms, or a class 151182007Sroberto * method we can use to get rid of them. 152182007Sroberto */ 15354359Sroberto if (!LIST_EMPTY(&mp->geom) && mp->destroy_geom == NULL) { 154132451Sroberto hh->error = EOPNOTSUPP; 155182007Sroberto return; 15654359Sroberto } 157132451Sroberto 158132451Sroberto /* We refuse to unload if anything is open */ 15954359Sroberto LIST_FOREACH(gp, &mp->geom, geom) { 160182007Sroberto LIST_FOREACH(pp, &gp->provider, provider) 16154359Sroberto if (pp->acr || pp->acw || pp->ace) { 162132451Sroberto hh->error = EBUSY; 16354359Sroberto return; 16454359Sroberto } 165132451Sroberto LIST_FOREACH(cp, &gp->consumer, consumer) 16654359Sroberto if (cp->acr || cp->acw || cp->ace) { 16754359Sroberto hh->error = EBUSY; 16854359Sroberto return; 16982498Sroberto } 170182007Sroberto } 171182007Sroberto 172106163Sroberto /* Bar new entries */ 17382498Sroberto mp->taste = NULL; 17482498Sroberto mp->config = NULL; 17582498Sroberto 17654359Sroberto error = 0; 177132451Sroberto for (;;) { 178132451Sroberto gp = LIST_FIRST(&mp->geom); 179132451Sroberto if (gp == NULL) 180132451Sroberto break; 181132451Sroberto error = mp->destroy_geom(NULL, mp, gp); 18282498Sroberto if (error != 0) 183132451Sroberto break; 18454359Sroberto } 18554359Sroberto if (error == 0) { 18654359Sroberto if (mp->fini != NULL) 187132451Sroberto mp->fini(mp); 188132451Sroberto LIST_REMOVE(mp, class); 189132451Sroberto } 190132451Sroberto hh->error = error; 19154359Sroberto return; 19254359Sroberto} 19354359Sroberto 194182007Srobertoint 195132451Srobertog_modevent(module_t mod, int type, void *data) 196182007Sroberto{ 197182007Sroberto struct g_hh00 *hh; 198132451Sroberto int error; 199132451Sroberto static int g_ignition; 200132451Sroberto struct g_class *mp; 201132451Sroberto 202182007Sroberto mp = data; 203182007Sroberto if (mp->version != G_VERSION) { 204106163Sroberto printf("GEOM class %s has Wrong version %x\n", 205132451Sroberto mp->name, mp->version); 206106163Sroberto return (EINVAL); 207182007Sroberto } 208182007Sroberto if (!g_ignition) { 209132451Sroberto g_ignition++; 210132451Sroberto g_init(); 211132451Sroberto } 212132451Sroberto hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO); 213132451Sroberto hh->mp = data; 214132451Sroberto error = EOPNOTSUPP; 215132451Sroberto switch (type) { 216132451Sroberto case MOD_LOAD: 217132451Sroberto g_trace(G_T_TOPOLOGY, "g_modevent(%s, LOAD)", hh->mp->name); 218132451Sroberto /* 219132451Sroberto * Once the system is not cold, MOD_LOAD calls will be 220132451Sroberto * from the userland and the g_event thread will be able 221132451Sroberto * to acknowledge their completion. 222132451Sroberto */ 223132451Sroberto if (cold) { 22456746Sroberto hh->post = 1; 225132451Sroberto error = g_post_event(g_load_class, hh, M_WAITOK, NULL); 226132451Sroberto } else { 227132451Sroberto error = g_waitfor_event(g_load_class, hh, M_WAITOK, 228132451Sroberto NULL); 229182007Sroberto if (error == 0) 230132451Sroberto error = hh->error; 231132451Sroberto g_free(hh); 232132451Sroberto } 233132451Sroberto break; 234132451Sroberto case MOD_UNLOAD: 235132451Sroberto g_trace(G_T_TOPOLOGY, "g_modevent(%s, UNLOAD)", hh->mp->name); 236132451Sroberto error = g_waitfor_event(g_unload_class, hh, M_WAITOK, NULL); 237132451Sroberto if (error == 0) 23854359Sroberto error = hh->error; 239132451Sroberto if (error == 0) { 24054359Sroberto KASSERT(LIST_EMPTY(&hh->mp->geom), 24154359Sroberto ("Unloaded class (%s) still has geom", hh->mp->name)); 24254359Sroberto } 24354359Sroberto g_free(hh); 24482498Sroberto break; 24554359Sroberto default: 24654359Sroberto g_free(hh); 24754359Sroberto break; 24854359Sroberto } 24954359Sroberto return (error); 25054359Sroberto} 25154359Sroberto 25254359Srobertostatic void 25354359Srobertog_retaste_event(void *arg, int flag) 25454359Sroberto{ 25554359Sroberto struct g_class *cp, *mp; 25654359Sroberto struct g_geom *gp, *gp2; 25754359Sroberto struct g_hh00 *hh; 25854359Sroberto struct g_provider *pp; 25954359Sroberto 260182007Sroberto g_topology_assert(); 261182007Sroberto if (flag == EV_CANCEL) /* XXX: can't happen ? */ 262182007Sroberto return; 263182007Sroberto if (g_shutdown) 264182007Sroberto return; 26554359Sroberto 26656746Sroberto hh = arg; 26756746Sroberto mp = hh->mp; 26856746Sroberto hh->error = 0; 26956746Sroberto if (hh->post) { 27056746Sroberto g_free(hh); 27156746Sroberto hh = NULL; 27256746Sroberto } 27356746Sroberto g_trace(G_T_TOPOLOGY, "g_retaste(%s)", mp->name); 27456746Sroberto 27556746Sroberto LIST_FOREACH(cp, &g_classes, class) { 27656746Sroberto LIST_FOREACH(gp, &cp->geom, geom) { 27756746Sroberto LIST_FOREACH(pp, &gp->provider, provider) { 27856746Sroberto if (pp->acr || pp->acw || pp->ace) 279182007Sroberto continue; 280182007Sroberto LIST_FOREACH(gp2, &mp->geom, geom) { 281182007Sroberto if (!strcmp(pp->name, gp2->name)) 282182007Sroberto break; 283182007Sroberto } 28454359Sroberto if (gp2 != NULL) 28554359Sroberto g_wither_geom(gp2, ENXIO); 28654359Sroberto mp->taste(mp, pp, 0); 28754359Sroberto g_topology_assert(); 28882498Sroberto } 28954359Sroberto } 29054359Sroberto } 291182007Sroberto} 292182007Sroberto 293182007Srobertoint 294182007Srobertog_retaste(struct g_class *mp) 295182007Sroberto{ 296182007Sroberto struct g_hh00 *hh; 297182007Sroberto int error; 298182007Sroberto 299182007Sroberto if (mp->taste == NULL) 300182007Sroberto return (EINVAL); 301182007Sroberto 30282498Sroberto hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO); 303182007Sroberto hh->mp = mp; 304182007Sroberto 305182007Sroberto if (cold) { 306182007Sroberto hh->post = 1; 307182007Sroberto error = g_post_event(g_retaste_event, hh, M_WAITOK, NULL); 308182007Sroberto } else { 309182007Sroberto error = g_waitfor_event(g_retaste_event, hh, M_WAITOK, NULL); 310182007Sroberto if (error == 0) 311182007Sroberto error = hh->error; 312182007Sroberto g_free(hh); 31354359Sroberto } 314182007Sroberto 315182007Sroberto return (error); 316106163Sroberto} 317182007Sroberto 318182007Srobertostruct g_geom * 319182007Srobertog_new_geomf(struct g_class *mp, const char *fmt, ...) 320182007Sroberto{ 321182007Sroberto struct g_geom *gp; 32254359Sroberto va_list ap; 32354359Sroberto struct sbuf *sb; 324106163Sroberto 325106163Sroberto g_topology_assert(); 326106163Sroberto G_VALID_CLASS(mp); 327106163Sroberto sb = sbuf_new_auto(); 328106163Sroberto va_start(ap, fmt); 329106163Sroberto sbuf_vprintf(sb, fmt, ap); 330106163Sroberto va_end(ap); 331106163Sroberto sbuf_finish(sb); 33254359Sroberto gp = g_malloc(sizeof *gp, M_WAITOK | M_ZERO); 333106163Sroberto gp->name = g_malloc(sbuf_len(sb) + 1, M_WAITOK | M_ZERO); 334182007Sroberto gp->class = mp; 335182007Sroberto gp->rank = 1; 336182007Sroberto LIST_INIT(&gp->consumer); 337182007Sroberto LIST_INIT(&gp->provider); 338182007Sroberto LIST_INSERT_HEAD(&mp->geom, gp, geom); 339106163Sroberto TAILQ_INSERT_HEAD(&geoms, gp, geoms); 340106163Sroberto strcpy(gp->name, sbuf_data(sb)); 341106163Sroberto sbuf_delete(sb); 342106163Sroberto /* Fill in defaults from class */ 343106163Sroberto gp->start = mp->start; 344106163Sroberto gp->spoiled = mp->spoiled; 345106163Sroberto gp->dumpconf = mp->dumpconf; 34654359Sroberto gp->access = mp->access; 347182007Sroberto gp->orphan = mp->orphan; 34854359Sroberto gp->ioctl = mp->ioctl; 34954359Sroberto return (gp); 35054359Sroberto} 351106163Sroberto 35254359Srobertovoid 35354359Srobertog_destroy_geom(struct g_geom *gp) 35454359Sroberto{ 355132451Sroberto 35654359Sroberto g_topology_assert(); 357182007Sroberto G_VALID_GEOM(gp); 358132451Sroberto g_trace(G_T_TOPOLOGY, "g_destroy_geom(%p(%s))", gp, gp->name); 359132451Sroberto KASSERT(LIST_EMPTY(&gp->consumer), 360132451Sroberto ("g_destroy_geom(%s) with consumer(s) [%p]", 361132451Sroberto gp->name, LIST_FIRST(&gp->consumer))); 362132451Sroberto KASSERT(LIST_EMPTY(&gp->provider), 363132451Sroberto ("g_destroy_geom(%s) with provider(s) [%p]", 364132451Sroberto gp->name, LIST_FIRST(&gp->provider))); 365132451Sroberto g_cancel_event(gp); 366132451Sroberto LIST_REMOVE(gp, geom); 367132451Sroberto TAILQ_REMOVE(&geoms, gp, geoms); 368132451Sroberto g_free(gp->name); 369132451Sroberto g_free(gp); 370182007Sroberto} 371182007Sroberto 372132451Sroberto/* 373182007Sroberto * This function is called (repeatedly) until the geom has withered away. 374132451Sroberto */ 375132451Srobertovoid 376132451Srobertog_wither_geom(struct g_geom *gp, int error) 377132451Sroberto{ 378132451Sroberto struct g_provider *pp; 37954359Sroberto 380106163Sroberto g_topology_assert(); 381182007Sroberto G_VALID_GEOM(gp); 382182007Sroberto g_trace(G_T_TOPOLOGY, "g_wither_geom(%p(%s))", gp, gp->name); 383132451Sroberto if (!(gp->flags & G_GEOM_WITHER)) { 384182007Sroberto gp->flags |= G_GEOM_WITHER; 385182007Sroberto LIST_FOREACH(pp, &gp->provider, provider) 38654359Sroberto if (!(pp->flags & G_PF_ORPHAN)) 387106163Sroberto g_orphan_provider(pp, error); 388182007Sroberto } 389182007Sroberto g_do_wither(); 390132451Sroberto} 391182007Sroberto 392182007Sroberto/* 393182007Sroberto * Convenience function to destroy a particular provider. 394182007Sroberto */ 395182007Srobertovoid 396182007Srobertog_wither_provider(struct g_provider *pp, int error) 397182007Sroberto{ 398182007Sroberto 399182007Sroberto pp->flags |= G_PF_WITHER; 400182007Sroberto if (!(pp->flags & G_PF_ORPHAN)) 401182007Sroberto g_orphan_provider(pp, error); 40254359Sroberto} 403132451Sroberto 40454359Sroberto/* 405132451Sroberto * This function is called (repeatedly) until the has withered away. 40654359Sroberto */ 407132451Srobertovoid 40854359Srobertog_wither_geom_close(struct g_geom *gp, int error) 409132451Sroberto{ 41054359Sroberto struct g_consumer *cp; 411132451Sroberto 41254359Sroberto g_topology_assert(); 413132451Sroberto G_VALID_GEOM(gp); 41454359Sroberto g_trace(G_T_TOPOLOGY, "g_wither_geom_close(%p(%s))", gp, gp->name); 415132451Sroberto LIST_FOREACH(cp, &gp->consumer, consumer) 41654359Sroberto if (cp->acr || cp->acw || cp->ace) 417132451Sroberto g_access(cp, -cp->acr, -cp->acw, -cp->ace); 41854359Sroberto g_wither_geom(gp, error); 419132451Sroberto} 42054359Sroberto 421132451Sroberto/* 42254359Sroberto * This function is called (repeatedly) until we cant wash away more 423132451Sroberto * withered bits at present. Return value contains two bits. Bit 0 42454359Sroberto * set means "withering stuff we can't wash now", bit 1 means "call 425132451Sroberto * me again, there may be stuff I didn't get the first time around. 426182007Sroberto */ 427182007Srobertoint 428182007Srobertog_wither_washer() 429182007Sroberto{ 43054359Sroberto struct g_class *mp; 431132451Sroberto struct g_geom *gp, *gp2; 432182007Sroberto struct g_provider *pp, *pp2; 433182007Sroberto struct g_consumer *cp, *cp2; 43454359Sroberto int result; 435132451Sroberto 43654359Sroberto result = 0; 437132451Sroberto g_topology_assert(); 43854359Sroberto LIST_FOREACH(mp, &g_classes, class) { 439132451Sroberto LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) { 44054359Sroberto LIST_FOREACH_SAFE(pp, &gp->provider, provider, pp2) { 441132451Sroberto if (!(pp->flags & G_PF_WITHER)) 44254359Sroberto continue; 443132451Sroberto if (LIST_EMPTY(&pp->consumers)) 444182007Sroberto g_destroy_provider(pp); 445182007Sroberto else 446182007Sroberto result |= 1; 447182007Sroberto } 448182007Sroberto if (!(gp->flags & G_GEOM_WITHER)) 449182007Sroberto continue; 450182007Sroberto LIST_FOREACH_SAFE(pp, &gp->provider, provider, pp2) { 451182007Sroberto if (LIST_EMPTY(&pp->consumers)) 452182007Sroberto g_destroy_provider(pp); 453182007Sroberto else 454182007Sroberto result |= 1; 455182007Sroberto } 456182007Sroberto LIST_FOREACH_SAFE(cp, &gp->consumer, consumer, cp2) { 457182007Sroberto if (cp->acr || cp->acw || cp->ace) { 45854359Sroberto result |= 1; 459182007Sroberto continue; 460182007Sroberto } 461132451Sroberto if (cp->provider != NULL) 462182007Sroberto g_detach(cp); 463182007Sroberto g_destroy_consumer(cp); 464132451Sroberto result |= 2; 465182007Sroberto } 466182007Sroberto if (LIST_EMPTY(&gp->provider) && 467182007Sroberto LIST_EMPTY(&gp->consumer)) 46854359Sroberto g_destroy_geom(gp); 46956746Sroberto else 470132451Sroberto result |= 1; 47156746Sroberto } 47256746Sroberto } 47356746Sroberto return (result); 47456746Sroberto} 47554359Sroberto 476132451Srobertostruct g_consumer * 477182007Srobertog_new_consumer(struct g_geom *gp) 47854359Sroberto{ 479106163Sroberto struct g_consumer *cp; 48056746Sroberto 48154359Sroberto g_topology_assert(); 48254359Sroberto G_VALID_GEOM(gp); 483132451Sroberto KASSERT(!(gp->flags & G_GEOM_WITHER), 48456746Sroberto ("g_new_consumer on WITHERing geom(%s) (class %s)", 48556746Sroberto gp->name, gp->class->name)); 48656746Sroberto KASSERT(gp->orphan != NULL, 48756746Sroberto ("g_new_consumer on geom(%s) (class %s) without orphan", 48854359Sroberto gp->name, gp->class->name)); 489182007Sroberto 490182007Sroberto cp = g_malloc(sizeof *cp, M_WAITOK | M_ZERO); 491182007Sroberto cp->geom = gp; 492182007Sroberto cp->stat = devstat_new_entry(cp, -1, 0, DEVSTAT_ALL_SUPPORTED, 493182007Sroberto DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX); 494132451Sroberto LIST_INSERT_HEAD(&gp->consumer, cp, consumer); 495132451Sroberto return(cp); 496132451Sroberto} 497132451Sroberto 498132451Srobertovoid 499132451Srobertog_destroy_consumer(struct g_consumer *cp) 500132451Sroberto{ 501132451Sroberto struct g_geom *gp; 502132451Sroberto 503132451Sroberto g_topology_assert(); 504132451Sroberto G_VALID_CONSUMER(cp); 505132451Sroberto g_trace(G_T_TOPOLOGY, "g_destroy_consumer(%p)", cp); 506132451Sroberto KASSERT (cp->provider == NULL, ("g_destroy_consumer but attached")); 507132451Sroberto KASSERT (cp->acr == 0, ("g_destroy_consumer with acr")); 508132451Sroberto KASSERT (cp->acw == 0, ("g_destroy_consumer with acw")); 50982498Sroberto KASSERT (cp->ace == 0, ("g_destroy_consumer with ace")); 510132451Sroberto g_cancel_event(cp); 51182498Sroberto gp = cp->geom; 512106163Sroberto LIST_REMOVE(cp, consumer); 51354359Sroberto devstat_remove_entry(cp->stat); 51454359Sroberto g_free(cp); 515132451Sroberto if (gp->flags & G_GEOM_WITHER) 51682498Sroberto g_do_wither(); 51782498Sroberto} 518132451Sroberto 519132451Srobertostatic void 520132451Srobertog_new_provider_event(void *arg, int flag) 521132451Sroberto{ 522132451Sroberto struct g_class *mp; 523132451Sroberto struct g_provider *pp; 524132451Sroberto struct g_consumer *cp; 525132451Sroberto int i; 526106163Sroberto 527106163Sroberto g_topology_assert(); 528132451Sroberto if (flag == EV_CANCEL) 529182007Sroberto return; 530132451Sroberto if (g_shutdown) 531132451Sroberto return; 532106163Sroberto pp = arg; 53382498Sroberto G_VALID_PROVIDER(pp); 534132451Sroberto KASSERT(!(pp->flags & G_PF_WITHER), 535132451Sroberto ("g_new_provider_event but withered")); 536132451Sroberto LIST_FOREACH(mp, &g_classes, class) { 537132451Sroberto if (mp->taste == NULL) 53882498Sroberto continue; 53982498Sroberto i = 1; 54082498Sroberto LIST_FOREACH(cp, &pp->consumers, consumers) 54182498Sroberto if (cp->geom->class == mp) 54282498Sroberto i = 0; 54382498Sroberto if (!i) 54454359Sroberto continue; 54554359Sroberto mp->taste(mp, pp, 0); 54682498Sroberto g_topology_assert(); 54782498Sroberto } 54882498Sroberto} 54954359Sroberto 55054359Sroberto 55182498Srobertostruct g_provider * 55254359Srobertog_new_providerf(struct g_geom *gp, const char *fmt, ...) 55354359Sroberto{ 55454359Sroberto struct g_provider *pp; 55582498Sroberto struct sbuf *sb; 55682498Sroberto va_list ap; 55754359Sroberto 55882498Sroberto g_topology_assert(); 559182007Sroberto G_VALID_GEOM(gp); 560106163Sroberto KASSERT(gp->access != NULL, 561106163Sroberto ("new provider on geom(%s) without ->access (class %s)", 56254359Sroberto gp->name, gp->class->name)); 56354359Sroberto KASSERT(gp->start != NULL, 56454359Sroberto ("new provider on geom(%s) without ->start (class %s)", 56554359Sroberto gp->name, gp->class->name)); 56654359Sroberto KASSERT(!(gp->flags & G_GEOM_WITHER), 56754359Sroberto ("new provider on WITHERing geom(%s) (class %s)", 568182007Sroberto gp->name, gp->class->name)); 56954359Sroberto sb = sbuf_new_auto(); 57054359Sroberto va_start(ap, fmt); 57182498Sroberto sbuf_vprintf(sb, fmt, ap); 57282498Sroberto va_end(ap); 57382498Sroberto sbuf_finish(sb); 57454359Sroberto pp = g_malloc(sizeof *pp + sbuf_len(sb) + 1, M_WAITOK | M_ZERO); 575182007Sroberto pp->name = (char *)(pp + 1); 576182007Sroberto strcpy(pp->name, sbuf_data(sb)); 57754359Sroberto sbuf_delete(sb); 57882498Sroberto LIST_INIT(&pp->consumers); 579132451Sroberto pp->error = ENXIO; 580132451Sroberto pp->geom = gp; 581132451Sroberto pp->stat = devstat_new_entry(pp, -1, 0, DEVSTAT_ALL_SUPPORTED, 582182007Sroberto DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX); 58354359Sroberto LIST_INSERT_HEAD(&gp->provider, pp, provider); 584106163Sroberto g_post_event(g_new_provider_event, pp, M_WAITOK, pp, gp, NULL); 58554359Sroberto return (pp); 58682498Sroberto} 58754359Sroberto 588182007Srobertovoid 589182007Srobertog_error_provider(struct g_provider *pp, int error) 590106163Sroberto{ 59154359Sroberto 59282498Sroberto /* G_VALID_PROVIDER(pp); We may not have g_topology */ 59382498Sroberto pp->error = error; 59482498Sroberto} 59582498Sroberto 59682498Srobertostruct g_provider * 59782498Srobertog_provider_by_name(char const *arg) 598106163Sroberto{ 59982498Sroberto struct g_class *cp; 60082498Sroberto struct g_geom *gp; 60182498Sroberto struct g_provider *pp; 60282498Sroberto 60382498Sroberto LIST_FOREACH(cp, &g_classes, class) { 60454359Sroberto LIST_FOREACH(gp, &cp->geom, geom) { 605132451Sroberto LIST_FOREACH(pp, &gp->provider, provider) { 606132451Sroberto if (!strcmp(arg, pp->name)) 60782498Sroberto return (pp); 60854359Sroberto } 60982498Sroberto } 61054359Sroberto } 611182007Sroberto return (NULL); 612182007Sroberto} 61382498Sroberto 614132451Srobertovoid 615132451Srobertog_destroy_provider(struct g_provider *pp) 616132451Sroberto{ 617132451Sroberto struct g_geom *gp; 618132451Sroberto 619132451Sroberto g_topology_assert(); 620132451Sroberto G_VALID_PROVIDER(pp); 621132451Sroberto KASSERT(LIST_EMPTY(&pp->consumers), 622106163Sroberto ("g_destroy_provider but attached")); 623106163Sroberto KASSERT (pp->acr == 0, ("g_destroy_provider with acr")); 624132451Sroberto KASSERT (pp->acw == 0, ("g_destroy_provider with acw")); 625182007Sroberto KASSERT (pp->ace == 0, ("g_destroy_provider with ace")); 626182007Sroberto g_cancel_event(pp); 627182007Sroberto LIST_REMOVE(pp, provider); 628182007Sroberto gp = pp->geom; 629132451Sroberto devstat_remove_entry(pp->stat); 630132451Sroberto g_free(pp); 631132451Sroberto if ((gp->flags & G_GEOM_WITHER)) 632132451Sroberto g_do_wither(); 633182007Sroberto} 634182007Sroberto 63582498Sroberto/* 63682498Sroberto * We keep the "geoms" list sorted by topological order (== increasing 63754359Sroberto * numerical rank) at all times. 63854359Sroberto * When an attach is done, the attaching geoms rank is invalidated 63954359Sroberto * and it is moved to the tail of the list. 64054359Sroberto * All geoms later in the sequence has their ranks reevaluated in 64154359Sroberto * sequence. If we cannot assign rank to a geom because it's 64282498Sroberto * prerequisites do not have rank, we move that element to the tail 64382498Sroberto * of the sequence with invalid rank as well. 64454359Sroberto * At some point we encounter our original geom and if we stil fail 645182007Sroberto * to assign it a rank, there must be a loop and we fail back to 646182007Sroberto * g_attach() which detach again and calls redo_rank again 647182007Sroberto * to fix up the damage. 648182007Sroberto * It would be much simpler code wise to do it recursively, but we 649182007Sroberto * can't risk that on the kernel stack. 650182007Sroberto */ 651182007Sroberto 652182007Srobertostatic int 653182007Srobertoredo_rank(struct g_geom *gp) 654182007Sroberto{ 655182007Sroberto struct g_consumer *cp; 656182007Sroberto struct g_geom *gp1, *gp2; 65782498Sroberto int n, m; 65882498Sroberto 65954359Sroberto g_topology_assert(); 66082498Sroberto G_VALID_GEOM(gp); 66182498Sroberto 66256746Sroberto /* Invalidate this geoms rank and move it to the tail */ 66382498Sroberto gp1 = TAILQ_NEXT(gp, geoms); 66482498Sroberto if (gp1 != NULL) { 66556746Sroberto gp->rank = 0; 66682498Sroberto TAILQ_REMOVE(&geoms, gp, geoms); 66782498Sroberto TAILQ_INSERT_TAIL(&geoms, gp, geoms); 66856746Sroberto } else { 66982498Sroberto gp1 = gp; 67082498Sroberto } 67156746Sroberto 67282498Sroberto /* re-rank the rest of the sequence */ 67382498Sroberto for (; gp1 != NULL; gp1 = gp2) { 67456746Sroberto gp1->rank = 0; 67582498Sroberto m = 1; 67682498Sroberto LIST_FOREACH(cp, &gp1->consumer, consumer) { 67756746Sroberto if (cp->provider == NULL) 67882498Sroberto continue; 67982498Sroberto n = cp->provider->geom->rank; 68056746Sroberto if (n == 0) { 68182498Sroberto m = 0; 68282498Sroberto break; 68356746Sroberto } else if (n >= m) 68482498Sroberto m = n + 1; 68582498Sroberto } 68656746Sroberto gp1->rank = m; 68782498Sroberto gp2 = TAILQ_NEXT(gp1, geoms); 68882498Sroberto 68956746Sroberto /* got a rank, moving on */ 69082498Sroberto if (m != 0) 69182498Sroberto continue; 69256746Sroberto 69382498Sroberto /* no rank to original geom means loop */ 69482498Sroberto if (gp == gp1) 69556746Sroberto return (ELOOP); 69682498Sroberto 69782498Sroberto /* no rank, put it at the end move on */ 69882498Sroberto TAILQ_REMOVE(&geoms, gp1, geoms); 69982498Sroberto TAILQ_INSERT_TAIL(&geoms, gp1, geoms); 70082498Sroberto } 70182498Sroberto return (0); 70282498Sroberto} 70382498Sroberto 70482498Srobertoint 70582498Srobertog_attach(struct g_consumer *cp, struct g_provider *pp) 70682498Sroberto{ 70782498Sroberto int error; 70882498Sroberto 70982498Sroberto g_topology_assert(); 71082498Sroberto G_VALID_CONSUMER(cp); 71182498Sroberto G_VALID_PROVIDER(pp); 71282498Sroberto KASSERT(cp->provider == NULL, ("attach but attached")); 71382498Sroberto cp->provider = pp; 71482498Sroberto LIST_INSERT_HEAD(&pp->consumers, cp, consumers); 71582498Sroberto error = redo_rank(cp->geom); 71682498Sroberto if (error) { 71782498Sroberto LIST_REMOVE(cp, consumers); 71882498Sroberto cp->provider = NULL; 71982498Sroberto redo_rank(cp->geom); 72082498Sroberto } 72182498Sroberto return (error); 72282498Sroberto} 72382498Sroberto 72482498Srobertovoid 72582498Srobertog_detach(struct g_consumer *cp) 72682498Sroberto{ 72782498Sroberto struct g_provider *pp; 72882498Sroberto 72982498Sroberto g_topology_assert(); 73082498Sroberto G_VALID_CONSUMER(cp); 73182498Sroberto g_trace(G_T_TOPOLOGY, "g_detach(%p)", cp); 73282498Sroberto KASSERT(cp->provider != NULL, ("detach but not attached")); 73382498Sroberto KASSERT(cp->acr == 0, ("detach but nonzero acr")); 73482498Sroberto KASSERT(cp->acw == 0, ("detach but nonzero acw")); 73554359Sroberto KASSERT(cp->ace == 0, ("detach but nonzero ace")); 73654359Sroberto KASSERT(cp->nstart == cp->nend, 73754359Sroberto ("detach with active requests")); 73854359Sroberto pp = cp->provider; 73954359Sroberto LIST_REMOVE(cp, consumers); 74054359Sroberto cp->provider = NULL; 74154359Sroberto if (pp->geom->flags & G_GEOM_WITHER) 74254359Sroberto g_do_wither(); 74354359Sroberto else if (pp->flags & G_PF_WITHER) 74454359Sroberto g_do_wither(); 74554359Sroberto redo_rank(cp->geom); 74654359Sroberto} 74754359Sroberto 74854359Sroberto/* 74954359Sroberto * g_access() 75054359Sroberto * 75154359Sroberto * Access-check with delta values. The question asked is "can provider 752 * "cp" change the access counters by the relative amounts dc[rwe] ?" 753 */ 754 755int 756g_access(struct g_consumer *cp, int dcr, int dcw, int dce) 757{ 758 struct g_provider *pp; 759 int pr,pw,pe; 760 int error; 761 762 g_topology_assert(); 763 G_VALID_CONSUMER(cp); 764 pp = cp->provider; 765 KASSERT(pp != NULL, ("access but not attached")); 766 G_VALID_PROVIDER(pp); 767 768 g_trace(G_T_ACCESS, "g_access(%p(%s), %d, %d, %d)", 769 cp, pp->name, dcr, dcw, dce); 770 771 KASSERT(cp->acr + dcr >= 0, ("access resulting in negative acr")); 772 KASSERT(cp->acw + dcw >= 0, ("access resulting in negative acw")); 773 KASSERT(cp->ace + dce >= 0, ("access resulting in negative ace")); 774 KASSERT(dcr != 0 || dcw != 0 || dce != 0, ("NOP access request")); 775 KASSERT(pp->geom->access != NULL, ("NULL geom->access")); 776 777 /* 778 * If our class cares about being spoiled, and we have been, we 779 * are probably just ahead of the event telling us that. Fail 780 * now rather than having to unravel this later. 781 */ 782 if (cp->geom->spoiled != NULL && cp->spoiled && 783 (dcr > 0 || dcw > 0 || dce > 0)) 784 return (ENXIO); 785 786 /* 787 * Figure out what counts the provider would have had, if this 788 * consumer had (r0w0e0) at this time. 789 */ 790 pr = pp->acr - cp->acr; 791 pw = pp->acw - cp->acw; 792 pe = pp->ace - cp->ace; 793 794 g_trace(G_T_ACCESS, 795 "open delta:[r%dw%de%d] old:[r%dw%de%d] provider:[r%dw%de%d] %p(%s)", 796 dcr, dcw, dce, 797 cp->acr, cp->acw, cp->ace, 798 pp->acr, pp->acw, pp->ace, 799 pp, pp->name); 800 801 /* If foot-shooting is enabled, any open on rank#1 is OK */ 802 if ((g_debugflags & 16) && pp->geom->rank == 1) 803 ; 804 /* If we try exclusive but already write: fail */ 805 else if (dce > 0 && pw > 0) 806 return (EPERM); 807 /* If we try write but already exclusive: fail */ 808 else if (dcw > 0 && pe > 0) 809 return (EPERM); 810 /* If we try to open more but provider is error'ed: fail */ 811 else if ((dcr > 0 || dcw > 0 || dce > 0) && pp->error != 0) 812 return (pp->error); 813 814 /* Ok then... */ 815 816 error = pp->geom->access(pp, dcr, dcw, dce); 817 KASSERT(dcr > 0 || dcw > 0 || dce > 0 || error == 0, 818 ("Geom provider %s::%s failed closing ->access()", 819 pp->geom->class->name, pp->name)); 820 if (!error) { 821 /* 822 * If we open first write, spoil any partner consumers. 823 * If we close last write and provider is not errored, 824 * trigger re-taste. 825 */ 826 if (pp->acw == 0 && dcw != 0) 827 g_spoil(pp, cp); 828 else if (pp->acw != 0 && pp->acw == -dcw && pp->error == 0 && 829 !(pp->geom->flags & G_GEOM_WITHER)) 830 g_post_event(g_new_provider_event, pp, M_WAITOK, 831 pp, NULL); 832 833 pp->acr += dcr; 834 pp->acw += dcw; 835 pp->ace += dce; 836 cp->acr += dcr; 837 cp->acw += dcw; 838 cp->ace += dce; 839 if (pp->acr != 0 || pp->acw != 0 || pp->ace != 0) 840 KASSERT(pp->sectorsize > 0, 841 ("Provider %s lacks sectorsize", pp->name)); 842 } 843 return (error); 844} 845 846int 847g_handleattr_int(struct bio *bp, const char *attribute, int val) 848{ 849 850 return (g_handleattr(bp, attribute, &val, sizeof val)); 851} 852 853int 854g_handleattr_off_t(struct bio *bp, const char *attribute, off_t val) 855{ 856 857 return (g_handleattr(bp, attribute, &val, sizeof val)); 858} 859 860int 861g_handleattr_str(struct bio *bp, const char *attribute, const char *str) 862{ 863 864 return (g_handleattr(bp, attribute, str, 0)); 865} 866 867int 868g_handleattr(struct bio *bp, const char *attribute, const void *val, int len) 869{ 870 int error = 0; 871 872 if (strcmp(bp->bio_attribute, attribute)) 873 return (0); 874 if (len == 0) { 875 bzero(bp->bio_data, bp->bio_length); 876 if (strlcpy(bp->bio_data, val, bp->bio_length) >= 877 bp->bio_length) { 878 printf("%s: %s bio_length %jd len %zu -> EFAULT\n", 879 __func__, bp->bio_to->name, 880 (intmax_t)bp->bio_length, strlen(val)); 881 error = EFAULT; 882 } 883 } else if (bp->bio_length == len) { 884 bcopy(val, bp->bio_data, len); 885 } else { 886 printf("%s: %s bio_length %jd len %d -> EFAULT\n", __func__, 887 bp->bio_to->name, (intmax_t)bp->bio_length, len); 888 error = EFAULT; 889 } 890 if (error == 0) 891 bp->bio_completed = bp->bio_length; 892 g_io_deliver(bp, error); 893 return (1); 894} 895 896int 897g_std_access(struct g_provider *pp, 898 int dr __unused, int dw __unused, int de __unused) 899{ 900 901 g_topology_assert(); 902 G_VALID_PROVIDER(pp); 903 return (0); 904} 905 906void 907g_std_done(struct bio *bp) 908{ 909 struct bio *bp2; 910 911 bp2 = bp->bio_parent; 912 if (bp2->bio_error == 0) 913 bp2->bio_error = bp->bio_error; 914 bp2->bio_completed += bp->bio_completed; 915 g_destroy_bio(bp); 916 bp2->bio_inbed++; 917 if (bp2->bio_children == bp2->bio_inbed) 918 g_io_deliver(bp2, bp2->bio_error); 919} 920 921/* XXX: maybe this is only g_slice_spoiled */ 922 923void 924g_std_spoiled(struct g_consumer *cp) 925{ 926 struct g_geom *gp; 927 struct g_provider *pp; 928 929 g_topology_assert(); 930 G_VALID_CONSUMER(cp); 931 g_trace(G_T_TOPOLOGY, "g_std_spoiled(%p)", cp); 932 g_detach(cp); 933 gp = cp->geom; 934 LIST_FOREACH(pp, &gp->provider, provider) 935 g_orphan_provider(pp, ENXIO); 936 g_destroy_consumer(cp); 937 if (LIST_EMPTY(&gp->provider) && LIST_EMPTY(&gp->consumer)) 938 g_destroy_geom(gp); 939 else 940 gp->flags |= G_GEOM_WITHER; 941} 942 943/* 944 * Spoiling happens when a provider is opened for writing, but consumers 945 * which are configured by in-band data are attached (slicers for instance). 946 * Since the write might potentially change the in-band data, such consumers 947 * need to re-evaluate their existence after the writing session closes. 948 * We do this by (offering to) tear them down when the open for write happens 949 * in return for a re-taste when it closes again. 950 * Together with the fact that such consumers grab an 'e' bit whenever they 951 * are open, regardless of mode, this ends up DTRT. 952 */ 953 954static void 955g_spoil_event(void *arg, int flag) 956{ 957 struct g_provider *pp; 958 struct g_consumer *cp, *cp2; 959 960 g_topology_assert(); 961 if (flag == EV_CANCEL) 962 return; 963 pp = arg; 964 G_VALID_PROVIDER(pp); 965 for (cp = LIST_FIRST(&pp->consumers); cp != NULL; cp = cp2) { 966 cp2 = LIST_NEXT(cp, consumers); 967 if (!cp->spoiled) 968 continue; 969 cp->spoiled = 0; 970 if (cp->geom->spoiled == NULL) 971 continue; 972 cp->geom->spoiled(cp); 973 g_topology_assert(); 974 } 975} 976 977void 978g_spoil(struct g_provider *pp, struct g_consumer *cp) 979{ 980 struct g_consumer *cp2; 981 982 g_topology_assert(); 983 G_VALID_PROVIDER(pp); 984 G_VALID_CONSUMER(cp); 985 986 LIST_FOREACH(cp2, &pp->consumers, consumers) { 987 if (cp2 == cp) 988 continue; 989/* 990 KASSERT(cp2->acr == 0, ("spoiling cp->acr = %d", cp2->acr)); 991 KASSERT(cp2->acw == 0, ("spoiling cp->acw = %d", cp2->acw)); 992*/ 993 KASSERT(cp2->ace == 0, ("spoiling cp->ace = %d", cp2->ace)); 994 cp2->spoiled++; 995 } 996 g_post_event(g_spoil_event, pp, M_WAITOK, pp, NULL); 997} 998 999int 1000g_getattr__(const char *attr, struct g_consumer *cp, void *var, int len) 1001{ 1002 int error, i; 1003 1004 i = len; 1005 error = g_io_getattr(attr, cp, &i, var); 1006 if (error) 1007 return (error); 1008 if (i != len) 1009 return (EINVAL); 1010 return (0); 1011} 1012 1013#if defined(DIAGNOSTIC) || defined(DDB) 1014/* 1015 * This function walks (topologically unsafely) the mesh and return a 1016 * non-zero integer if it finds the argument pointer is an object. 1017 * The return value indicates which type of object it is belived to be. 1018 * If topology is not locked, this function is potentially dangerous, 1019 * but since it is for debugging purposes and can be useful for instance 1020 * from DDB, we do not assert topology lock is held. 1021 */ 1022int 1023g_valid_obj(void const *ptr) 1024{ 1025 struct g_class *mp; 1026 struct g_geom *gp; 1027 struct g_consumer *cp; 1028 struct g_provider *pp; 1029 1030 LIST_FOREACH(mp, &g_classes, class) { 1031 if (ptr == mp) 1032 return (1); 1033 LIST_FOREACH(gp, &mp->geom, geom) { 1034 if (ptr == gp) 1035 return (2); 1036 LIST_FOREACH(cp, &gp->consumer, consumer) 1037 if (ptr == cp) 1038 return (3); 1039 LIST_FOREACH(pp, &gp->provider, provider) 1040 if (ptr == pp) 1041 return (4); 1042 } 1043 } 1044 return(0); 1045} 1046#endif 1047 1048#ifdef DDB 1049 1050#define gprintf(...) do { \ 1051 db_printf("%*s", indent, ""); \ 1052 db_printf(__VA_ARGS__); \ 1053} while (0) 1054#define gprintln(...) do { \ 1055 gprintf(__VA_ARGS__); \ 1056 db_printf("\n"); \ 1057} while (0) 1058 1059#define ADDFLAG(obj, flag, sflag) do { \ 1060 if ((obj)->flags & (flag)) { \ 1061 if (comma) \ 1062 strlcat(str, ",", size); \ 1063 strlcat(str, (sflag), size); \ 1064 comma = 1; \ 1065 } \ 1066} while (0) 1067 1068static char * 1069provider_flags_to_string(struct g_provider *pp, char *str, size_t size) 1070{ 1071 int comma = 0; 1072 1073 bzero(str, size); 1074 if (pp->flags == 0) { 1075 strlcpy(str, "NONE", size); 1076 return (str); 1077 } 1078 ADDFLAG(pp, G_PF_CANDELETE, "G_PF_CANDELETE"); 1079 ADDFLAG(pp, G_PF_WITHER, "G_PF_WITHER"); 1080 ADDFLAG(pp, G_PF_ORPHAN, "G_PF_ORPHAN"); 1081 return (str); 1082} 1083 1084static char * 1085geom_flags_to_string(struct g_geom *gp, char *str, size_t size) 1086{ 1087 int comma = 0; 1088 1089 bzero(str, size); 1090 if (gp->flags == 0) { 1091 strlcpy(str, "NONE", size); 1092 return (str); 1093 } 1094 ADDFLAG(gp, G_GEOM_WITHER, "G_GEOM_WITHER"); 1095 return (str); 1096} 1097static void 1098db_show_geom_consumer(int indent, struct g_consumer *cp) 1099{ 1100 1101 if (indent == 0) { 1102 gprintln("consumer: %p", cp); 1103 gprintln(" class: %s (%p)", cp->geom->class->name, 1104 cp->geom->class); 1105 gprintln(" geom: %s (%p)", cp->geom->name, cp->geom); 1106 if (cp->provider == NULL) 1107 gprintln(" provider: none"); 1108 else { 1109 gprintln(" provider: %s (%p)", cp->provider->name, 1110 cp->provider); 1111 } 1112 gprintln(" access: r%dw%de%d", cp->acr, cp->acw, cp->ace); 1113 gprintln(" spoiled: %d", cp->spoiled); 1114 gprintln(" nstart: %u", cp->nstart); 1115 gprintln(" nend: %u", cp->nend); 1116 } else { 1117 gprintf("consumer: %p (%s), access=r%dw%de%d", cp, 1118 cp->provider != NULL ? cp->provider->name : "none", 1119 cp->acr, cp->acw, cp->ace); 1120 if (cp->spoiled) 1121 db_printf(", spoiled=%d", cp->spoiled); 1122 db_printf("\n"); 1123 } 1124} 1125 1126static void 1127db_show_geom_provider(int indent, struct g_provider *pp) 1128{ 1129 struct g_consumer *cp; 1130 char flags[64]; 1131 1132 if (indent == 0) { 1133 gprintln("provider: %s (%p)", pp->name, pp); 1134 gprintln(" class: %s (%p)", pp->geom->class->name, 1135 pp->geom->class); 1136 gprintln(" geom: %s (%p)", pp->geom->name, pp->geom); 1137 gprintln(" mediasize: %jd", (intmax_t)pp->mediasize); 1138 gprintln(" sectorsize: %u", pp->sectorsize); 1139 gprintln(" stripesize: %u", pp->stripesize); 1140 gprintln(" stripeoffset: %u", pp->stripeoffset); 1141 gprintln(" access: r%dw%de%d", pp->acr, pp->acw, 1142 pp->ace); 1143 gprintln(" flags: %s (0x%04x)", 1144 provider_flags_to_string(pp, flags, sizeof(flags)), 1145 pp->flags); 1146 gprintln(" error: %d", pp->error); 1147 gprintln(" nstart: %u", pp->nstart); 1148 gprintln(" nend: %u", pp->nend); 1149 if (LIST_EMPTY(&pp->consumers)) 1150 gprintln(" consumers: none"); 1151 } else { 1152 gprintf("provider: %s (%p), access=r%dw%de%d", 1153 pp->name, pp, pp->acr, pp->acw, pp->ace); 1154 if (pp->flags != 0) { 1155 db_printf(", flags=%s (0x%04x)", 1156 provider_flags_to_string(pp, flags, sizeof(flags)), 1157 pp->flags); 1158 } 1159 db_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 db_printf(", flags=%s (0x%04x)", 1191 geom_flags_to_string(gp, flags, sizeof(flags)), 1192 gp->flags); 1193 } 1194 db_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 db_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 db_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 db_printf("Not a GEOM object.\n"); 1256 break; 1257 } 1258 } 1259} 1260 1261static void 1262db_print_bio_cmd(struct bio *bp) 1263{ 1264 db_printf(" cmd: "); 1265 switch (bp->bio_cmd) { 1266 case BIO_READ: db_printf("BIO_READ"); break; 1267 case BIO_WRITE: db_printf("BIO_WRITE"); break; 1268 case BIO_DELETE: db_printf("BIO_DELETE"); break; 1269 case BIO_GETATTR: db_printf("BIO_GETATTR"); break; 1270 case BIO_FLUSH: db_printf("BIO_FLUSH"); break; 1271 case BIO_CMD0: db_printf("BIO_CMD0"); break; 1272 case BIO_CMD1: db_printf("BIO_CMD1"); break; 1273 case BIO_CMD2: db_printf("BIO_CMD2"); break; 1274 default: db_printf("UNKNOWN"); break; 1275 } 1276 db_printf("\n"); 1277} 1278 1279static void 1280db_print_bio_flags(struct bio *bp) 1281{ 1282 int comma; 1283 1284 comma = 0; 1285 db_printf(" flags: "); 1286 if (bp->bio_flags & BIO_ERROR) { 1287 db_printf("BIO_ERROR"); 1288 comma = 1; 1289 } 1290 if (bp->bio_flags & BIO_DONE) { 1291 db_printf("%sBIO_DONE", (comma ? ", " : "")); 1292 comma = 1; 1293 } 1294 if (bp->bio_flags & BIO_ONQUEUE) 1295 db_printf("%sBIO_ONQUEUE", (comma ? ", " : "")); 1296 db_printf("\n"); 1297} 1298 1299/* 1300 * Print useful information in a BIO 1301 */ 1302DB_SHOW_COMMAND(bio, db_show_bio) 1303{ 1304 struct bio *bp; 1305 1306 if (have_addr) { 1307 bp = (struct bio *)addr; 1308 db_printf("BIO %p\n", bp); 1309 db_print_bio_cmd(bp); 1310 db_print_bio_flags(bp); 1311 db_printf(" cflags: 0x%hhx\n", bp->bio_cflags); 1312 db_printf(" pflags: 0x%hhx\n", bp->bio_pflags); 1313 db_printf(" offset: %lld\n", bp->bio_offset); 1314 db_printf(" length: %lld\n", bp->bio_length); 1315 db_printf(" bcount: %ld\n", bp->bio_bcount); 1316 db_printf(" resid: %ld\n", bp->bio_resid); 1317 db_printf(" completed: %lld\n", bp->bio_completed); 1318 db_printf(" children: %u\n", bp->bio_children); 1319 db_printf(" inbed: %u\n", bp->bio_inbed); 1320 db_printf(" error: %d\n", bp->bio_error); 1321 db_printf(" parent: %p\n", bp->bio_parent); 1322 db_printf(" driver1: %p\n", bp->bio_driver1); 1323 db_printf(" driver2: %p\n", bp->bio_driver2); 1324 db_printf(" caller1: %p\n", bp->bio_caller1); 1325 db_printf(" caller2: %p\n", bp->bio_caller2); 1326 db_printf(" bio_from: %p\n", bp->bio_from); 1327 db_printf(" bio_to: %p\n", bp->bio_to); 1328 } 1329} 1330 1331#undef gprintf 1332#undef gprintln 1333#undef ADDFLAG 1334 1335#endif /* DDB */ 1336