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/mountver/g_mountver.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2010 Edward Tomasz Napierala <trasz@FreeBSD.org>
    5  * Copyright (c) 2004-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/kernel.h>
   36 #include <sys/module.h>
   37 #include <sys/lock.h>
   38 #include <sys/mutex.h>
   39 #include <sys/bio.h>
   40 #include <sys/disk.h>
   41 #include <sys/proc.h>
   42 #include <sys/sbuf.h>
   43 #include <sys/sysctl.h>
   44 #include <sys/malloc.h>
   45 #include <sys/eventhandler.h>
   46 #include <geom/geom.h>
   47 #include <geom/geom_dbg.h>
   48 #include <geom/mountver/g_mountver.h>
   49 
   50 SYSCTL_DECL(_kern_geom);
   51 static SYSCTL_NODE(_kern_geom, OID_AUTO, mountver, CTLFLAG_RW | CTLFLAG_MPSAFE,
   52     0, "GEOM_MOUNTVER stuff");
   53 static u_int g_mountver_debug = 0;
   54 static u_int g_mountver_check_ident = 1;
   55 SYSCTL_UINT(_kern_geom_mountver, OID_AUTO, debug, CTLFLAG_RW,
   56     &g_mountver_debug, 0, "Debug level");
   57 SYSCTL_UINT(_kern_geom_mountver, OID_AUTO, check_ident, CTLFLAG_RW,
   58     &g_mountver_check_ident, 0, "Check disk ident when reattaching");
   59 
   60 static eventhandler_tag g_mountver_pre_sync = NULL;
   61 
   62 static void g_mountver_queue(struct bio *bp);
   63 static void g_mountver_orphan(struct g_consumer *cp);
   64 static void g_mountver_resize(struct g_consumer *cp);
   65 static int g_mountver_destroy(struct g_geom *gp, boolean_t force);
   66 static g_taste_t g_mountver_taste;
   67 static int g_mountver_destroy_geom(struct gctl_req *req, struct g_class *mp,
   68     struct g_geom *gp);
   69 static void g_mountver_config(struct gctl_req *req, struct g_class *mp,
   70     const char *verb);
   71 static void g_mountver_dumpconf(struct sbuf *sb, const char *indent,
   72     struct g_geom *gp, struct g_consumer *cp, struct g_provider *pp);
   73 static void g_mountver_init(struct g_class *mp);
   74 static void g_mountver_fini(struct g_class *mp);
   75 
   76 struct g_class g_mountver_class = {
   77         .name = G_MOUNTVER_CLASS_NAME,
   78         .version = G_VERSION,
   79         .ctlreq = g_mountver_config,
   80         .taste = g_mountver_taste,
   81         .destroy_geom = g_mountver_destroy_geom,
   82         .init = g_mountver_init,
   83         .fini = g_mountver_fini
   84 };
   85 
   86 static void
   87 g_mountver_detach(void *arg, int flags __unused)
   88 {
   89         struct g_consumer *cp = arg;
   90 
   91         g_topology_assert();
   92         if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0)
   93                 g_access(cp, -cp->acr, -cp->acw, -cp->ace);
   94         g_detach(cp);
   95 }
   96 
   97 static void
   98 g_mountver_done(struct bio *bp)
   99 {
  100         struct g_mountver_softc *sc;
  101         struct g_geom *gp;
  102         struct g_consumer *cp;
  103         struct bio *pbp;
  104 
  105         cp = bp->bio_from;
  106         gp = cp->geom;
  107         if (bp->bio_error != ENXIO) {
  108                 g_std_done(bp);
  109                 goto done;
  110         }
  111 
  112         /*
  113          * When the device goes away, it's possible that few requests
  114          * will be completed with ENXIO before g_mountver_orphan()
  115          * gets called.  To work around that, we have to queue requests
  116          * that failed with ENXIO, in order to send them later.
  117          */
  118         pbp = bp->bio_parent;
  119         KASSERT(pbp->bio_to == LIST_FIRST(&gp->provider),
  120             ("parent request was for someone else"));
  121         g_destroy_bio(bp);
  122         pbp->bio_inbed++;
  123         g_mountver_queue(pbp);
  124 
  125 done:
  126         sc = gp->softc;
  127         mtx_lock(&sc->sc_mtx);
  128         if (--cp->index == 0 && sc->sc_orphaned)
  129                 g_post_event(g_mountver_detach, cp, M_NOWAIT, NULL);
  130         mtx_unlock(&sc->sc_mtx);
  131 }
  132 
  133 /*
  134  * Send the BIO down.  The function is called with sc_mtx held to cover
  135  * the race with orphan, but drops it before external calls.
  136  */
  137 static void
  138 g_mountver_send(struct g_geom *gp, struct bio *bp)
  139 {
  140         struct g_mountver_softc *sc = gp->softc;
  141         struct g_consumer *cp;
  142         struct bio *cbp;
  143 
  144         mtx_assert(&sc->sc_mtx, MA_OWNED);
  145         cbp = g_clone_bio(bp);
  146         if (cbp == NULL) {
  147                 mtx_unlock(&sc->sc_mtx);
  148                 g_io_deliver(bp, ENOMEM);
  149                 return;
  150         }
  151         cp = LIST_FIRST(&gp->consumer);
  152         cp->index++;
  153         mtx_unlock(&sc->sc_mtx);
  154 
  155         cbp->bio_done = g_mountver_done;
  156         g_io_request(cbp, cp);
  157 }
  158 
  159 static void
  160 g_mountver_queue(struct bio *bp)
  161 {
  162         struct g_mountver_softc *sc;
  163         struct g_geom *gp;
  164 
  165         gp = bp->bio_to->geom;
  166         sc = gp->softc;
  167 
  168         mtx_lock(&sc->sc_mtx);
  169         TAILQ_INSERT_TAIL(&sc->sc_queue, bp, bio_queue);
  170         mtx_unlock(&sc->sc_mtx);
  171 }
  172 
  173 static void
  174 g_mountver_send_queued(struct g_geom *gp)
  175 {
  176         struct g_mountver_softc *sc;
  177         struct bio *bp;
  178 
  179         sc = gp->softc;
  180 
  181         mtx_lock(&sc->sc_mtx);
  182         while ((bp = TAILQ_FIRST(&sc->sc_queue)) != NULL && !sc->sc_orphaned) {
  183                 TAILQ_REMOVE(&sc->sc_queue, bp, bio_queue);
  184                 G_MOUNTVER_LOGREQ(bp, "Sending queued request.");
  185                 /* sc_mtx is dropped inside */
  186                 g_mountver_send(gp, bp);
  187                 mtx_lock(&sc->sc_mtx);
  188         }
  189         mtx_unlock(&sc->sc_mtx);
  190 }
  191 
  192 static void
  193 g_mountver_discard_queued(struct g_geom *gp)
  194 {
  195         struct g_mountver_softc *sc;
  196         struct bio *bp;
  197 
  198         sc = gp->softc;
  199 
  200         mtx_lock(&sc->sc_mtx);
  201         while ((bp = TAILQ_FIRST(&sc->sc_queue)) != NULL) {
  202                 TAILQ_REMOVE(&sc->sc_queue, bp, bio_queue);
  203                 mtx_unlock(&sc->sc_mtx);
  204                 G_MOUNTVER_LOGREQ(bp, "Discarding queued request.");
  205                 g_io_deliver(bp, ENXIO);
  206                 mtx_lock(&sc->sc_mtx);
  207         }
  208         mtx_unlock(&sc->sc_mtx);
  209 }
  210 
  211 static void
  212 g_mountver_start(struct bio *bp)
  213 {
  214         struct g_mountver_softc *sc;
  215         struct g_geom *gp;
  216 
  217         gp = bp->bio_to->geom;
  218         sc = gp->softc;
  219         G_MOUNTVER_LOGREQ(bp, "Request received.");
  220 
  221         /*
  222          * It is possible that some bios were returned with ENXIO, even though
  223          * orphaning didn't happen yet.  In that case, queue all subsequent
  224          * requests in order to maintain ordering.
  225          */
  226         mtx_lock(&sc->sc_mtx);
  227         if (sc->sc_orphaned || !TAILQ_EMPTY(&sc->sc_queue)) {
  228                 mtx_unlock(&sc->sc_mtx);
  229                 if (sc->sc_shutting_down) {
  230                         G_MOUNTVER_LOGREQ(bp, "Discarding request due to shutdown.");
  231                         g_io_deliver(bp, ENXIO);
  232                         return;
  233                 }
  234                 G_MOUNTVER_LOGREQ(bp, "Queueing request.");
  235                 g_mountver_queue(bp);
  236                 if (!sc->sc_orphaned)
  237                         g_mountver_send_queued(gp);
  238         } else {
  239                 G_MOUNTVER_LOGREQ(bp, "Sending request.");
  240                 /* sc_mtx is dropped inside */
  241                 g_mountver_send(gp, bp);
  242         }
  243 }
  244 
  245 static int
  246 g_mountver_access(struct g_provider *pp, int dr, int dw, int de)
  247 {
  248         struct g_mountver_softc *sc;
  249         struct g_geom *gp;
  250         struct g_consumer *cp;
  251 
  252         g_topology_assert();
  253 
  254         gp = pp->geom;
  255         cp = LIST_FIRST(&gp->consumer);
  256         sc = gp->softc;
  257         if (sc == NULL && dr <= 0 && dw <= 0 && de <= 0)
  258                 return (0);
  259         KASSERT(sc != NULL, ("Trying to access withered provider \"%s\".", pp->name));
  260 
  261         sc->sc_access_r += dr;
  262         sc->sc_access_w += dw;
  263         sc->sc_access_e += de;
  264 
  265         if (sc->sc_orphaned)
  266                 return (0);
  267 
  268         return (g_access(cp, dr, dw, de));
  269 }
  270 
  271 static int
  272 g_mountver_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp)
  273 {
  274         struct g_mountver_softc *sc;
  275         struct g_geom *gp;
  276         struct g_provider *newpp;
  277         struct g_consumer *cp;
  278         struct g_geom_alias *gap;
  279         char name[64];
  280         int error;
  281         int identsize = DISK_IDENT_SIZE;
  282 
  283         g_topology_assert();
  284 
  285         gp = NULL;
  286         newpp = NULL;
  287         cp = NULL;
  288 
  289         snprintf(name, sizeof(name), "%s%s", pp->name, G_MOUNTVER_SUFFIX);
  290         LIST_FOREACH(gp, &mp->geom, geom) {
  291                 if (strcmp(gp->name, name) == 0) {
  292                         gctl_error(req, "Provider %s already exists.", name);
  293                         return (EEXIST);
  294                 }
  295         }
  296         gp = g_new_geomf(mp, "%s", name);
  297         sc = g_malloc(sizeof(*sc), M_WAITOK | M_ZERO);
  298         mtx_init(&sc->sc_mtx, "gmountver", NULL, MTX_DEF | MTX_RECURSE);
  299         TAILQ_INIT(&sc->sc_queue);
  300         sc->sc_provider_name = strdup(pp->name, M_GEOM);
  301         gp->softc = sc;
  302         gp->start = g_mountver_start;
  303         gp->orphan = g_mountver_orphan;
  304         gp->resize = g_mountver_resize;
  305         gp->access = g_mountver_access;
  306         gp->dumpconf = g_mountver_dumpconf;
  307 
  308         newpp = g_new_providerf(gp, "%s", gp->name);
  309         newpp->mediasize = pp->mediasize;
  310         newpp->sectorsize = pp->sectorsize;
  311         newpp->flags |= G_PF_DIRECT_SEND | G_PF_DIRECT_RECEIVE;
  312         LIST_FOREACH(gap, &pp->aliases, ga_next)
  313                 g_provider_add_alias(newpp, "%s%s", gap->ga_alias, G_MOUNTVER_SUFFIX);
  314 
  315         if ((pp->flags & G_PF_ACCEPT_UNMAPPED) != 0) {
  316                 G_MOUNTVER_DEBUG(0, "Unmapped supported for %s.", gp->name);
  317                 newpp->flags |= G_PF_ACCEPT_UNMAPPED;
  318         } else {
  319                 G_MOUNTVER_DEBUG(0, "Unmapped unsupported for %s.", gp->name);
  320                 newpp->flags &= ~G_PF_ACCEPT_UNMAPPED;
  321         }
  322 
  323         cp = g_new_consumer(gp);
  324         cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE;
  325         error = g_attach(cp, pp);
  326         if (error != 0) {
  327                 gctl_error(req, "Cannot attach to provider %s.", pp->name);
  328                 goto fail;
  329         }
  330         error = g_access(cp, 1, 0, 0);
  331         if (error != 0) {
  332                 gctl_error(req, "Cannot access provider %s.", pp->name);
  333                 goto fail;
  334         }
  335         error = g_io_getattr("GEOM::ident", cp, &identsize, sc->sc_ident);
  336         g_access(cp, -1, 0, 0);
  337         if (error != 0) {
  338                 if (g_mountver_check_ident) {
  339                         gctl_error(req, "Cannot get disk ident from %s; error = %d.", pp->name, error);
  340                         goto fail;
  341                 }
  342 
  343                 G_MOUNTVER_DEBUG(0, "Cannot get disk ident from %s; error = %d.", pp->name, error);
  344                 sc->sc_ident[0] = '\0';
  345         }
  346 
  347         g_error_provider(newpp, 0);
  348         G_MOUNTVER_DEBUG(0, "Device %s created.", gp->name);
  349         return (0);
  350 fail:
  351         g_free(sc->sc_provider_name);
  352         if (cp->provider != NULL)
  353                 g_detach(cp);
  354         g_destroy_consumer(cp);
  355         g_destroy_provider(newpp);
  356         g_free(gp->softc);
  357         g_destroy_geom(gp);
  358         return (error);
  359 }
  360 
  361 static int
  362 g_mountver_destroy(struct g_geom *gp, boolean_t force)
  363 {
  364         struct g_mountver_softc *sc;
  365         struct g_provider *pp;
  366 
  367         g_topology_assert();
  368         if (gp->softc == NULL)
  369                 return (ENXIO);
  370         sc = gp->softc;
  371         pp = LIST_FIRST(&gp->provider);
  372         if (pp != NULL && (pp->acr != 0 || pp->acw != 0 || pp->ace != 0)) {
  373                 if (force) {
  374                         G_MOUNTVER_DEBUG(0, "Device %s is still open, so it "
  375                             "can't be definitely removed.", pp->name);
  376                 } else {
  377                         G_MOUNTVER_DEBUG(1, "Device %s is still open (r%dw%de%d).",
  378                             pp->name, pp->acr, pp->acw, pp->ace);
  379                         return (EBUSY);
  380                 }
  381         } else {
  382                 G_MOUNTVER_DEBUG(0, "Device %s removed.", gp->name);
  383         }
  384         if (pp != NULL)
  385                 g_wither_provider(pp, ENXIO);
  386         g_mountver_discard_queued(gp);
  387         g_free(sc->sc_provider_name);
  388         g_free(gp->softc);
  389         gp->softc = NULL;
  390         g_wither_geom(gp, ENXIO);
  391 
  392         return (0);
  393 }
  394 
  395 static int
  396 g_mountver_destroy_geom(struct gctl_req *req, struct g_class *mp, struct g_geom *gp)
  397 {
  398 
  399         return (g_mountver_destroy(gp, 0));
  400 }
  401 
  402 static void
  403 g_mountver_ctl_create(struct gctl_req *req, struct g_class *mp)
  404 {
  405         struct g_provider *pp;
  406         char param[16];
  407         int i, *nargs;
  408 
  409         g_topology_assert();
  410 
  411         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
  412         if (nargs == NULL) {
  413                 gctl_error(req, "No '%s' argument", "nargs");
  414                 return;
  415         }
  416         if (*nargs <= 0) {
  417                 gctl_error(req, "Missing device(s).");
  418                 return;
  419         }
  420         for (i = 0; i < *nargs; i++) {
  421                 snprintf(param, sizeof(param), "arg%d", i);
  422                 pp = gctl_get_provider(req, param);
  423                 if (pp == NULL)
  424                         return;
  425                 if (g_mountver_create(req, mp, pp) != 0)
  426                         return;
  427         }
  428 }
  429 
  430 static struct g_geom *
  431 g_mountver_find_geom(struct g_class *mp, const char *name)
  432 {
  433         struct g_geom *gp;
  434 
  435         LIST_FOREACH(gp, &mp->geom, geom) {
  436                 if (strcmp(gp->name, name) == 0)
  437                         return (gp);
  438         }
  439         return (NULL);
  440 }
  441 
  442 static void
  443 g_mountver_ctl_destroy(struct gctl_req *req, struct g_class *mp)
  444 {
  445         int *nargs, *force, error, i;
  446         struct g_geom *gp;
  447         const char *name;
  448         char param[16];
  449 
  450         g_topology_assert();
  451 
  452         nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
  453         if (nargs == NULL) {
  454                 gctl_error(req, "No '%s' argument", "nargs");
  455                 return;
  456         }
  457         if (*nargs <= 0) {
  458                 gctl_error(req, "Missing device(s).");
  459                 return;
  460         }
  461         force = gctl_get_paraml(req, "force", sizeof(*force));
  462         if (force == NULL) {
  463                 gctl_error(req, "No 'force' argument");
  464                 return;
  465         }
  466 
  467         for (i = 0; i < *nargs; i++) {
  468                 snprintf(param, sizeof(param), "arg%d", i);
  469                 name = gctl_get_asciiparam(req, param);
  470                 if (name == NULL) {
  471                         gctl_error(req, "No 'arg%d' argument", i);
  472                         return;
  473                 }
  474                 if (strncmp(name, _PATH_DEV, strlen(_PATH_DEV)) == 0)
  475                         name += strlen(_PATH_DEV);
  476                 gp = g_mountver_find_geom(mp, name);
  477                 if (gp == NULL) {
  478                         G_MOUNTVER_DEBUG(1, "Device %s is invalid.", name);
  479                         gctl_error(req, "Device %s is invalid.", name);
  480                         return;
  481                 }
  482                 error = g_mountver_destroy(gp, *force);
  483                 if (error != 0) {
  484                         gctl_error(req, "Cannot destroy device %s (error=%d).",
  485                             gp->name, error);
  486                         return;
  487                 }
  488         }
  489 }
  490 
  491 static void
  492 g_mountver_orphan(struct g_consumer *cp)
  493 {
  494         struct g_mountver_softc *sc;
  495         int done;
  496 
  497         g_topology_assert();
  498 
  499         sc = cp->geom->softc;
  500         mtx_lock(&sc->sc_mtx);
  501         sc->sc_orphaned = 1;
  502         done = (cp->index == 0);
  503         mtx_unlock(&sc->sc_mtx);
  504         if (done)
  505                 g_mountver_detach(cp, 0);
  506         G_MOUNTVER_DEBUG(0, "%s is offline.  Mount verification in progress.", sc->sc_provider_name);
  507 }
  508 
  509 static void
  510 g_mountver_resize(struct g_consumer *cp)
  511 {
  512         struct g_geom *gp;
  513         struct g_provider *pp;
  514 
  515         gp = cp->geom;
  516 
  517         LIST_FOREACH(pp, &gp->provider, provider)
  518                 g_resize_provider(pp, cp->provider->mediasize);
  519 }
  520 
  521 static int
  522 g_mountver_ident_matches(struct g_geom *gp)
  523 {
  524         struct g_consumer *cp;
  525         struct g_mountver_softc *sc;
  526         char ident[DISK_IDENT_SIZE];
  527         int error, identsize = DISK_IDENT_SIZE;
  528 
  529         sc = gp->softc;
  530         cp = LIST_FIRST(&gp->consumer);
  531 
  532         if (g_mountver_check_ident == 0)
  533                 return (0);
  534 
  535         error = g_access(cp, 1, 0, 0);
  536         if (error != 0) {
  537                 G_MOUNTVER_DEBUG(0, "Cannot access %s; "
  538                     "not attaching; error = %d.", gp->name, error);
  539                 return (1);
  540         }
  541         error = g_io_getattr("GEOM::ident", cp, &identsize, ident);
  542         g_access(cp, -1, 0, 0);
  543         if (error != 0) {
  544                 G_MOUNTVER_DEBUG(0, "Cannot get disk ident for %s; "
  545                     "not attaching; error = %d.", gp->name, error);
  546                 return (1);
  547         }
  548         if (strcmp(ident, sc->sc_ident) != 0) {
  549                 G_MOUNTVER_DEBUG(1, "Disk ident for %s (\"%s\") is different "
  550                     "from expected \"%s\", not attaching.", gp->name, ident,
  551                     sc->sc_ident);
  552                 return (1);
  553         }
  554 
  555         return (0);
  556 }
  557 
  558 static struct g_geom *
  559 g_mountver_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
  560 {
  561         struct g_mountver_softc *sc;
  562         struct g_consumer *cp;
  563         struct g_geom *gp;
  564         int error;
  565 
  566         g_topology_assert();
  567         g_trace(G_T_TOPOLOGY, "%s(%s, %s)", __func__, mp->name, pp->name);
  568         G_MOUNTVER_DEBUG(2, "Tasting %s.", pp->name);
  569 
  570         /*
  571          * Let's check if device already exists.
  572          */
  573         LIST_FOREACH(gp, &mp->geom, geom) {
  574                 sc = gp->softc;
  575                 if (sc == NULL)
  576                         continue;
  577 
  578                 /* Already attached? */
  579                 if (pp == LIST_FIRST(&gp->provider))
  580                         return (NULL);
  581 
  582                 if (sc->sc_orphaned && strcmp(pp->name, sc->sc_provider_name) == 0)
  583                         break;
  584         }
  585         if (gp == NULL)
  586                 return (NULL);
  587 
  588         cp = LIST_FIRST(&gp->consumer);
  589         error = g_attach(cp, pp);
  590         if (error != 0) {
  591                 G_MOUNTVER_DEBUG(0, "Cannot attach to %s; error = %d.", pp->name, error);
  592                 return (NULL);
  593         }
  594 
  595         error = g_mountver_ident_matches(gp);
  596         if (error != 0) {
  597                 g_detach(cp);
  598                 return (NULL);
  599         }
  600         if (sc->sc_access_r > 0 || sc->sc_access_w > 0 || sc->sc_access_e > 0) {
  601                 error = g_access(cp, sc->sc_access_r, sc->sc_access_w, sc->sc_access_e);
  602                 if (error != 0) {
  603                         G_MOUNTVER_DEBUG(0, "Cannot access %s; error = %d.", pp->name, error);
  604                         g_detach(cp);
  605                         return (NULL);
  606                 }
  607         }
  608         sc->sc_orphaned = 0;
  609         g_mountver_send_queued(gp);
  610         G_MOUNTVER_DEBUG(0, "%s has completed mount verification.", sc->sc_provider_name);
  611 
  612         return (gp);
  613 }
  614 
  615 static void
  616 g_mountver_config(struct gctl_req *req, struct g_class *mp, const char *verb)
  617 {
  618         uint32_t *version;
  619 
  620         g_topology_assert();
  621 
  622         version = gctl_get_paraml(req, "version", sizeof(*version));
  623         if (version == NULL) {
  624                 gctl_error(req, "No '%s' argument.", "version");
  625                 return;
  626         }
  627         if (*version != G_MOUNTVER_VERSION) {
  628                 gctl_error(req, "Userland and kernel parts are out of sync.");
  629                 return;
  630         }
  631 
  632         if (strcmp(verb, "create") == 0) {
  633                 g_mountver_ctl_create(req, mp);
  634                 return;
  635         } else if (strcmp(verb, "destroy") == 0) {
  636                 g_mountver_ctl_destroy(req, mp);
  637                 return;
  638         }
  639 
  640         gctl_error(req, "Unknown verb.");
  641 }
  642 
  643 static void
  644 g_mountver_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
  645     struct g_consumer *cp, struct g_provider *pp)
  646 {
  647         struct g_mountver_softc *sc;
  648 
  649         if (pp != NULL || cp != NULL)
  650                 return;
  651 
  652         sc = gp->softc;
  653         sbuf_printf(sb, "%s<State>%s</State>\n", indent,
  654             sc->sc_orphaned ? "OFFLINE" : "ONLINE");
  655         sbuf_printf(sb, "%s<Provider-Name>%s</Provider-Name>\n", indent, sc->sc_provider_name);
  656         sbuf_printf(sb, "%s<Disk-Ident>%s</Disk-Ident>\n", indent, sc->sc_ident);
  657 }
  658 
  659 static void
  660 g_mountver_shutdown_pre_sync(void *arg, int howto)
  661 {
  662         struct g_mountver_softc *sc;
  663         struct g_class *mp;
  664         struct g_geom *gp, *gp2;
  665 
  666         mp = arg;
  667         g_topology_lock();
  668         LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
  669                 if (gp->softc == NULL)
  670                         continue;
  671                 sc = gp->softc;
  672                 sc->sc_shutting_down = 1;
  673                 if (sc->sc_orphaned)
  674                         g_mountver_destroy(gp, 1);
  675         }
  676         g_topology_unlock();
  677 }
  678 
  679 static void
  680 g_mountver_init(struct g_class *mp)
  681 {
  682 
  683         g_mountver_pre_sync = EVENTHANDLER_REGISTER(shutdown_pre_sync,
  684             g_mountver_shutdown_pre_sync, mp, SHUTDOWN_PRI_FIRST);
  685         if (g_mountver_pre_sync == NULL)
  686                 G_MOUNTVER_DEBUG(0, "Warning! Cannot register shutdown event.");
  687 }
  688 
  689 static void
  690 g_mountver_fini(struct g_class *mp)
  691 {
  692 
  693         if (g_mountver_pre_sync != NULL)
  694                 EVENTHANDLER_DEREGISTER(shutdown_pre_sync, g_mountver_pre_sync);
  695 }
  696 
  697 DECLARE_GEOM_CLASS(g_mountver_class, g_mountver);
  698 MODULE_VERSION(geom_mountver, 0);

Cache object: 90470e588affd0e100d257a1d16fb929


[ 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.