192108Sphk/*- 292108Sphk * Copyright (c) 2002 Poul-Henning Kamp 392108Sphk * Copyright (c) 2002 Networks Associates Technology, Inc. 492108Sphk * All rights reserved. 592108Sphk * 692108Sphk * This software was developed for the FreeBSD Project by Poul-Henning Kamp 792108Sphk * and NAI Labs, the Security Research Division of Network Associates, Inc. 892108Sphk * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 992108Sphk * DARPA CHATS research program. 1092108Sphk * 1192108Sphk * Redistribution and use in source and binary forms, with or without 1292108Sphk * modification, are permitted provided that the following conditions 1392108Sphk * are met: 1492108Sphk * 1. Redistributions of source code must retain the above copyright 1592108Sphk * notice, this list of conditions and the following disclaimer. 1692108Sphk * 2. Redistributions in binary form must reproduce the above copyright 1792108Sphk * notice, this list of conditions and the following disclaimer in the 1892108Sphk * documentation and/or other materials provided with the distribution. 1992108Sphk * 3. The names of the authors may not be used to endorse or promote 2092108Sphk * products derived from this software without specific prior written 2192108Sphk * permission. 2292108Sphk * 2392108Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2492108Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2592108Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2692108Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2792108Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2892108Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2992108Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3092108Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3192108Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3292108Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3392108Sphk * SUCH DAMAGE. 3492108Sphk */ 3592108Sphk 36116196Sobrien#include <sys/cdefs.h> 37116196Sobrien__FBSDID("$FreeBSD: stable/10/sys/geom/geom_subr.c 332096 2018-04-06 12:23:59Z avg $"); 3892108Sphk 39162326Spjd#include "opt_ddb.h" 40162326Spjd 4192108Sphk#include <sys/param.h> 4292108Sphk#include <sys/systm.h> 43112370Sphk#include <sys/devicestat.h> 4492108Sphk#include <sys/kernel.h> 4592108Sphk#include <sys/malloc.h> 4692108Sphk#include <sys/bio.h> 4792108Sphk#include <sys/sysctl.h> 4892108Sphk#include <sys/proc.h> 4992108Sphk#include <sys/kthread.h> 5092108Sphk#include <sys/lock.h> 5192108Sphk#include <sys/mutex.h> 5292108Sphk#include <sys/errno.h> 5392108Sphk#include <sys/sbuf.h> 5492108Sphk#include <geom/geom.h> 5593250Sphk#include <geom/geom_int.h> 5692108Sphk#include <machine/stdarg.h> 5792108Sphk 58162326Spjd#ifdef DDB 59162326Spjd#include <ddb/ddb.h> 60162326Spjd#endif 61162326Spjd 62206859Sjh#ifdef KDB 63206859Sjh#include <sys/kdb.h> 64206859Sjh#endif 65206859Sjh 6693774Sphkstruct class_list_head g_classes = LIST_HEAD_INITIALIZER(g_classes); 6792108Sphkstatic struct g_tailq_head geoms = TAILQ_HEAD_INITIALIZER(geoms); 6892108Sphkchar *g_wait_event, *g_wait_up, *g_wait_down, *g_wait_sim; 6992108Sphk 70115473Sphkstruct g_hh00 { 71238213Strasz struct g_class *mp; 72238213Strasz struct g_provider *pp; 73238213Strasz off_t size; 74238213Strasz int error; 75238213Strasz int post; 76115473Sphk}; 77113927Sphk 78113927Sphk/* 79113927Sphk * This event offers a new class a chance to taste all preexisting providers. 80113927Sphk */ 81113927Sphkstatic void 82115473Sphkg_load_class(void *arg, int flag) 83113927Sphk{ 84115473Sphk struct g_hh00 *hh; 85113927Sphk struct g_class *mp2, *mp; 86113927Sphk struct g_geom *gp; 87113927Sphk struct g_provider *pp; 88113927Sphk 89113927Sphk g_topology_assert(); 90115473Sphk if (flag == EV_CANCEL) /* XXX: can't happen ? */ 91113927Sphk return; 92113927Sphk if (g_shutdown) 93113927Sphk return; 94115473Sphk 95115473Sphk hh = arg; 96115473Sphk mp = hh->mp; 97144157Sphk hh->error = 0; 98144157Sphk if (hh->post) { 99136797Sarr g_free(hh); 100144157Sphk hh = NULL; 101144157Sphk } 102115473Sphk g_trace(G_T_TOPOLOGY, "g_load_class(%s)", mp->name); 103124883Sphk KASSERT(mp->name != NULL && *mp->name != '\0', 104124883Sphk ("GEOM class has no name")); 105115845Sphk LIST_FOREACH(mp2, &g_classes, class) { 106136797Sarr if (mp2 == mp) { 107136797Sarr printf("The GEOM class %s is already loaded.\n", 108136797Sarr mp2->name); 109144157Sphk if (hh != NULL) 110144157Sphk hh->error = EEXIST; 111136797Sarr return; 112136797Sarr } else if (strcmp(mp2->name, mp->name) == 0) { 113136797Sarr printf("A GEOM class %s is already loaded.\n", 114136797Sarr mp2->name); 115144157Sphk if (hh != NULL) 116144157Sphk hh->error = EEXIST; 117136797Sarr return; 118136797Sarr } 119115845Sphk } 120115473Sphk 121122888Sphk LIST_INIT(&mp->geom); 122122888Sphk LIST_INSERT_HEAD(&g_classes, mp, class); 123115473Sphk if (mp->init != NULL) 124115473Sphk mp->init(mp); 125115473Sphk if (mp->taste == NULL) 126113927Sphk return; 127115473Sphk LIST_FOREACH(mp2, &g_classes, class) { 128115473Sphk if (mp == mp2) 129113927Sphk continue; 130115473Sphk LIST_FOREACH(gp, &mp2->geom, geom) { 131113927Sphk LIST_FOREACH(pp, &gp->provider, provider) { 132115473Sphk mp->taste(mp, pp, 0); 133113927Sphk g_topology_assert(); 134113927Sphk } 135113927Sphk } 136113927Sphk } 137113927Sphk} 138113927Sphk 139207671Sjhstatic int 140207671Sjhg_unload_class(struct g_class *mp) 14192108Sphk{ 142115473Sphk struct g_geom *gp; 143115473Sphk struct g_provider *pp; 144115473Sphk struct g_consumer *cp; 145115473Sphk int error; 14692108Sphk 147207671Sjh g_topology_lock(); 148207671Sjh g_trace(G_T_TOPOLOGY, "g_unload_class(%s)", mp->name); 149207671Sjhretry: 150126798Sphk G_VALID_CLASS(mp); 151115473Sphk LIST_FOREACH(gp, &mp->geom, geom) { 152207671Sjh /* We refuse to unload if anything is open */ 153115473Sphk LIST_FOREACH(pp, &gp->provider, provider) 154115473Sphk if (pp->acr || pp->acw || pp->ace) { 155207671Sjh g_topology_unlock(); 156207671Sjh return (EBUSY); 157115473Sphk } 158115473Sphk LIST_FOREACH(cp, &gp->consumer, consumer) 159115473Sphk if (cp->acr || cp->acw || cp->ace) { 160207671Sjh g_topology_unlock(); 161207671Sjh return (EBUSY); 162115473Sphk } 163207671Sjh /* If the geom is withering, wait for it to finish. */ 164207671Sjh if (gp->flags & G_GEOM_WITHER) { 165207671Sjh g_topology_sleep(mp, 1); 166207671Sjh goto retry; 167207671Sjh } 168115473Sphk } 169115473Sphk 170207671Sjh /* 171207671Sjh * We allow unloading if we have no geoms, or a class 172207671Sjh * method we can use to get rid of them. 173207671Sjh */ 174207671Sjh if (!LIST_EMPTY(&mp->geom) && mp->destroy_geom == NULL) { 175207671Sjh g_topology_unlock(); 176207671Sjh return (EOPNOTSUPP); 177207671Sjh } 178207671Sjh 179115473Sphk /* Bar new entries */ 180115473Sphk mp->taste = NULL; 181115473Sphk mp->config = NULL; 182115473Sphk 183207671Sjh LIST_FOREACH(gp, &mp->geom, geom) { 184207671Sjh error = mp->destroy_geom(NULL, mp, gp); 185207671Sjh if (error != 0) { 186207671Sjh g_topology_unlock(); 187207671Sjh return (error); 188207671Sjh } 189207671Sjh } 190207671Sjh /* Wait for withering to finish. */ 191126832Sphk for (;;) { 192126832Sphk gp = LIST_FIRST(&mp->geom); 193126832Sphk if (gp == NULL) 194126832Sphk break; 195207671Sjh KASSERT(gp->flags & G_GEOM_WITHER, 196207671Sjh ("Non-withering geom in class %s", mp->name)); 197207671Sjh g_topology_sleep(mp, 1); 198115473Sphk } 199207671Sjh G_VALID_CLASS(mp); 200207671Sjh if (mp->fini != NULL) 201207671Sjh mp->fini(mp); 202207671Sjh LIST_REMOVE(mp, class); 203207671Sjh g_topology_unlock(); 204207671Sjh 205207671Sjh return (0); 206115473Sphk} 207115473Sphk 208115473Sphkint 209115473Sphkg_modevent(module_t mod, int type, void *data) 210115473Sphk{ 211115473Sphk struct g_hh00 *hh; 212115473Sphk int error; 213115473Sphk static int g_ignition; 214133312Sphk struct g_class *mp; 215115473Sphk 216133312Sphk mp = data; 217133319Sphk if (mp->version != G_VERSION) { 218133312Sphk printf("GEOM class %s has Wrong version %x\n", 219133312Sphk mp->name, mp->version); 220133312Sphk return (EINVAL); 221133312Sphk } 22292108Sphk if (!g_ignition) { 22392108Sphk g_ignition++; 22492108Sphk g_init(); 22592108Sphk } 226115473Sphk error = EOPNOTSUPP; 227115473Sphk switch (type) { 228115473Sphk case MOD_LOAD: 229207671Sjh g_trace(G_T_TOPOLOGY, "g_modevent(%s, LOAD)", mp->name); 230207671Sjh hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO); 231207671Sjh hh->mp = mp; 232136414Sgreen /* 233136414Sgreen * Once the system is not cold, MOD_LOAD calls will be 234136414Sgreen * from the userland and the g_event thread will be able 235136414Sgreen * to acknowledge their completion. 236136414Sgreen */ 237136797Sarr if (cold) { 238136797Sarr hh->post = 1; 239136797Sarr error = g_post_event(g_load_class, hh, M_WAITOK, NULL); 240136797Sarr } else { 241136797Sarr error = g_waitfor_event(g_load_class, hh, M_WAITOK, 242136797Sarr NULL); 243136797Sarr if (error == 0) 244136797Sarr error = hh->error; 245136797Sarr g_free(hh); 246136797Sarr } 247115473Sphk break; 248115473Sphk case MOD_UNLOAD: 249207671Sjh g_trace(G_T_TOPOLOGY, "g_modevent(%s, UNLOAD)", mp->name); 250207671Sjh DROP_GIANT(); 251207671Sjh error = g_unload_class(mp); 252207671Sjh PICKUP_GIANT(); 253119298Sphk if (error == 0) { 254207671Sjh KASSERT(LIST_EMPTY(&mp->geom), 255207671Sjh ("Unloaded class (%s) still has geom", mp->name)); 256119298Sphk } 257115473Sphk break; 258115473Sphk } 259115473Sphk return (error); 26092108Sphk} 26192108Sphk 262177509Smarcelstatic void 263177509Smarcelg_retaste_event(void *arg, int flag) 264177509Smarcel{ 265238886Smav struct g_class *mp, *mp2; 266238886Smav struct g_geom *gp; 267177509Smarcel struct g_hh00 *hh; 268177509Smarcel struct g_provider *pp; 269238886Smav struct g_consumer *cp; 270177509Smarcel 271177509Smarcel g_topology_assert(); 272177509Smarcel if (flag == EV_CANCEL) /* XXX: can't happen ? */ 273177509Smarcel return; 274255860Sdes if (g_shutdown || g_notaste) 275177509Smarcel return; 276177509Smarcel 277177509Smarcel hh = arg; 278177509Smarcel mp = hh->mp; 279177509Smarcel hh->error = 0; 280177509Smarcel if (hh->post) { 281177509Smarcel g_free(hh); 282177509Smarcel hh = NULL; 283177509Smarcel } 284177509Smarcel g_trace(G_T_TOPOLOGY, "g_retaste(%s)", mp->name); 285177509Smarcel 286238886Smav LIST_FOREACH(mp2, &g_classes, class) { 287238886Smav LIST_FOREACH(gp, &mp2->geom, geom) { 288177509Smarcel LIST_FOREACH(pp, &gp->provider, provider) { 289177509Smarcel if (pp->acr || pp->acw || pp->ace) 290177509Smarcel continue; 291238886Smav LIST_FOREACH(cp, &pp->consumers, consumers) { 292238886Smav if (cp->geom->class == mp && 293238886Smav (cp->flags & G_CF_ORPHAN) == 0) 294177681Smarcel break; 295177681Smarcel } 296238886Smav if (cp != NULL) { 297238886Smav cp->flags |= G_CF_ORPHAN; 298238886Smav g_wither_geom(cp->geom, ENXIO); 299238886Smav } 300177509Smarcel mp->taste(mp, pp, 0); 301177509Smarcel g_topology_assert(); 302177509Smarcel } 303177509Smarcel } 304177509Smarcel } 305177509Smarcel} 306177509Smarcel 307177509Smarcelint 308177509Smarcelg_retaste(struct g_class *mp) 309177509Smarcel{ 310177509Smarcel struct g_hh00 *hh; 311177509Smarcel int error; 312177509Smarcel 313177509Smarcel if (mp->taste == NULL) 314177509Smarcel return (EINVAL); 315177509Smarcel 316177509Smarcel hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO); 317177509Smarcel hh->mp = mp; 318177509Smarcel 319177509Smarcel if (cold) { 320177509Smarcel hh->post = 1; 321177509Smarcel error = g_post_event(g_retaste_event, hh, M_WAITOK, NULL); 322177509Smarcel } else { 323177509Smarcel error = g_waitfor_event(g_retaste_event, hh, M_WAITOK, NULL); 324177509Smarcel if (error == 0) 325177509Smarcel error = hh->error; 326177509Smarcel g_free(hh); 327177509Smarcel } 328177509Smarcel 329177509Smarcel return (error); 330177509Smarcel} 331177509Smarcel 33292108Sphkstruct g_geom * 333107953Sphkg_new_geomf(struct g_class *mp, const char *fmt, ...) 33492108Sphk{ 33592108Sphk struct g_geom *gp; 33692108Sphk va_list ap; 33792108Sphk struct sbuf *sb; 33892108Sphk 33992108Sphk g_topology_assert(); 340126798Sphk G_VALID_CLASS(mp); 341181463Sdes sb = sbuf_new_auto(); 34292108Sphk va_start(ap, fmt); 34392108Sphk sbuf_vprintf(sb, fmt, ap); 344115949Sphk va_end(ap); 34592108Sphk sbuf_finish(sb); 346111119Simp gp = g_malloc(sizeof *gp, M_WAITOK | M_ZERO); 347111119Simp gp->name = g_malloc(sbuf_len(sb) + 1, M_WAITOK | M_ZERO); 34893248Sphk gp->class = mp; 34992108Sphk gp->rank = 1; 35092108Sphk LIST_INIT(&gp->consumer); 35192108Sphk LIST_INIT(&gp->provider); 35292108Sphk LIST_INSERT_HEAD(&mp->geom, gp, geom); 35392108Sphk TAILQ_INSERT_HEAD(&geoms, gp, geoms); 35492108Sphk strcpy(gp->name, sbuf_data(sb)); 35592108Sphk sbuf_delete(sb); 356133312Sphk /* Fill in defaults from class */ 357133312Sphk gp->start = mp->start; 358133312Sphk gp->spoiled = mp->spoiled; 359223089Sgibbs gp->attrchanged = mp->attrchanged; 360237518Sken gp->providergone = mp->providergone; 361133312Sphk gp->dumpconf = mp->dumpconf; 362133312Sphk gp->access = mp->access; 363133312Sphk gp->orphan = mp->orphan; 364133312Sphk gp->ioctl = mp->ioctl; 365238213Strasz gp->resize = mp->resize; 36692108Sphk return (gp); 36792108Sphk} 36892108Sphk 36992108Sphkvoid 37092108Sphkg_destroy_geom(struct g_geom *gp) 37192108Sphk{ 37292108Sphk 373126798Sphk g_topology_assert(); 374126798Sphk G_VALID_GEOM(gp); 37592108Sphk g_trace(G_T_TOPOLOGY, "g_destroy_geom(%p(%s))", gp, gp->name); 37692108Sphk KASSERT(LIST_EMPTY(&gp->consumer), 37792108Sphk ("g_destroy_geom(%s) with consumer(s) [%p]", 37892108Sphk gp->name, LIST_FIRST(&gp->consumer))); 37992108Sphk KASSERT(LIST_EMPTY(&gp->provider), 38092108Sphk ("g_destroy_geom(%s) with provider(s) [%p]", 381124371Sphk gp->name, LIST_FIRST(&gp->provider))); 382112988Sphk g_cancel_event(gp); 38392108Sphk LIST_REMOVE(gp, geom); 38492108Sphk TAILQ_REMOVE(&geoms, gp, geoms); 38595310Sphk g_free(gp->name); 38692108Sphk g_free(gp); 38792108Sphk} 38892108Sphk 389114495Sphk/* 390185768Slulf * This function is called (repeatedly) until the geom has withered away. 391114495Sphk */ 392114495Sphkvoid 393114495Sphkg_wither_geom(struct g_geom *gp, int error) 394114495Sphk{ 395131820Sphk struct g_provider *pp; 396114495Sphk 397126798Sphk g_topology_assert(); 398126798Sphk G_VALID_GEOM(gp); 399114495Sphk g_trace(G_T_TOPOLOGY, "g_wither_geom(%p(%s))", gp, gp->name); 400114495Sphk if (!(gp->flags & G_GEOM_WITHER)) { 401114495Sphk gp->flags |= G_GEOM_WITHER; 402114495Sphk LIST_FOREACH(pp, &gp->provider, provider) 403126726Sphk if (!(pp->flags & G_PF_ORPHAN)) 404126726Sphk g_orphan_provider(pp, error); 405114495Sphk } 406131820Sphk g_do_wither(); 407131820Sphk} 408131820Sphk 409131820Sphk/* 410157619Smarcel * Convenience function to destroy a particular provider. 411157619Smarcel */ 412157619Smarcelvoid 413157619Smarcelg_wither_provider(struct g_provider *pp, int error) 414157619Smarcel{ 415157619Smarcel 416157619Smarcel pp->flags |= G_PF_WITHER; 417157619Smarcel if (!(pp->flags & G_PF_ORPHAN)) 418157619Smarcel g_orphan_provider(pp, error); 419157619Smarcel} 420157619Smarcel 421157619Smarcel/* 422137032Sphk * This function is called (repeatedly) until the has withered away. 423137032Sphk */ 424137032Sphkvoid 425137032Sphkg_wither_geom_close(struct g_geom *gp, int error) 426137032Sphk{ 427137032Sphk struct g_consumer *cp; 428137032Sphk 429137032Sphk g_topology_assert(); 430137032Sphk G_VALID_GEOM(gp); 431137032Sphk g_trace(G_T_TOPOLOGY, "g_wither_geom_close(%p(%s))", gp, gp->name); 432137032Sphk LIST_FOREACH(cp, &gp->consumer, consumer) 433137032Sphk if (cp->acr || cp->acw || cp->ace) 434137032Sphk g_access(cp, -cp->acr, -cp->acw, -cp->ace); 435137032Sphk g_wither_geom(gp, error); 436137032Sphk} 437137032Sphk 438137032Sphk/* 439131820Sphk * This function is called (repeatedly) until we cant wash away more 440248674Smav * withered bits at present. 441131820Sphk */ 442248674Smavvoid 443131820Sphkg_wither_washer() 444131820Sphk{ 445131820Sphk struct g_class *mp; 446131820Sphk struct g_geom *gp, *gp2; 447131820Sphk struct g_provider *pp, *pp2; 448131820Sphk struct g_consumer *cp, *cp2; 449131820Sphk 450131820Sphk g_topology_assert(); 451131820Sphk LIST_FOREACH(mp, &g_classes, class) { 452131820Sphk LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) { 453131820Sphk LIST_FOREACH_SAFE(pp, &gp->provider, provider, pp2) { 454131820Sphk if (!(pp->flags & G_PF_WITHER)) 455131820Sphk continue; 456131820Sphk if (LIST_EMPTY(&pp->consumers)) 457131820Sphk g_destroy_provider(pp); 458131820Sphk } 459131820Sphk if (!(gp->flags & G_GEOM_WITHER)) 460131820Sphk continue; 461131820Sphk LIST_FOREACH_SAFE(pp, &gp->provider, provider, pp2) { 462131820Sphk if (LIST_EMPTY(&pp->consumers)) 463131820Sphk g_destroy_provider(pp); 464131820Sphk } 465131820Sphk LIST_FOREACH_SAFE(cp, &gp->consumer, consumer, cp2) { 466248674Smav if (cp->acr || cp->acw || cp->ace) 467131820Sphk continue; 468131877Sphk if (cp->provider != NULL) 469131877Sphk g_detach(cp); 470131820Sphk g_destroy_consumer(cp); 471131820Sphk } 472131820Sphk if (LIST_EMPTY(&gp->provider) && 473131820Sphk LIST_EMPTY(&gp->consumer)) 474131820Sphk g_destroy_geom(gp); 475131820Sphk } 476114495Sphk } 477114495Sphk} 478114495Sphk 47992108Sphkstruct g_consumer * 48092108Sphkg_new_consumer(struct g_geom *gp) 48192108Sphk{ 48292108Sphk struct g_consumer *cp; 48392108Sphk 48492108Sphk g_topology_assert(); 485126798Sphk G_VALID_GEOM(gp); 486124883Sphk KASSERT(!(gp->flags & G_GEOM_WITHER), 487124883Sphk ("g_new_consumer on WITHERing geom(%s) (class %s)", 488124883Sphk gp->name, gp->class->name)); 48993776Sphk KASSERT(gp->orphan != NULL, 49093776Sphk ("g_new_consumer on geom(%s) (class %s) without orphan", 49193776Sphk gp->name, gp->class->name)); 49292108Sphk 493111119Simp cp = g_malloc(sizeof *cp, M_WAITOK | M_ZERO); 49492108Sphk cp->geom = gp; 495112370Sphk cp->stat = devstat_new_entry(cp, -1, 0, DEVSTAT_ALL_SUPPORTED, 496112370Sphk DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX); 49792108Sphk LIST_INSERT_HEAD(&gp->consumer, cp, consumer); 49892108Sphk return(cp); 49992108Sphk} 50092108Sphk 50192108Sphkvoid 50292108Sphkg_destroy_consumer(struct g_consumer *cp) 50392108Sphk{ 504114495Sphk struct g_geom *gp; 50592108Sphk 506126798Sphk g_topology_assert(); 507126798Sphk G_VALID_CONSUMER(cp); 50892108Sphk g_trace(G_T_TOPOLOGY, "g_destroy_consumer(%p)", cp); 50992108Sphk KASSERT (cp->provider == NULL, ("g_destroy_consumer but attached")); 51092108Sphk KASSERT (cp->acr == 0, ("g_destroy_consumer with acr")); 51192108Sphk KASSERT (cp->acw == 0, ("g_destroy_consumer with acw")); 51292108Sphk KASSERT (cp->ace == 0, ("g_destroy_consumer with ace")); 513112988Sphk g_cancel_event(cp); 514114495Sphk gp = cp->geom; 51592108Sphk LIST_REMOVE(cp, consumer); 516112370Sphk devstat_remove_entry(cp->stat); 51792108Sphk g_free(cp); 518114495Sphk if (gp->flags & G_GEOM_WITHER) 519131820Sphk g_do_wither(); 52092108Sphk} 52192108Sphk 522113930Sphkstatic void 523113930Sphkg_new_provider_event(void *arg, int flag) 524113930Sphk{ 525113930Sphk struct g_class *mp; 526113930Sphk struct g_provider *pp; 527238886Smav struct g_consumer *cp, *next_cp; 528113930Sphk 529113930Sphk g_topology_assert(); 530113930Sphk if (flag == EV_CANCEL) 531113930Sphk return; 532113930Sphk if (g_shutdown) 533113930Sphk return; 534113930Sphk pp = arg; 535126798Sphk G_VALID_PROVIDER(pp); 536179097Spjd KASSERT(!(pp->flags & G_PF_WITHER), 537179097Spjd ("g_new_provider_event but withered")); 538238886Smav LIST_FOREACH_SAFE(cp, &pp->consumers, consumers, next_cp) { 539238886Smav if ((cp->flags & G_CF_ORPHAN) == 0 && 540238886Smav cp->geom->attrchanged != NULL) 541238886Smav cp->geom->attrchanged(cp, "GEOM::media"); 542238886Smav } 543255860Sdes if (g_notaste) 544255860Sdes return; 545113930Sphk LIST_FOREACH(mp, &g_classes, class) { 546113930Sphk if (mp->taste == NULL) 547113930Sphk continue; 548113930Sphk LIST_FOREACH(cp, &pp->consumers, consumers) 549238886Smav if (cp->geom->class == mp && 550238886Smav (cp->flags & G_CF_ORPHAN) == 0) 551193547Spjd break; 552193547Spjd if (cp != NULL) 553113930Sphk continue; 554114511Sphk mp->taste(mp, pp, 0); 555113930Sphk g_topology_assert(); 556113930Sphk } 557113930Sphk} 558113930Sphk 559113930Sphk 56092108Sphkstruct g_provider * 561107953Sphkg_new_providerf(struct g_geom *gp, const char *fmt, ...) 56292108Sphk{ 56392108Sphk struct g_provider *pp; 56492108Sphk struct sbuf *sb; 56592108Sphk va_list ap; 56692108Sphk 56792108Sphk g_topology_assert(); 568126798Sphk G_VALID_GEOM(gp); 569126832Sphk KASSERT(gp->access != NULL, 570126832Sphk ("new provider on geom(%s) without ->access (class %s)", 571126832Sphk gp->name, gp->class->name)); 572124883Sphk KASSERT(gp->start != NULL, 573125332Spjd ("new provider on geom(%s) without ->start (class %s)", 574125332Spjd gp->name, gp->class->name)); 575124883Sphk KASSERT(!(gp->flags & G_GEOM_WITHER), 576125332Spjd ("new provider on WITHERing geom(%s) (class %s)", 577125332Spjd gp->name, gp->class->name)); 578181463Sdes sb = sbuf_new_auto(); 57992108Sphk va_start(ap, fmt); 58092108Sphk sbuf_vprintf(sb, fmt, ap); 581115949Sphk va_end(ap); 58292108Sphk sbuf_finish(sb); 583111119Simp pp = g_malloc(sizeof *pp + sbuf_len(sb) + 1, M_WAITOK | M_ZERO); 58492108Sphk pp->name = (char *)(pp + 1); 58592108Sphk strcpy(pp->name, sbuf_data(sb)); 58692108Sphk sbuf_delete(sb); 58792108Sphk LIST_INIT(&pp->consumers); 58892108Sphk pp->error = ENXIO; 58992108Sphk pp->geom = gp; 590112370Sphk pp->stat = devstat_new_entry(pp, -1, 0, DEVSTAT_ALL_SUPPORTED, 591112370Sphk DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX); 59292108Sphk LIST_INSERT_HEAD(&gp->provider, pp, provider); 593126832Sphk g_post_event(g_new_provider_event, pp, M_WAITOK, pp, gp, NULL); 59492108Sphk return (pp); 59592108Sphk} 59692108Sphk 59792108Sphkvoid 59892108Sphkg_error_provider(struct g_provider *pp, int error) 59992108Sphk{ 60092108Sphk 601126798Sphk /* G_VALID_PROVIDER(pp); We may not have g_topology */ 60292108Sphk pp->error = error; 60392108Sphk} 60492108Sphk 605238213Straszstatic void 606238213Straszg_resize_provider_event(void *arg, int flag) 607238213Strasz{ 608238213Strasz struct g_hh00 *hh; 609238213Strasz struct g_class *mp; 610238213Strasz struct g_geom *gp; 611238213Strasz struct g_provider *pp; 612238213Strasz struct g_consumer *cp, *cp2; 613238213Strasz off_t size; 614238213Strasz 615238213Strasz g_topology_assert(); 616238213Strasz if (g_shutdown) 617238213Strasz return; 618238213Strasz 619238213Strasz hh = arg; 620238213Strasz pp = hh->pp; 621238213Strasz size = hh->size; 622238565Strasz g_free(hh); 623238213Strasz 624238213Strasz G_VALID_PROVIDER(pp); 625238213Strasz g_trace(G_T_TOPOLOGY, "g_resize_provider_event(%p)", pp); 626238213Strasz 627238213Strasz LIST_FOREACH_SAFE(cp, &pp->consumers, consumers, cp2) { 628238213Strasz gp = cp->geom; 629238886Smav if (gp->resize == NULL && size < pp->mediasize) { 630238886Smav cp->flags |= G_CF_ORPHAN; 631238213Strasz cp->geom->orphan(cp); 632238886Smav } 633238213Strasz } 634238213Strasz 635238213Strasz pp->mediasize = size; 636238213Strasz 637238213Strasz LIST_FOREACH_SAFE(cp, &pp->consumers, consumers, cp2) { 638238213Strasz gp = cp->geom; 639238213Strasz if (gp->resize != NULL) 640238213Strasz gp->resize(cp); 641238213Strasz } 642238213Strasz 643238213Strasz /* 644238213Strasz * After resizing, the previously invalid GEOM class metadata 645238213Strasz * might become valid. This means we should retaste. 646238213Strasz */ 647238213Strasz LIST_FOREACH(mp, &g_classes, class) { 648238213Strasz if (mp->taste == NULL) 649238213Strasz continue; 650238213Strasz LIST_FOREACH(cp, &pp->consumers, consumers) 651238886Smav if (cp->geom->class == mp && 652238886Smav (cp->flags & G_CF_ORPHAN) == 0) 653238213Strasz break; 654238213Strasz if (cp != NULL) 655238213Strasz continue; 656238213Strasz mp->taste(mp, pp, 0); 657238213Strasz g_topology_assert(); 658238213Strasz } 659238213Strasz} 660238213Strasz 661238213Straszvoid 662238213Straszg_resize_provider(struct g_provider *pp, off_t size) 663238213Strasz{ 664238213Strasz struct g_hh00 *hh; 665238213Strasz 666238213Strasz G_VALID_PROVIDER(pp); 667238213Strasz 668238213Strasz if (size == pp->mediasize) 669238213Strasz return; 670238213Strasz 671238213Strasz hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO); 672238213Strasz hh->pp = pp; 673238213Strasz hh->size = size; 674238213Strasz g_post_event(g_resize_provider_event, hh, M_WAITOK, NULL); 675238213Strasz} 676238213Strasz 677239987Spjd#ifndef _PATH_DEV 678239987Spjd#define _PATH_DEV "/dev/" 679239987Spjd#endif 680239987Spjd 681115850Sphkstruct g_provider * 682115850Sphkg_provider_by_name(char const *arg) 683115850Sphk{ 684115850Sphk struct g_class *cp; 685115850Sphk struct g_geom *gp; 686281298Smav struct g_provider *pp, *wpp; 68792108Sphk 688239987Spjd if (strncmp(arg, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) 689239987Spjd arg += sizeof(_PATH_DEV) - 1; 690239987Spjd 691281298Smav wpp = NULL; 692115850Sphk LIST_FOREACH(cp, &g_classes, class) { 693115850Sphk LIST_FOREACH(gp, &cp->geom, geom) { 694115850Sphk LIST_FOREACH(pp, &gp->provider, provider) { 695281298Smav if (strcmp(arg, pp->name) != 0) 696281298Smav continue; 697281298Smav if ((gp->flags & G_GEOM_WITHER) == 0 && 698281298Smav (pp->flags & G_PF_WITHER) == 0) 699115850Sphk return (pp); 700281298Smav else 701281298Smav wpp = pp; 702115850Sphk } 703115850Sphk } 704115850Sphk } 705239987Spjd 706281298Smav return (wpp); 707115850Sphk} 708115850Sphk 70992108Sphkvoid 71092108Sphkg_destroy_provider(struct g_provider *pp) 71192108Sphk{ 71292108Sphk struct g_geom *gp; 71392108Sphk 71492108Sphk g_topology_assert(); 715126798Sphk G_VALID_PROVIDER(pp); 71692108Sphk KASSERT(LIST_EMPTY(&pp->consumers), 71792108Sphk ("g_destroy_provider but attached")); 71892108Sphk KASSERT (pp->acr == 0, ("g_destroy_provider with acr")); 71992108Sphk KASSERT (pp->acw == 0, ("g_destroy_provider with acw")); 720179097Spjd KASSERT (pp->ace == 0, ("g_destroy_provider with ace")); 721112988Sphk g_cancel_event(pp); 72292108Sphk LIST_REMOVE(pp, provider); 72392108Sphk gp = pp->geom; 724112370Sphk devstat_remove_entry(pp->stat); 725237518Sken /* 726237518Sken * If a callback was provided, send notification that the provider 727237518Sken * is now gone. 728237518Sken */ 729237518Sken if (gp->providergone != NULL) 730237518Sken gp->providergone(pp); 731237518Sken 73292108Sphk g_free(pp); 733114495Sphk if ((gp->flags & G_GEOM_WITHER)) 734131820Sphk g_do_wither(); 73592108Sphk} 73692108Sphk 73792108Sphk/* 73892108Sphk * We keep the "geoms" list sorted by topological order (== increasing 73992108Sphk * numerical rank) at all times. 74092108Sphk * When an attach is done, the attaching geoms rank is invalidated 74192108Sphk * and it is moved to the tail of the list. 74292108Sphk * All geoms later in the sequence has their ranks reevaluated in 74392108Sphk * sequence. If we cannot assign rank to a geom because it's 74492108Sphk * prerequisites do not have rank, we move that element to the tail 74592108Sphk * of the sequence with invalid rank as well. 74692108Sphk * At some point we encounter our original geom and if we stil fail 74792108Sphk * to assign it a rank, there must be a loop and we fail back to 74898066Sphk * g_attach() which detach again and calls redo_rank again 74992108Sphk * to fix up the damage. 75092108Sphk * It would be much simpler code wise to do it recursively, but we 75192108Sphk * can't risk that on the kernel stack. 75292108Sphk */ 75392108Sphk 75492108Sphkstatic int 75592108Sphkredo_rank(struct g_geom *gp) 75692108Sphk{ 75792108Sphk struct g_consumer *cp; 75892108Sphk struct g_geom *gp1, *gp2; 75992108Sphk int n, m; 76092108Sphk 76192108Sphk g_topology_assert(); 762126798Sphk G_VALID_GEOM(gp); 76392108Sphk 76492108Sphk /* Invalidate this geoms rank and move it to the tail */ 76592108Sphk gp1 = TAILQ_NEXT(gp, geoms); 76692108Sphk if (gp1 != NULL) { 76792108Sphk gp->rank = 0; 76892108Sphk TAILQ_REMOVE(&geoms, gp, geoms); 76992108Sphk TAILQ_INSERT_TAIL(&geoms, gp, geoms); 77092108Sphk } else { 77192108Sphk gp1 = gp; 77292108Sphk } 77392108Sphk 77492108Sphk /* re-rank the rest of the sequence */ 77592108Sphk for (; gp1 != NULL; gp1 = gp2) { 77692108Sphk gp1->rank = 0; 77792108Sphk m = 1; 77892108Sphk LIST_FOREACH(cp, &gp1->consumer, consumer) { 77992108Sphk if (cp->provider == NULL) 78092108Sphk continue; 78192108Sphk n = cp->provider->geom->rank; 78292108Sphk if (n == 0) { 78392108Sphk m = 0; 78492108Sphk break; 78592108Sphk } else if (n >= m) 78692108Sphk m = n + 1; 78792108Sphk } 78892108Sphk gp1->rank = m; 78992108Sphk gp2 = TAILQ_NEXT(gp1, geoms); 79092108Sphk 79192108Sphk /* got a rank, moving on */ 79292108Sphk if (m != 0) 79392108Sphk continue; 79492108Sphk 79592108Sphk /* no rank to original geom means loop */ 79695550Sphk if (gp == gp1) 79792108Sphk return (ELOOP); 79892108Sphk 79992108Sphk /* no rank, put it at the end move on */ 80092108Sphk TAILQ_REMOVE(&geoms, gp1, geoms); 80192108Sphk TAILQ_INSERT_TAIL(&geoms, gp1, geoms); 80292108Sphk } 80392108Sphk return (0); 80492108Sphk} 80592108Sphk 80692108Sphkint 80792108Sphkg_attach(struct g_consumer *cp, struct g_provider *pp) 80892108Sphk{ 80992108Sphk int error; 81092108Sphk 81192108Sphk g_topology_assert(); 812126798Sphk G_VALID_CONSUMER(cp); 813126798Sphk G_VALID_PROVIDER(pp); 814204069Spjd g_trace(G_T_TOPOLOGY, "g_attach(%p, %p)", cp, pp); 81592108Sphk KASSERT(cp->provider == NULL, ("attach but attached")); 81692108Sphk cp->provider = pp; 81792108Sphk LIST_INSERT_HEAD(&pp->consumers, cp, consumers); 81892108Sphk error = redo_rank(cp->geom); 81992108Sphk if (error) { 82092108Sphk LIST_REMOVE(cp, consumers); 82192108Sphk cp->provider = NULL; 82292108Sphk redo_rank(cp->geom); 82392108Sphk } 82492108Sphk return (error); 82592108Sphk} 82692108Sphk 82792108Sphkvoid 82898066Sphkg_detach(struct g_consumer *cp) 82992108Sphk{ 83092108Sphk struct g_provider *pp; 83192108Sphk 832126798Sphk g_topology_assert(); 833126798Sphk G_VALID_CONSUMER(cp); 83498066Sphk g_trace(G_T_TOPOLOGY, "g_detach(%p)", cp); 83598066Sphk KASSERT(cp->provider != NULL, ("detach but not attached")); 83698066Sphk KASSERT(cp->acr == 0, ("detach but nonzero acr")); 83798066Sphk KASSERT(cp->acw == 0, ("detach but nonzero acw")); 83898066Sphk KASSERT(cp->ace == 0, ("detach but nonzero ace")); 839112028Sphk KASSERT(cp->nstart == cp->nend, 840110541Sphk ("detach with active requests")); 84192108Sphk pp = cp->provider; 84292108Sphk LIST_REMOVE(cp, consumers); 84392108Sphk cp->provider = NULL; 844248674Smav if ((cp->geom->flags & G_GEOM_WITHER) || 845248674Smav (pp->geom->flags & G_GEOM_WITHER) || 846248674Smav (pp->flags & G_PF_WITHER)) 847131820Sphk g_do_wither(); 84892108Sphk redo_rank(cp->geom); 84992108Sphk} 85092108Sphk 85192108Sphk/* 852125755Sphk * g_access() 85392108Sphk * 85492108Sphk * Access-check with delta values. The question asked is "can provider 85592108Sphk * "cp" change the access counters by the relative amounts dc[rwe] ?" 85692108Sphk */ 85792108Sphk 85892108Sphkint 859125755Sphkg_access(struct g_consumer *cp, int dcr, int dcw, int dce) 86092108Sphk{ 86192108Sphk struct g_provider *pp; 862332096Savg struct g_geom *gp; 863332096Savg int pw, pe; 864332096Savg#ifdef INVARIANTS 865332096Savg int sr, sw, se; 866332096Savg#endif 86792108Sphk int error; 86892108Sphk 869126798Sphk g_topology_assert(); 870126798Sphk G_VALID_CONSUMER(cp); 87192108Sphk pp = cp->provider; 872127162Spjd KASSERT(pp != NULL, ("access but not attached")); 873126798Sphk G_VALID_PROVIDER(pp); 874332096Savg gp = pp->geom; 87592108Sphk 876125755Sphk g_trace(G_T_ACCESS, "g_access(%p(%s), %d, %d, %d)", 87792108Sphk cp, pp->name, dcr, dcw, dce); 87892108Sphk 87992108Sphk KASSERT(cp->acr + dcr >= 0, ("access resulting in negative acr")); 88092108Sphk KASSERT(cp->acw + dcw >= 0, ("access resulting in negative acw")); 88192108Sphk KASSERT(cp->ace + dce >= 0, ("access resulting in negative ace")); 882124294Sphk KASSERT(dcr != 0 || dcw != 0 || dce != 0, ("NOP access request")); 883332096Savg KASSERT(gp->access != NULL, ("NULL geom->access")); 88492108Sphk 88592108Sphk /* 88693248Sphk * If our class cares about being spoiled, and we have been, we 88792108Sphk * are probably just ahead of the event telling us that. Fail 88892108Sphk * now rather than having to unravel this later. 88992108Sphk */ 890238886Smav if (cp->geom->spoiled != NULL && (cp->flags & G_CF_SPOILED) && 891131798Sphk (dcr > 0 || dcw > 0 || dce > 0)) 892131798Sphk return (ENXIO); 89392108Sphk 89492108Sphk /* 895332096Savg * A number of GEOM classes either need to perform an I/O on the first 896332096Savg * open or to acquire a different subsystem's lock. To do that they 897332096Savg * may have to drop the topology lock. 898332096Savg * Other GEOM classes perform special actions when opening a lower rank 899332096Savg * geom for the first time. As a result, more than one thread may 900332096Savg * end up performing the special actions. 901332096Savg * So, we prevent concurrent "first" opens by marking the consumer with 902332096Savg * special flag. 903332096Savg * 904332096Savg * Note that if the geom's access method never drops the topology lock, 905332096Savg * then we will never see G_GEOM_IN_ACCESS here. 906332096Savg */ 907332096Savg while ((gp->flags & G_GEOM_IN_ACCESS) != 0) { 908332096Savg g_trace(G_T_ACCESS, 909332096Savg "%s: race on geom %s via provider %s and consumer of %s", 910332096Savg __func__, gp->name, pp->name, cp->geom->name); 911332096Savg gp->flags |= G_GEOM_ACCESS_WAIT; 912332096Savg g_topology_sleep(gp, 0); 913332096Savg } 914332096Savg 915332096Savg /* 91692108Sphk * Figure out what counts the provider would have had, if this 91792108Sphk * consumer had (r0w0e0) at this time. 91892108Sphk */ 91992108Sphk pw = pp->acw - cp->acw; 92092108Sphk pe = pp->ace - cp->ace; 92192108Sphk 92292108Sphk g_trace(G_T_ACCESS, 92392108Sphk "open delta:[r%dw%de%d] old:[r%dw%de%d] provider:[r%dw%de%d] %p(%s)", 92492108Sphk dcr, dcw, dce, 92592108Sphk cp->acr, cp->acw, cp->ace, 92692108Sphk pp->acr, pp->acw, pp->ace, 92792108Sphk pp, pp->name); 92892108Sphk 929110759Sphk /* If foot-shooting is enabled, any open on rank#1 is OK */ 930332096Savg if ((g_debugflags & 16) && gp->rank == 1) 931110759Sphk ; 93292108Sphk /* If we try exclusive but already write: fail */ 933110759Sphk else if (dce > 0 && pw > 0) 93492108Sphk return (EPERM); 93592108Sphk /* If we try write but already exclusive: fail */ 936110759Sphk else if (dcw > 0 && pe > 0) 93792108Sphk return (EPERM); 93892108Sphk /* If we try to open more but provider is error'ed: fail */ 939110759Sphk else if ((dcr > 0 || dcw > 0 || dce > 0) && pp->error != 0) 94092108Sphk return (pp->error); 94192108Sphk 94292108Sphk /* Ok then... */ 94392108Sphk 944332096Savg#ifdef INVARIANTS 945332096Savg sr = cp->acr; 946332096Savg sw = cp->acw; 947332096Savg se = cp->ace; 948332096Savg#endif 949332096Savg gp->flags |= G_GEOM_IN_ACCESS; 950332096Savg error = gp->access(pp, dcr, dcw, dce); 951125802Sphk KASSERT(dcr > 0 || dcw > 0 || dce > 0 || error == 0, 952266031Sbdrewery ("Geom provider %s::%s dcr=%d dcw=%d dce=%d error=%d failed " 953332096Savg "closing ->access()", gp->class->name, pp->name, dcr, dcw, 954266031Sbdrewery dce, error)); 955332096Savg 956332096Savg g_topology_assert(); 957332096Savg gp->flags &= ~G_GEOM_IN_ACCESS; 958332096Savg KASSERT(cp->acr == sr && cp->acw == sw && cp->ace == se, 959332096Savg ("Access counts changed during geom->access")); 960332096Savg if ((gp->flags & G_GEOM_ACCESS_WAIT) != 0) { 961332096Savg gp->flags &= ~G_GEOM_ACCESS_WAIT; 962332096Savg wakeup(gp); 963332096Savg } 964332096Savg 96592108Sphk if (!error) { 966112979Sphk /* 967112979Sphk * If we open first write, spoil any partner consumers. 968152565Sjdp * If we close last write and provider is not errored, 969152565Sjdp * trigger re-taste. 970112979Sphk */ 971112979Sphk if (pp->acw == 0 && dcw != 0) 972112979Sphk g_spoil(pp, cp); 973152565Sjdp else if (pp->acw != 0 && pp->acw == -dcw && pp->error == 0 && 974332096Savg !(gp->flags & G_GEOM_WITHER)) 975113937Sphk g_post_event(g_new_provider_event, pp, M_WAITOK, 976113937Sphk pp, NULL); 977112979Sphk 97892108Sphk pp->acr += dcr; 97992108Sphk pp->acw += dcw; 98092108Sphk pp->ace += dce; 98192108Sphk cp->acr += dcr; 98292108Sphk cp->acw += dcw; 98392108Sphk cp->ace += dce; 984134824Sphk if (pp->acr != 0 || pp->acw != 0 || pp->ace != 0) 985134824Sphk KASSERT(pp->sectorsize > 0, 986134824Sphk ("Provider %s lacks sectorsize", pp->name)); 987248674Smav if ((cp->geom->flags & G_GEOM_WITHER) && 988248674Smav cp->acr == 0 && cp->acw == 0 && cp->ace == 0) 989248674Smav g_do_wither(); 99092108Sphk } 99192108Sphk return (error); 99292108Sphk} 99392108Sphk 99492108Sphkint 995107953Sphkg_handleattr_int(struct bio *bp, const char *attribute, int val) 99692108Sphk{ 99792108Sphk 99898066Sphk return (g_handleattr(bp, attribute, &val, sizeof val)); 99992108Sphk} 100092108Sphk 100192108Sphkint 1002271238Ssmhg_handleattr_uint16_t(struct bio *bp, const char *attribute, uint16_t val) 1003271238Ssmh{ 1004271238Ssmh 1005271238Ssmh return (g_handleattr(bp, attribute, &val, sizeof val)); 1006271238Ssmh} 1007271238Ssmh 1008271238Ssmhint 1009107953Sphkg_handleattr_off_t(struct bio *bp, const char *attribute, off_t val) 101092108Sphk{ 101192108Sphk 101298066Sphk return (g_handleattr(bp, attribute, &val, sizeof val)); 101392108Sphk} 101492108Sphk 101592108Sphkint 1016187973Smarcelg_handleattr_str(struct bio *bp, const char *attribute, const char *str) 1017169282Spjd{ 1018169282Spjd 1019169282Spjd return (g_handleattr(bp, attribute, str, 0)); 1020169282Spjd} 1021169282Spjd 1022169282Spjdint 1023187973Smarcelg_handleattr(struct bio *bp, const char *attribute, const void *val, int len) 102492108Sphk{ 1025169282Spjd int error = 0; 102692108Sphk 102792108Sphk if (strcmp(bp->bio_attribute, attribute)) 102892108Sphk return (0); 1029169282Spjd if (len == 0) { 1030169282Spjd bzero(bp->bio_data, bp->bio_length); 1031169282Spjd if (strlcpy(bp->bio_data, val, bp->bio_length) >= 1032169282Spjd bp->bio_length) { 1033169282Spjd printf("%s: %s bio_length %jd len %zu -> EFAULT\n", 1034169282Spjd __func__, bp->bio_to->name, 1035169282Spjd (intmax_t)bp->bio_length, strlen(val)); 1036169282Spjd error = EFAULT; 1037169282Spjd } 1038169282Spjd } else if (bp->bio_length == len) { 103992108Sphk bcopy(val, bp->bio_data, len); 1040169282Spjd } else { 1041169282Spjd printf("%s: %s bio_length %jd len %d -> EFAULT\n", __func__, 1042169282Spjd bp->bio_to->name, (intmax_t)bp->bio_length, len); 1043169282Spjd error = EFAULT; 104492108Sphk } 1045188054Smarcel if (error == 0) 1046188054Smarcel bp->bio_completed = bp->bio_length; 1047104195Sphk g_io_deliver(bp, error); 104892108Sphk return (1); 104992108Sphk} 105092108Sphk 105192108Sphkint 1052126798Sphkg_std_access(struct g_provider *pp, 105392108Sphk int dr __unused, int dw __unused, int de __unused) 105492108Sphk{ 105592108Sphk 1056126798Sphk g_topology_assert(); 1057126798Sphk G_VALID_PROVIDER(pp); 105892108Sphk return (0); 105992108Sphk} 106092108Sphk 106192108Sphkvoid 106292108Sphkg_std_done(struct bio *bp) 106392108Sphk{ 106492108Sphk struct bio *bp2; 106592108Sphk 1066110517Sphk bp2 = bp->bio_parent; 1067104701Sphk if (bp2->bio_error == 0) 1068104701Sphk bp2->bio_error = bp->bio_error; 1069104701Sphk bp2->bio_completed += bp->bio_completed; 107092108Sphk g_destroy_bio(bp); 1071110523Sphk bp2->bio_inbed++; 1072110523Sphk if (bp2->bio_children == bp2->bio_inbed) 1073104701Sphk g_io_deliver(bp2, bp2->bio_error); 107492108Sphk} 107592108Sphk 107692108Sphk/* XXX: maybe this is only g_slice_spoiled */ 107792108Sphk 107892108Sphkvoid 107992108Sphkg_std_spoiled(struct g_consumer *cp) 108092108Sphk{ 1081114511Sphk struct g_geom *gp; 1082114511Sphk struct g_provider *pp; 108392108Sphk 1084126798Sphk g_topology_assert(); 1085126798Sphk G_VALID_CONSUMER(cp); 108692108Sphk g_trace(G_T_TOPOLOGY, "g_std_spoiled(%p)", cp); 1087238886Smav cp->flags |= G_CF_ORPHAN; 1088114511Sphk g_detach(cp); 1089114511Sphk gp = cp->geom; 1090114511Sphk LIST_FOREACH(pp, &gp->provider, provider) 1091114511Sphk g_orphan_provider(pp, ENXIO); 1092114511Sphk g_destroy_consumer(cp); 1093114511Sphk if (LIST_EMPTY(&gp->provider) && LIST_EMPTY(&gp->consumer)) 1094114511Sphk g_destroy_geom(gp); 1095114511Sphk else 1096114511Sphk gp->flags |= G_GEOM_WITHER; 109792108Sphk} 109892108Sphk 109992108Sphk/* 110092108Sphk * Spoiling happens when a provider is opened for writing, but consumers 110192108Sphk * which are configured by in-band data are attached (slicers for instance). 110292108Sphk * Since the write might potentially change the in-band data, such consumers 110392108Sphk * need to re-evaluate their existence after the writing session closes. 110492108Sphk * We do this by (offering to) tear them down when the open for write happens 110592108Sphk * in return for a re-taste when it closes again. 110692108Sphk * Together with the fact that such consumers grab an 'e' bit whenever they 110792108Sphk * are open, regardless of mode, this ends up DTRT. 110892108Sphk */ 110992108Sphk 1110113929Sphkstatic void 1111113929Sphkg_spoil_event(void *arg, int flag) 1112113929Sphk{ 1113113929Sphk struct g_provider *pp; 1114113929Sphk struct g_consumer *cp, *cp2; 1115113929Sphk 1116113929Sphk g_topology_assert(); 1117113929Sphk if (flag == EV_CANCEL) 1118113929Sphk return; 1119113929Sphk pp = arg; 1120126798Sphk G_VALID_PROVIDER(pp); 1121266679Sae g_trace(G_T_TOPOLOGY, "%s %p(%s:%s:%s)", __func__, pp, 1122266679Sae pp->geom->class->name, pp->geom->name, pp->name); 1123113929Sphk for (cp = LIST_FIRST(&pp->consumers); cp != NULL; cp = cp2) { 1124113929Sphk cp2 = LIST_NEXT(cp, consumers); 1125238886Smav if ((cp->flags & G_CF_SPOILED) == 0) 1126113929Sphk continue; 1127238886Smav cp->flags &= ~G_CF_SPOILED; 1128113929Sphk if (cp->geom->spoiled == NULL) 1129113929Sphk continue; 1130113929Sphk cp->geom->spoiled(cp); 1131113929Sphk g_topology_assert(); 1132113929Sphk } 1133113929Sphk} 1134113929Sphk 113592108Sphkvoid 113692108Sphkg_spoil(struct g_provider *pp, struct g_consumer *cp) 113792108Sphk{ 113892108Sphk struct g_consumer *cp2; 113992108Sphk 114092108Sphk g_topology_assert(); 1141126798Sphk G_VALID_PROVIDER(pp); 1142126798Sphk G_VALID_CONSUMER(cp); 114392108Sphk 114492108Sphk LIST_FOREACH(cp2, &pp->consumers, consumers) { 114592108Sphk if (cp2 == cp) 114692108Sphk continue; 114792108Sphk/* 114892108Sphk KASSERT(cp2->acr == 0, ("spoiling cp->acr = %d", cp2->acr)); 114992108Sphk KASSERT(cp2->acw == 0, ("spoiling cp->acw = %d", cp2->acw)); 115092108Sphk*/ 115192108Sphk KASSERT(cp2->ace == 0, ("spoiling cp->ace = %d", cp2->ace)); 1152238886Smav cp2->flags |= G_CF_SPOILED; 115392108Sphk } 1154113937Sphk g_post_event(g_spoil_event, pp, M_WAITOK, pp, NULL); 115592108Sphk} 115692108Sphk 1157238886Smavstatic void 1158238886Smavg_media_changed_event(void *arg, int flag) 1159238886Smav{ 1160238886Smav struct g_provider *pp; 1161238886Smav int retaste; 1162238886Smav 1163238886Smav g_topology_assert(); 1164238886Smav if (flag == EV_CANCEL) 1165238886Smav return; 1166238886Smav pp = arg; 1167238886Smav G_VALID_PROVIDER(pp); 1168238886Smav 1169238886Smav /* 1170238886Smav * If provider was not open for writing, queue retaste after spoiling. 1171238886Smav * If it was, retaste will happen automatically on close. 1172238886Smav */ 1173238886Smav retaste = (pp->acw == 0 && pp->error == 0 && 1174238886Smav !(pp->geom->flags & G_GEOM_WITHER)); 1175238886Smav g_spoil_event(arg, flag); 1176238886Smav if (retaste) 1177238886Smav g_post_event(g_new_provider_event, pp, M_WAITOK, pp, NULL); 1178238886Smav} 1179238886Smav 118094284Sphkint 1181238886Smavg_media_changed(struct g_provider *pp, int flag) 1182238886Smav{ 1183238886Smav struct g_consumer *cp; 1184238886Smav 1185238886Smav LIST_FOREACH(cp, &pp->consumers, consumers) 1186238886Smav cp->flags |= G_CF_SPOILED; 1187238886Smav return (g_post_event(g_media_changed_event, pp, flag, pp, NULL)); 1188238886Smav} 1189238886Smav 1190238886Smavint 1191238886Smavg_media_gone(struct g_provider *pp, int flag) 1192238886Smav{ 1193238886Smav struct g_consumer *cp; 1194238886Smav 1195238886Smav LIST_FOREACH(cp, &pp->consumers, consumers) 1196238886Smav cp->flags |= G_CF_SPOILED; 1197238886Smav return (g_post_event(g_spoil_event, pp, flag, pp, NULL)); 1198238886Smav} 1199238886Smav 1200238886Smavint 120194284Sphkg_getattr__(const char *attr, struct g_consumer *cp, void *var, int len) 120294284Sphk{ 120394284Sphk int error, i; 120494284Sphk 120594284Sphk i = len; 120694284Sphk error = g_io_getattr(attr, cp, &i, var); 120794284Sphk if (error) 120894284Sphk return (error); 120994284Sphk if (i != len) 121094284Sphk return (EINVAL); 121194284Sphk return (0); 121294284Sphk} 121395310Sphk 1214221101Smavstatic int 1215221101Smavg_get_device_prefix_len(const char *name) 1216221101Smav{ 1217221101Smav int len; 1218221101Smav 1219221101Smav if (strncmp(name, "ada", 3) == 0) 1220221101Smav len = 3; 1221221101Smav else if (strncmp(name, "ad", 2) == 0) 1222221101Smav len = 2; 1223221101Smav else 1224221101Smav return (0); 1225221101Smav if (name[len] < '0' || name[len] > '9') 1226221101Smav return (0); 1227221101Smav do { 1228221101Smav len++; 1229221101Smav } while (name[len] >= '0' && name[len] <= '9'); 1230221101Smav return (len); 1231221101Smav} 1232221101Smav 1233221101Smavint 1234221101Smavg_compare_names(const char *namea, const char *nameb) 1235221101Smav{ 1236221101Smav int deva, devb; 1237221101Smav 1238221101Smav if (strcmp(namea, nameb) == 0) 1239221101Smav return (1); 1240221101Smav deva = g_get_device_prefix_len(namea); 1241221101Smav if (deva == 0) 1242221101Smav return (0); 1243221101Smav devb = g_get_device_prefix_len(nameb); 1244221101Smav if (devb == 0) 1245221101Smav return (0); 1246221101Smav if (strcmp(namea + deva, nameb + devb) == 0) 1247221101Smav return (1); 1248221101Smav return (0); 1249221101Smav} 1250221101Smav 1251162326Spjd#if defined(DIAGNOSTIC) || defined(DDB) 125295310Sphk/* 1253206859Sjh * This function walks the mesh and returns a non-zero integer if it 1254206859Sjh * finds the argument pointer is an object. The return value indicates 1255206859Sjh * which type of object it is believed to be. If topology is not locked, 1256206859Sjh * this function is potentially dangerous, but we don't assert that the 1257206859Sjh * topology lock is held when called from debugger. 1258122762Sphk */ 1259126798Sphkint 1260122762Sphkg_valid_obj(void const *ptr) 1261122762Sphk{ 1262122762Sphk struct g_class *mp; 1263122762Sphk struct g_geom *gp; 1264122762Sphk struct g_consumer *cp; 1265122762Sphk struct g_provider *pp; 1266122762Sphk 1267206859Sjh#ifdef KDB 1268206859Sjh if (kdb_active == 0) 1269206859Sjh#endif 1270206859Sjh g_topology_assert(); 1271195257Strasz 1272122762Sphk LIST_FOREACH(mp, &g_classes, class) { 1273122762Sphk if (ptr == mp) 1274122762Sphk return (1); 1275122762Sphk LIST_FOREACH(gp, &mp->geom, geom) { 1276122762Sphk if (ptr == gp) 1277126798Sphk return (2); 1278122762Sphk LIST_FOREACH(cp, &gp->consumer, consumer) 1279122762Sphk if (ptr == cp) 1280126798Sphk return (3); 1281122762Sphk LIST_FOREACH(pp, &gp->provider, provider) 1282122762Sphk if (ptr == pp) 1283126798Sphk return (4); 1284122762Sphk } 1285122762Sphk } 1286122762Sphk return(0); 1287122762Sphk} 1288126798Sphk#endif 1289162326Spjd 1290162326Spjd#ifdef DDB 1291162326Spjd 1292162326Spjd#define gprintf(...) do { \ 1293192803Slulf db_printf("%*s", indent, ""); \ 1294192803Slulf db_printf(__VA_ARGS__); \ 1295162326Spjd} while (0) 1296162326Spjd#define gprintln(...) do { \ 1297162326Spjd gprintf(__VA_ARGS__); \ 1298192803Slulf db_printf("\n"); \ 1299162326Spjd} while (0) 1300162326Spjd 1301162326Spjd#define ADDFLAG(obj, flag, sflag) do { \ 1302162326Spjd if ((obj)->flags & (flag)) { \ 1303162326Spjd if (comma) \ 1304162326Spjd strlcat(str, ",", size); \ 1305162326Spjd strlcat(str, (sflag), size); \ 1306162326Spjd comma = 1; \ 1307162326Spjd } \ 1308162326Spjd} while (0) 1309162326Spjd 1310162326Spjdstatic char * 1311162326Spjdprovider_flags_to_string(struct g_provider *pp, char *str, size_t size) 1312162326Spjd{ 1313162326Spjd int comma = 0; 1314162326Spjd 1315162326Spjd bzero(str, size); 1316162326Spjd if (pp->flags == 0) { 1317162326Spjd strlcpy(str, "NONE", size); 1318162326Spjd return (str); 1319162326Spjd } 1320162326Spjd ADDFLAG(pp, G_PF_WITHER, "G_PF_WITHER"); 1321162326Spjd ADDFLAG(pp, G_PF_ORPHAN, "G_PF_ORPHAN"); 1322162326Spjd return (str); 1323162326Spjd} 1324162326Spjd 1325162326Spjdstatic char * 1326162326Spjdgeom_flags_to_string(struct g_geom *gp, char *str, size_t size) 1327162326Spjd{ 1328162326Spjd int comma = 0; 1329162326Spjd 1330162326Spjd bzero(str, size); 1331162326Spjd if (gp->flags == 0) { 1332162326Spjd strlcpy(str, "NONE", size); 1333162326Spjd return (str); 1334162326Spjd } 1335162326Spjd ADDFLAG(gp, G_GEOM_WITHER, "G_GEOM_WITHER"); 1336162326Spjd return (str); 1337162326Spjd} 1338162326Spjdstatic void 1339162326Spjddb_show_geom_consumer(int indent, struct g_consumer *cp) 1340162326Spjd{ 1341162326Spjd 1342162326Spjd if (indent == 0) { 1343162326Spjd gprintln("consumer: %p", cp); 1344162326Spjd gprintln(" class: %s (%p)", cp->geom->class->name, 1345162326Spjd cp->geom->class); 1346162326Spjd gprintln(" geom: %s (%p)", cp->geom->name, cp->geom); 1347162326Spjd if (cp->provider == NULL) 1348162326Spjd gprintln(" provider: none"); 1349162326Spjd else { 1350162326Spjd gprintln(" provider: %s (%p)", cp->provider->name, 1351162326Spjd cp->provider); 1352162326Spjd } 1353162326Spjd gprintln(" access: r%dw%de%d", cp->acr, cp->acw, cp->ace); 1354238886Smav gprintln(" flags: 0x%04x", cp->flags); 1355162326Spjd gprintln(" nstart: %u", cp->nstart); 1356162326Spjd gprintln(" nend: %u", cp->nend); 1357162326Spjd } else { 1358162326Spjd gprintf("consumer: %p (%s), access=r%dw%de%d", cp, 1359162326Spjd cp->provider != NULL ? cp->provider->name : "none", 1360162326Spjd cp->acr, cp->acw, cp->ace); 1361238886Smav if (cp->flags) 1362238886Smav db_printf(", flags=0x%04x", cp->flags); 1363192803Slulf db_printf("\n"); 1364162326Spjd } 1365162326Spjd} 1366162326Spjd 1367162326Spjdstatic void 1368162326Spjddb_show_geom_provider(int indent, struct g_provider *pp) 1369162326Spjd{ 1370162326Spjd struct g_consumer *cp; 1371162326Spjd char flags[64]; 1372162326Spjd 1373162326Spjd if (indent == 0) { 1374162326Spjd gprintln("provider: %s (%p)", pp->name, pp); 1375162326Spjd gprintln(" class: %s (%p)", pp->geom->class->name, 1376162326Spjd pp->geom->class); 1377162326Spjd gprintln(" geom: %s (%p)", pp->geom->name, pp->geom); 1378162326Spjd gprintln(" mediasize: %jd", (intmax_t)pp->mediasize); 1379162326Spjd gprintln(" sectorsize: %u", pp->sectorsize); 1380162326Spjd gprintln(" stripesize: %u", pp->stripesize); 1381162326Spjd gprintln(" stripeoffset: %u", pp->stripeoffset); 1382162326Spjd gprintln(" access: r%dw%de%d", pp->acr, pp->acw, 1383162326Spjd pp->ace); 1384162326Spjd gprintln(" flags: %s (0x%04x)", 1385162326Spjd provider_flags_to_string(pp, flags, sizeof(flags)), 1386162326Spjd pp->flags); 1387162326Spjd gprintln(" error: %d", pp->error); 1388162326Spjd gprintln(" nstart: %u", pp->nstart); 1389162326Spjd gprintln(" nend: %u", pp->nend); 1390162326Spjd if (LIST_EMPTY(&pp->consumers)) 1391162326Spjd gprintln(" consumers: none"); 1392162326Spjd } else { 1393162326Spjd gprintf("provider: %s (%p), access=r%dw%de%d", 1394162326Spjd pp->name, pp, pp->acr, pp->acw, pp->ace); 1395162326Spjd if (pp->flags != 0) { 1396192803Slulf db_printf(", flags=%s (0x%04x)", 1397162326Spjd provider_flags_to_string(pp, flags, sizeof(flags)), 1398162326Spjd pp->flags); 1399162326Spjd } 1400192803Slulf db_printf("\n"); 1401162326Spjd } 1402162326Spjd if (!LIST_EMPTY(&pp->consumers)) { 1403179094Spjd LIST_FOREACH(cp, &pp->consumers, consumers) { 1404162326Spjd db_show_geom_consumer(indent + 2, cp); 1405179094Spjd if (db_pager_quit) 1406179094Spjd break; 1407179094Spjd } 1408162326Spjd } 1409162326Spjd} 1410162326Spjd 1411162326Spjdstatic void 1412162326Spjddb_show_geom_geom(int indent, struct g_geom *gp) 1413162326Spjd{ 1414162326Spjd struct g_provider *pp; 1415162326Spjd struct g_consumer *cp; 1416162326Spjd char flags[64]; 1417162326Spjd 1418162326Spjd if (indent == 0) { 1419162326Spjd gprintln("geom: %s (%p)", gp->name, gp); 1420162326Spjd gprintln(" class: %s (%p)", gp->class->name, gp->class); 1421162326Spjd gprintln(" flags: %s (0x%04x)", 1422162326Spjd geom_flags_to_string(gp, flags, sizeof(flags)), gp->flags); 1423162326Spjd gprintln(" rank: %d", gp->rank); 1424162326Spjd if (LIST_EMPTY(&gp->provider)) 1425162326Spjd gprintln(" providers: none"); 1426162326Spjd if (LIST_EMPTY(&gp->consumer)) 1427162326Spjd gprintln(" consumers: none"); 1428162326Spjd } else { 1429162326Spjd gprintf("geom: %s (%p), rank=%d", gp->name, gp, gp->rank); 1430162326Spjd if (gp->flags != 0) { 1431192803Slulf db_printf(", flags=%s (0x%04x)", 1432162326Spjd geom_flags_to_string(gp, flags, sizeof(flags)), 1433162326Spjd gp->flags); 1434162326Spjd } 1435192803Slulf db_printf("\n"); 1436162326Spjd } 1437162326Spjd if (!LIST_EMPTY(&gp->provider)) { 1438179094Spjd LIST_FOREACH(pp, &gp->provider, provider) { 1439162326Spjd db_show_geom_provider(indent + 2, pp); 1440179094Spjd if (db_pager_quit) 1441179094Spjd break; 1442179094Spjd } 1443162326Spjd } 1444162326Spjd if (!LIST_EMPTY(&gp->consumer)) { 1445179094Spjd LIST_FOREACH(cp, &gp->consumer, consumer) { 1446162326Spjd db_show_geom_consumer(indent + 2, cp); 1447179094Spjd if (db_pager_quit) 1448179094Spjd break; 1449179094Spjd } 1450162326Spjd } 1451162326Spjd} 1452162326Spjd 1453162326Spjdstatic void 1454162326Spjddb_show_geom_class(struct g_class *mp) 1455162326Spjd{ 1456162326Spjd struct g_geom *gp; 1457162326Spjd 1458192803Slulf db_printf("class: %s (%p)\n", mp->name, mp); 1459179094Spjd LIST_FOREACH(gp, &mp->geom, geom) { 1460162326Spjd db_show_geom_geom(2, gp); 1461179094Spjd if (db_pager_quit) 1462179094Spjd break; 1463179094Spjd } 1464162326Spjd} 1465162326Spjd 1466162326Spjd/* 1467162326Spjd * Print the GEOM topology or the given object. 1468162326Spjd */ 1469162326SpjdDB_SHOW_COMMAND(geom, db_show_geom) 1470162326Spjd{ 1471162326Spjd struct g_class *mp; 1472162326Spjd 1473162326Spjd if (!have_addr) { 1474162326Spjd /* No address given, print the entire topology. */ 1475162326Spjd LIST_FOREACH(mp, &g_classes, class) { 1476162326Spjd db_show_geom_class(mp); 1477192803Slulf db_printf("\n"); 1478179094Spjd if (db_pager_quit) 1479179094Spjd break; 1480162326Spjd } 1481162326Spjd } else { 1482162326Spjd switch (g_valid_obj((void *)addr)) { 1483162326Spjd case 1: 1484162326Spjd db_show_geom_class((struct g_class *)addr); 1485162326Spjd break; 1486162326Spjd case 2: 1487162326Spjd db_show_geom_geom(0, (struct g_geom *)addr); 1488162326Spjd break; 1489162326Spjd case 3: 1490162326Spjd db_show_geom_consumer(0, (struct g_consumer *)addr); 1491162326Spjd break; 1492162326Spjd case 4: 1493162326Spjd db_show_geom_provider(0, (struct g_provider *)addr); 1494162326Spjd break; 1495162326Spjd default: 1496192803Slulf db_printf("Not a GEOM object.\n"); 1497162326Spjd break; 1498162326Spjd } 1499162326Spjd } 1500162326Spjd} 1501162326Spjd 1502192797Slulfstatic void 1503192797Slulfdb_print_bio_cmd(struct bio *bp) 1504192797Slulf{ 1505192803Slulf db_printf(" cmd: "); 1506192797Slulf switch (bp->bio_cmd) { 1507192803Slulf case BIO_READ: db_printf("BIO_READ"); break; 1508192803Slulf case BIO_WRITE: db_printf("BIO_WRITE"); break; 1509192803Slulf case BIO_DELETE: db_printf("BIO_DELETE"); break; 1510192803Slulf case BIO_GETATTR: db_printf("BIO_GETATTR"); break; 1511192803Slulf case BIO_FLUSH: db_printf("BIO_FLUSH"); break; 1512192803Slulf case BIO_CMD0: db_printf("BIO_CMD0"); break; 1513192803Slulf case BIO_CMD1: db_printf("BIO_CMD1"); break; 1514192803Slulf case BIO_CMD2: db_printf("BIO_CMD2"); break; 1515192803Slulf default: db_printf("UNKNOWN"); break; 1516192797Slulf } 1517192803Slulf db_printf("\n"); 1518192797Slulf} 1519192797Slulf 1520192797Slulfstatic void 1521192797Slulfdb_print_bio_flags(struct bio *bp) 1522192797Slulf{ 1523192797Slulf int comma; 1524192797Slulf 1525192797Slulf comma = 0; 1526192803Slulf db_printf(" flags: "); 1527192797Slulf if (bp->bio_flags & BIO_ERROR) { 1528192803Slulf db_printf("BIO_ERROR"); 1529192797Slulf comma = 1; 1530192797Slulf } 1531192797Slulf if (bp->bio_flags & BIO_DONE) { 1532192803Slulf db_printf("%sBIO_DONE", (comma ? ", " : "")); 1533192797Slulf comma = 1; 1534192797Slulf } 1535192797Slulf if (bp->bio_flags & BIO_ONQUEUE) 1536192803Slulf db_printf("%sBIO_ONQUEUE", (comma ? ", " : "")); 1537192803Slulf db_printf("\n"); 1538192797Slulf} 1539192797Slulf 1540192797Slulf/* 1541192797Slulf * Print useful information in a BIO 1542192797Slulf */ 1543192797SlulfDB_SHOW_COMMAND(bio, db_show_bio) 1544192797Slulf{ 1545192797Slulf struct bio *bp; 1546192797Slulf 1547192797Slulf if (have_addr) { 1548192797Slulf bp = (struct bio *)addr; 1549192803Slulf db_printf("BIO %p\n", bp); 1550192797Slulf db_print_bio_cmd(bp); 1551192797Slulf db_print_bio_flags(bp); 1552192803Slulf db_printf(" cflags: 0x%hhx\n", bp->bio_cflags); 1553192803Slulf db_printf(" pflags: 0x%hhx\n", bp->bio_pflags); 1554192808Slulf db_printf(" offset: %jd\n", (intmax_t)bp->bio_offset); 1555192808Slulf db_printf(" length: %jd\n", (intmax_t)bp->bio_length); 1556192803Slulf db_printf(" bcount: %ld\n", bp->bio_bcount); 1557192803Slulf db_printf(" resid: %ld\n", bp->bio_resid); 1558192808Slulf db_printf(" completed: %jd\n", (intmax_t)bp->bio_completed); 1559192803Slulf db_printf(" children: %u\n", bp->bio_children); 1560192803Slulf db_printf(" inbed: %u\n", bp->bio_inbed); 1561192803Slulf db_printf(" error: %d\n", bp->bio_error); 1562192803Slulf db_printf(" parent: %p\n", bp->bio_parent); 1563192803Slulf db_printf(" driver1: %p\n", bp->bio_driver1); 1564192803Slulf db_printf(" driver2: %p\n", bp->bio_driver2); 1565192803Slulf db_printf(" caller1: %p\n", bp->bio_caller1); 1566192803Slulf db_printf(" caller2: %p\n", bp->bio_caller2); 1567192803Slulf db_printf(" bio_from: %p\n", bp->bio_from); 1568192803Slulf db_printf(" bio_to: %p\n", bp->bio_to); 1569192797Slulf } 1570192797Slulf} 1571192797Slulf 1572162326Spjd#undef gprintf 1573162326Spjd#undef gprintln 1574162326Spjd#undef ADDFLAG 1575162326Spjd 1576162326Spjd#endif /* DDB */ 1577