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