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/dev/vinum/vinum.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) 1997, 1998
    3  *      Nan Yang Computer Services Limited.  All rights reserved.
    4  *
    5  *  Written by Greg Lehey
    6  *
    7  *  This software is distributed under the so-called ``Berkeley
    8  *  License'':
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by Nan Yang Computer
   21  *      Services Limited.
   22  * 4. Neither the name of the Company nor the names of its contributors
   23  *    may be used to endorse or promote products derived from this software
   24  *    without specific prior written permission.
   25  *
   26  * This software is provided ``as is'', and any express or implied
   27  * warranties, including, but not limited to, the implied warranties of
   28  * merchantability and fitness for a particular purpose are disclaimed.
   29  * In no event shall the company or contributors be liable for any
   30  * direct, indirect, incidental, special, exemplary, or consequential
   31  * damages (including, but not limited to, procurement of substitute
   32  * goods or services; loss of use, data, or profits; or business
   33  * interruption) however caused and on any theory of liability, whether
   34  * in contract, strict liability, or tort (including negligence or
   35  * otherwise) arising in any way out of the use of this software, even if
   36  * advised of the possibility of such damage.
   37  *
   38  * $Id: vinum.c,v 1.1.1.1 2003/10/10 03:07:37 grog Exp $
   39  * $FreeBSD$
   40  */
   41 
   42 #define STATIC static                                       /* nothing while we're testing XXX */
   43 
   44 #include <dev/vinum/vinumhdr.h>
   45 #ifdef VINUMDEBUG
   46 #include <sys/reboot.h>
   47 int debug = 0;
   48 extern int total_malloced;
   49 extern int malloccount;
   50 extern struct mc malloced[];
   51 #endif
   52 #include <dev/vinum/request.h>
   53 
   54 const struct cdevsw vinum_cdevsw =
   55 {
   56     vinumopen, vinumclose, vinumread, vinumwrite, vinumioctl,
   57     nostop, notty, nopoll, nommap, nokqfilter, D_DISK
   58 };
   59 
   60 const struct bdevsw vinum_bdevsw =
   61 {
   62     vinumopen, vinumclose, vinumstrategy, vinumioctl,
   63     nodump, vinumsize, D_DISK
   64 };
   65 
   66 /* Called by main() during pseudo-device attachment. */
   67 void vinumattach(void *);
   68 
   69 struct _vinum_conf vinum_conf;                              /* configuration information */
   70 
   71 /*
   72  * Called by main() during pseudo-device attachment.  All we need
   73  * to do is allocate enough space for devices to be configured later, and
   74  * add devsw entries.
   75  */
   76 void
   77 vinumattach(void *dummy)
   78 {
   79 /* modload should prevent multiple loads, so this is worth a panic */
   80     if ((vinum_conf.flags & VF_LOADED) != 0)
   81         panic("vinum: already loaded");
   82 
   83     log(LOG_INFO, "vinum: loaded\n");
   84 #ifdef VINUMDEBUG
   85     vinum_conf.flags |= VF_LOADED | VF_HASDEBUG;            /* we're loaded now, and we support debug */
   86 #else
   87     vinum_conf.flags |= VF_LOADED;                          /* we're loaded now */
   88 #endif
   89 
   90     daemonq = NULL;                                         /* initialize daemon's work queue */
   91     dqend = NULL;
   92 
   93     vinum_conf.version = VINUMVERSION;                      /* note what version we are */
   94 
   95     /* allocate space: drives... */
   96     DRIVE = (struct drive *) Malloc(sizeof(struct drive) * INITIAL_DRIVES);
   97     CHECKALLOC(DRIVE, "vinum: no memory\n");
   98     bzero(DRIVE, sizeof(struct drive) * INITIAL_DRIVES);
   99     vinum_conf.drives_allocated = INITIAL_DRIVES;           /* number of drive slots allocated */
  100     vinum_conf.drives_used = 0;                             /* and number in use */
  101 
  102     /* volumes, ... */
  103     VOL = (struct volume *) Malloc(sizeof(struct volume) * INITIAL_VOLUMES);
  104     CHECKALLOC(VOL, "vinum: no memory\n");
  105     bzero(VOL, sizeof(struct volume) * INITIAL_VOLUMES);
  106     vinum_conf.volumes_allocated = INITIAL_VOLUMES;         /* number of volume slots allocated */
  107     vinum_conf.volumes_used = 0;                            /* and number in use */
  108 
  109     /* plexes, ... */
  110     PLEX = (struct plex *) Malloc(sizeof(struct plex) * INITIAL_PLEXES);
  111     CHECKALLOC(PLEX, "vinum: no memory\n");
  112     bzero(PLEX, sizeof(struct plex) * INITIAL_PLEXES);
  113     vinum_conf.plexes_allocated = INITIAL_PLEXES;           /* number of plex slots allocated */
  114     vinum_conf.plexes_used = 0;                             /* and number in use */
  115 
  116     /* and subdisks */
  117     SD = (struct sd *) Malloc(sizeof(struct sd) * INITIAL_SUBDISKS);
  118     CHECKALLOC(SD, "vinum: no memory\n");
  119     bzero(SD, sizeof(struct sd) * INITIAL_SUBDISKS);
  120     vinum_conf.subdisks_allocated = INITIAL_SUBDISKS;       /* number of sd slots allocated */
  121     vinum_conf.subdisks_used = 0;                           /* and number in use */
  122 }
  123 
  124 /*
  125  * Check if we have anything open.  If confopen is != 0,
  126  * that goes for the super device as well, otherwise
  127  * only for volumes.
  128  *
  129  * Return 0 if not inactive, 1 if inactive.
  130  */
  131 int
  132 vinum_inactive(int confopen)
  133 {
  134     int i;
  135     int can_do = 1;                                         /* assume we can do it */
  136 
  137     if (confopen && (vinum_conf.flags & VF_OPEN))           /* open by vinum(8)? */
  138         return 0;                                           /* can't do it while we're open */
  139     lock_config();
  140     for (i = 0; i < vinum_conf.volumes_allocated; i++) {
  141         if ((VOL[i].state > volume_down)
  142             && (VOL[i].flags & VF_OPEN)) {                  /* volume is open */
  143             can_do = 0;
  144             break;
  145         }
  146     }
  147     unlock_config();
  148     return can_do;
  149 }
  150 
  151 /*
  152  * Free all structures.
  153  * If cleardrive is 0, save the configuration; otherwise
  154  * remove the configuration from the drive.
  155  *
  156  * Before coming here, ensure that no volumes are open.
  157  */
  158 void
  159 free_vinum(int cleardrive)
  160 {
  161     int i;
  162     int drives_allocated = vinum_conf.drives_allocated;
  163 
  164     if (DRIVE != NULL) {
  165         if (cleardrive) {                                   /* remove the vinum config */
  166             for (i = 0; i < drives_allocated; i++)
  167                 remove_drive(i);                            /* remove the drive */
  168         } else {                                            /* keep the config */
  169             for (i = 0; i < drives_allocated; i++)
  170                 free_drive(&DRIVE[i]);                      /* close files and things */
  171         }
  172         Free(DRIVE);
  173     }
  174     while ((vinum_conf.flags & (VF_STOPPING | VF_DAEMONOPEN))
  175         == (VF_STOPPING | VF_DAEMONOPEN)) {                 /* at least one daemon open, we're stopping */
  176         queue_daemon_request(daemonrq_return, (union daemoninfo) 0); /* stop the daemon */
  177         tsleep(&vinumclose, PUSER, "vstop", 1);             /* and wait for it */
  178     }
  179     if (SD != NULL) {
  180         for (i = 0; i < vinum_conf.subdisks_allocated; i++) {
  181             struct sd *sd = &SD[i];
  182 
  183             if (sd->state != sd_unallocated)
  184                 free_sd(i);
  185         }
  186         Free(SD);
  187     }
  188     if (PLEX != NULL) {
  189         for (i = 0; i < vinum_conf.plexes_allocated; i++) {
  190             struct plex *plex = &PLEX[i];
  191 
  192             if (plex->state != plex_unallocated)            /* we have real data there */
  193                 free_plex(i);
  194         }
  195         Free(PLEX);
  196     }
  197     if (VOL != NULL) {
  198         for (i = 0; i < vinum_conf.volumes_allocated; i++) {
  199             struct volume *volume = &VOL[i];
  200 
  201             if (volume->state != volume_unallocated)
  202                 free_volume(i);
  203         }
  204         Free(VOL);
  205     }
  206     bzero(&vinum_conf, sizeof(vinum_conf));
  207     vinum_conf.version = VINUMVERSION;                      /* reinstate version number */
  208 }
  209 
  210 
  211 /* ARGSUSED */
  212 /* Open a vinum object */
  213 int
  214 vinumopen(dev_t dev,
  215     int flags,
  216     int fmt,
  217     struct proc *p)
  218 {
  219     int error;
  220     unsigned int index;
  221     struct volume *vol;
  222     struct plex *plex;
  223     struct sd *sd;
  224     int devminor;                                           /* minor number */
  225 
  226     devminor = minor(dev);
  227     error = 0;
  228     /* First, decide what we're looking at */
  229     switch (DEVTYPE(dev)) {
  230     case VINUM_VOLUME_TYPE:
  231         /*
  232          * The super device and daemon device are the last two
  233          * volume numbers, so check for them first.
  234          */
  235         if ((devminor == VINUM_DAEMON_VOL)                  /* daemon device */
  236         ||(devminor == VINUM_SUPERDEV_VOL)) {               /* or normal super device */
  237             error = suser(p->p_ucred, &p->p_acflag);        /* are we root? */
  238 
  239             if (error == 0) {                               /* yes, can do */
  240                 if (devminor == VINUM_DAEMON_VOL)           /* daemon device */
  241                     vinum_conf.flags |= VF_DAEMONOPEN;      /* we're open */
  242                 else if (devminor == VINUM_SUPERDEV_VOL)
  243                     vinum_conf.flags |= VF_OPEN;            /* we're open */
  244             }
  245             return error;
  246         }
  247         /* Must be a real volume.  Check. */
  248         index = Volno(dev);
  249         if (index >= vinum_conf.volumes_allocated)
  250             return ENXIO;                                   /* no such device */
  251         vol = &VOL[index];
  252 
  253         switch (vol->state) {
  254         case volume_unallocated:
  255         case volume_uninit:
  256             return ENXIO;
  257 
  258         case volume_up:
  259             vol->flags |= VF_OPEN;                          /* note we're open */
  260             return 0;
  261 
  262         case volume_down:
  263             return EIO;
  264 
  265         default:
  266             return EINVAL;
  267         }
  268 
  269     case VINUM_PLEX_TYPE:
  270         index = Plexno(dev);                                /* get plex index in vinum_conf */
  271         if (index >= vinum_conf.plexes_allocated)
  272             return ENXIO;                                   /* no such device */
  273         plex = &PLEX[index];
  274 
  275         switch (plex->state) {
  276         case plex_unallocated:
  277             return ENXIO;
  278 
  279         case plex_referenced:
  280             return EINVAL;
  281 
  282         default:
  283             plex->flags |= VF_OPEN;                         /* note we're open */
  284             return 0;
  285         }
  286 
  287     case VINUM_SD_TYPE:
  288     case VINUM_SD2_TYPE:
  289         index = Sdno(dev);                                  /* get the subdisk number */
  290         if (index >= vinum_conf.subdisks_allocated)         /* not a valid SD entry */
  291             return ENXIO;                                   /* no such device */
  292         sd = &SD[index];
  293 
  294         /*
  295          * Opening a subdisk is always a special operation, so
  296          * we ignore the state as long as it represents a real
  297          * subdisk.
  298          */
  299         switch (sd->state) {
  300         case sd_unallocated:
  301             return ENXIO;
  302 
  303         case sd_uninit:
  304         case sd_referenced:
  305             return EINVAL;
  306 
  307         default:
  308             sd->flags |= VF_OPEN;                           /* note we're open */
  309             return 0;
  310         }
  311     }
  312     return 0;                                               /* to keep the compiler happy */
  313 }
  314 
  315 /* ARGSUSED */
  316 int
  317 vinumclose(dev_t dev,
  318     int flags,
  319     int fmt,
  320     struct proc *p)
  321 {
  322     unsigned int index;
  323     struct volume *vol;
  324     int devminor;
  325 
  326     devminor = minor(dev);
  327     /* First, decide what we're looking at */
  328     switch (DEVTYPE(dev)) {
  329     case VINUM_VOLUME_TYPE:
  330         /*
  331          * The super device and daemon device are the last two
  332          * volume numbers, so check for them first.
  333          */
  334         if ((devminor == VINUM_DAEMON_VOL)                  /* daemon device */
  335         ||(devminor == VINUM_SUPERDEV_VOL)) {               /* or normal super device */
  336             /*
  337              * don't worry about whether we're root:
  338              * nobody else would get this far.
  339              */
  340             if (devminor == VINUM_SUPERDEV_VOL)             /* normal superdev */
  341                 vinum_conf.flags &= ~VF_OPEN;               /* no longer open */
  342             else {                                          /* the daemon device */
  343                 vinum_conf.flags &= ~VF_DAEMONOPEN;         /* no longer open */
  344                 if (vinum_conf.flags & VF_STOPPING)         /* we're trying to stop, */
  345                     wakeup(&vinumclose);                    /* we can continue now */
  346             }
  347             return 0;
  348         }
  349         /* Real volume */
  350         index = Volno(dev);
  351         if (index >= vinum_conf.volumes_allocated)
  352             return ENXIO;                                   /* no such device */
  353         vol = &VOL[index];
  354 
  355         switch (vol->state) {
  356         case volume_unallocated:
  357         case volume_uninit:
  358             return ENXIO;
  359 
  360         case volume_up:
  361             vol->flags &= ~VF_OPEN;                         /* reset our flags */
  362             return 0;
  363 
  364         case volume_down:
  365             return EIO;
  366 
  367         default:
  368             return EINVAL;
  369         }
  370 
  371     case VINUM_PLEX_TYPE:
  372         if (Volno(dev) >= vinum_conf.volumes_allocated)
  373             return ENXIO;
  374         /* FALLTHROUGH */
  375 
  376     case VINUM_SD_TYPE:
  377         if ((Volno(dev) >= vinum_conf.volumes_allocated) || /* no such volume */
  378             (Plexno(dev) >= vinum_conf.plexes_allocated))   /* or no such plex */
  379             return ENXIO;                                   /* no such device */
  380         /* FALLTHROUGH */
  381 
  382     default:
  383         return ENODEV;                                      /* don't know what to do with these */
  384     }
  385 }
  386 
  387 
  388 /* size routine */
  389 int
  390 vinumsize(dev_t dev)
  391 {
  392     struct volume *vol;
  393     int size;
  394 
  395     vol = &VOL[Volno(dev)];
  396 
  397     if (vol->state == volume_up)
  398         size = vol->size;
  399     else
  400         return 0;                                           /* err on the size of conservatism */
  401 
  402     return size;
  403 }
  404 
  405 int
  406 vinumdump(dev_t dev, daddr_t da, caddr_t ca, size_t size)
  407 {
  408     return ENXIO;                                           /* Implement this! XXX. */
  409 }
  410 
  411 /* Local Variables: */
  412 /* fill-column: 60 */
  413 /* End: */

Cache object: 697ebab2896b68e74ea9bb4cd4083c06


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