xref: /freebsd/sys/geom/geom_io.c (revision ee75e7de7be45027fa02ffbc673446d97f83e0b8)
1dd84a43cSPoul-Henning Kamp /*-
2dd84a43cSPoul-Henning Kamp  * Copyright (c) 2002 Poul-Henning Kamp
3dd84a43cSPoul-Henning Kamp  * Copyright (c) 2002 Networks Associates Technology, Inc.
4*ee75e7deSKonstantin Belousov  * Copyright (c) 2013 The FreeBSD Foundation
5dd84a43cSPoul-Henning Kamp  * All rights reserved.
6dd84a43cSPoul-Henning Kamp  *
7dd84a43cSPoul-Henning Kamp  * This software was developed for the FreeBSD Project by Poul-Henning Kamp
8dd84a43cSPoul-Henning Kamp  * and NAI Labs, the Security Research Division of Network Associates, Inc.
9dd84a43cSPoul-Henning Kamp  * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
10dd84a43cSPoul-Henning Kamp  * DARPA CHATS research program.
11dd84a43cSPoul-Henning Kamp  *
12*ee75e7deSKonstantin Belousov  * Portions of this software were developed by Konstantin Belousov
13*ee75e7deSKonstantin Belousov  * under sponsorship from the FreeBSD Foundation.
14*ee75e7deSKonstantin Belousov  *
15dd84a43cSPoul-Henning Kamp  * Redistribution and use in source and binary forms, with or without
16dd84a43cSPoul-Henning Kamp  * modification, are permitted provided that the following conditions
17dd84a43cSPoul-Henning Kamp  * are met:
18dd84a43cSPoul-Henning Kamp  * 1. Redistributions of source code must retain the above copyright
19dd84a43cSPoul-Henning Kamp  *    notice, this list of conditions and the following disclaimer.
20dd84a43cSPoul-Henning Kamp  * 2. Redistributions in binary form must reproduce the above copyright
21dd84a43cSPoul-Henning Kamp  *    notice, this list of conditions and the following disclaimer in the
22dd84a43cSPoul-Henning Kamp  *    documentation and/or other materials provided with the distribution.
23dd84a43cSPoul-Henning Kamp  * 3. The names of the authors may not be used to endorse or promote
24dd84a43cSPoul-Henning Kamp  *    products derived from this software without specific prior written
25dd84a43cSPoul-Henning Kamp  *    permission.
26dd84a43cSPoul-Henning Kamp  *
27dd84a43cSPoul-Henning Kamp  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28dd84a43cSPoul-Henning Kamp  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29dd84a43cSPoul-Henning Kamp  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30dd84a43cSPoul-Henning Kamp  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
31dd84a43cSPoul-Henning Kamp  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32dd84a43cSPoul-Henning Kamp  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33dd84a43cSPoul-Henning Kamp  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34dd84a43cSPoul-Henning Kamp  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35dd84a43cSPoul-Henning Kamp  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36dd84a43cSPoul-Henning Kamp  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37dd84a43cSPoul-Henning Kamp  * SUCH DAMAGE.
38dd84a43cSPoul-Henning Kamp  */
39dd84a43cSPoul-Henning Kamp 
4050b1faefSDavid E. O'Brien #include <sys/cdefs.h>
4150b1faefSDavid E. O'Brien __FBSDID("$FreeBSD$");
42dd84a43cSPoul-Henning Kamp 
43dd84a43cSPoul-Henning Kamp #include <sys/param.h>
44dd84a43cSPoul-Henning Kamp #include <sys/systm.h>
45dd84a43cSPoul-Henning Kamp #include <sys/kernel.h>
46dd84a43cSPoul-Henning Kamp #include <sys/malloc.h>
47dd84a43cSPoul-Henning Kamp #include <sys/bio.h>
4849dbb61dSRobert Watson #include <sys/ktr.h>
4951460da8SJohn Baldwin #include <sys/proc.h>
503b378147SPawel Jakub Dawidek #include <sys/stack.h>
51*ee75e7deSKonstantin Belousov #include <sys/sysctl.h>
52dd84a43cSPoul-Henning Kamp 
53dd84a43cSPoul-Henning Kamp #include <sys/errno.h>
54dd84a43cSPoul-Henning Kamp #include <geom/geom.h>
55b1876192SPoul-Henning Kamp #include <geom/geom_int.h>
56e24cbd90SPoul-Henning Kamp #include <sys/devicestat.h>
57dd84a43cSPoul-Henning Kamp 
585ffb2c8bSPoul-Henning Kamp #include <vm/uma.h>
59*ee75e7deSKonstantin Belousov #include <vm/vm.h>
60*ee75e7deSKonstantin Belousov #include <vm/vm_param.h>
61*ee75e7deSKonstantin Belousov #include <vm/vm_kern.h>
62*ee75e7deSKonstantin Belousov #include <vm/vm_page.h>
63*ee75e7deSKonstantin Belousov #include <vm/vm_object.h>
64*ee75e7deSKonstantin Belousov #include <vm/vm_extern.h>
65*ee75e7deSKonstantin Belousov #include <vm/vm_map.h>
665ffb2c8bSPoul-Henning Kamp 
67dd84a43cSPoul-Henning Kamp static struct g_bioq g_bio_run_down;
68dd84a43cSPoul-Henning Kamp static struct g_bioq g_bio_run_up;
695fcf4e43SPoul-Henning Kamp static struct g_bioq g_bio_run_task;
70dd84a43cSPoul-Henning Kamp 
713432e4fdSPoul-Henning Kamp static u_int pace;
725ffb2c8bSPoul-Henning Kamp static uma_zone_t	biozone;
733432e4fdSPoul-Henning Kamp 
746231f75bSLuigi Rizzo /*
756231f75bSLuigi Rizzo  * The head of the list of classifiers used in g_io_request.
766231f75bSLuigi Rizzo  * Use g_register_classifier() and g_unregister_classifier()
776231f75bSLuigi Rizzo  * to add/remove entries to the list.
786231f75bSLuigi Rizzo  * Classifiers are invoked in registration order.
796231f75bSLuigi Rizzo  */
806231f75bSLuigi Rizzo static TAILQ_HEAD(g_classifier_tailq, g_classifier_hook)
816231f75bSLuigi Rizzo     g_classifier_tailq = TAILQ_HEAD_INITIALIZER(g_classifier_tailq);
826231f75bSLuigi Rizzo 
83dd84a43cSPoul-Henning Kamp #include <machine/atomic.h>
84dd84a43cSPoul-Henning Kamp 
85dd84a43cSPoul-Henning Kamp static void
86dd84a43cSPoul-Henning Kamp g_bioq_lock(struct g_bioq *bq)
87dd84a43cSPoul-Henning Kamp {
88dd84a43cSPoul-Henning Kamp 
89dd84a43cSPoul-Henning Kamp 	mtx_lock(&bq->bio_queue_lock);
90dd84a43cSPoul-Henning Kamp }
91dd84a43cSPoul-Henning Kamp 
92dd84a43cSPoul-Henning Kamp static void
93dd84a43cSPoul-Henning Kamp g_bioq_unlock(struct g_bioq *bq)
94dd84a43cSPoul-Henning Kamp {
95dd84a43cSPoul-Henning Kamp 
96dd84a43cSPoul-Henning Kamp 	mtx_unlock(&bq->bio_queue_lock);
97dd84a43cSPoul-Henning Kamp }
98dd84a43cSPoul-Henning Kamp 
99dd84a43cSPoul-Henning Kamp #if 0
100dd84a43cSPoul-Henning Kamp static void
101dd84a43cSPoul-Henning Kamp g_bioq_destroy(struct g_bioq *bq)
102dd84a43cSPoul-Henning Kamp {
103dd84a43cSPoul-Henning Kamp 
104dd84a43cSPoul-Henning Kamp 	mtx_destroy(&bq->bio_queue_lock);
105dd84a43cSPoul-Henning Kamp }
106dd84a43cSPoul-Henning Kamp #endif
107dd84a43cSPoul-Henning Kamp 
108dd84a43cSPoul-Henning Kamp static void
109dd84a43cSPoul-Henning Kamp g_bioq_init(struct g_bioq *bq)
110dd84a43cSPoul-Henning Kamp {
111dd84a43cSPoul-Henning Kamp 
112dd84a43cSPoul-Henning Kamp 	TAILQ_INIT(&bq->bio_queue);
1136008862bSJohn Baldwin 	mtx_init(&bq->bio_queue_lock, "bio queue", NULL, MTX_DEF);
114dd84a43cSPoul-Henning Kamp }
115dd84a43cSPoul-Henning Kamp 
116dd84a43cSPoul-Henning Kamp static struct bio *
117dd84a43cSPoul-Henning Kamp g_bioq_first(struct g_bioq *bq)
118dd84a43cSPoul-Henning Kamp {
119dd84a43cSPoul-Henning Kamp 	struct bio *bp;
120dd84a43cSPoul-Henning Kamp 
121dd84a43cSPoul-Henning Kamp 	bp = TAILQ_FIRST(&bq->bio_queue);
122dd84a43cSPoul-Henning Kamp 	if (bp != NULL) {
123dcbd0fe5SPoul-Henning Kamp 		KASSERT((bp->bio_flags & BIO_ONQUEUE),
124dcbd0fe5SPoul-Henning Kamp 		    ("Bio not on queue bp=%p target %p", bp, bq));
125dcbd0fe5SPoul-Henning Kamp 		bp->bio_flags &= ~BIO_ONQUEUE;
126dd84a43cSPoul-Henning Kamp 		TAILQ_REMOVE(&bq->bio_queue, bp, bio_queue);
127dd84a43cSPoul-Henning Kamp 		bq->bio_queue_length--;
128dd84a43cSPoul-Henning Kamp 	}
129dd84a43cSPoul-Henning Kamp 	return (bp);
130dd84a43cSPoul-Henning Kamp }
131dd84a43cSPoul-Henning Kamp 
132dd84a43cSPoul-Henning Kamp struct bio *
133dd84a43cSPoul-Henning Kamp g_new_bio(void)
134dd84a43cSPoul-Henning Kamp {
135dd84a43cSPoul-Henning Kamp 	struct bio *bp;
136dd84a43cSPoul-Henning Kamp 
1375ffb2c8bSPoul-Henning Kamp 	bp = uma_zalloc(biozone, M_NOWAIT | M_ZERO);
1383b378147SPawel Jakub Dawidek #ifdef KTR
139b656c1b8SPawel Jakub Dawidek 	if ((KTR_COMPILE & KTR_GEOM) && (ktr_mask & KTR_GEOM)) {
1403b378147SPawel Jakub Dawidek 		struct stack st;
1413b378147SPawel Jakub Dawidek 
1423b378147SPawel Jakub Dawidek 		CTR1(KTR_GEOM, "g_new_bio(): %p", bp);
1433b378147SPawel Jakub Dawidek 		stack_save(&st);
1443b378147SPawel Jakub Dawidek 		CTRSTACK(KTR_GEOM, &st, 3, 0);
1453b378147SPawel Jakub Dawidek 	}
1463b378147SPawel Jakub Dawidek #endif
147dd84a43cSPoul-Henning Kamp 	return (bp);
148dd84a43cSPoul-Henning Kamp }
149dd84a43cSPoul-Henning Kamp 
150a2033c96SPoul-Henning Kamp struct bio *
151a2033c96SPoul-Henning Kamp g_alloc_bio(void)
152a2033c96SPoul-Henning Kamp {
153a2033c96SPoul-Henning Kamp 	struct bio *bp;
154a2033c96SPoul-Henning Kamp 
155a2033c96SPoul-Henning Kamp 	bp = uma_zalloc(biozone, M_WAITOK | M_ZERO);
1563b378147SPawel Jakub Dawidek #ifdef KTR
157b656c1b8SPawel Jakub Dawidek 	if ((KTR_COMPILE & KTR_GEOM) && (ktr_mask & KTR_GEOM)) {
1583b378147SPawel Jakub Dawidek 		struct stack st;
1593b378147SPawel Jakub Dawidek 
1603b378147SPawel Jakub Dawidek 		CTR1(KTR_GEOM, "g_alloc_bio(): %p", bp);
1613b378147SPawel Jakub Dawidek 		stack_save(&st);
1623b378147SPawel Jakub Dawidek 		CTRSTACK(KTR_GEOM, &st, 3, 0);
1633b378147SPawel Jakub Dawidek 	}
1643b378147SPawel Jakub Dawidek #endif
165a2033c96SPoul-Henning Kamp 	return (bp);
166a2033c96SPoul-Henning Kamp }
167a2033c96SPoul-Henning Kamp 
168dd84a43cSPoul-Henning Kamp void
169dd84a43cSPoul-Henning Kamp g_destroy_bio(struct bio *bp)
170dd84a43cSPoul-Henning Kamp {
1713b378147SPawel Jakub Dawidek #ifdef KTR
172b656c1b8SPawel Jakub Dawidek 	if ((KTR_COMPILE & KTR_GEOM) && (ktr_mask & KTR_GEOM)) {
1733b378147SPawel Jakub Dawidek 		struct stack st;
174dd84a43cSPoul-Henning Kamp 
1753b378147SPawel Jakub Dawidek 		CTR1(KTR_GEOM, "g_destroy_bio(): %p", bp);
1763b378147SPawel Jakub Dawidek 		stack_save(&st);
1773b378147SPawel Jakub Dawidek 		CTRSTACK(KTR_GEOM, &st, 3, 0);
1783b378147SPawel Jakub Dawidek 	}
1793b378147SPawel Jakub Dawidek #endif
1805ffb2c8bSPoul-Henning Kamp 	uma_zfree(biozone, bp);
181dd84a43cSPoul-Henning Kamp }
182dd84a43cSPoul-Henning Kamp 
183dd84a43cSPoul-Henning Kamp struct bio *
184dd84a43cSPoul-Henning Kamp g_clone_bio(struct bio *bp)
185dd84a43cSPoul-Henning Kamp {
186dd84a43cSPoul-Henning Kamp 	struct bio *bp2;
187dd84a43cSPoul-Henning Kamp 
1885ffb2c8bSPoul-Henning Kamp 	bp2 = uma_zalloc(biozone, M_NOWAIT | M_ZERO);
189a1bd3ee2SPoul-Henning Kamp 	if (bp2 != NULL) {
190936cc461SPoul-Henning Kamp 		bp2->bio_parent = bp;
191dd84a43cSPoul-Henning Kamp 		bp2->bio_cmd = bp->bio_cmd;
19282a6ae10SJim Harris 		/*
19382a6ae10SJim Harris 		 *  BIO_ORDERED flag may be used by disk drivers to enforce
19482a6ae10SJim Harris 		 *  ordering restrictions, so this flag needs to be cloned.
195*ee75e7deSKonstantin Belousov 		 *  BIO_UNMAPPED should be inherited, to properly indicate
196*ee75e7deSKonstantin Belousov 		 *  which way the buffer is passed.
19782a6ae10SJim Harris 		 *  Other bio flags are not suitable for cloning.
19882a6ae10SJim Harris 		 */
199*ee75e7deSKonstantin Belousov 		bp2->bio_flags = bp->bio_flags & (BIO_ORDERED | BIO_UNMAPPED);
200dd84a43cSPoul-Henning Kamp 		bp2->bio_length = bp->bio_length;
201dd84a43cSPoul-Henning Kamp 		bp2->bio_offset = bp->bio_offset;
202dd84a43cSPoul-Henning Kamp 		bp2->bio_data = bp->bio_data;
203*ee75e7deSKonstantin Belousov 		bp2->bio_ma = bp->bio_ma;
204*ee75e7deSKonstantin Belousov 		bp2->bio_ma_n = bp->bio_ma_n;
205*ee75e7deSKonstantin Belousov 		bp2->bio_ma_offset = bp->bio_ma_offset;
206dd84a43cSPoul-Henning Kamp 		bp2->bio_attribute = bp->bio_attribute;
2076231f75bSLuigi Rizzo 		/* Inherit classification info from the parent */
2086231f75bSLuigi Rizzo 		bp2->bio_classifier1 = bp->bio_classifier1;
2096231f75bSLuigi Rizzo 		bp2->bio_classifier2 = bp->bio_classifier2;
210801bb689SPoul-Henning Kamp 		bp->bio_children++;
211a1bd3ee2SPoul-Henning Kamp 	}
2123b378147SPawel Jakub Dawidek #ifdef KTR
213b656c1b8SPawel Jakub Dawidek 	if ((KTR_COMPILE & KTR_GEOM) && (ktr_mask & KTR_GEOM)) {
2143b378147SPawel Jakub Dawidek 		struct stack st;
2153b378147SPawel Jakub Dawidek 
216ad572235SRuslan Ermilov 		CTR2(KTR_GEOM, "g_clone_bio(%p): %p", bp, bp2);
2173b378147SPawel Jakub Dawidek 		stack_save(&st);
2183b378147SPawel Jakub Dawidek 		CTRSTACK(KTR_GEOM, &st, 3, 0);
2193b378147SPawel Jakub Dawidek 	}
2203b378147SPawel Jakub Dawidek #endif
221dd84a43cSPoul-Henning Kamp 	return(bp2);
222dd84a43cSPoul-Henning Kamp }
223dd84a43cSPoul-Henning Kamp 
2244bec0ff1SPawel Jakub Dawidek struct bio *
2254bec0ff1SPawel Jakub Dawidek g_duplicate_bio(struct bio *bp)
2264bec0ff1SPawel Jakub Dawidek {
2274bec0ff1SPawel Jakub Dawidek 	struct bio *bp2;
2284bec0ff1SPawel Jakub Dawidek 
2294bec0ff1SPawel Jakub Dawidek 	bp2 = uma_zalloc(biozone, M_WAITOK | M_ZERO);
230*ee75e7deSKonstantin Belousov 	bp2->bio_flags = bp->bio_flags & BIO_UNMAPPED;
2314bec0ff1SPawel Jakub Dawidek 	bp2->bio_parent = bp;
2324bec0ff1SPawel Jakub Dawidek 	bp2->bio_cmd = bp->bio_cmd;
2334bec0ff1SPawel Jakub Dawidek 	bp2->bio_length = bp->bio_length;
2344bec0ff1SPawel Jakub Dawidek 	bp2->bio_offset = bp->bio_offset;
2354bec0ff1SPawel Jakub Dawidek 	bp2->bio_data = bp->bio_data;
236*ee75e7deSKonstantin Belousov 	bp2->bio_ma = bp->bio_ma;
237*ee75e7deSKonstantin Belousov 	bp2->bio_ma_n = bp->bio_ma_n;
238*ee75e7deSKonstantin Belousov 	bp2->bio_ma_offset = bp->bio_ma_offset;
2394bec0ff1SPawel Jakub Dawidek 	bp2->bio_attribute = bp->bio_attribute;
2404bec0ff1SPawel Jakub Dawidek 	bp->bio_children++;
2414bec0ff1SPawel Jakub Dawidek #ifdef KTR
242b656c1b8SPawel Jakub Dawidek 	if ((KTR_COMPILE & KTR_GEOM) && (ktr_mask & KTR_GEOM)) {
2434bec0ff1SPawel Jakub Dawidek 		struct stack st;
2444bec0ff1SPawel Jakub Dawidek 
2454bec0ff1SPawel Jakub Dawidek 		CTR2(KTR_GEOM, "g_duplicate_bio(%p): %p", bp, bp2);
2464bec0ff1SPawel Jakub Dawidek 		stack_save(&st);
2474bec0ff1SPawel Jakub Dawidek 		CTRSTACK(KTR_GEOM, &st, 3, 0);
2484bec0ff1SPawel Jakub Dawidek 	}
2494bec0ff1SPawel Jakub Dawidek #endif
2504bec0ff1SPawel Jakub Dawidek 	return(bp2);
2514bec0ff1SPawel Jakub Dawidek }
2524bec0ff1SPawel Jakub Dawidek 
253dd84a43cSPoul-Henning Kamp void
254dd84a43cSPoul-Henning Kamp g_io_init()
255dd84a43cSPoul-Henning Kamp {
256dd84a43cSPoul-Henning Kamp 
257dd84a43cSPoul-Henning Kamp 	g_bioq_init(&g_bio_run_down);
258dd84a43cSPoul-Henning Kamp 	g_bioq_init(&g_bio_run_up);
2595fcf4e43SPoul-Henning Kamp 	g_bioq_init(&g_bio_run_task);
2605ffb2c8bSPoul-Henning Kamp 	biozone = uma_zcreate("g_bio", sizeof (struct bio),
2615ffb2c8bSPoul-Henning Kamp 	    NULL, NULL,
2625ffb2c8bSPoul-Henning Kamp 	    NULL, NULL,
2635ffb2c8bSPoul-Henning Kamp 	    0, 0);
264dd84a43cSPoul-Henning Kamp }
265dd84a43cSPoul-Henning Kamp 
266dd84a43cSPoul-Henning Kamp int
2670d3f37a8SPoul-Henning Kamp g_io_getattr(const char *attr, struct g_consumer *cp, int *len, void *ptr)
268dd84a43cSPoul-Henning Kamp {
269dd84a43cSPoul-Henning Kamp 	struct bio *bp;
270dd84a43cSPoul-Henning Kamp 	int error;
271dd84a43cSPoul-Henning Kamp 
272dd84a43cSPoul-Henning Kamp 	g_trace(G_T_BIO, "bio_getattr(%s)", attr);
273a2033c96SPoul-Henning Kamp 	bp = g_alloc_bio();
274dd84a43cSPoul-Henning Kamp 	bp->bio_cmd = BIO_GETATTR;
275dd84a43cSPoul-Henning Kamp 	bp->bio_done = NULL;
276dd84a43cSPoul-Henning Kamp 	bp->bio_attribute = attr;
277dd84a43cSPoul-Henning Kamp 	bp->bio_length = *len;
278dd84a43cSPoul-Henning Kamp 	bp->bio_data = ptr;
279dd84a43cSPoul-Henning Kamp 	g_io_request(bp, cp);
28053706245SPoul-Henning Kamp 	error = biowait(bp, "ggetattr");
281dd84a43cSPoul-Henning Kamp 	*len = bp->bio_completed;
282dd84a43cSPoul-Henning Kamp 	g_destroy_bio(bp);
283dd84a43cSPoul-Henning Kamp 	return (error);
284dd84a43cSPoul-Henning Kamp }
285dd84a43cSPoul-Henning Kamp 
286c3618c65SPawel Jakub Dawidek int
287c3618c65SPawel Jakub Dawidek g_io_flush(struct g_consumer *cp)
288c3618c65SPawel Jakub Dawidek {
289c3618c65SPawel Jakub Dawidek 	struct bio *bp;
290c3618c65SPawel Jakub Dawidek 	int error;
291c3618c65SPawel Jakub Dawidek 
292c3618c65SPawel Jakub Dawidek 	g_trace(G_T_BIO, "bio_flush(%s)", cp->provider->name);
293c3618c65SPawel Jakub Dawidek 	bp = g_alloc_bio();
294c3618c65SPawel Jakub Dawidek 	bp->bio_cmd = BIO_FLUSH;
295f03f7a0cSJustin T. Gibbs 	bp->bio_flags |= BIO_ORDERED;
296c3618c65SPawel Jakub Dawidek 	bp->bio_done = NULL;
297c3618c65SPawel Jakub Dawidek 	bp->bio_attribute = NULL;
298c3618c65SPawel Jakub Dawidek 	bp->bio_offset = cp->provider->mediasize;
299c3618c65SPawel Jakub Dawidek 	bp->bio_length = 0;
300c3618c65SPawel Jakub Dawidek 	bp->bio_data = NULL;
301c3618c65SPawel Jakub Dawidek 	g_io_request(bp, cp);
302c3618c65SPawel Jakub Dawidek 	error = biowait(bp, "gflush");
303c3618c65SPawel Jakub Dawidek 	g_destroy_bio(bp);
304c3618c65SPawel Jakub Dawidek 	return (error);
305c3618c65SPawel Jakub Dawidek }
306c3618c65SPawel Jakub Dawidek 
307e39d70d4SPoul-Henning Kamp static int
308e39d70d4SPoul-Henning Kamp g_io_check(struct bio *bp)
309e39d70d4SPoul-Henning Kamp {
310e39d70d4SPoul-Henning Kamp 	struct g_consumer *cp;
311e39d70d4SPoul-Henning Kamp 	struct g_provider *pp;
312e39d70d4SPoul-Henning Kamp 
313e39d70d4SPoul-Henning Kamp 	cp = bp->bio_from;
314e39d70d4SPoul-Henning Kamp 	pp = bp->bio_to;
315e39d70d4SPoul-Henning Kamp 
316e39d70d4SPoul-Henning Kamp 	/* Fail if access counters dont allow the operation */
317e39d70d4SPoul-Henning Kamp 	switch(bp->bio_cmd) {
318e39d70d4SPoul-Henning Kamp 	case BIO_READ:
319e39d70d4SPoul-Henning Kamp 	case BIO_GETATTR:
320e39d70d4SPoul-Henning Kamp 		if (cp->acr == 0)
321e39d70d4SPoul-Henning Kamp 			return (EPERM);
322e39d70d4SPoul-Henning Kamp 		break;
323e39d70d4SPoul-Henning Kamp 	case BIO_WRITE:
324e39d70d4SPoul-Henning Kamp 	case BIO_DELETE:
325c3618c65SPawel Jakub Dawidek 	case BIO_FLUSH:
326e39d70d4SPoul-Henning Kamp 		if (cp->acw == 0)
327e39d70d4SPoul-Henning Kamp 			return (EPERM);
328e39d70d4SPoul-Henning Kamp 		break;
329e39d70d4SPoul-Henning Kamp 	default:
330e39d70d4SPoul-Henning Kamp 		return (EPERM);
331e39d70d4SPoul-Henning Kamp 	}
332e39d70d4SPoul-Henning Kamp 	/* if provider is marked for error, don't disturb. */
333e39d70d4SPoul-Henning Kamp 	if (pp->error)
334e39d70d4SPoul-Henning Kamp 		return (pp->error);
3353631c638SAlexander Motin 	if (cp->flags & G_CF_ORPHAN)
3363631c638SAlexander Motin 		return (ENXIO);
337e39d70d4SPoul-Henning Kamp 
338e39d70d4SPoul-Henning Kamp 	switch(bp->bio_cmd) {
339e39d70d4SPoul-Henning Kamp 	case BIO_READ:
340e39d70d4SPoul-Henning Kamp 	case BIO_WRITE:
341e39d70d4SPoul-Henning Kamp 	case BIO_DELETE:
3422a842317SAndriy Gapon 		/* Zero sectorsize or mediasize is probably a lack of media. */
3432a842317SAndriy Gapon 		if (pp->sectorsize == 0 || pp->mediasize == 0)
34443bff1a7SPoul-Henning Kamp 			return (ENXIO);
345e39d70d4SPoul-Henning Kamp 		/* Reject I/O not on sector boundary */
346e39d70d4SPoul-Henning Kamp 		if (bp->bio_offset % pp->sectorsize)
347e39d70d4SPoul-Henning Kamp 			return (EINVAL);
348e39d70d4SPoul-Henning Kamp 		/* Reject I/O not integral sector long */
349e39d70d4SPoul-Henning Kamp 		if (bp->bio_length % pp->sectorsize)
350e39d70d4SPoul-Henning Kamp 			return (EINVAL);
351d1b8bf47SPoul-Henning Kamp 		/* Reject requests before or past the end of media. */
352d1b8bf47SPoul-Henning Kamp 		if (bp->bio_offset < 0)
353d1b8bf47SPoul-Henning Kamp 			return (EIO);
354e39d70d4SPoul-Henning Kamp 		if (bp->bio_offset > pp->mediasize)
355e39d70d4SPoul-Henning Kamp 			return (EIO);
356e39d70d4SPoul-Henning Kamp 		break;
357e39d70d4SPoul-Henning Kamp 	default:
358e39d70d4SPoul-Henning Kamp 		break;
359e39d70d4SPoul-Henning Kamp 	}
360e39d70d4SPoul-Henning Kamp 	return (0);
361e39d70d4SPoul-Henning Kamp }
362e39d70d4SPoul-Henning Kamp 
3636231f75bSLuigi Rizzo /*
3646231f75bSLuigi Rizzo  * bio classification support.
3656231f75bSLuigi Rizzo  *
3666231f75bSLuigi Rizzo  * g_register_classifier() and g_unregister_classifier()
3676231f75bSLuigi Rizzo  * are used to add/remove a classifier from the list.
3686231f75bSLuigi Rizzo  * The list is protected using the g_bio_run_down lock,
3696231f75bSLuigi Rizzo  * because the classifiers are called in this path.
3706231f75bSLuigi Rizzo  *
3716231f75bSLuigi Rizzo  * g_io_request() passes bio's that are not already classified
3726231f75bSLuigi Rizzo  * (i.e. those with bio_classifier1 == NULL) to g_run_classifiers().
3736231f75bSLuigi Rizzo  * Classifiers can store their result in the two fields
3746231f75bSLuigi Rizzo  * bio_classifier1 and bio_classifier2.
3756231f75bSLuigi Rizzo  * A classifier that updates one of the fields should
3766231f75bSLuigi Rizzo  * return a non-zero value.
3776231f75bSLuigi Rizzo  * If no classifier updates the field, g_run_classifiers() sets
3786231f75bSLuigi Rizzo  * bio_classifier1 = BIO_NOTCLASSIFIED to avoid further calls.
3796231f75bSLuigi Rizzo  */
3806231f75bSLuigi Rizzo 
3816231f75bSLuigi Rizzo int
3826231f75bSLuigi Rizzo g_register_classifier(struct g_classifier_hook *hook)
3836231f75bSLuigi Rizzo {
3846231f75bSLuigi Rizzo 
3856231f75bSLuigi Rizzo 	g_bioq_lock(&g_bio_run_down);
3866231f75bSLuigi Rizzo 	TAILQ_INSERT_TAIL(&g_classifier_tailq, hook, link);
3876231f75bSLuigi Rizzo 	g_bioq_unlock(&g_bio_run_down);
3886231f75bSLuigi Rizzo 
3896231f75bSLuigi Rizzo 	return (0);
3906231f75bSLuigi Rizzo }
3916231f75bSLuigi Rizzo 
3926231f75bSLuigi Rizzo void
3936231f75bSLuigi Rizzo g_unregister_classifier(struct g_classifier_hook *hook)
3946231f75bSLuigi Rizzo {
3956231f75bSLuigi Rizzo 	struct g_classifier_hook *entry;
3966231f75bSLuigi Rizzo 
3976231f75bSLuigi Rizzo 	g_bioq_lock(&g_bio_run_down);
3986231f75bSLuigi Rizzo 	TAILQ_FOREACH(entry, &g_classifier_tailq, link) {
3996231f75bSLuigi Rizzo 		if (entry == hook) {
4006231f75bSLuigi Rizzo 			TAILQ_REMOVE(&g_classifier_tailq, hook, link);
4016231f75bSLuigi Rizzo 			break;
4026231f75bSLuigi Rizzo 		}
4036231f75bSLuigi Rizzo 	}
4046231f75bSLuigi Rizzo 	g_bioq_unlock(&g_bio_run_down);
4056231f75bSLuigi Rizzo }
4066231f75bSLuigi Rizzo 
4076231f75bSLuigi Rizzo static void
4086231f75bSLuigi Rizzo g_run_classifiers(struct bio *bp)
4096231f75bSLuigi Rizzo {
4106231f75bSLuigi Rizzo 	struct g_classifier_hook *hook;
4116231f75bSLuigi Rizzo 	int classified = 0;
4126231f75bSLuigi Rizzo 
4136231f75bSLuigi Rizzo 	TAILQ_FOREACH(hook, &g_classifier_tailq, link)
4146231f75bSLuigi Rizzo 		classified |= hook->func(hook->arg, bp);
4156231f75bSLuigi Rizzo 
4166231f75bSLuigi Rizzo 	if (!classified)
4176231f75bSLuigi Rizzo 		bp->bio_classifier1 = BIO_NOTCLASSIFIED;
4186231f75bSLuigi Rizzo }
4196231f75bSLuigi Rizzo 
420dd84a43cSPoul-Henning Kamp void
421dd84a43cSPoul-Henning Kamp g_io_request(struct bio *bp, struct g_consumer *cp)
422dd84a43cSPoul-Henning Kamp {
423801bb689SPoul-Henning Kamp 	struct g_provider *pp;
4240d883b11SAlexander Motin 	int first;
425dd84a43cSPoul-Henning Kamp 
426d0e17c1bSPoul-Henning Kamp 	KASSERT(cp != NULL, ("NULL cp in g_io_request"));
427d0e17c1bSPoul-Henning Kamp 	KASSERT(bp != NULL, ("NULL bp in g_io_request"));
428e060b6bdSPoul-Henning Kamp 	pp = cp->provider;
429801bb689SPoul-Henning Kamp 	KASSERT(pp != NULL, ("consumer not attached in g_io_request"));
43092ee312dSPawel Jakub Dawidek #ifdef DIAGNOSTIC
43192ee312dSPawel Jakub Dawidek 	KASSERT(bp->bio_driver1 == NULL,
43292ee312dSPawel Jakub Dawidek 	    ("bio_driver1 used by the consumer (geom %s)", cp->geom->name));
43392ee312dSPawel Jakub Dawidek 	KASSERT(bp->bio_driver2 == NULL,
43492ee312dSPawel Jakub Dawidek 	    ("bio_driver2 used by the consumer (geom %s)", cp->geom->name));
43592ee312dSPawel Jakub Dawidek 	KASSERT(bp->bio_pflags == 0,
43692ee312dSPawel Jakub Dawidek 	    ("bio_pflags used by the consumer (geom %s)", cp->geom->name));
43792ee312dSPawel Jakub Dawidek 	/*
43892ee312dSPawel Jakub Dawidek 	 * Remember consumer's private fields, so we can detect if they were
43992ee312dSPawel Jakub Dawidek 	 * modified by the provider.
44092ee312dSPawel Jakub Dawidek 	 */
44192ee312dSPawel Jakub Dawidek 	bp->_bio_caller1 = bp->bio_caller1;
44292ee312dSPawel Jakub Dawidek 	bp->_bio_caller2 = bp->bio_caller2;
44392ee312dSPawel Jakub Dawidek 	bp->_bio_cflags = bp->bio_cflags;
44492ee312dSPawel Jakub Dawidek #endif
445801bb689SPoul-Henning Kamp 
4461ded77b2SPawel Jakub Dawidek 	if (bp->bio_cmd & (BIO_READ|BIO_WRITE|BIO_GETATTR)) {
447c3618c65SPawel Jakub Dawidek 		KASSERT(bp->bio_data != NULL,
4481ded77b2SPawel Jakub Dawidek 		    ("NULL bp->data in g_io_request(cmd=%hhu)", bp->bio_cmd));
4491ded77b2SPawel Jakub Dawidek 	}
4501ded77b2SPawel Jakub Dawidek 	if (bp->bio_cmd & (BIO_DELETE|BIO_FLUSH)) {
4511ded77b2SPawel Jakub Dawidek 		KASSERT(bp->bio_data == NULL,
4521ded77b2SPawel Jakub Dawidek 		    ("non-NULL bp->data in g_io_request(cmd=%hhu)",
4531ded77b2SPawel Jakub Dawidek 		    bp->bio_cmd));
454c3618c65SPawel Jakub Dawidek 	}
455dcbd0fe5SPoul-Henning Kamp 	if (bp->bio_cmd & (BIO_READ|BIO_WRITE|BIO_DELETE)) {
456dcbd0fe5SPoul-Henning Kamp 		KASSERT(bp->bio_offset % cp->provider->sectorsize == 0,
457dcbd0fe5SPoul-Henning Kamp 		    ("wrong offset %jd for sectorsize %u",
458dcbd0fe5SPoul-Henning Kamp 		    bp->bio_offset, cp->provider->sectorsize));
459dcbd0fe5SPoul-Henning Kamp 		KASSERT(bp->bio_length % cp->provider->sectorsize == 0,
460dcbd0fe5SPoul-Henning Kamp 		    ("wrong length %jd for sectorsize %u",
461dcbd0fe5SPoul-Henning Kamp 		    bp->bio_length, cp->provider->sectorsize));
462dcbd0fe5SPoul-Henning Kamp 	}
463dcbd0fe5SPoul-Henning Kamp 
464f7717523SStephan Uphoff 	g_trace(G_T_BIO, "bio_request(%p) from %p(%s) to %p(%s) cmd %d",
465f7717523SStephan Uphoff 	    bp, cp, cp->geom->name, pp, pp->name, bp->bio_cmd);
466f7717523SStephan Uphoff 
467dd84a43cSPoul-Henning Kamp 	bp->bio_from = cp;
468801bb689SPoul-Henning Kamp 	bp->bio_to = pp;
4692fccec19SPoul-Henning Kamp 	bp->bio_error = 0;
4702fccec19SPoul-Henning Kamp 	bp->bio_completed = 0;
471dd84a43cSPoul-Henning Kamp 
47219fa21aaSPoul-Henning Kamp 	KASSERT(!(bp->bio_flags & BIO_ONQUEUE),
47319fa21aaSPoul-Henning Kamp 	    ("Bio already on queue bp=%p", bp));
47419fa21aaSPoul-Henning Kamp 	bp->bio_flags |= BIO_ONQUEUE;
47519fa21aaSPoul-Henning Kamp 
476a5be8eb5SAlexander Motin 	if (g_collectstats)
47719fa21aaSPoul-Henning Kamp 		binuptime(&bp->bio_t0);
478a5be8eb5SAlexander Motin 	else
479a5be8eb5SAlexander Motin 		getbinuptime(&bp->bio_t0);
4808827c821SPoul-Henning Kamp 
4818827c821SPoul-Henning Kamp 	/*
4828827c821SPoul-Henning Kamp 	 * The statistics collection is lockless, as such, but we
4838827c821SPoul-Henning Kamp 	 * can not update one instance of the statistics from more
4848827c821SPoul-Henning Kamp 	 * than one thread at a time, so grab the lock first.
4856231f75bSLuigi Rizzo 	 *
4866231f75bSLuigi Rizzo 	 * We also use the lock to protect the list of classifiers.
4878827c821SPoul-Henning Kamp 	 */
48819fa21aaSPoul-Henning Kamp 	g_bioq_lock(&g_bio_run_down);
4896231f75bSLuigi Rizzo 
4906231f75bSLuigi Rizzo 	if (!TAILQ_EMPTY(&g_classifier_tailq) && !bp->bio_classifier1)
4916231f75bSLuigi Rizzo 		g_run_classifiers(bp);
4926231f75bSLuigi Rizzo 
493cf457284SPoul-Henning Kamp 	if (g_collectstats & 1)
49419fa21aaSPoul-Henning Kamp 		devstat_start_transaction(pp->stat, &bp->bio_t0);
495cf457284SPoul-Henning Kamp 	if (g_collectstats & 2)
49619fa21aaSPoul-Henning Kamp 		devstat_start_transaction(cp->stat, &bp->bio_t0);
49719fa21aaSPoul-Henning Kamp 
49819fa21aaSPoul-Henning Kamp 	pp->nstart++;
499cf457284SPoul-Henning Kamp 	cp->nstart++;
5000d883b11SAlexander Motin 	first = TAILQ_EMPTY(&g_bio_run_down.bio_queue);
50119fa21aaSPoul-Henning Kamp 	TAILQ_INSERT_TAIL(&g_bio_run_down.bio_queue, bp, bio_queue);
50219fa21aaSPoul-Henning Kamp 	g_bio_run_down.bio_queue_length++;
50319fa21aaSPoul-Henning Kamp 	g_bioq_unlock(&g_bio_run_down);
504e39d70d4SPoul-Henning Kamp 
5052fccec19SPoul-Henning Kamp 	/* Pass it on down. */
5060d883b11SAlexander Motin 	if (first)
507dd84a43cSPoul-Henning Kamp 		wakeup(&g_wait_down);
508dd84a43cSPoul-Henning Kamp }
509dd84a43cSPoul-Henning Kamp 
510dd84a43cSPoul-Henning Kamp void
51172840432SPoul-Henning Kamp g_io_deliver(struct bio *bp, int error)
512dd84a43cSPoul-Henning Kamp {
513801bb689SPoul-Henning Kamp 	struct g_consumer *cp;
514801bb689SPoul-Henning Kamp 	struct g_provider *pp;
5150d883b11SAlexander Motin 	int first;
516dd84a43cSPoul-Henning Kamp 
517e060b6bdSPoul-Henning Kamp 	KASSERT(bp != NULL, ("NULL bp in g_io_deliver"));
518801bb689SPoul-Henning Kamp 	pp = bp->bio_to;
519f7eeab17SPoul-Henning Kamp 	KASSERT(pp != NULL, ("NULL bio_to in g_io_deliver"));
520f7eeab17SPoul-Henning Kamp 	cp = bp->bio_from;
521f7eeab17SPoul-Henning Kamp 	if (cp == NULL) {
522f7eeab17SPoul-Henning Kamp 		bp->bio_error = error;
523f7eeab17SPoul-Henning Kamp 		bp->bio_done(bp);
524f7eeab17SPoul-Henning Kamp 		return;
525f7eeab17SPoul-Henning Kamp 	}
526801bb689SPoul-Henning Kamp 	KASSERT(cp != NULL, ("NULL bio_from in g_io_deliver"));
527801bb689SPoul-Henning Kamp 	KASSERT(cp->geom != NULL, ("NULL bio_from->geom in g_io_deliver"));
528fb231f36SEdward Tomasz Napierala #ifdef DIAGNOSTIC
529fb231f36SEdward Tomasz Napierala 	/*
530fb231f36SEdward Tomasz Napierala 	 * Some classes - GJournal in particular - can modify bio's
531fb231f36SEdward Tomasz Napierala 	 * private fields while the bio is in transit; G_GEOM_VOLATILE_BIO
532fb231f36SEdward Tomasz Napierala 	 * flag means it's an expected behaviour for that particular geom.
533fb231f36SEdward Tomasz Napierala 	 */
534fb231f36SEdward Tomasz Napierala 	if ((cp->geom->flags & G_GEOM_VOLATILE_BIO) == 0) {
535fb231f36SEdward Tomasz Napierala 		KASSERT(bp->bio_caller1 == bp->_bio_caller1,
536fb231f36SEdward Tomasz Napierala 		    ("bio_caller1 used by the provider %s", pp->name));
537fb231f36SEdward Tomasz Napierala 		KASSERT(bp->bio_caller2 == bp->_bio_caller2,
538fb231f36SEdward Tomasz Napierala 		    ("bio_caller2 used by the provider %s", pp->name));
539fb231f36SEdward Tomasz Napierala 		KASSERT(bp->bio_cflags == bp->_bio_cflags,
540fb231f36SEdward Tomasz Napierala 		    ("bio_cflags used by the provider %s", pp->name));
541fb231f36SEdward Tomasz Napierala 	}
542fb231f36SEdward Tomasz Napierala #endif
54346aeebecSPawel Jakub Dawidek 	KASSERT(bp->bio_completed >= 0, ("bio_completed can't be less than 0"));
54446aeebecSPawel Jakub Dawidek 	KASSERT(bp->bio_completed <= bp->bio_length,
54546aeebecSPawel Jakub Dawidek 	    ("bio_completed can't be greater than bio_length"));
5465ab413bfSPoul-Henning Kamp 
547dd84a43cSPoul-Henning Kamp 	g_trace(G_T_BIO,
5480355b86eSPoul-Henning Kamp "g_io_deliver(%p) from %p(%s) to %p(%s) cmd %d error %d off %jd len %jd",
549801bb689SPoul-Henning Kamp 	    bp, cp, cp->geom->name, pp, pp->name, bp->bio_cmd, error,
5500355b86eSPoul-Henning Kamp 	    (intmax_t)bp->bio_offset, (intmax_t)bp->bio_length);
551801bb689SPoul-Henning Kamp 
55219fa21aaSPoul-Henning Kamp 	KASSERT(!(bp->bio_flags & BIO_ONQUEUE),
55319fa21aaSPoul-Henning Kamp 	    ("Bio already on queue bp=%p", bp));
55419fa21aaSPoul-Henning Kamp 
555dcbd0fe5SPoul-Henning Kamp 	/*
556dcbd0fe5SPoul-Henning Kamp 	 * XXX: next two doesn't belong here
557dcbd0fe5SPoul-Henning Kamp 	 */
558e24cbd90SPoul-Henning Kamp 	bp->bio_bcount = bp->bio_length;
559e24cbd90SPoul-Henning Kamp 	bp->bio_resid = bp->bio_bcount - bp->bio_completed;
56019fa21aaSPoul-Henning Kamp 
5618827c821SPoul-Henning Kamp 	/*
5628827c821SPoul-Henning Kamp 	 * The statistics collection is lockless, as such, but we
5638827c821SPoul-Henning Kamp 	 * can not update one instance of the statistics from more
5648827c821SPoul-Henning Kamp 	 * than one thread at a time, so grab the lock first.
5658827c821SPoul-Henning Kamp 	 */
56619fa21aaSPoul-Henning Kamp 	g_bioq_lock(&g_bio_run_up);
567cf457284SPoul-Henning Kamp 	if (g_collectstats & 1)
568e24cbd90SPoul-Henning Kamp 		devstat_end_transaction_bio(pp->stat, bp);
569cf457284SPoul-Henning Kamp 	if (g_collectstats & 2)
570cf457284SPoul-Henning Kamp 		devstat_end_transaction_bio(cp->stat, bp);
5718827c821SPoul-Henning Kamp 
572c6ae9b5fSPoul-Henning Kamp 	cp->nend++;
573c6ae9b5fSPoul-Henning Kamp 	pp->nend++;
57419fa21aaSPoul-Henning Kamp 	if (error != ENOMEM) {
57519fa21aaSPoul-Henning Kamp 		bp->bio_error = error;
5760d883b11SAlexander Motin 		first = TAILQ_EMPTY(&g_bio_run_up.bio_queue);
57719fa21aaSPoul-Henning Kamp 		TAILQ_INSERT_TAIL(&g_bio_run_up.bio_queue, bp, bio_queue);
578276f72c5SPoul-Henning Kamp 		bp->bio_flags |= BIO_ONQUEUE;
57919fa21aaSPoul-Henning Kamp 		g_bio_run_up.bio_queue_length++;
58019fa21aaSPoul-Henning Kamp 		g_bioq_unlock(&g_bio_run_up);
5810d883b11SAlexander Motin 		if (first)
58219fa21aaSPoul-Henning Kamp 			wakeup(&g_wait_up);
58319fa21aaSPoul-Henning Kamp 		return;
58419fa21aaSPoul-Henning Kamp 	}
58519fa21aaSPoul-Henning Kamp 	g_bioq_unlock(&g_bio_run_up);
586dd84a43cSPoul-Henning Kamp 
5872cc9686eSPoul-Henning Kamp 	if (bootverbose)
588801bb689SPoul-Henning Kamp 		printf("ENOMEM %p on %p(%s)\n", bp, pp, pp->name);
5891b949c05SPawel Jakub Dawidek 	bp->bio_children = 0;
5901b949c05SPawel Jakub Dawidek 	bp->bio_inbed = 0;
59160114438SPawel Jakub Dawidek 	bp->bio_driver1 = NULL;
59260114438SPawel Jakub Dawidek 	bp->bio_driver2 = NULL;
59360114438SPawel Jakub Dawidek 	bp->bio_pflags = 0;
594801bb689SPoul-Henning Kamp 	g_io_request(bp, cp);
5953432e4fdSPoul-Henning Kamp 	pace++;
5963432e4fdSPoul-Henning Kamp 	return;
5973432e4fdSPoul-Henning Kamp }
598dd84a43cSPoul-Henning Kamp 
599*ee75e7deSKonstantin Belousov SYSCTL_DECL(_kern_geom);
600*ee75e7deSKonstantin Belousov 
601*ee75e7deSKonstantin Belousov static long transient_maps;
602*ee75e7deSKonstantin Belousov SYSCTL_LONG(_kern_geom, OID_AUTO, transient_maps, CTLFLAG_RD,
603*ee75e7deSKonstantin Belousov     &transient_maps, 0,
604*ee75e7deSKonstantin Belousov     "Total count of the transient mapping requests");
605*ee75e7deSKonstantin Belousov u_int transient_map_retries = 10;
606*ee75e7deSKonstantin Belousov SYSCTL_UINT(_kern_geom, OID_AUTO, transient_map_retries, CTLFLAG_RW,
607*ee75e7deSKonstantin Belousov     &transient_map_retries, 0,
608*ee75e7deSKonstantin Belousov     "Max count of retries used before giving up on creating transient map");
609*ee75e7deSKonstantin Belousov int transient_map_hard_failures;
610*ee75e7deSKonstantin Belousov SYSCTL_INT(_kern_geom, OID_AUTO, transient_map_hard_failures, CTLFLAG_RD,
611*ee75e7deSKonstantin Belousov     &transient_map_hard_failures, 0,
612*ee75e7deSKonstantin Belousov     "Failures to establish the transient mapping due to retry attempts "
613*ee75e7deSKonstantin Belousov     "exhausted");
614*ee75e7deSKonstantin Belousov int transient_map_soft_failures;
615*ee75e7deSKonstantin Belousov SYSCTL_INT(_kern_geom, OID_AUTO, transient_map_soft_failures, CTLFLAG_RD,
616*ee75e7deSKonstantin Belousov     &transient_map_soft_failures, 0,
617*ee75e7deSKonstantin Belousov     "Count of retried failures to establish the transient mapping");
618*ee75e7deSKonstantin Belousov int inflight_transient_maps;
619*ee75e7deSKonstantin Belousov SYSCTL_INT(_kern_geom, OID_AUTO, inflight_transient_maps, CTLFLAG_RD,
620*ee75e7deSKonstantin Belousov     &inflight_transient_maps, 0,
621*ee75e7deSKonstantin Belousov     "Current count of the active transient maps");
622*ee75e7deSKonstantin Belousov 
623*ee75e7deSKonstantin Belousov static int
624*ee75e7deSKonstantin Belousov g_io_transient_map_bio(struct bio *bp)
625*ee75e7deSKonstantin Belousov {
626*ee75e7deSKonstantin Belousov 	vm_offset_t addr;
627*ee75e7deSKonstantin Belousov 	long size;
628*ee75e7deSKonstantin Belousov 	u_int retried;
629*ee75e7deSKonstantin Belousov 	int rv;
630*ee75e7deSKonstantin Belousov 
631*ee75e7deSKonstantin Belousov 	size = round_page(bp->bio_ma_offset + bp->bio_length);
632*ee75e7deSKonstantin Belousov 	KASSERT(size / PAGE_SIZE == bp->bio_ma_n, ("Bio too short %p", bp));
633*ee75e7deSKonstantin Belousov 	addr = 0;
634*ee75e7deSKonstantin Belousov 	retried = 0;
635*ee75e7deSKonstantin Belousov 	atomic_add_long(&transient_maps, 1);
636*ee75e7deSKonstantin Belousov retry:
637*ee75e7deSKonstantin Belousov 	vm_map_lock(bio_transient_map);
638*ee75e7deSKonstantin Belousov 	if (vm_map_findspace(bio_transient_map, vm_map_min(bio_transient_map),
639*ee75e7deSKonstantin Belousov 	    size, &addr)) {
640*ee75e7deSKonstantin Belousov 		vm_map_unlock(bio_transient_map);
641*ee75e7deSKonstantin Belousov 		if (transient_map_retries != 0 &&
642*ee75e7deSKonstantin Belousov 		    retried >= transient_map_retries) {
643*ee75e7deSKonstantin Belousov 			g_io_deliver(bp, EDEADLK/* XXXKIB */);
644*ee75e7deSKonstantin Belousov 			CTR2(KTR_GEOM, "g_down cannot map bp %p provider %s",
645*ee75e7deSKonstantin Belousov 			    bp, bp->bio_to->name);
646*ee75e7deSKonstantin Belousov 			atomic_add_int(&transient_map_hard_failures, 1);
647*ee75e7deSKonstantin Belousov 			return (1);
648*ee75e7deSKonstantin Belousov 		} else {
649*ee75e7deSKonstantin Belousov 			/*
650*ee75e7deSKonstantin Belousov 			 * Naive attempt to quisce the I/O to get more
651*ee75e7deSKonstantin Belousov 			 * in-flight requests completed and defragment
652*ee75e7deSKonstantin Belousov 			 * the bio_transient_map.
653*ee75e7deSKonstantin Belousov 			 */
654*ee75e7deSKonstantin Belousov 			CTR3(KTR_GEOM, "g_down retrymap bp %p provider %s r %d",
655*ee75e7deSKonstantin Belousov 			    bp, bp->bio_to->name, retried);
656*ee75e7deSKonstantin Belousov 			pause("g_d_tra", hz / 10);
657*ee75e7deSKonstantin Belousov 			retried++;
658*ee75e7deSKonstantin Belousov 			atomic_add_int(&transient_map_soft_failures, 1);
659*ee75e7deSKonstantin Belousov 			goto retry;
660*ee75e7deSKonstantin Belousov 		}
661*ee75e7deSKonstantin Belousov 	}
662*ee75e7deSKonstantin Belousov 	rv = vm_map_insert(bio_transient_map, NULL, 0, addr, addr + size,
663*ee75e7deSKonstantin Belousov 	    VM_PROT_RW, VM_PROT_RW, MAP_NOFAULT);
664*ee75e7deSKonstantin Belousov 	KASSERT(rv == KERN_SUCCESS,
665*ee75e7deSKonstantin Belousov 	    ("vm_map_insert(bio_transient_map) rv %d %jx %lx",
666*ee75e7deSKonstantin Belousov 	    rv, (uintmax_t)addr, size));
667*ee75e7deSKonstantin Belousov 	vm_map_unlock(bio_transient_map);
668*ee75e7deSKonstantin Belousov 	atomic_add_int(&inflight_transient_maps, 1);
669*ee75e7deSKonstantin Belousov 	pmap_qenter((vm_offset_t)addr, bp->bio_ma, OFF_TO_IDX(size));
670*ee75e7deSKonstantin Belousov 	bp->bio_data = (caddr_t)addr + bp->bio_ma_offset;
671*ee75e7deSKonstantin Belousov 	bp->bio_flags |= BIO_TRANSIENT_MAPPING;
672*ee75e7deSKonstantin Belousov 	bp->bio_flags &= ~BIO_UNMAPPED;
673*ee75e7deSKonstantin Belousov 	return (0);
674*ee75e7deSKonstantin Belousov }
675*ee75e7deSKonstantin Belousov 
676dd84a43cSPoul-Henning Kamp void
677dd84a43cSPoul-Henning Kamp g_io_schedule_down(struct thread *tp __unused)
678dd84a43cSPoul-Henning Kamp {
679dd84a43cSPoul-Henning Kamp 	struct bio *bp;
680e39d70d4SPoul-Henning Kamp 	off_t excess;
681e39d70d4SPoul-Henning Kamp 	int error;
682dd84a43cSPoul-Henning Kamp 
683dd84a43cSPoul-Henning Kamp 	for(;;) {
684f0e185d7SPoul-Henning Kamp 		g_bioq_lock(&g_bio_run_down);
685dd84a43cSPoul-Henning Kamp 		bp = g_bioq_first(&g_bio_run_down);
686f0e185d7SPoul-Henning Kamp 		if (bp == NULL) {
68749dbb61dSRobert Watson 			CTR0(KTR_GEOM, "g_down going to sleep");
688f0e185d7SPoul-Henning Kamp 			msleep(&g_wait_down, &g_bio_run_down.bio_queue_lock,
6897fc019afSAlexander Motin 			    PRIBIO | PDROP, "-", 0);
690f0e185d7SPoul-Henning Kamp 			continue;
691f0e185d7SPoul-Henning Kamp 		}
69249dbb61dSRobert Watson 		CTR0(KTR_GEOM, "g_down has work to do");
693f0e185d7SPoul-Henning Kamp 		g_bioq_unlock(&g_bio_run_down);
694376ceb79SPoul-Henning Kamp 		if (pace > 0) {
69549dbb61dSRobert Watson 			CTR1(KTR_GEOM, "g_down pacing self (pace %d)", pace);
6964d70511aSJohn Baldwin 			pause("g_down", hz/10);
697376ceb79SPoul-Henning Kamp 			pace--;
698376ceb79SPoul-Henning Kamp 		}
699e39d70d4SPoul-Henning Kamp 		error = g_io_check(bp);
700e39d70d4SPoul-Henning Kamp 		if (error) {
70149dbb61dSRobert Watson 			CTR3(KTR_GEOM, "g_down g_io_check on bp %p provider "
70249dbb61dSRobert Watson 			    "%s returned %d", bp, bp->bio_to->name, error);
703e39d70d4SPoul-Henning Kamp 			g_io_deliver(bp, error);
704e39d70d4SPoul-Henning Kamp 			continue;
705e39d70d4SPoul-Henning Kamp 		}
70649dbb61dSRobert Watson 		CTR2(KTR_GEOM, "g_down processing bp %p provider %s", bp,
70749dbb61dSRobert Watson 		    bp->bio_to->name);
708392d56b4SPoul-Henning Kamp 		switch (bp->bio_cmd) {
709392d56b4SPoul-Henning Kamp 		case BIO_READ:
710392d56b4SPoul-Henning Kamp 		case BIO_WRITE:
711392d56b4SPoul-Henning Kamp 		case BIO_DELETE:
712e39d70d4SPoul-Henning Kamp 			/* Truncate requests to the end of providers media. */
71349dbb61dSRobert Watson 			/*
71449dbb61dSRobert Watson 			 * XXX: What if we truncate because of offset being
71549dbb61dSRobert Watson 			 * bad, not length?
71649dbb61dSRobert Watson 			 */
717e39d70d4SPoul-Henning Kamp 			excess = bp->bio_offset + bp->bio_length;
718e39d70d4SPoul-Henning Kamp 			if (excess > bp->bio_to->mediasize) {
719e39d70d4SPoul-Henning Kamp 				excess -= bp->bio_to->mediasize;
720e39d70d4SPoul-Henning Kamp 				bp->bio_length -= excess;
72149dbb61dSRobert Watson 				if (excess > 0)
72249dbb61dSRobert Watson 					CTR3(KTR_GEOM, "g_down truncated bio "
72349dbb61dSRobert Watson 					    "%p provider %s by %d", bp,
72449dbb61dSRobert Watson 					    bp->bio_to->name, excess);
725e39d70d4SPoul-Henning Kamp 			}
726e39d70d4SPoul-Henning Kamp 			/* Deliver zero length transfers right here. */
727e39d70d4SPoul-Henning Kamp 			if (bp->bio_length == 0) {
728e39d70d4SPoul-Henning Kamp 				g_io_deliver(bp, 0);
72949dbb61dSRobert Watson 				CTR2(KTR_GEOM, "g_down terminated 0-length "
73049dbb61dSRobert Watson 				    "bp %p provider %s", bp, bp->bio_to->name);
731e39d70d4SPoul-Henning Kamp 				continue;
732e39d70d4SPoul-Henning Kamp 			}
733392d56b4SPoul-Henning Kamp 			break;
734392d56b4SPoul-Henning Kamp 		default:
735392d56b4SPoul-Henning Kamp 			break;
736392d56b4SPoul-Henning Kamp 		}
737*ee75e7deSKonstantin Belousov 		if ((bp->bio_flags & BIO_UNMAPPED) != 0 &&
738*ee75e7deSKonstantin Belousov 		    (bp->bio_to->flags & G_PF_ACCEPT_UNMAPPED) == 0 &&
739*ee75e7deSKonstantin Belousov 		    (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE)) {
740*ee75e7deSKonstantin Belousov 			if (g_io_transient_map_bio(bp))
741*ee75e7deSKonstantin Belousov 				continue;
742*ee75e7deSKonstantin Belousov 		}
74351460da8SJohn Baldwin 		THREAD_NO_SLEEPING();
74449dbb61dSRobert Watson 		CTR4(KTR_GEOM, "g_down starting bp %p provider %s off %ld "
74549dbb61dSRobert Watson 		    "len %ld", bp, bp->bio_to->name, bp->bio_offset,
74649dbb61dSRobert Watson 		    bp->bio_length);
747dd84a43cSPoul-Henning Kamp 		bp->bio_to->geom->start(bp);
74851460da8SJohn Baldwin 		THREAD_SLEEPING_OK();
749dd84a43cSPoul-Henning Kamp 	}
750dd84a43cSPoul-Henning Kamp }
751dd84a43cSPoul-Henning Kamp 
752dd84a43cSPoul-Henning Kamp void
7535fcf4e43SPoul-Henning Kamp bio_taskqueue(struct bio *bp, bio_task_t *func, void *arg)
7545fcf4e43SPoul-Henning Kamp {
7555fcf4e43SPoul-Henning Kamp 	bp->bio_task = func;
7565fcf4e43SPoul-Henning Kamp 	bp->bio_task_arg = arg;
7575fcf4e43SPoul-Henning Kamp 	/*
7585fcf4e43SPoul-Henning Kamp 	 * The taskqueue is actually just a second queue off the "up"
7595fcf4e43SPoul-Henning Kamp 	 * queue, so we use the same lock.
7605fcf4e43SPoul-Henning Kamp 	 */
7615fcf4e43SPoul-Henning Kamp 	g_bioq_lock(&g_bio_run_up);
762dcbd0fe5SPoul-Henning Kamp 	KASSERT(!(bp->bio_flags & BIO_ONQUEUE),
763dcbd0fe5SPoul-Henning Kamp 	    ("Bio already on queue bp=%p target taskq", bp));
764dcbd0fe5SPoul-Henning Kamp 	bp->bio_flags |= BIO_ONQUEUE;
7655fcf4e43SPoul-Henning Kamp 	TAILQ_INSERT_TAIL(&g_bio_run_task.bio_queue, bp, bio_queue);
7665fcf4e43SPoul-Henning Kamp 	g_bio_run_task.bio_queue_length++;
7675fcf4e43SPoul-Henning Kamp 	wakeup(&g_wait_up);
7685fcf4e43SPoul-Henning Kamp 	g_bioq_unlock(&g_bio_run_up);
7695fcf4e43SPoul-Henning Kamp }
7705fcf4e43SPoul-Henning Kamp 
7715fcf4e43SPoul-Henning Kamp 
7725fcf4e43SPoul-Henning Kamp void
773dd84a43cSPoul-Henning Kamp g_io_schedule_up(struct thread *tp __unused)
774dd84a43cSPoul-Henning Kamp {
775dd84a43cSPoul-Henning Kamp 	struct bio *bp;
776dd84a43cSPoul-Henning Kamp 	for(;;) {
777f0e185d7SPoul-Henning Kamp 		g_bioq_lock(&g_bio_run_up);
7785fcf4e43SPoul-Henning Kamp 		bp = g_bioq_first(&g_bio_run_task);
7795fcf4e43SPoul-Henning Kamp 		if (bp != NULL) {
7805fcf4e43SPoul-Henning Kamp 			g_bioq_unlock(&g_bio_run_up);
78151460da8SJohn Baldwin 			THREAD_NO_SLEEPING();
78249dbb61dSRobert Watson 			CTR1(KTR_GEOM, "g_up processing task bp %p", bp);
7835fcf4e43SPoul-Henning Kamp 			bp->bio_task(bp->bio_task_arg);
78451460da8SJohn Baldwin 			THREAD_SLEEPING_OK();
7855fcf4e43SPoul-Henning Kamp 			continue;
7865fcf4e43SPoul-Henning Kamp 		}
787dd84a43cSPoul-Henning Kamp 		bp = g_bioq_first(&g_bio_run_up);
788f0e185d7SPoul-Henning Kamp 		if (bp != NULL) {
789f0e185d7SPoul-Henning Kamp 			g_bioq_unlock(&g_bio_run_up);
79051460da8SJohn Baldwin 			THREAD_NO_SLEEPING();
79149dbb61dSRobert Watson 			CTR4(KTR_GEOM, "g_up biodone bp %p provider %s off "
792c4901b67SSean Bruno 			    "%jd len %ld", bp, bp->bio_to->name,
79349dbb61dSRobert Watson 			    bp->bio_offset, bp->bio_length);
79453706245SPoul-Henning Kamp 			biodone(bp);
79551460da8SJohn Baldwin 			THREAD_SLEEPING_OK();
796f0e185d7SPoul-Henning Kamp 			continue;
797f0e185d7SPoul-Henning Kamp 		}
79849dbb61dSRobert Watson 		CTR0(KTR_GEOM, "g_up going to sleep");
799f0e185d7SPoul-Henning Kamp 		msleep(&g_wait_up, &g_bio_run_up.bio_queue_lock,
8007fc019afSAlexander Motin 		    PRIBIO | PDROP, "-", 0);
801dd84a43cSPoul-Henning Kamp 	}
802dd84a43cSPoul-Henning Kamp }
803dd84a43cSPoul-Henning Kamp 
804dd84a43cSPoul-Henning Kamp void *
805dd84a43cSPoul-Henning Kamp g_read_data(struct g_consumer *cp, off_t offset, off_t length, int *error)
806dd84a43cSPoul-Henning Kamp {
807dd84a43cSPoul-Henning Kamp 	struct bio *bp;
808dd84a43cSPoul-Henning Kamp 	void *ptr;
809dd84a43cSPoul-Henning Kamp 	int errorc;
810dd84a43cSPoul-Henning Kamp 
8118dd5480dSPawel Jakub Dawidek 	KASSERT(length > 0 && length >= cp->provider->sectorsize &&
8128dd5480dSPawel Jakub Dawidek 	    length <= MAXPHYS, ("g_read_data(): invalid length %jd",
8138dd5480dSPawel Jakub Dawidek 	    (intmax_t)length));
8143eb6ffdfSPoul-Henning Kamp 
815a2033c96SPoul-Henning Kamp 	bp = g_alloc_bio();
816dd84a43cSPoul-Henning Kamp 	bp->bio_cmd = BIO_READ;
817dd84a43cSPoul-Henning Kamp 	bp->bio_done = NULL;
818dd84a43cSPoul-Henning Kamp 	bp->bio_offset = offset;
819dd84a43cSPoul-Henning Kamp 	bp->bio_length = length;
820a163d034SWarner Losh 	ptr = g_malloc(length, M_WAITOK);
821dd84a43cSPoul-Henning Kamp 	bp->bio_data = ptr;
822dd84a43cSPoul-Henning Kamp 	g_io_request(bp, cp);
82353706245SPoul-Henning Kamp 	errorc = biowait(bp, "gread");
824dd84a43cSPoul-Henning Kamp 	if (error != NULL)
825dd84a43cSPoul-Henning Kamp 		*error = errorc;
826dd84a43cSPoul-Henning Kamp 	g_destroy_bio(bp);
827dd84a43cSPoul-Henning Kamp 	if (errorc) {
828dd84a43cSPoul-Henning Kamp 		g_free(ptr);
829dd84a43cSPoul-Henning Kamp 		ptr = NULL;
830dd84a43cSPoul-Henning Kamp 	}
831dd84a43cSPoul-Henning Kamp 	return (ptr);
832dd84a43cSPoul-Henning Kamp }
83390b1cd56SPoul-Henning Kamp 
83490b1cd56SPoul-Henning Kamp int
83590b1cd56SPoul-Henning Kamp g_write_data(struct g_consumer *cp, off_t offset, void *ptr, off_t length)
83690b1cd56SPoul-Henning Kamp {
83790b1cd56SPoul-Henning Kamp 	struct bio *bp;
83890b1cd56SPoul-Henning Kamp 	int error;
83990b1cd56SPoul-Henning Kamp 
8408dd5480dSPawel Jakub Dawidek 	KASSERT(length > 0 && length >= cp->provider->sectorsize &&
8418dd5480dSPawel Jakub Dawidek 	    length <= MAXPHYS, ("g_write_data(): invalid length %jd",
8428dd5480dSPawel Jakub Dawidek 	    (intmax_t)length));
8433eb6ffdfSPoul-Henning Kamp 
844a2033c96SPoul-Henning Kamp 	bp = g_alloc_bio();
84590b1cd56SPoul-Henning Kamp 	bp->bio_cmd = BIO_WRITE;
84690b1cd56SPoul-Henning Kamp 	bp->bio_done = NULL;
84790b1cd56SPoul-Henning Kamp 	bp->bio_offset = offset;
84890b1cd56SPoul-Henning Kamp 	bp->bio_length = length;
84990b1cd56SPoul-Henning Kamp 	bp->bio_data = ptr;
85090b1cd56SPoul-Henning Kamp 	g_io_request(bp, cp);
85190b1cd56SPoul-Henning Kamp 	error = biowait(bp, "gwrite");
85290b1cd56SPoul-Henning Kamp 	g_destroy_bio(bp);
85390b1cd56SPoul-Henning Kamp 	return (error);
85490b1cd56SPoul-Henning Kamp }
85572e33095SPawel Jakub Dawidek 
8562b17fb95SPawel Jakub Dawidek int
8572b17fb95SPawel Jakub Dawidek g_delete_data(struct g_consumer *cp, off_t offset, off_t length)
8582b17fb95SPawel Jakub Dawidek {
8592b17fb95SPawel Jakub Dawidek 	struct bio *bp;
8602b17fb95SPawel Jakub Dawidek 	int error;
8612b17fb95SPawel Jakub Dawidek 
862eed6cda9SPoul-Henning Kamp 	KASSERT(length > 0 && length >= cp->provider->sectorsize,
863eed6cda9SPoul-Henning Kamp 	    ("g_delete_data(): invalid length %jd", (intmax_t)length));
8642b17fb95SPawel Jakub Dawidek 
8652b17fb95SPawel Jakub Dawidek 	bp = g_alloc_bio();
8662b17fb95SPawel Jakub Dawidek 	bp->bio_cmd = BIO_DELETE;
8672b17fb95SPawel Jakub Dawidek 	bp->bio_done = NULL;
8682b17fb95SPawel Jakub Dawidek 	bp->bio_offset = offset;
8692b17fb95SPawel Jakub Dawidek 	bp->bio_length = length;
8702b17fb95SPawel Jakub Dawidek 	bp->bio_data = NULL;
8712b17fb95SPawel Jakub Dawidek 	g_io_request(bp, cp);
8722b17fb95SPawel Jakub Dawidek 	error = biowait(bp, "gdelete");
8732b17fb95SPawel Jakub Dawidek 	g_destroy_bio(bp);
8742b17fb95SPawel Jakub Dawidek 	return (error);
8752b17fb95SPawel Jakub Dawidek }
8762b17fb95SPawel Jakub Dawidek 
87772e33095SPawel Jakub Dawidek void
87872e33095SPawel Jakub Dawidek g_print_bio(struct bio *bp)
87972e33095SPawel Jakub Dawidek {
88072e33095SPawel Jakub Dawidek 	const char *pname, *cmd = NULL;
88172e33095SPawel Jakub Dawidek 
88272e33095SPawel Jakub Dawidek 	if (bp->bio_to != NULL)
88372e33095SPawel Jakub Dawidek 		pname = bp->bio_to->name;
88472e33095SPawel Jakub Dawidek 	else
88572e33095SPawel Jakub Dawidek 		pname = "[unknown]";
88672e33095SPawel Jakub Dawidek 
88772e33095SPawel Jakub Dawidek 	switch (bp->bio_cmd) {
88872e33095SPawel Jakub Dawidek 	case BIO_GETATTR:
88972e33095SPawel Jakub Dawidek 		cmd = "GETATTR";
89072e33095SPawel Jakub Dawidek 		printf("%s[%s(attr=%s)]", pname, cmd, bp->bio_attribute);
89172e33095SPawel Jakub Dawidek 		return;
892c3618c65SPawel Jakub Dawidek 	case BIO_FLUSH:
893c3618c65SPawel Jakub Dawidek 		cmd = "FLUSH";
894c3618c65SPawel Jakub Dawidek 		printf("%s[%s]", pname, cmd);
895c3618c65SPawel Jakub Dawidek 		return;
89672e33095SPawel Jakub Dawidek 	case BIO_READ:
89772e33095SPawel Jakub Dawidek 		cmd = "READ";
8987ce513a5SEdward Tomasz Napierala 		break;
89972e33095SPawel Jakub Dawidek 	case BIO_WRITE:
90072e33095SPawel Jakub Dawidek 		cmd = "WRITE";
9017ce513a5SEdward Tomasz Napierala 		break;
90272e33095SPawel Jakub Dawidek 	case BIO_DELETE:
90372e33095SPawel Jakub Dawidek 		cmd = "DELETE";
9047ce513a5SEdward Tomasz Napierala 		break;
90572e33095SPawel Jakub Dawidek 	default:
90672e33095SPawel Jakub Dawidek 		cmd = "UNKNOWN";
90772e33095SPawel Jakub Dawidek 		printf("%s[%s()]", pname, cmd);
90872e33095SPawel Jakub Dawidek 		return;
90972e33095SPawel Jakub Dawidek 	}
9107ce513a5SEdward Tomasz Napierala 	printf("%s[%s(offset=%jd, length=%jd)]", pname, cmd,
9117ce513a5SEdward Tomasz Napierala 	    (intmax_t)bp->bio_offset, (intmax_t)bp->bio_length);
91272e33095SPawel Jakub Dawidek }
913