The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/geom/geom_io.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: ef532f4e8f20c2208aeda586f2b65780


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.