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/vinum/geom_vinum_rm.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) 2004 Lukas Ertl
    3  *  All rights reserved.
    4  * 
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 
   14  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 #include <sys/param.h>
   32 #include <sys/libkern.h>
   33 #include <sys/kernel.h>
   34 #include <sys/malloc.h>
   35 
   36 #include <geom/geom.h>
   37 #include <geom/vinum/geom_vinum_var.h>
   38 #include <geom/vinum/geom_vinum.h>
   39 #include <geom/vinum/geom_vinum_share.h>
   40 
   41 static int      gv_rm_drive(struct gv_softc *, struct gctl_req *,
   42                     struct gv_drive *, int);
   43 static int      gv_rm_plex(struct gv_softc *, struct gctl_req *,
   44                     struct gv_plex *, int);
   45 static int      gv_rm_vol(struct gv_softc *, struct gctl_req *,
   46                     struct gv_volume *, int);
   47 
   48 /* General 'remove' routine. */
   49 void
   50 gv_remove(struct g_geom *gp, struct gctl_req *req)
   51 {
   52         struct gv_softc *sc;
   53         struct gv_volume *v;
   54         struct gv_plex *p;
   55         struct gv_sd *s;
   56         struct gv_drive *d;
   57         int *argc, *flags;
   58         char *argv, buf[20];
   59         int i, type, err;
   60 
   61         argc = gctl_get_paraml(req, "argc", sizeof(*argc));
   62         flags = gctl_get_paraml(req, "flags", sizeof(*flags));
   63 
   64         if (argc == NULL || *argc == 0) {
   65                 gctl_error(req, "no arguments given");
   66                 return;
   67         }
   68 
   69         sc = gp->softc;
   70 
   71         for (i = 0; i < *argc; i++) {
   72                 snprintf(buf, sizeof(buf), "argv%d", i);
   73                 argv = gctl_get_param(req, buf, NULL);
   74                 if (argv == NULL)
   75                         continue;
   76                 type = gv_object_type(sc, argv);
   77                 switch (type) {
   78                 case GV_TYPE_VOL:
   79                         v = gv_find_vol(sc, argv);
   80                         if (v == NULL) {
   81                                 gctl_error(req, "unknown volume '%s'", argv);
   82                                 return;
   83                         }
   84                         err = gv_rm_vol(sc, req, v, *flags);
   85                         if (err)
   86                                 return;
   87                         break;
   88                 case GV_TYPE_PLEX:
   89                         p = gv_find_plex(sc, argv);
   90                         if (p == NULL) {
   91                                 gctl_error(req, "unknown plex '%s'", argv);
   92                                 return;
   93                         }
   94                         err = gv_rm_plex(sc, req, p, *flags);
   95                         if (err)
   96                                 return;
   97                         break;
   98                 case GV_TYPE_SD:
   99                         s = gv_find_sd(sc, argv);
  100                         if (s == NULL) {
  101                                 gctl_error(req, "unknown subdisk '%s'", argv);
  102                                 return;
  103                         }
  104                         err = gv_rm_sd(sc, req, s, *flags);
  105                         if (err)
  106                                 return;
  107                         break;
  108                 case GV_TYPE_DRIVE:
  109                         d = gv_find_drive(sc, argv);
  110                         if (d == NULL) {
  111                                 gctl_error(req, "unknown drive '%s'", argv);
  112                                 return;
  113                         }
  114                         err = gv_rm_drive(sc, req, d, *flags);
  115                         if (err)
  116                                 return;
  117                         break;
  118                 default:
  119                         gctl_error(req, "unknown object '%s'", argv);
  120                         return;
  121                 }
  122         }
  123 
  124         gv_save_config_all(sc);
  125 }
  126 
  127 /* Resets configuration */
  128 int
  129 gv_resetconfig(struct g_geom *gp, struct gctl_req *req)
  130 {
  131         struct gv_softc *sc;
  132         struct gv_drive *d, *d2;
  133         struct gv_volume *v, *v2;
  134         struct gv_plex *p, *p2;
  135         struct gv_sd *s, *s2;
  136         int flags;
  137 
  138         d = NULL;
  139         d2 = NULL;
  140         p = NULL;
  141         p2 = NULL;
  142         s = NULL;
  143         s2 = NULL;
  144         flags = GV_FLAG_R;
  145         sc = gp->softc;
  146         /* First loop through to make sure no volumes are up */
  147         LIST_FOREACH_SAFE(v, &sc->volumes, volume, v2) {
  148                 if (gv_is_open(v->geom)) {
  149                         gctl_error(req, "volume '%s' is busy", v->name);
  150                         return (-1);
  151                 }
  152         }
  153         /* Then if not, we remove everything. */
  154         LIST_FOREACH_SAFE(v, &sc->volumes, volume, v2)
  155                 gv_rm_vol(sc, req, v, flags);
  156         LIST_FOREACH_SAFE(p, &sc->plexes, plex, p2)
  157                 gv_rm_plex(sc, req, p, flags);
  158         LIST_FOREACH_SAFE(s, &sc->subdisks, sd, s2)
  159                 gv_rm_sd(sc, req, s, flags);
  160         LIST_FOREACH_SAFE(d, &sc->drives, drive, d2)
  161                 gv_rm_drive(sc, req, d, flags);
  162         gv_save_config_all(sc);
  163         return (0);
  164 }
  165 
  166 /* Remove a volume. */
  167 static int
  168 gv_rm_vol(struct gv_softc *sc, struct gctl_req *req, struct gv_volume *v, int flags)
  169 {
  170         struct g_geom *gp;
  171         struct gv_plex *p, *p2;
  172         int err;
  173 
  174         g_topology_assert();
  175         KASSERT(v != NULL, ("gv_rm_vol: NULL v"));
  176 
  177         /* If this volume has plexes, we want a recursive removal. */
  178         if (!LIST_EMPTY(&v->plexes) && !(flags & GV_FLAG_R)) {
  179                 gctl_error(req, "volume '%s' has attached plexes", v->name);
  180                 return (-1);
  181         }
  182 
  183         gp = v->geom;
  184 
  185         /* Check if any of our consumers is open. */
  186         if (gp != NULL && gv_is_open(gp)) {
  187                 gctl_error(req, "volume '%s' is busy", v->name);
  188                 return (-1);
  189         }
  190 
  191         /* Remove the plexes our volume has. */
  192         LIST_FOREACH_SAFE(p, &v->plexes, in_volume, p2) {
  193                 v->plexcount--;
  194                 LIST_REMOVE(p, in_volume);
  195                 p->vol_sc = NULL;
  196 
  197                 err = gv_rm_plex(sc, req, p, flags);
  198                 if (err)
  199                         return (err);
  200         }
  201 
  202         /* Clean up and let our geom fade away. */
  203         LIST_REMOVE(v, volume);
  204         gv_kill_vol_thread(v);
  205         g_free(v);
  206         if (gp != NULL) {
  207                 gp->softc = NULL;
  208                 g_wither_geom(gp, ENXIO);
  209         }
  210 
  211         return (0);
  212 }
  213 
  214 /* Remove a plex. */
  215 static int
  216 gv_rm_plex(struct gv_softc *sc, struct gctl_req *req, struct gv_plex *p, int flags)
  217 {
  218         struct g_geom *gp;
  219         struct gv_volume *v;
  220         struct gv_sd *s, *s2;
  221         int err;
  222 
  223         g_topology_assert();
  224 
  225         KASSERT(p != NULL, ("gv_rm_plex: NULL p"));
  226 
  227         /* If this plex has subdisks, we want a recursive removal. */
  228         if (!LIST_EMPTY(&p->subdisks) && !(flags & GV_FLAG_R)) {
  229                 gctl_error(req, "plex '%s' has attached subdisks", p->name);
  230                 return (-1);
  231         }
  232 
  233         if (p->vol_sc != NULL && p->vol_sc->plexcount == 1) {
  234                 gctl_error(req, "plex '%s' is still attached to volume '%s'",
  235                     p->name, p->volume);
  236                 return (-1);
  237         }
  238 
  239         gp = p->geom;
  240 
  241         /* Check if any of our consumers is open. */
  242         if (gp != NULL && gv_is_open(gp)) {
  243                 gctl_error(req, "plex '%s' is busy", p->name);
  244                 return (-1);
  245         }
  246 
  247         /* Remove the subdisks our plex has. */
  248         LIST_FOREACH_SAFE(s, &p->subdisks, in_plex, s2) {
  249 #if 0
  250                 LIST_REMOVE(s, in_plex);
  251                 s->plex_sc = NULL;
  252 #endif
  253 
  254                 err = gv_rm_sd(sc, req, s, flags);
  255                 if (err)
  256                         return (err);
  257         }
  258 
  259         v = p->vol_sc;
  260         /* Clean up and let our geom fade away. */
  261         LIST_REMOVE(p, plex);
  262         if (p->vol_sc != NULL) {
  263                 p->vol_sc->plexcount--;
  264                 LIST_REMOVE(p, in_volume);
  265                 p->vol_sc = NULL;
  266                 /* Correctly update the volume size. */
  267                 gv_update_vol_size(v, gv_vol_size(v));
  268         }
  269 
  270         gv_kill_plex_thread(p);
  271         g_free(p);
  272 
  273         if (gp != NULL) {
  274                 gp->softc = NULL;
  275                 g_wither_geom(gp, ENXIO);
  276         }
  277 
  278         return (0);
  279 }
  280 
  281 /* Remove a subdisk. */
  282 int
  283 gv_rm_sd(struct gv_softc *sc, struct gctl_req *req, struct gv_sd *s, int flags)
  284 {
  285         struct g_provider *pp;
  286         struct gv_plex *p;
  287         struct gv_volume *v;
  288 
  289         KASSERT(s != NULL, ("gv_rm_sd: NULL s"));
  290 
  291         pp = s->provider;
  292         p = s->plex_sc;
  293         v = NULL;
  294 
  295         /* Clean up. */
  296         if (p != NULL) {
  297                 LIST_REMOVE(s, in_plex);
  298 
  299                 p->sdcount--;
  300                 /* Update the plexsize. */
  301                 p->size = gv_plex_size(p);
  302                 v = p->vol_sc;
  303                 if (v != NULL) {
  304                         /* Update the size of our plex' volume. */
  305                         gv_update_vol_size(v, gv_vol_size(v));
  306                 }
  307         }
  308         if (s->drive_sc)
  309                 LIST_REMOVE(s, from_drive);
  310         LIST_REMOVE(s, sd);
  311         gv_free_sd(s);
  312         g_free(s);
  313 
  314         /* If the subdisk has a provider we need to clean up this one too. */
  315         if (pp != NULL) {
  316                 pp->flags |= G_PF_WITHER;
  317                 g_orphan_provider(pp, ENXIO);
  318         }
  319 
  320         return (0);
  321 }
  322 
  323 /* Remove a drive. */
  324 static int
  325 gv_rm_drive(struct gv_softc *sc, struct gctl_req *req, struct gv_drive *d, int flags)
  326 {
  327         struct g_geom *gp;
  328         struct g_consumer *cp;
  329         struct gv_freelist *fl, *fl2;
  330         struct gv_plex *p;
  331         struct gv_sd *s, *s2;
  332         struct gv_volume *v;
  333         int err;
  334 
  335         KASSERT(d != NULL, ("gv_rm_drive: NULL d"));
  336         gp = d->geom;
  337         KASSERT(gp != NULL, ("gv_rm_drive: NULL gp"));
  338 
  339         /* We don't allow to remove open drives. */
  340         if (gv_is_open(gp)) {
  341                 gctl_error(req, "drive '%s' is open", d->name);
  342                 return (-1);
  343         }
  344 
  345         /* A drive with subdisks needs a recursive removal. */
  346         if (!LIST_EMPTY(&d->subdisks) && !(flags & GV_FLAG_R)) {
  347                 gctl_error(req, "drive '%s' still has subdisks", d->name);
  348                 return (-1);
  349         }
  350 
  351         cp = LIST_FIRST(&gp->consumer);
  352         err = g_access(cp, 0, 1, 0);
  353         if (err) {
  354                 printf("GEOM_VINUM: gv_rm_drive: couldn't access '%s', errno: "
  355                     "%d\n", cp->provider->name, err);
  356                 return (err);
  357         }
  358 
  359         /* Clear the Vinum Magic. */
  360         d->hdr->magic = GV_NOMAGIC;
  361         g_topology_unlock();
  362         err = g_write_data(cp, GV_HDR_OFFSET, d->hdr, GV_HDR_LEN);
  363         if (err) {
  364                 printf("GEOM_VINUM: gv_rm_drive: couldn't write header to '%s'"
  365                     ", errno: %d\n", cp->provider->name, err);
  366                 d->hdr->magic = GV_MAGIC;
  367         }
  368         g_topology_lock();
  369         g_access(cp, 0, -1, 0);
  370 
  371         /* Remove all associated subdisks, plexes, volumes. */
  372         if (!LIST_EMPTY(&d->subdisks)) {
  373                 LIST_FOREACH_SAFE(s, &d->subdisks, from_drive, s2) {
  374                         p = s->plex_sc;
  375                         if (p != NULL) {
  376                                 v = p->vol_sc;
  377                                 if (v != NULL)
  378                                         gv_rm_vol(sc, req, v, flags);
  379                         }
  380                 }
  381         }
  382 
  383         /* Clean up. */
  384         LIST_FOREACH_SAFE(fl, &d->freelist, freelist, fl2) {
  385                 LIST_REMOVE(fl, freelist);
  386                 g_free(fl);
  387         }
  388         LIST_REMOVE(d, drive);
  389 
  390         gv_kill_drive_thread(d);
  391         gp = d->geom;
  392         d->geom = NULL;
  393         g_free(d->hdr);
  394         g_free(d);
  395         gv_save_config_all(sc);
  396         g_wither_geom(gp, ENXIO);
  397 
  398         return (err);
  399 }

Cache object: c7ce52178cad53cca93b0119c8b74a1a


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