78 G_CLASS_INITIALIZER 79}; 80 81int 82g_dev_print(void) 83{ 84 struct g_geom *gp; 85 86 if (LIST_EMPTY(&g_dev_class.geom)) 87 return (0); 88 printf("List of GEOM disk devices:\n "); 89 LIST_FOREACH(gp, &g_dev_class.geom, geom) 90 printf(" %s", gp->name); 91 printf("\n"); 92 return (1); 93} 94 95/* 96 * XXX: This is disgusting and wrong in every way imaginable: The only reason 97 * XXX: we have a clone function is because of the root-mount hack we currently 98 * XXX: employ. An improvment would be to unregister this cloner once we know 99 * XXX: we no longer need it. Ideally, root-fs would be mounted through DEVFS 100 * XXX: eliminating the need for this hack. 101 */ 102static void 103g_dev_clone(void *arg __unused, char *name, int namelen __unused, dev_t *dev) 104{ 105 struct g_geom *gp; 106 107 if (*dev != NODEV) 108 return; 109 110 g_waitidle(); 111 112 /* g_topology_lock(); */ 113 LIST_FOREACH(gp, &g_dev_class.geom, geom) { 114 if (strcmp(gp->name, name)) 115 continue; 116 *dev = gp->softc; 117 g_trace(G_T_TOPOLOGY, "g_dev_clone(%s) = %p", name, *dev); 118 return; 119 } 120 /* g_topology_unlock(); */ 121 return; 122} 123 124static void 125g_dev_register_cloner(void *foo __unused) 126{ 127 static int once; 128 129 /* XXX: why would this happen more than once ?? */ 130 if (!once) { 131 EVENTHANDLER_REGISTER(dev_clone, g_dev_clone, 0, 1000); 132 once++; 133 } 134} 135 136SYSINIT(geomdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE,g_dev_register_cloner,NULL); 137 138static struct g_geom * 139g_dev_taste(struct g_class *mp, struct g_provider *pp, int insist __unused) 140{ 141 struct g_geom *gp; 142 struct g_consumer *cp; 143 static int unit = GEOM_MINOR_PROVIDERS; 144 int error; 145 dev_t dev; 146 147 g_trace(G_T_TOPOLOGY, "dev_taste(%s,%s)", mp->name, pp->name); 148 g_topology_assert(); 149 LIST_FOREACH(cp, &pp->consumers, consumers) 150 if (cp->geom->class == mp) 151 return (NULL); 152 gp = g_new_geomf(mp, pp->name); 153 gp->orphan = g_dev_orphan; 154 cp = g_new_consumer(gp); 155 error = g_attach(cp, pp); 156 KASSERT(error == 0, 157 ("g_dev_taste(%s) failed to g_attach, err=%d", pp->name, error)); 158 /* 159 * XXX: I'm not 100% sure we can call make_dev(9) without Giant 160 * yet. Once we can, we don't need to drop topology here either. 161 */ 162 g_topology_unlock(); 163 mtx_lock(&Giant); 164 dev = make_dev(&g_dev_cdevsw, unit2minor(unit++), 165 UID_ROOT, GID_OPERATOR, 0640, gp->name); 166 if (pp->flags & G_PF_CANDELETE) 167 dev->si_flags |= SI_CANDELETE; 168 mtx_unlock(&Giant); 169 g_topology_lock(); 170 dev->si_iosize_max = MAXPHYS; 171 dev->si_stripesize = pp->stripesize; 172 dev->si_stripeoffset = pp->stripeoffset; 173 gp->softc = dev; 174 dev->si_drv1 = gp; 175 dev->si_drv2 = cp; 176 return (gp); 177} 178 179static int 180g_dev_open(dev_t dev, int flags, int fmt, struct thread *td) 181{ 182 struct g_geom *gp; 183 struct g_consumer *cp; 184 int error, r, w, e; 185 186 gp = dev->si_drv1; 187 cp = dev->si_drv2; 188 if (gp == NULL || cp == NULL) 189 return(ENXIO); 190 g_trace(G_T_ACCESS, "g_dev_open(%s, %d, %d, %p)", 191 gp->name, flags, fmt, td); 192 DROP_GIANT(); 193 g_topology_lock(); 194 r = flags & FREAD ? 1 : 0; 195 w = flags & FWRITE ? 1 : 0; 196#ifdef notyet 197 e = flags & O_EXCL ? 1 : 0; 198#else 199 e = 0; 200#endif 201 error = g_access_rel(cp, r, w, e); 202 g_topology_unlock(); 203 PICKUP_GIANT(); 204 g_waitidle(); 205 dev->si_bsize_phys = cp->provider->sectorsize; 206 return(error); 207} 208 209static int 210g_dev_close(dev_t dev, int flags, int fmt, struct thread *td) 211{ 212 struct g_geom *gp; 213 struct g_consumer *cp; 214 int error, r, w, e; 215 216 gp = dev->si_drv1; 217 cp = dev->si_drv2; 218 if (gp == NULL || cp == NULL) 219 return(ENXIO); 220 g_trace(G_T_ACCESS, "g_dev_close(%s, %d, %d, %p)", 221 gp->name, flags, fmt, td); 222 DROP_GIANT(); 223 g_topology_lock(); 224 r = flags & FREAD ? -1 : 0; 225 w = flags & FWRITE ? -1 : 0; 226#ifdef notyet 227 e = flags & O_EXCL ? -1 : 0; 228#else 229 e = 0; 230#endif 231 error = g_access_rel(cp, r, w, e); 232 g_topology_unlock(); 233 PICKUP_GIANT(); 234 g_waitidle(); 235 return (error); 236} 237 238static int 239g_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td) 240{ 241 struct g_geom *gp, *gp2; 242 struct g_consumer *cp; 243 struct g_provider *pp2; 244 struct g_kerneldump kd; 245 int i, error; 246 u_int u; 247 struct g_ioctl *gio; 248 249 gp = dev->si_drv1; 250 cp = dev->si_drv2; 251 pp2 = cp->provider; 252 gp2 = pp2->geom; 253 gio = NULL; 254 255 error = 0; 256 DROP_GIANT(); 257 258 gio = NULL; 259 i = IOCPARM_LEN(cmd); 260 switch (cmd) { 261 case DIOCGSECTORSIZE: 262 *(u_int *)data = cp->provider->sectorsize; 263 if (*(u_int *)data == 0) 264 error = ENOENT; 265 break; 266 case DIOCGMEDIASIZE: 267 *(off_t *)data = cp->provider->mediasize; 268 if (*(off_t *)data == 0) 269 error = ENOENT; 270 break; 271 case DIOCGFWSECTORS: 272 error = g_io_getattr("GEOM::fwsectors", cp, &i, data); 273 if (error == 0 && *(u_int *)data == 0) 274 error = ENOENT; 275 break; 276 case DIOCGFWHEADS: 277 error = g_io_getattr("GEOM::fwheads", cp, &i, data); 278 if (error == 0 && *(u_int *)data == 0) 279 error = ENOENT; 280 break; 281 case DIOCGFRONTSTUFF: 282 error = g_io_getattr("GEOM::frontstuff", cp, &i, data); 283 break; 284 case DIOCSKERNELDUMP: 285 u = *((u_int *)data); 286 if (!u) { 287 set_dumper(NULL); 288 error = 0; 289 break; 290 } 291 kd.offset = 0; 292 kd.length = OFF_MAX; 293 i = sizeof kd; 294 error = g_io_getattr("GEOM::kerneldump", cp, &i, &kd); 295 if (!error) 296 dev->si_flags |= SI_DUMPDEV; 297 break; 298 299 default: 300 gio = g_malloc(sizeof *gio, M_WAITOK | M_ZERO); 301 gio->cmd = cmd; 302 gio->data = data; 303 gio->fflag = fflag; 304 gio->td = td; 305 i = sizeof *gio; 306 /* 307 * We always issue ioctls as getattr since the direction of data 308 * movement in ioctl is no indication of the ioctl being a "set" 309 * or "get" type ioctl or if such simplistic terms even apply 310 */ 311 error = g_io_getattr("GEOM::ioctl", cp, &i, gio); 312 break; 313 } 314 315 PICKUP_GIANT(); 316 if (error == EDIRIOCTL) { 317 KASSERT(gio != NULL, ("NULL gio but EDIRIOCTL")); 318 KASSERT(gio->func != NULL, ("NULL function but EDIRIOCTL")); 319 error = (gio->func)(gio->dev, cmd, data, fflag, td); 320 } 321 g_waitidle(); 322 if (gio != NULL && (error == EOPNOTSUPP || error == ENOIOCTL)) { 323 if (g_debugflags & G_T_TOPOLOGY) { 324 i = IOCGROUP(cmd); 325 printf("IOCTL(0x%lx) \"%s\"", cmd, gp->name); 326 if (i > ' ' && i <= '~') 327 printf(" '%c'", (int)IOCGROUP(cmd)); 328 else 329 printf(" 0x%lx", IOCGROUP(cmd)); 330 printf("/%ld ", cmd & 0xff); 331 if (cmd & IOC_IN) 332 printf("I"); 333 if (cmd & IOC_OUT) 334 printf("O"); 335 printf("(%ld) = ENOIOCTL\n", IOCPARM_LEN(cmd)); 336 } 337 error = ENOTTY; 338 } 339 if (gio != NULL) 340 g_free(gio); 341 return (error); 342} 343 344static void 345g_dev_done(struct bio *bp2) 346{ 347 struct bio *bp; 348 349 bp = bp2->bio_parent; 350 bp->bio_error = bp2->bio_error; 351 if (bp->bio_error != 0) { 352 g_trace(G_T_BIO, "g_dev_done(%p) had error %d", 353 bp2, bp->bio_error); 354 bp->bio_flags |= BIO_ERROR; 355 } else { 356 g_trace(G_T_BIO, "g_dev_done(%p/%p) resid %ld completed %jd", 357 bp2, bp, bp->bio_resid, (intmax_t)bp2->bio_completed); 358 } 359 bp->bio_resid = bp->bio_bcount - bp2->bio_completed; 360 g_destroy_bio(bp2); 361 mtx_lock(&Giant); 362 biodone(bp); 363 mtx_unlock(&Giant); 364} 365 366static void 367g_dev_strategy(struct bio *bp) 368{ 369 struct g_geom *gp; 370 struct g_consumer *cp; 371 struct bio *bp2; 372 dev_t dev; 373 374 KASSERT(bp->bio_cmd == BIO_READ || 375 bp->bio_cmd == BIO_WRITE || 376 bp->bio_cmd == BIO_DELETE, 377 ("Wrong bio_cmd bio=%p cmd=%d", bp, bp->bio_cmd)); 378 dev = bp->bio_dev; 379 gp = dev->si_drv1; 380 cp = dev->si_drv2; 381 bp2 = g_clone_bio(bp); 382 KASSERT(bp2 != NULL, ("XXX: ENOMEM in a bad place")); 383 bp2->bio_offset = (off_t)bp->bio_blkno << DEV_BSHIFT; 384 KASSERT(bp2->bio_offset >= 0, 385 ("Negative bio_offset (%jd) on bio %p", 386 (intmax_t)bp2->bio_offset, bp)); 387 bp2->bio_length = (off_t)bp->bio_bcount; 388 bp2->bio_done = g_dev_done; 389 g_trace(G_T_BIO, 390 "g_dev_strategy(%p/%p) offset %jd length %jd data %p cmd %d", 391 bp, bp2, (intmax_t)bp->bio_offset, (intmax_t)bp2->bio_length, 392 bp2->bio_data, bp2->bio_cmd); 393 g_io_request(bp2, cp); 394} 395 396/* 397 * g_dev_orphan() 398 * 399 * Called from below when the provider orphaned us. 400 * - Clear any dump settings. 401 * - Destroy the dev_t to prevent any more request from coming in. The 402 * provider is already marked with an error, so anything which comes in 403 * in the interrim will be returned immediately. 404 * - Wait for any outstanding I/O to finish. 405 * - Set our access counts to zero, whatever they were. 406 * - Detach and self-destruct. 407 */ 408 409static void 410g_dev_orphan(struct g_consumer *cp) 411{ 412 struct g_geom *gp; 413 dev_t dev; 414 415 g_topology_assert(); 416 gp = cp->geom; 417 dev = gp->softc; 418 g_trace(G_T_TOPOLOGY, "g_dev_orphan(%p(%s))", cp, gp->name); 419 420 /* Reset any dump-area set on this device */ 421 if (dev->si_flags & SI_DUMPDEV) 422 set_dumper(NULL); 423 424 /* Destroy the dev_t so we get no more requests */ 425 destroy_dev(dev); 426 427 /* Wait for the cows to come home */ 428 while (cp->nstart != cp->nend) 429 msleep(&dev, NULL, PRIBIO, "gdevorphan", 1); 430 431 if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0) 432 g_access_rel(cp, -cp->acr, -cp->acw, -cp->ace); 433 434 g_detach(cp); 435 g_destroy_consumer(cp); 436 g_destroy_geom(gp); 437} 438 439DECLARE_GEOM_CLASS(g_dev_class, g_dev);
| 77 G_CLASS_INITIALIZER 78}; 79 80int 81g_dev_print(void) 82{ 83 struct g_geom *gp; 84 85 if (LIST_EMPTY(&g_dev_class.geom)) 86 return (0); 87 printf("List of GEOM disk devices:\n "); 88 LIST_FOREACH(gp, &g_dev_class.geom, geom) 89 printf(" %s", gp->name); 90 printf("\n"); 91 return (1); 92} 93 94/* 95 * XXX: This is disgusting and wrong in every way imaginable: The only reason 96 * XXX: we have a clone function is because of the root-mount hack we currently 97 * XXX: employ. An improvment would be to unregister this cloner once we know 98 * XXX: we no longer need it. Ideally, root-fs would be mounted through DEVFS 99 * XXX: eliminating the need for this hack. 100 */ 101static void 102g_dev_clone(void *arg __unused, char *name, int namelen __unused, dev_t *dev) 103{ 104 struct g_geom *gp; 105 106 if (*dev != NODEV) 107 return; 108 109 g_waitidle(); 110 111 /* g_topology_lock(); */ 112 LIST_FOREACH(gp, &g_dev_class.geom, geom) { 113 if (strcmp(gp->name, name)) 114 continue; 115 *dev = gp->softc; 116 g_trace(G_T_TOPOLOGY, "g_dev_clone(%s) = %p", name, *dev); 117 return; 118 } 119 /* g_topology_unlock(); */ 120 return; 121} 122 123static void 124g_dev_register_cloner(void *foo __unused) 125{ 126 static int once; 127 128 /* XXX: why would this happen more than once ?? */ 129 if (!once) { 130 EVENTHANDLER_REGISTER(dev_clone, g_dev_clone, 0, 1000); 131 once++; 132 } 133} 134 135SYSINIT(geomdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE,g_dev_register_cloner,NULL); 136 137static struct g_geom * 138g_dev_taste(struct g_class *mp, struct g_provider *pp, int insist __unused) 139{ 140 struct g_geom *gp; 141 struct g_consumer *cp; 142 static int unit = GEOM_MINOR_PROVIDERS; 143 int error; 144 dev_t dev; 145 146 g_trace(G_T_TOPOLOGY, "dev_taste(%s,%s)", mp->name, pp->name); 147 g_topology_assert(); 148 LIST_FOREACH(cp, &pp->consumers, consumers) 149 if (cp->geom->class == mp) 150 return (NULL); 151 gp = g_new_geomf(mp, pp->name); 152 gp->orphan = g_dev_orphan; 153 cp = g_new_consumer(gp); 154 error = g_attach(cp, pp); 155 KASSERT(error == 0, 156 ("g_dev_taste(%s) failed to g_attach, err=%d", pp->name, error)); 157 /* 158 * XXX: I'm not 100% sure we can call make_dev(9) without Giant 159 * yet. Once we can, we don't need to drop topology here either. 160 */ 161 g_topology_unlock(); 162 mtx_lock(&Giant); 163 dev = make_dev(&g_dev_cdevsw, unit2minor(unit++), 164 UID_ROOT, GID_OPERATOR, 0640, gp->name); 165 if (pp->flags & G_PF_CANDELETE) 166 dev->si_flags |= SI_CANDELETE; 167 mtx_unlock(&Giant); 168 g_topology_lock(); 169 dev->si_iosize_max = MAXPHYS; 170 dev->si_stripesize = pp->stripesize; 171 dev->si_stripeoffset = pp->stripeoffset; 172 gp->softc = dev; 173 dev->si_drv1 = gp; 174 dev->si_drv2 = cp; 175 return (gp); 176} 177 178static int 179g_dev_open(dev_t dev, int flags, int fmt, struct thread *td) 180{ 181 struct g_geom *gp; 182 struct g_consumer *cp; 183 int error, r, w, e; 184 185 gp = dev->si_drv1; 186 cp = dev->si_drv2; 187 if (gp == NULL || cp == NULL) 188 return(ENXIO); 189 g_trace(G_T_ACCESS, "g_dev_open(%s, %d, %d, %p)", 190 gp->name, flags, fmt, td); 191 DROP_GIANT(); 192 g_topology_lock(); 193 r = flags & FREAD ? 1 : 0; 194 w = flags & FWRITE ? 1 : 0; 195#ifdef notyet 196 e = flags & O_EXCL ? 1 : 0; 197#else 198 e = 0; 199#endif 200 error = g_access_rel(cp, r, w, e); 201 g_topology_unlock(); 202 PICKUP_GIANT(); 203 g_waitidle(); 204 dev->si_bsize_phys = cp->provider->sectorsize; 205 return(error); 206} 207 208static int 209g_dev_close(dev_t dev, int flags, int fmt, struct thread *td) 210{ 211 struct g_geom *gp; 212 struct g_consumer *cp; 213 int error, r, w, e; 214 215 gp = dev->si_drv1; 216 cp = dev->si_drv2; 217 if (gp == NULL || cp == NULL) 218 return(ENXIO); 219 g_trace(G_T_ACCESS, "g_dev_close(%s, %d, %d, %p)", 220 gp->name, flags, fmt, td); 221 DROP_GIANT(); 222 g_topology_lock(); 223 r = flags & FREAD ? -1 : 0; 224 w = flags & FWRITE ? -1 : 0; 225#ifdef notyet 226 e = flags & O_EXCL ? -1 : 0; 227#else 228 e = 0; 229#endif 230 error = g_access_rel(cp, r, w, e); 231 g_topology_unlock(); 232 PICKUP_GIANT(); 233 g_waitidle(); 234 return (error); 235} 236 237static int 238g_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td) 239{ 240 struct g_geom *gp, *gp2; 241 struct g_consumer *cp; 242 struct g_provider *pp2; 243 struct g_kerneldump kd; 244 int i, error; 245 u_int u; 246 struct g_ioctl *gio; 247 248 gp = dev->si_drv1; 249 cp = dev->si_drv2; 250 pp2 = cp->provider; 251 gp2 = pp2->geom; 252 gio = NULL; 253 254 error = 0; 255 DROP_GIANT(); 256 257 gio = NULL; 258 i = IOCPARM_LEN(cmd); 259 switch (cmd) { 260 case DIOCGSECTORSIZE: 261 *(u_int *)data = cp->provider->sectorsize; 262 if (*(u_int *)data == 0) 263 error = ENOENT; 264 break; 265 case DIOCGMEDIASIZE: 266 *(off_t *)data = cp->provider->mediasize; 267 if (*(off_t *)data == 0) 268 error = ENOENT; 269 break; 270 case DIOCGFWSECTORS: 271 error = g_io_getattr("GEOM::fwsectors", cp, &i, data); 272 if (error == 0 && *(u_int *)data == 0) 273 error = ENOENT; 274 break; 275 case DIOCGFWHEADS: 276 error = g_io_getattr("GEOM::fwheads", cp, &i, data); 277 if (error == 0 && *(u_int *)data == 0) 278 error = ENOENT; 279 break; 280 case DIOCGFRONTSTUFF: 281 error = g_io_getattr("GEOM::frontstuff", cp, &i, data); 282 break; 283 case DIOCSKERNELDUMP: 284 u = *((u_int *)data); 285 if (!u) { 286 set_dumper(NULL); 287 error = 0; 288 break; 289 } 290 kd.offset = 0; 291 kd.length = OFF_MAX; 292 i = sizeof kd; 293 error = g_io_getattr("GEOM::kerneldump", cp, &i, &kd); 294 if (!error) 295 dev->si_flags |= SI_DUMPDEV; 296 break; 297 298 default: 299 gio = g_malloc(sizeof *gio, M_WAITOK | M_ZERO); 300 gio->cmd = cmd; 301 gio->data = data; 302 gio->fflag = fflag; 303 gio->td = td; 304 i = sizeof *gio; 305 /* 306 * We always issue ioctls as getattr since the direction of data 307 * movement in ioctl is no indication of the ioctl being a "set" 308 * or "get" type ioctl or if such simplistic terms even apply 309 */ 310 error = g_io_getattr("GEOM::ioctl", cp, &i, gio); 311 break; 312 } 313 314 PICKUP_GIANT(); 315 if (error == EDIRIOCTL) { 316 KASSERT(gio != NULL, ("NULL gio but EDIRIOCTL")); 317 KASSERT(gio->func != NULL, ("NULL function but EDIRIOCTL")); 318 error = (gio->func)(gio->dev, cmd, data, fflag, td); 319 } 320 g_waitidle(); 321 if (gio != NULL && (error == EOPNOTSUPP || error == ENOIOCTL)) { 322 if (g_debugflags & G_T_TOPOLOGY) { 323 i = IOCGROUP(cmd); 324 printf("IOCTL(0x%lx) \"%s\"", cmd, gp->name); 325 if (i > ' ' && i <= '~') 326 printf(" '%c'", (int)IOCGROUP(cmd)); 327 else 328 printf(" 0x%lx", IOCGROUP(cmd)); 329 printf("/%ld ", cmd & 0xff); 330 if (cmd & IOC_IN) 331 printf("I"); 332 if (cmd & IOC_OUT) 333 printf("O"); 334 printf("(%ld) = ENOIOCTL\n", IOCPARM_LEN(cmd)); 335 } 336 error = ENOTTY; 337 } 338 if (gio != NULL) 339 g_free(gio); 340 return (error); 341} 342 343static void 344g_dev_done(struct bio *bp2) 345{ 346 struct bio *bp; 347 348 bp = bp2->bio_parent; 349 bp->bio_error = bp2->bio_error; 350 if (bp->bio_error != 0) { 351 g_trace(G_T_BIO, "g_dev_done(%p) had error %d", 352 bp2, bp->bio_error); 353 bp->bio_flags |= BIO_ERROR; 354 } else { 355 g_trace(G_T_BIO, "g_dev_done(%p/%p) resid %ld completed %jd", 356 bp2, bp, bp->bio_resid, (intmax_t)bp2->bio_completed); 357 } 358 bp->bio_resid = bp->bio_bcount - bp2->bio_completed; 359 g_destroy_bio(bp2); 360 mtx_lock(&Giant); 361 biodone(bp); 362 mtx_unlock(&Giant); 363} 364 365static void 366g_dev_strategy(struct bio *bp) 367{ 368 struct g_geom *gp; 369 struct g_consumer *cp; 370 struct bio *bp2; 371 dev_t dev; 372 373 KASSERT(bp->bio_cmd == BIO_READ || 374 bp->bio_cmd == BIO_WRITE || 375 bp->bio_cmd == BIO_DELETE, 376 ("Wrong bio_cmd bio=%p cmd=%d", bp, bp->bio_cmd)); 377 dev = bp->bio_dev; 378 gp = dev->si_drv1; 379 cp = dev->si_drv2; 380 bp2 = g_clone_bio(bp); 381 KASSERT(bp2 != NULL, ("XXX: ENOMEM in a bad place")); 382 bp2->bio_offset = (off_t)bp->bio_blkno << DEV_BSHIFT; 383 KASSERT(bp2->bio_offset >= 0, 384 ("Negative bio_offset (%jd) on bio %p", 385 (intmax_t)bp2->bio_offset, bp)); 386 bp2->bio_length = (off_t)bp->bio_bcount; 387 bp2->bio_done = g_dev_done; 388 g_trace(G_T_BIO, 389 "g_dev_strategy(%p/%p) offset %jd length %jd data %p cmd %d", 390 bp, bp2, (intmax_t)bp->bio_offset, (intmax_t)bp2->bio_length, 391 bp2->bio_data, bp2->bio_cmd); 392 g_io_request(bp2, cp); 393} 394 395/* 396 * g_dev_orphan() 397 * 398 * Called from below when the provider orphaned us. 399 * - Clear any dump settings. 400 * - Destroy the dev_t to prevent any more request from coming in. The 401 * provider is already marked with an error, so anything which comes in 402 * in the interrim will be returned immediately. 403 * - Wait for any outstanding I/O to finish. 404 * - Set our access counts to zero, whatever they were. 405 * - Detach and self-destruct. 406 */ 407 408static void 409g_dev_orphan(struct g_consumer *cp) 410{ 411 struct g_geom *gp; 412 dev_t dev; 413 414 g_topology_assert(); 415 gp = cp->geom; 416 dev = gp->softc; 417 g_trace(G_T_TOPOLOGY, "g_dev_orphan(%p(%s))", cp, gp->name); 418 419 /* Reset any dump-area set on this device */ 420 if (dev->si_flags & SI_DUMPDEV) 421 set_dumper(NULL); 422 423 /* Destroy the dev_t so we get no more requests */ 424 destroy_dev(dev); 425 426 /* Wait for the cows to come home */ 427 while (cp->nstart != cp->nend) 428 msleep(&dev, NULL, PRIBIO, "gdevorphan", 1); 429 430 if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0) 431 g_access_rel(cp, -cp->acr, -cp->acw, -cp->ace); 432 433 g_detach(cp); 434 g_destroy_consumer(cp); 435 g_destroy_geom(gp); 436} 437 438DECLARE_GEOM_CLASS(g_dev_class, g_dev);
|