]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - sys/geom/geom_io.c
MFC r238198 (by trasz):
[FreeBSD/stable/9.git] / sys / geom / geom_io.c
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/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/bio.h>
44 #include <sys/ktr.h>
45 #include <sys/proc.h>
46 #include <sys/stack.h>
47
48 #include <sys/errno.h>
49 #include <geom/geom.h>
50 #include <geom/geom_int.h>
51 #include <sys/devicestat.h>
52
53 #include <vm/uma.h>
54
55 static struct g_bioq g_bio_run_down;
56 static struct g_bioq g_bio_run_up;
57 static struct g_bioq g_bio_run_task;
58
59 static u_int pace;
60 static uma_zone_t       biozone;
61
62 /*
63  * The head of the list of classifiers used in g_io_request.
64  * Use g_register_classifier() and g_unregister_classifier()
65  * to add/remove entries to the list.
66  * Classifiers are invoked in registration order.
67  */
68 static TAILQ_HEAD(g_classifier_tailq, g_classifier_hook)
69     g_classifier_tailq = TAILQ_HEAD_INITIALIZER(g_classifier_tailq);
70
71 #include <machine/atomic.h>
72
73 static void
74 g_bioq_lock(struct g_bioq *bq)
75 {
76
77         mtx_lock(&bq->bio_queue_lock);
78 }
79
80 static void
81 g_bioq_unlock(struct g_bioq *bq)
82 {
83
84         mtx_unlock(&bq->bio_queue_lock);
85 }
86
87 #if 0
88 static void
89 g_bioq_destroy(struct g_bioq *bq)
90 {
91
92         mtx_destroy(&bq->bio_queue_lock);
93 }
94 #endif
95
96 static void
97 g_bioq_init(struct g_bioq *bq)
98 {
99
100         TAILQ_INIT(&bq->bio_queue);
101         mtx_init(&bq->bio_queue_lock, "bio queue", NULL, MTX_DEF);
102 }
103
104 static struct bio *
105 g_bioq_first(struct g_bioq *bq)
106 {
107         struct bio *bp;
108
109         bp = TAILQ_FIRST(&bq->bio_queue);
110         if (bp != NULL) {
111                 KASSERT((bp->bio_flags & BIO_ONQUEUE),
112                     ("Bio not on queue bp=%p target %p", bp, bq));
113                 bp->bio_flags &= ~BIO_ONQUEUE;
114                 TAILQ_REMOVE(&bq->bio_queue, bp, bio_queue);
115                 bq->bio_queue_length--;
116         }
117         return (bp);
118 }
119
120 struct bio *
121 g_new_bio(void)
122 {
123         struct bio *bp;
124
125         bp = uma_zalloc(biozone, M_NOWAIT | M_ZERO);
126 #ifdef KTR
127         if ((KTR_COMPILE & KTR_GEOM) && (ktr_mask & KTR_GEOM)) {
128                 struct stack st;
129
130                 CTR1(KTR_GEOM, "g_new_bio(): %p", bp);
131                 stack_save(&st);
132                 CTRSTACK(KTR_GEOM, &st, 3, 0);
133         }
134 #endif
135         return (bp);
136 }
137
138 struct bio *
139 g_alloc_bio(void)
140 {
141         struct bio *bp;
142
143         bp = uma_zalloc(biozone, M_WAITOK | M_ZERO);
144 #ifdef KTR
145         if ((KTR_COMPILE & KTR_GEOM) && (ktr_mask & KTR_GEOM)) {
146                 struct stack st;
147
148                 CTR1(KTR_GEOM, "g_alloc_bio(): %p", bp);
149                 stack_save(&st);
150                 CTRSTACK(KTR_GEOM, &st, 3, 0);
151         }
152 #endif
153         return (bp);
154 }
155
156 void
157 g_destroy_bio(struct bio *bp)
158 {
159 #ifdef KTR
160         if ((KTR_COMPILE & KTR_GEOM) && (ktr_mask & KTR_GEOM)) {
161                 struct stack st;
162
163                 CTR1(KTR_GEOM, "g_destroy_bio(): %p", bp);
164                 stack_save(&st);
165                 CTRSTACK(KTR_GEOM, &st, 3, 0);
166         }
167 #endif
168         uma_zfree(biozone, bp);
169 }
170
171 struct bio *
172 g_clone_bio(struct bio *bp)
173 {
174         struct bio *bp2;
175
176         bp2 = uma_zalloc(biozone, M_NOWAIT | M_ZERO);
177         if (bp2 != NULL) {
178                 bp2->bio_parent = bp;
179                 bp2->bio_cmd = bp->bio_cmd;
180                 /*
181                  *  BIO_ORDERED flag may be used by disk drivers to enforce
182                  *  ordering restrictions, so this flag needs to be cloned.
183                  *  Other bio flags are not suitable for cloning.
184                  */
185                 bp2->bio_flags = bp->bio_flags & BIO_ORDERED;
186                 bp2->bio_length = bp->bio_length;
187                 bp2->bio_offset = bp->bio_offset;
188                 bp2->bio_data = bp->bio_data;
189                 bp2->bio_attribute = bp->bio_attribute;
190                 /* Inherit classification info from the parent */
191                 bp2->bio_classifier1 = bp->bio_classifier1;
192                 bp2->bio_classifier2 = bp->bio_classifier2;
193                 bp->bio_children++;
194         }
195 #ifdef KTR
196         if ((KTR_COMPILE & KTR_GEOM) && (ktr_mask & KTR_GEOM)) {
197                 struct stack st;
198
199                 CTR2(KTR_GEOM, "g_clone_bio(%p): %p", bp, bp2);
200                 stack_save(&st);
201                 CTRSTACK(KTR_GEOM, &st, 3, 0);
202         }
203 #endif
204         return(bp2);
205 }
206
207 struct bio *
208 g_duplicate_bio(struct bio *bp)
209 {
210         struct bio *bp2;
211
212         bp2 = uma_zalloc(biozone, M_WAITOK | M_ZERO);
213         bp2->bio_parent = bp;
214         bp2->bio_cmd = bp->bio_cmd;
215         bp2->bio_length = bp->bio_length;
216         bp2->bio_offset = bp->bio_offset;
217         bp2->bio_data = bp->bio_data;
218         bp2->bio_attribute = bp->bio_attribute;
219         bp->bio_children++;
220 #ifdef KTR
221         if ((KTR_COMPILE & KTR_GEOM) && (ktr_mask & KTR_GEOM)) {
222                 struct stack st;
223
224                 CTR2(KTR_GEOM, "g_duplicate_bio(%p): %p", bp, bp2);
225                 stack_save(&st);
226                 CTRSTACK(KTR_GEOM, &st, 3, 0);
227         }
228 #endif
229         return(bp2);
230 }
231
232 void
233 g_io_init()
234 {
235
236         g_bioq_init(&g_bio_run_down);
237         g_bioq_init(&g_bio_run_up);
238         g_bioq_init(&g_bio_run_task);
239         biozone = uma_zcreate("g_bio", sizeof (struct bio),
240             NULL, NULL,
241             NULL, NULL,
242             0, 0);
243 }
244
245 int
246 g_io_getattr(const char *attr, struct g_consumer *cp, int *len, void *ptr)
247 {
248         struct bio *bp;
249         int error;
250
251         g_trace(G_T_BIO, "bio_getattr(%s)", attr);
252         bp = g_alloc_bio();
253         bp->bio_cmd = BIO_GETATTR;
254         bp->bio_done = NULL;
255         bp->bio_attribute = attr;
256         bp->bio_length = *len;
257         bp->bio_data = ptr;
258         g_io_request(bp, cp);
259         error = biowait(bp, "ggetattr");
260         *len = bp->bio_completed;
261         g_destroy_bio(bp);
262         return (error);
263 }
264
265 int
266 g_io_flush(struct g_consumer *cp)
267 {
268         struct bio *bp;
269         int error;
270
271         g_trace(G_T_BIO, "bio_flush(%s)", cp->provider->name);
272         bp = g_alloc_bio();
273         bp->bio_cmd = BIO_FLUSH;
274         bp->bio_flags |= BIO_ORDERED;
275         bp->bio_done = NULL;
276         bp->bio_attribute = NULL;
277         bp->bio_offset = cp->provider->mediasize;
278         bp->bio_length = 0;
279         bp->bio_data = NULL;
280         g_io_request(bp, cp);
281         error = biowait(bp, "gflush");
282         g_destroy_bio(bp);
283         return (error);
284 }
285
286 static int
287 g_io_check(struct bio *bp)
288 {
289         struct g_consumer *cp;
290         struct g_provider *pp;
291
292         cp = bp->bio_from;
293         pp = bp->bio_to;
294
295         /* Fail if access counters dont allow the operation */
296         switch(bp->bio_cmd) {
297         case BIO_READ:
298         case BIO_GETATTR:
299                 if (cp->acr == 0)
300                         return (EPERM);
301                 break;
302         case BIO_WRITE:
303         case BIO_DELETE:
304         case BIO_FLUSH:
305                 if (cp->acw == 0)
306                         return (EPERM);
307                 break;
308         default:
309                 return (EPERM);
310         }
311         /* if provider is marked for error, don't disturb. */
312         if (pp->error)
313                 return (pp->error);
314
315         switch(bp->bio_cmd) {
316         case BIO_READ:
317         case BIO_WRITE:
318         case BIO_DELETE:
319                 /* Zero sectorsize or mediasize is probably a lack of media. */
320                 if (pp->sectorsize == 0 || pp->mediasize == 0)
321                         return (ENXIO);
322                 /* Reject I/O not on sector boundary */
323                 if (bp->bio_offset % pp->sectorsize)
324                         return (EINVAL);
325                 /* Reject I/O not integral sector long */
326                 if (bp->bio_length % pp->sectorsize)
327                         return (EINVAL);
328                 /* Reject requests before or past the end of media. */
329                 if (bp->bio_offset < 0)
330                         return (EIO);
331                 if (bp->bio_offset > pp->mediasize)
332                         return (EIO);
333                 break;
334         default:
335                 break;
336         }
337         return (0);
338 }
339
340 /*
341  * bio classification support.
342  *
343  * g_register_classifier() and g_unregister_classifier()
344  * are used to add/remove a classifier from the list.
345  * The list is protected using the g_bio_run_down lock,
346  * because the classifiers are called in this path.
347  *
348  * g_io_request() passes bio's that are not already classified
349  * (i.e. those with bio_classifier1 == NULL) to g_run_classifiers().
350  * Classifiers can store their result in the two fields
351  * bio_classifier1 and bio_classifier2.
352  * A classifier that updates one of the fields should
353  * return a non-zero value.
354  * If no classifier updates the field, g_run_classifiers() sets
355  * bio_classifier1 = BIO_NOTCLASSIFIED to avoid further calls.
356  */
357
358 int
359 g_register_classifier(struct g_classifier_hook *hook)
360 {
361
362         g_bioq_lock(&g_bio_run_down);
363         TAILQ_INSERT_TAIL(&g_classifier_tailq, hook, link);
364         g_bioq_unlock(&g_bio_run_down);
365
366         return (0);
367 }
368
369 void
370 g_unregister_classifier(struct g_classifier_hook *hook)
371 {
372         struct g_classifier_hook *entry;
373
374         g_bioq_lock(&g_bio_run_down);
375         TAILQ_FOREACH(entry, &g_classifier_tailq, link) {
376                 if (entry == hook) {
377                         TAILQ_REMOVE(&g_classifier_tailq, hook, link);
378                         break;
379                 }
380         }
381         g_bioq_unlock(&g_bio_run_down);
382 }
383
384 static void
385 g_run_classifiers(struct bio *bp)
386 {
387         struct g_classifier_hook *hook;
388         int classified = 0;
389
390         TAILQ_FOREACH(hook, &g_classifier_tailq, link)
391                 classified |= hook->func(hook->arg, bp);
392
393         if (!classified)
394                 bp->bio_classifier1 = BIO_NOTCLASSIFIED;
395 }
396
397 void
398 g_io_request(struct bio *bp, struct g_consumer *cp)
399 {
400         struct g_provider *pp;
401         int first;
402
403         KASSERT(cp != NULL, ("NULL cp in g_io_request"));
404         KASSERT(bp != NULL, ("NULL bp in g_io_request"));
405         pp = cp->provider;
406         KASSERT(pp != NULL, ("consumer not attached in g_io_request"));
407 #ifdef DIAGNOSTIC
408         KASSERT(bp->bio_driver1 == NULL,
409             ("bio_driver1 used by the consumer (geom %s)", cp->geom->name));
410         KASSERT(bp->bio_driver2 == NULL,
411             ("bio_driver2 used by the consumer (geom %s)", cp->geom->name));
412         KASSERT(bp->bio_pflags == 0,
413             ("bio_pflags used by the consumer (geom %s)", cp->geom->name));
414         /*
415          * Remember consumer's private fields, so we can detect if they were
416          * modified by the provider.
417          */
418         bp->_bio_caller1 = bp->bio_caller1;
419         bp->_bio_caller2 = bp->bio_caller2;
420         bp->_bio_cflags = bp->bio_cflags;
421 #endif
422
423         if (bp->bio_cmd & (BIO_READ|BIO_WRITE|BIO_GETATTR)) {
424                 KASSERT(bp->bio_data != NULL,
425                     ("NULL bp->data in g_io_request(cmd=%hhu)", bp->bio_cmd));
426         }
427         if (bp->bio_cmd & (BIO_DELETE|BIO_FLUSH)) {
428                 KASSERT(bp->bio_data == NULL,
429                     ("non-NULL bp->data in g_io_request(cmd=%hhu)",
430                     bp->bio_cmd));
431         }
432         if (bp->bio_cmd & (BIO_READ|BIO_WRITE|BIO_DELETE)) {
433                 KASSERT(bp->bio_offset % cp->provider->sectorsize == 0,
434                     ("wrong offset %jd for sectorsize %u",
435                     bp->bio_offset, cp->provider->sectorsize));
436                 KASSERT(bp->bio_length % cp->provider->sectorsize == 0,
437                     ("wrong length %jd for sectorsize %u",
438                     bp->bio_length, cp->provider->sectorsize));
439         }
440
441         g_trace(G_T_BIO, "bio_request(%p) from %p(%s) to %p(%s) cmd %d",
442             bp, cp, cp->geom->name, pp, pp->name, bp->bio_cmd);
443
444         bp->bio_from = cp;
445         bp->bio_to = pp;
446         bp->bio_error = 0;
447         bp->bio_completed = 0;
448
449         KASSERT(!(bp->bio_flags & BIO_ONQUEUE),
450             ("Bio already on queue bp=%p", bp));
451         bp->bio_flags |= BIO_ONQUEUE;
452
453         if (g_collectstats)
454                 binuptime(&bp->bio_t0);
455         else
456                 getbinuptime(&bp->bio_t0);
457
458         /*
459          * The statistics collection is lockless, as such, but we
460          * can not update one instance of the statistics from more
461          * than one thread at a time, so grab the lock first.
462          *
463          * We also use the lock to protect the list of classifiers.
464          */
465         g_bioq_lock(&g_bio_run_down);
466
467         if (!TAILQ_EMPTY(&g_classifier_tailq) && !bp->bio_classifier1)
468                 g_run_classifiers(bp);
469
470         if (g_collectstats & 1)
471                 devstat_start_transaction(pp->stat, &bp->bio_t0);
472         if (g_collectstats & 2)
473                 devstat_start_transaction(cp->stat, &bp->bio_t0);
474
475         pp->nstart++;
476         cp->nstart++;
477         first = TAILQ_EMPTY(&g_bio_run_down.bio_queue);
478         TAILQ_INSERT_TAIL(&g_bio_run_down.bio_queue, bp, bio_queue);
479         g_bio_run_down.bio_queue_length++;
480         g_bioq_unlock(&g_bio_run_down);
481
482         /* Pass it on down. */
483         if (first)
484                 wakeup(&g_wait_down);
485 }
486
487 void
488 g_io_deliver(struct bio *bp, int error)
489 {
490         struct g_consumer *cp;
491         struct g_provider *pp;
492         int first;
493
494         KASSERT(bp != NULL, ("NULL bp in g_io_deliver"));
495         pp = bp->bio_to;
496         KASSERT(pp != NULL, ("NULL bio_to in g_io_deliver"));
497         cp = bp->bio_from;
498         if (cp == NULL) {
499                 bp->bio_error = error;
500                 bp->bio_done(bp);
501                 return;
502         }
503         KASSERT(cp != NULL, ("NULL bio_from in g_io_deliver"));
504         KASSERT(cp->geom != NULL, ("NULL bio_from->geom in g_io_deliver"));
505 #ifdef DIAGNOSTIC
506         /*
507          * Some classes - GJournal in particular - can modify bio's
508          * private fields while the bio is in transit; G_GEOM_VOLATILE_BIO
509          * flag means it's an expected behaviour for that particular geom.
510          */
511         if ((cp->geom->flags & G_GEOM_VOLATILE_BIO) == 0) {
512                 KASSERT(bp->bio_caller1 == bp->_bio_caller1,
513                     ("bio_caller1 used by the provider %s", pp->name));
514                 KASSERT(bp->bio_caller2 == bp->_bio_caller2,
515                     ("bio_caller2 used by the provider %s", pp->name));
516                 KASSERT(bp->bio_cflags == bp->_bio_cflags,
517                     ("bio_cflags used by the provider %s", pp->name));
518         }
519 #endif
520         KASSERT(bp->bio_completed >= 0, ("bio_completed can't be less than 0"));
521         KASSERT(bp->bio_completed <= bp->bio_length,
522             ("bio_completed can't be greater than bio_length"));
523
524         g_trace(G_T_BIO,
525 "g_io_deliver(%p) from %p(%s) to %p(%s) cmd %d error %d off %jd len %jd",
526             bp, cp, cp->geom->name, pp, pp->name, bp->bio_cmd, error,
527             (intmax_t)bp->bio_offset, (intmax_t)bp->bio_length);
528
529         KASSERT(!(bp->bio_flags & BIO_ONQUEUE),
530             ("Bio already on queue bp=%p", bp));
531
532         /*
533          * XXX: next two doesn't belong here
534          */
535         bp->bio_bcount = bp->bio_length;
536         bp->bio_resid = bp->bio_bcount - bp->bio_completed;
537
538         /*
539          * The statistics collection is lockless, as such, but we
540          * can not update one instance of the statistics from more
541          * than one thread at a time, so grab the lock first.
542          */
543         g_bioq_lock(&g_bio_run_up);
544         if (g_collectstats & 1)
545                 devstat_end_transaction_bio(pp->stat, bp);
546         if (g_collectstats & 2)
547                 devstat_end_transaction_bio(cp->stat, bp);
548
549         cp->nend++;
550         pp->nend++;
551         if (error != ENOMEM) {
552                 bp->bio_error = error;
553                 first = TAILQ_EMPTY(&g_bio_run_up.bio_queue);
554                 TAILQ_INSERT_TAIL(&g_bio_run_up.bio_queue, bp, bio_queue);
555                 bp->bio_flags |= BIO_ONQUEUE;
556                 g_bio_run_up.bio_queue_length++;
557                 g_bioq_unlock(&g_bio_run_up);
558                 if (first)
559                         wakeup(&g_wait_up);
560                 return;
561         }
562         g_bioq_unlock(&g_bio_run_up);
563
564         if (bootverbose)
565                 printf("ENOMEM %p on %p(%s)\n", bp, pp, pp->name);
566         bp->bio_children = 0;
567         bp->bio_inbed = 0;
568         g_io_request(bp, cp);
569         pace++;
570         return;
571 }
572
573 void
574 g_io_schedule_down(struct thread *tp __unused)
575 {
576         struct bio *bp;
577         off_t excess;
578         int error;
579
580         for(;;) {
581                 g_bioq_lock(&g_bio_run_down);
582                 bp = g_bioq_first(&g_bio_run_down);
583                 if (bp == NULL) {
584                         CTR0(KTR_GEOM, "g_down going to sleep");
585                         msleep(&g_wait_down, &g_bio_run_down.bio_queue_lock,
586                             PRIBIO | PDROP, "-", 0);
587                         continue;
588                 }
589                 CTR0(KTR_GEOM, "g_down has work to do");
590                 g_bioq_unlock(&g_bio_run_down);
591                 if (pace > 0) {
592                         CTR1(KTR_GEOM, "g_down pacing self (pace %d)", pace);
593                         pause("g_down", hz/10);
594                         pace--;
595                 }
596                 error = g_io_check(bp);
597                 if (error) {
598                         CTR3(KTR_GEOM, "g_down g_io_check on bp %p provider "
599                             "%s returned %d", bp, bp->bio_to->name, error);
600                         g_io_deliver(bp, error);
601                         continue;
602                 }
603                 CTR2(KTR_GEOM, "g_down processing bp %p provider %s", bp,
604                     bp->bio_to->name);
605                 switch (bp->bio_cmd) {
606                 case BIO_READ:
607                 case BIO_WRITE:
608                 case BIO_DELETE:
609                         /* Truncate requests to the end of providers media. */
610                         /*
611                          * XXX: What if we truncate because of offset being
612                          * bad, not length?
613                          */
614                         excess = bp->bio_offset + bp->bio_length;
615                         if (excess > bp->bio_to->mediasize) {
616                                 excess -= bp->bio_to->mediasize;
617                                 bp->bio_length -= excess;
618                                 if (excess > 0)
619                                         CTR3(KTR_GEOM, "g_down truncated bio "
620                                             "%p provider %s by %d", bp,
621                                             bp->bio_to->name, excess);
622                         }
623                         /* Deliver zero length transfers right here. */
624                         if (bp->bio_length == 0) {
625                                 g_io_deliver(bp, 0);
626                                 CTR2(KTR_GEOM, "g_down terminated 0-length "
627                                     "bp %p provider %s", bp, bp->bio_to->name);
628                                 continue;
629                         }
630                         break;
631                 default:
632                         break;
633                 }
634                 THREAD_NO_SLEEPING();
635                 CTR4(KTR_GEOM, "g_down starting bp %p provider %s off %ld "
636                     "len %ld", bp, bp->bio_to->name, bp->bio_offset,
637                     bp->bio_length);
638                 bp->bio_to->geom->start(bp);
639                 THREAD_SLEEPING_OK();
640         }
641 }
642
643 void
644 bio_taskqueue(struct bio *bp, bio_task_t *func, void *arg)
645 {
646         bp->bio_task = func;
647         bp->bio_task_arg = arg;
648         /*
649          * The taskqueue is actually just a second queue off the "up"
650          * queue, so we use the same lock.
651          */
652         g_bioq_lock(&g_bio_run_up);
653         KASSERT(!(bp->bio_flags & BIO_ONQUEUE),
654             ("Bio already on queue bp=%p target taskq", bp));
655         bp->bio_flags |= BIO_ONQUEUE;
656         TAILQ_INSERT_TAIL(&g_bio_run_task.bio_queue, bp, bio_queue);
657         g_bio_run_task.bio_queue_length++;
658         wakeup(&g_wait_up);
659         g_bioq_unlock(&g_bio_run_up);
660 }
661
662
663 void
664 g_io_schedule_up(struct thread *tp __unused)
665 {
666         struct bio *bp;
667         for(;;) {
668                 g_bioq_lock(&g_bio_run_up);
669                 bp = g_bioq_first(&g_bio_run_task);
670                 if (bp != NULL) {
671                         g_bioq_unlock(&g_bio_run_up);
672                         THREAD_NO_SLEEPING();
673                         CTR1(KTR_GEOM, "g_up processing task bp %p", bp);
674                         bp->bio_task(bp->bio_task_arg);
675                         THREAD_SLEEPING_OK();
676                         continue;
677                 }
678                 bp = g_bioq_first(&g_bio_run_up);
679                 if (bp != NULL) {
680                         g_bioq_unlock(&g_bio_run_up);
681                         THREAD_NO_SLEEPING();
682                         CTR4(KTR_GEOM, "g_up biodone bp %p provider %s off "
683                             "%jd len %ld", bp, bp->bio_to->name,
684                             bp->bio_offset, bp->bio_length);
685                         biodone(bp);
686                         THREAD_SLEEPING_OK();
687                         continue;
688                 }
689                 CTR0(KTR_GEOM, "g_up going to sleep");
690                 msleep(&g_wait_up, &g_bio_run_up.bio_queue_lock,
691                     PRIBIO | PDROP, "-", 0);
692         }
693 }
694
695 void *
696 g_read_data(struct g_consumer *cp, off_t offset, off_t length, int *error)
697 {
698         struct bio *bp;
699         void *ptr;
700         int errorc;
701
702         KASSERT(length > 0 && length >= cp->provider->sectorsize &&
703             length <= MAXPHYS, ("g_read_data(): invalid length %jd",
704             (intmax_t)length));
705
706         bp = g_alloc_bio();
707         bp->bio_cmd = BIO_READ;
708         bp->bio_done = NULL;
709         bp->bio_offset = offset;
710         bp->bio_length = length;
711         ptr = g_malloc(length, M_WAITOK);
712         bp->bio_data = ptr;
713         g_io_request(bp, cp);
714         errorc = biowait(bp, "gread");
715         if (error != NULL)
716                 *error = errorc;
717         g_destroy_bio(bp);
718         if (errorc) {
719                 g_free(ptr);
720                 ptr = NULL;
721         }
722         return (ptr);
723 }
724
725 int
726 g_write_data(struct g_consumer *cp, off_t offset, void *ptr, off_t length)
727 {
728         struct bio *bp;
729         int error;
730
731         KASSERT(length > 0 && length >= cp->provider->sectorsize &&
732             length <= MAXPHYS, ("g_write_data(): invalid length %jd",
733             (intmax_t)length));
734
735         bp = g_alloc_bio();
736         bp->bio_cmd = BIO_WRITE;
737         bp->bio_done = NULL;
738         bp->bio_offset = offset;
739         bp->bio_length = length;
740         bp->bio_data = ptr;
741         g_io_request(bp, cp);
742         error = biowait(bp, "gwrite");
743         g_destroy_bio(bp);
744         return (error);
745 }
746
747 int
748 g_delete_data(struct g_consumer *cp, off_t offset, off_t length)
749 {
750         struct bio *bp;
751         int error;
752
753         KASSERT(length > 0 && length >= cp->provider->sectorsize,
754             ("g_delete_data(): invalid length %jd", (intmax_t)length));
755
756         bp = g_alloc_bio();
757         bp->bio_cmd = BIO_DELETE;
758         bp->bio_done = NULL;
759         bp->bio_offset = offset;
760         bp->bio_length = length;
761         bp->bio_data = NULL;
762         g_io_request(bp, cp);
763         error = biowait(bp, "gdelete");
764         g_destroy_bio(bp);
765         return (error);
766 }
767
768 void
769 g_print_bio(struct bio *bp)
770 {
771         const char *pname, *cmd = NULL;
772
773         if (bp->bio_to != NULL)
774                 pname = bp->bio_to->name;
775         else
776                 pname = "[unknown]";
777
778         switch (bp->bio_cmd) {
779         case BIO_GETATTR:
780                 cmd = "GETATTR";
781                 printf("%s[%s(attr=%s)]", pname, cmd, bp->bio_attribute);
782                 return;
783         case BIO_FLUSH:
784                 cmd = "FLUSH";
785                 printf("%s[%s]", pname, cmd);
786                 return;
787         case BIO_READ:
788                 cmd = "READ";
789                 break;
790         case BIO_WRITE:
791                 cmd = "WRITE";
792                 break;
793         case BIO_DELETE:
794                 cmd = "DELETE";
795                 break;
796         default:
797                 cmd = "UNKNOWN";
798                 printf("%s[%s()]", pname, cmd);
799                 return;
800         }
801         printf("%s[%s(offset=%jd, length=%jd)]", pname, cmd,
802             (intmax_t)bp->bio_offset, (intmax_t)bp->bio_length);
803 }