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/vinumioctl.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  * XXX replace all the checks on object validity with
    3  * calls to valid<object>
    4  */
    5 /*-
    6  * Copyright (c) 1997, 1998, 1999
    7  *      Nan Yang Computer Services Limited.  All rights reserved.
    8  *
    9  *  Parts copyright (c) 1997, 1998 Cybernet Corporation, NetMAX project.
   10  *
   11  *  Written by Greg Lehey
   12  *
   13  *  This software is distributed under the so-called ``Berkeley
   14  *  License'':
   15  *
   16  * Redistribution and use in source and binary forms, with or without
   17  * modification, are permitted provided that the following conditions
   18  * are met:
   19  * 1. Redistributions of source code must retain the above copyright
   20  *    notice, this list of conditions and the following disclaimer.
   21  * 2. Redistributions in binary form must reproduce the above copyright
   22  *    notice, this list of conditions and the following disclaimer in the
   23  *    documentation and/or other materials provided with the distribution.
   24  * 3. All advertising materials mentioning features or use of this software
   25  *    must display the following acknowledgement:
   26  *      This product includes software developed by Nan Yang Computer
   27  *      Services Limited.
   28  * 4. Neither the name of the Company nor the names of its contributors
   29  *    may be used to endorse or promote products derived from this software
   30  *    without specific prior written permission.
   31  *
   32  * This software is provided ``as is'', and any express or implied
   33  * warranties, including, but not limited to, the implied warranties of
   34  * merchantability and fitness for a particular purpose are disclaimed.
   35  * In no event shall the company or contributors be liable for any
   36  * direct, indirect, incidental, special, exemplary, or consequential
   37  * damages (including, but not limited to, procurement of substitute
   38  * goods or services; loss of use, data, or profits; or business
   39  * interruption) however caused and on any theory of liability, whether
   40  * in contract, strict liability, or tort (including negligence or
   41  * otherwise) arising in any way out of the use of this software, even if
   42  * advised of the possibility of such damage.
   43  *
   44  * $Id: vinumioctl.c,v 1.1.1.1.2.1 2004/09/18 16:48:07 he Exp $
   45  * $FreeBSD$
   46  */
   47 
   48 #include <dev/vinum/vinumhdr.h>
   49 #include <dev/vinum/request.h>
   50 
   51 #ifdef VINUMDEBUG
   52 #include <sys/reboot.h>
   53 #endif
   54 #include "opt_kgdb.h"
   55 #ifdef KGDB
   56 #include <sys/kgdb.h>
   57 #endif
   58 
   59 void attachobject(struct vinum_ioctl_msg *);
   60 void detachobject(struct vinum_ioctl_msg *);
   61 void renameobject(struct vinum_rename_msg *);
   62 void replaceobject(struct vinum_ioctl_msg *);
   63 void moveobject(struct vinum_ioctl_msg *);
   64 
   65 label_t command_fail;                                       /* return on a failed command */
   66 
   67 /* ioctl routine */
   68 int
   69 vinumioctl(dev_t dev,
   70     u_long cmd,
   71     caddr_t data,
   72     int flag,
   73     struct proc *p)
   74 {
   75     unsigned int objno;
   76     struct sd *sd;
   77     struct plex *plex;
   78     struct volume *vol;
   79 
   80     /* First, decide what we're looking at */
   81     if ((minor(dev) == VINUM_SUPERDEV_MINOR)
   82         || (minor(dev) == VINUM_DAEMON_MINOR))
   83         return vinum_super_ioctl(dev, cmd, data);
   84     else                                                    /* real device */
   85         switch (DEVTYPE(dev)) {
   86         case VINUM_SD_TYPE:
   87         case VINUM_SD2_TYPE:                                /* second half of sd namespace */
   88             objno = Sdno(dev);
   89 
   90             sd = &SD[objno];
   91 
   92             switch (cmd) {
   93             case DIOCGDINFO:                                /* get disk label */
   94                 get_volume_label(sd->name, 1, sd->sectors, (struct disklabel *) data);
   95                 return 0;
   96 
   97                 /*
   98                  * We don't have this stuff on hardware,
   99                  * so just pretend to do it so that
  100                  * utilities don't get upset.
  101                  */
  102             case DIOCWDINFO:                                /* write partition info */
  103             case DIOCSDINFO:                                /* set partition info */
  104                 return 0;                                   /* not a titty */
  105 
  106             default:
  107                 return ENOTTY;                              /* not my kind of ioctl */
  108             }
  109             break;
  110 
  111         case VINUM_PLEX_TYPE:
  112             objno = Plexno(dev);
  113 
  114             plex = &PLEX[objno];
  115 
  116             switch (cmd) {
  117             case DIOCGDINFO:                                /* get disk label */
  118                 get_volume_label(plex->name, 1, plex->length, (struct disklabel *) data);
  119                 return 0;
  120 
  121                 /*
  122                  * We don't have this stuff on hardware,
  123                  * so just pretend to do it so that
  124                  * utilities don't get upset.
  125                  */
  126             case DIOCWDINFO:                                /* write partition info */
  127             case DIOCSDINFO:                                /* set partition info */
  128                 return 0;                                   /* not a titty */
  129 
  130             default:
  131                 return ENOTTY;                              /* not my kind of ioctl */
  132             }
  133             break;
  134 
  135         case VINUM_VOLUME_TYPE:
  136             objno = Volno(dev);
  137 
  138             if ((unsigned) objno >= (unsigned) vinum_conf.volumes_allocated) /* not a valid volume */
  139                 return ENXIO;
  140             vol = &VOL[objno];
  141             if (vol->state != volume_up)                    /* not up, */
  142                 return EIO;                                 /* I/O error */
  143 
  144             switch (cmd) {
  145             case DIOCGDINFO:                                /* get disk label */
  146                 get_volume_label(vol->name, vol->plexes, vol->size, (struct disklabel *) data);
  147                 return 0;
  148 
  149                 /*
  150                  * Care!  DIOCGPART returns *pointers* to
  151                  * the caller, so we need to store this crap
  152                  * as well.  And yes, we need it.
  153                  */
  154             case DIOCGPART:                                 /* get partition information */
  155                 get_volume_label(vol->name, vol->plexes, vol->size, &vol->label);
  156                 ((struct partinfo *) data)->disklab = &vol->label;
  157                 ((struct partinfo *) data)->part = &vol->label.d_partitions[0];
  158                 return 0;
  159 
  160                 /*
  161                  * We don't have this stuff on hardware,
  162                  * so just pretend to do it so that
  163                  * utilities don't get upset.
  164                  */
  165             case DIOCWDINFO:                                /* write partition info */
  166             case DIOCSDINFO:                                /* set partition info */
  167                 return 0;                                   /* not a titty */
  168 
  169             case DIOCWLABEL:                                /* set or reset label writeable */
  170                 if ((flag & FWRITE) == 0)                   /* not writeable? */
  171                     return EACCES;                          /* no, die */
  172                 if (*(int *) data != 0)                     /* set it? */
  173                     vol->flags |= VF_WLABEL;                /* yes */
  174                 else
  175                     vol->flags &= ~VF_WLABEL;               /* no, reset */
  176                 break;
  177 
  178             default:
  179                 return ENOTTY;                              /* not my kind of ioctl */
  180             }
  181             break;
  182         }
  183 
  184     return EINVAL;
  185 }
  186 
  187 /* Handle ioctls for the super device */
  188 int
  189 vinum_super_ioctl(dev_t dev,
  190     u_long cmd,
  191     caddr_t data)
  192 {
  193     int error = 0;
  194     unsigned int index;                                     /* for transferring config info */
  195     unsigned int sdno;                                      /* for transferring config info */
  196     int fe;                                                 /* free list element number */
  197     struct _ioctl_reply *ioctl_reply = (struct _ioctl_reply *) data; /* struct to return */
  198 
  199     ioctl_reply = (struct _ioctl_reply *) data;             /* save the address to reply to */
  200     if (error)                                              /* bombed out */
  201         return 0;                                           /* the reply will contain meaningful info */
  202     switch (cmd) {
  203 #ifdef VINUMDEBUG
  204     case VINUM_DEBUG:
  205         if (((struct debuginfo *) data)->changeit)          /* change debug settings */
  206             debug = (((struct debuginfo *) data)->param);
  207 #ifdef KGDB
  208         else
  209             kgdb_connect(1);                                /* go into debugger */
  210 #endif
  211         ioctl_reply = (struct _ioctl_reply *) data;         /* reinstate the address to reply to */
  212         ioctl_reply->error = 0;
  213         return 0;
  214 #endif
  215 
  216     case VINUM_CREATE:                                      /* create a vinum object */
  217         error = lock_config();                              /* get the config for us alone */
  218         if (error)                                          /* can't do it, */
  219             return error;                                   /* give up */
  220         error = setjmp(&command_fail);                      /* come back here on error */
  221         if (error == 0)                                     /* first time, */
  222             ioctl_reply->error = parse_user_config((char *) data, /* update the config */
  223                 &keyword_set);
  224         else if (ioctl_reply->error == 0) {                 /* longjmp, but no error status */
  225             ioctl_reply->error = EINVAL;                    /* note that something's up */
  226             ioctl_reply->msg[0] = '\0';                     /* no message? */
  227         }
  228         unlock_config();
  229         return 0;                                           /* must be 0 to return the real error info */
  230 
  231     case VINUM_GETCONFIG:                                   /* get the configuration information */
  232         bcopy(&vinum_conf, data, sizeof(vinum_conf));
  233         return 0;
  234 
  235         /* start configuring the subsystem */
  236     case VINUM_STARTCONFIG:
  237         return start_config(*(int *) data);                 /* just lock it.  Parameter is 'force' */
  238 
  239         /*
  240          * Move the individual parts of the config to user space.
  241          *
  242          * Specify the index of the object in the first word of data,
  243          * and return the object there
  244          */
  245     case VINUM_DRIVECONFIG:
  246         index = *(int *) data;                              /* get the index */
  247         if (index >= (unsigned) vinum_conf.drives_allocated) /* can't do it */
  248             return ENXIO;                                   /* bang */
  249         bcopy(&DRIVE[index], data, sizeof(struct _drive));  /* copy the config item out */
  250         return 0;
  251 
  252     case VINUM_SDCONFIG:
  253         index = *(int *) data;                              /* get the index */
  254         if (index >= (unsigned) vinum_conf.subdisks_allocated) /* can't do it */
  255             return ENXIO;                                   /* bang */
  256         bcopy(&SD[index], data, sizeof(struct _sd));        /* copy the config item out */
  257         return 0;
  258 
  259     case VINUM_PLEXCONFIG:
  260         index = *(int *) data;                              /* get the index */
  261         if (index >= (unsigned) vinum_conf.plexes_allocated) /* can't do it */
  262             return ENXIO;                                   /* bang */
  263         bcopy(&PLEX[index], data, sizeof(struct _plex));    /* copy the config item out */
  264         return 0;
  265 
  266     case VINUM_VOLCONFIG:
  267         index = *(int *) data;                              /* get the index */
  268         if (index >= (unsigned) vinum_conf.volumes_allocated) /* can't do it */
  269             return ENXIO;                                   /* bang */
  270         bcopy(&VOL[index], data, sizeof(struct _volume));   /* copy the config item out */
  271         return 0;
  272 
  273     case VINUM_PLEXSDCONFIG:
  274         index = *(int *) data;                              /* get the plex index */
  275         sdno = ((int *) data)[1];                           /* and the sd index */
  276         if ((index >= (unsigned) vinum_conf.plexes_allocated) /* plex doesn't exist */
  277         ||(sdno >= PLEX[index].subdisks))                   /* or it doesn't have this many subdisks */
  278             return ENXIO;                                   /* bang */
  279         bcopy(&SD[PLEX[index].sdnos[sdno]],                 /* copy the config item out */
  280             data,
  281             sizeof(struct _sd));
  282         return 0;
  283 
  284         /*
  285          * We get called in two places: one from the
  286          * userland config routines, which call us
  287          * to complete the config and save it.  This
  288          * call supplies the value 0 as a parameter.
  289          *
  290          * The other place is from the user "saveconfig"
  291          * routine, which can only work if we're *not*
  292          * configuring.  In this case, supply parameter 1.
  293          */
  294     case VINUM_SAVECONFIG:
  295         if (VFLAGS & VF_CONFIGURING) {                      /* must be us, the others are asleep */
  296             if (*(int *) data == 0)                         /* finish config */
  297                 finish_config(1);                           /* finish the configuration and update it */
  298             else
  299                 return EBUSY;                               /* can't do it now */
  300         }
  301         save_config();                                      /* save configuration to disk */
  302         return 0;
  303 
  304     case VINUM_RELEASECONFIG:                               /* release the config */
  305         if (VFLAGS & VF_CONFIGURING) {                      /* must be us, the others are asleep */
  306             finish_config(0);                               /* finish the configuration, don't change it */
  307             save_config();                                  /* save configuration to disk */
  308         } else
  309             error = EINVAL;                                 /* release what config? */
  310         return error;
  311 
  312     case VINUM_INIT:
  313         ioctl_reply = (struct _ioctl_reply *) data;         /* reinstate the address to reply to */
  314         ioctl_reply->error = 0;
  315         return 0;
  316 
  317     case VINUM_RESETCONFIG:
  318         if (vinum_inactive(0)) {                            /* if the volumes are not active */
  319             /*
  320              * Note the open count.  We may be called from v, so we'll be open.
  321              * Keep the count so we don't underflow
  322              */
  323             free_vinum(1);                                  /* clean up everything */
  324             log(LOG_NOTICE, "vinum: CONFIGURATION OBLITERATED\n");
  325             ioctl_reply = (struct _ioctl_reply *) data;     /* reinstate the address to reply to */
  326             ioctl_reply->error = 0;
  327             return 0;
  328         }
  329         return EBUSY;
  330 
  331     case VINUM_SETSTATE:
  332         setstate((struct vinum_ioctl_msg *) data);          /* set an object state */
  333         return 0;
  334 
  335         /*
  336          * Set state by force, without changing
  337          * anything else.
  338          */
  339     case VINUM_SETSTATE_FORCE:
  340         setstate_by_force((struct vinum_ioctl_msg *) data); /* set an object state */
  341         return 0;
  342 
  343 #ifdef VINUMDEBUG
  344     case VINUM_MEMINFO:
  345         vinum_meminfo(data);
  346         return 0;
  347 
  348     case VINUM_MALLOCINFO:
  349         return vinum_mallocinfo(data);
  350 
  351     case VINUM_RQINFO:
  352         return vinum_rqinfo(data);
  353 #endif
  354 
  355     case VINUM_LABEL:                                       /* label a volume */
  356         ioctl_reply->error = write_volume_label(*(int *) data); /* index of the volume to label */
  357         ioctl_reply->msg[0] = '\0';                         /* no message */
  358         return 0;
  359 
  360     case VINUM_REMOVE:
  361         remove((struct vinum_ioctl_msg *) data);            /* remove an object */
  362         return 0;
  363 
  364     case VINUM_GETFREELIST:                                 /* get a drive free list element */
  365         index = *(int *) data;                              /* get the drive index */
  366         fe = ((int *) data)[1];                             /* and the free list element */
  367         if ((index >= (unsigned) vinum_conf.drives_allocated) /* plex doesn't exist */
  368         ||(DRIVE[index].state == drive_unallocated))
  369             return ENODEV;
  370         if (fe >= DRIVE[index].freelist_entries)            /* no such entry */
  371             return ENOENT;
  372         bcopy(&DRIVE[index].freelist[fe],
  373             data,
  374             sizeof(struct drive_freelist));
  375         return 0;
  376 
  377     case VINUM_RESETSTATS:
  378         resetstats((struct vinum_ioctl_msg *) data);        /* reset object stats */
  379         return 0;
  380 
  381         /* attach an object to a superordinate object */
  382     case VINUM_ATTACH:
  383         attachobject((struct vinum_ioctl_msg *) data);
  384         return 0;
  385 
  386         /* detach an object from a superordinate object */
  387     case VINUM_DETACH:
  388         detachobject((struct vinum_ioctl_msg *) data);
  389         return 0;
  390 
  391         /* rename an object */
  392     case VINUM_RENAME:
  393         renameobject((struct vinum_rename_msg *) data);
  394         return 0;
  395 
  396         /* replace an object */
  397     case VINUM_REPLACE:
  398         replaceobject((struct vinum_ioctl_msg *) data);
  399         return 0;
  400 
  401     case VINUM_DAEMON:
  402         vinum_daemon();                                     /* perform the daemon */
  403         return 0;
  404 
  405     case VINUM_FINDDAEMON:                                  /* check for presence of daemon */
  406         return vinum_finddaemon();
  407         return 0;
  408 
  409     case VINUM_SETDAEMON:                                   /* set daemon flags */
  410         return vinum_setdaemonopts(*(int *) data);
  411 
  412     case VINUM_GETDAEMON:                                   /* get daemon flags */
  413         *(int *) data = daemon_options;
  414         return 0;
  415 
  416     case VINUM_PARITYOP:                                    /* check/rebuild RAID-4/5 parity */
  417         parityops((struct vinum_ioctl_msg *) data);
  418         return 0;
  419 
  420         /* move an object */
  421     case VINUM_MOVE:
  422         moveobject((struct vinum_ioctl_msg *) data);
  423         return 0;
  424 
  425     default:
  426         /* unsupported ioctl */
  427         return EINVAL;
  428     }
  429 }
  430 
  431 /*
  432  * The following four functions check the supplied
  433  * object index and return a pointer to the object
  434  * if it exists.  Otherwise they longjump out via
  435  * throw_rude_remark.
  436  */
  437 struct drive *
  438 validdrive(int driveno, struct _ioctl_reply *reply)
  439 {
  440     if ((driveno < vinum_conf.drives_allocated)
  441         && (DRIVE[driveno].state > drive_referenced))
  442         return &DRIVE[driveno];
  443     strcpy(reply->msg, "No such drive");
  444     reply->error = ENOENT;
  445     return NULL;
  446 }
  447 
  448 struct sd *
  449 validsd(int sdno, struct _ioctl_reply *reply)
  450 {
  451     if ((sdno < vinum_conf.subdisks_allocated)
  452         && (SD[sdno].state > sd_referenced))
  453         return &SD[sdno];
  454     strcpy(reply->msg, "No such subdisk");
  455     reply->error = ENOENT;
  456     return NULL;
  457 }
  458 
  459 struct plex *
  460 validplex(int plexno, struct _ioctl_reply *reply)
  461 {
  462     if ((plexno < vinum_conf.plexes_allocated)
  463         && (PLEX[plexno].state > plex_referenced))
  464         return &PLEX[plexno];
  465     strcpy(reply->msg, "No such plex");
  466     reply->error = ENOENT;
  467     return NULL;
  468 }
  469 
  470 struct volume *
  471 validvol(int volno, struct _ioctl_reply *reply)
  472 {
  473     if ((volno < vinum_conf.volumes_allocated)
  474         && (VOL[volno].state > volume_uninit))
  475         return &VOL[volno];
  476     strcpy(reply->msg, "No such volume");
  477     reply->error = ENOENT;
  478     return NULL;
  479 }
  480 
  481 /* reset an object's stats */
  482 void
  483 resetstats(struct vinum_ioctl_msg *msg)
  484 {
  485     struct _ioctl_reply *reply = (struct _ioctl_reply *) msg;
  486 
  487     switch (msg->type) {
  488     case drive_object:
  489         if (msg->index < vinum_conf.drives_allocated) {
  490             struct drive *drive = &DRIVE[msg->index];
  491             if (drive->state > drive_referenced) {
  492                 drive->reads = 0;                           /* number of reads on this drive */
  493                 drive->writes = 0;                          /* number of writes on this drive */
  494                 drive->bytes_read = 0;                      /* number of bytes read */
  495                 drive->bytes_written = 0;                   /* number of bytes written */
  496                 reply->error = 0;
  497                 return;
  498             }
  499             reply->error = EINVAL;
  500             return;
  501         }
  502     case sd_object:
  503         if (msg->index < vinum_conf.subdisks_allocated) {
  504             struct sd *sd = &SD[msg->index];
  505             if (sd->state > sd_referenced) {
  506                 sd->reads = 0;                              /* number of reads on this subdisk */
  507                 sd->writes = 0;                             /* number of writes on this subdisk */
  508                 sd->bytes_read = 0;                         /* number of bytes read */
  509                 sd->bytes_written = 0;                      /* number of bytes written */
  510                 reply->error = 0;
  511                 return;
  512             }
  513             reply->error = EINVAL;
  514             return;
  515         }
  516         break;
  517 
  518     case plex_object:
  519         if (msg->index < vinum_conf.plexes_allocated) {
  520             struct plex *plex = &PLEX[msg->index];
  521             if (plex->state > plex_referenced) {
  522                 plex->reads = 0;
  523                 plex->writes = 0;                           /* number of writes on this plex */
  524                 plex->bytes_read = 0;                       /* number of bytes read */
  525                 plex->bytes_written = 0;                    /* number of bytes written */
  526                 plex->recovered_reads = 0;                  /* number of recovered read operations */
  527                 plex->degraded_writes = 0;                  /* number of degraded writes */
  528                 plex->parityless_writes = 0;                /* number of parityless writes */
  529                 plex->multiblock = 0;                       /* requests that needed more than one block */
  530                 plex->multistripe = 0;                      /* requests that needed more than one stripe */
  531                 reply->error = 0;
  532                 return;
  533             }
  534             reply->error = EINVAL;
  535             return;
  536         }
  537         break;
  538 
  539     case volume_object:
  540         if (msg->index < vinum_conf.volumes_allocated) {
  541             struct volume *vol = &VOL[msg->index];
  542             if (vol->state > volume_uninit) {
  543                 vol->bytes_read = 0;                        /* number of bytes read */
  544                 vol->bytes_written = 0;                     /* number of bytes written */
  545                 vol->reads = 0;                             /* number of reads on this volume */
  546                 vol->writes = 0;                            /* number of writes on this volume */
  547                 vol->recovered_reads = 0;                   /* reads recovered from another plex */
  548                 reply->error = 0;
  549                 return;
  550             }
  551             reply->error = EINVAL;
  552             return;
  553         }
  554     case invalid_object:                                    /* can't get this */
  555         reply->error = EINVAL;
  556         return;
  557     }
  558 }
  559 
  560 /* attach an object to a superior object */
  561 void
  562 attachobject(struct vinum_ioctl_msg *msg)
  563 {
  564     struct _ioctl_reply *reply = (struct _ioctl_reply *) msg;
  565     int sdno;
  566     struct sd *sd;
  567     struct plex *plex;
  568     struct volume *vol;
  569 
  570     switch (msg->type) {
  571     case drive_object:                                      /* you can't attach a drive to anything */
  572     case volume_object:                                     /* nor a volume */
  573     case invalid_object:                                    /* "this can't happen" */
  574         reply->error = EINVAL;
  575         reply->msg[0] = '\0';                               /* vinum(8) doesn't do this */
  576         return;
  577 
  578     case sd_object:
  579         sd = validsd(msg->index, reply);
  580         if (sd == NULL)                                     /* not a valid subdisk  */
  581             return;
  582         plex = validplex(msg->otherobject, reply);
  583         if (plex) {
  584             /*
  585              * We should be more intelligent about this.
  586              * We should be able to reattach a dead
  587              * subdisk, but if we want to increase the total
  588              * number of subdisks, we have a lot of reshuffling
  589              * to do. XXX
  590              */
  591             if ((plex->organization != plex_concat)         /* can't attach to striped and RAID-4/5 */
  592             &&(!msg->force)) {                              /* without using force */
  593                 reply->error = EINVAL;                      /* no message, the user should check */
  594                 strcpy(reply->msg, "Can't attach to this plex organization");
  595             } else if (sd->plexno >= 0) {                   /* already belong to a plex */
  596                 reply->error = EBUSY;                       /* no message, the user should check */
  597                 sprintf(reply->msg, "%s is already attached to %s",
  598                     sd->name,
  599                     sd[sd->plexno].name);
  600                 reply->msg[0] = '\0';
  601             } else {
  602                 sd->plexoffset = msg->offset;               /* this is where we want it */
  603                 set_sd_state(sd->sdno, sd_stale, setstate_force); /* make sure it's stale */
  604                 give_sd_to_plex(plex->plexno, sd->sdno);    /* and give it to the plex */
  605                 update_sd_config(sd->sdno, 0);
  606                 save_config();
  607                 if (sd->state == sd_reviving)
  608                     reply->error = EAGAIN;                  /* need to revive it */
  609                 else
  610                     reply->error = 0;
  611             }
  612         }
  613         break;
  614 
  615     case plex_object:
  616         plex = validplex(msg->index, reply);                /* get plex */
  617         if (plex == NULL)
  618             return;
  619         vol = validvol(msg->otherobject, reply);            /* and volume information */
  620         if (vol) {
  621             if (vol->plexes == MAXPLEX) {                   /* we have too many already */
  622                 reply->error = ENOSPC;                      /* nowhere to put it */
  623                 strcpy(reply->msg, "Too many plexes");
  624             } else if (plex->volno >= 0) {                  /* the plex has an owner */
  625                 reply->error = EBUSY;                       /* no message, the user should check */
  626                 sprintf(reply->msg, "%s is already attached to %s",
  627                     plex->name,
  628                     VOL[plex->volno].name);
  629             } else {
  630                 for (sdno = 0; sdno < plex->subdisks; sdno++) {
  631                     sd = &SD[plex->sdnos[sdno]];
  632 
  633                     if (sd->state > sd_down)                /* real subdisk, vaguely accessible */
  634                         set_sd_state(plex->sdnos[sdno], sd_stale, setstate_force); /* make it stale */
  635                 }
  636                 set_plex_state(plex->plexno, plex_up, setstate_none); /* update plex state */
  637                 give_plex_to_volume(msg->otherobject, msg->index); /* and give it to the volume */
  638                 update_plex_config(plex->plexno, 0);
  639                 save_config();
  640                 reply->error = 0;                           /* all went well */
  641             }
  642         }
  643     }
  644 }
  645 
  646 /* detach an object from a superior object */
  647 void
  648 detachobject(struct vinum_ioctl_msg *msg)
  649 {
  650     struct _ioctl_reply *reply = (struct _ioctl_reply *) msg;
  651     struct sd *sd;
  652     struct plex *plex;
  653     struct volume *vol;
  654     int sdno;
  655     int plexno;
  656 
  657     switch (msg->type) {
  658     case drive_object:                                      /* you can't detach a drive from anything */
  659     case volume_object:                                     /* nor a volume */
  660     case invalid_object:                                    /* "this can't happen" */
  661         reply->error = EINVAL;
  662         reply->msg[0] = '\0';                               /* vinum(8) doesn't do this */
  663         return;
  664 
  665     case sd_object:
  666         sd = validsd(msg->index, reply);
  667         if (sd == NULL)
  668             return;
  669         if (sd->plexno < 0) {                               /* doesn't belong to a plex */
  670             reply->error = ENOENT;
  671             strcpy(reply->msg, "Subdisk is not attached");
  672             return;
  673         } else {                                            /* valid plex number */
  674             plex = &PLEX[sd->plexno];
  675             if ((!msg->force)                               /* don't force things */
  676             &&((plex->state == plex_up)                     /* and the plex is up */
  677             ||((plex->state == plex_flaky) && sd->state == sd_up))) { /* or flaky with this sd up */
  678                 reply->error = EBUSY;                       /* we need this sd */
  679                 reply->msg[0] = '\0';
  680                 return;
  681             }
  682             sd->plexno = -1;                                /* anonymous sd */
  683             if (plex->subdisks == 1) {                      /* this was the only subdisk */
  684                 Free(plex->sdnos);                          /* free the subdisk array */
  685                 plex->sdnos = NULL;                         /* and note the fact */
  686                 plex->subdisks_allocated = 0;               /* no subdisk space */
  687             } else {
  688                 for (sdno = 0; sdno < plex->subdisks; sdno++) {
  689                     if (plex->sdnos[sdno] == msg->index)    /* found our subdisk */
  690                         break;
  691                 }
  692                 if (sdno < (plex->subdisks - 1))            /* not the last one, compact */
  693                     bcopy(&plex->sdnos[sdno + 1],
  694                         &plex->sdnos[sdno],
  695                         (plex->subdisks - 1 - sdno) * sizeof(int));
  696             }
  697             plex->subdisks--;
  698             if (!bcmp(plex->name, sd->name, strlen(plex->name) + 1))
  699                 /* this subdisk is named after the plex */
  700             {
  701                 bcopy(sd->name,
  702                     &sd->name[3],
  703                     min(strlen(sd->name) + 1, MAXSDNAME - 3));
  704                 bcopy("ex-", sd->name, 3);
  705                 sd->name[MAXSDNAME - 1] = '\0';
  706             }
  707             update_plex_config(plex->plexno, 0);
  708             if (isstriped(plex))                            /* we've just mutilated our plex, */
  709                 set_plex_state(plex->plexno,
  710                     plex_down,
  711                     setstate_force | setstate_configuring);
  712             save_config();
  713             reply->error = 0;
  714         }
  715         return;
  716 
  717     case plex_object:
  718         plex = validplex(msg->index, reply);                /* get plex */
  719         if (plex == NULL)
  720             return;
  721         if (plex->volno >= 0) {
  722             int volno = plex->volno;
  723 
  724             vol = &VOL[volno];
  725             if ((!msg->force)                               /* don't force things */
  726             &&((vol->state == volume_up)                    /* and the volume is up */
  727             &&(vol->plexes == 1))) {                        /* and this is the last plex */
  728                 /*
  729                    * XXX As elsewhere, check whether we will lose
  730                    * mapping by removing this plex
  731                  */
  732                 reply->error = EBUSY;                       /* we need this plex */
  733                 reply->msg[0] = '\0';
  734                 return;
  735             }
  736             plex->volno = -1;                               /* anonymous plex */
  737             for (plexno = 0; plexno < vol->plexes; plexno++) {
  738                 if (vol->plex[plexno] == msg->index)        /* found our plex */
  739                     break;
  740             }
  741             if (plexno < (vol->plexes - 1))                 /* not the last one, compact */
  742                 bcopy(&vol->plex[plexno + 1],
  743                     &vol->plex[plexno],
  744                     (vol->plexes - 1 - plexno) * sizeof(int));
  745             vol->plexes--;
  746             vol->last_plex_read = 0;                        /* don't go beyond the end */
  747             if (!bcmp(vol->name, plex->name, strlen(vol->name) + 1))
  748                 /* this plex is named after the volume */
  749             {
  750                 /* First, check if the subdisks are the same */
  751                 if (msg->recurse) {
  752                     int sdno;
  753 
  754                     for (sdno = 0; sdno < plex->subdisks; sdno++) {
  755                         struct sd *sd = &SD[plex->sdnos[sdno]];
  756 
  757                         if (!bcmp(plex->name, sd->name, strlen(plex->name) + 1))
  758                                                             /* subdisk is named after the plex */
  759                         {
  760                             bcopy(sd->name,
  761                                 &sd->name[3],
  762                                 min(strlen(sd->name) + 1, MAXSDNAME - 3));
  763                             bcopy("ex-", sd->name, 3);
  764                             sd->name[MAXSDNAME - 1] = '\0';
  765                         }
  766                     }
  767                 }
  768                 bcopy(plex->name,
  769                     &plex->name[3],
  770                     min(strlen(plex->name) + 1, MAXPLEXNAME - 3));
  771                 bcopy("ex-", plex->name, 3);
  772                 plex->name[MAXPLEXNAME - 1] = '\0';
  773             }
  774             update_volume_config(volno, 0);
  775             save_config();
  776             reply->error = 0;
  777         } else {
  778             reply->error = ENOENT;
  779             strcpy(reply->msg, "Plex is not attached");
  780         }
  781     }
  782 }
  783 
  784 void
  785 renameobject(struct vinum_rename_msg *msg)
  786 {
  787     struct _ioctl_reply *reply = (struct _ioctl_reply *) msg;
  788     struct drive *drive;
  789     struct sd *sd;
  790     struct plex *plex;
  791     struct volume *vol;
  792 
  793     switch (msg->type) {
  794     case drive_object:                                      /* you can't attach a drive to anything */
  795         if (find_drive(msg->newname, 0) >= 0) {             /* we have that name already, */
  796             reply->error = EEXIST;
  797             reply->msg[0] = '\0';
  798             return;
  799         }
  800         drive = validdrive(msg->index, reply);
  801         if (drive) {
  802             bcopy(msg->newname, drive->label.name, MAXDRIVENAME);
  803             save_config();
  804             reply->error = 0;
  805         }
  806         return;
  807 
  808     case sd_object:                                         /* you can't attach a subdisk to anything */
  809         if (find_subdisk(msg->newname, 0) >= 0) {           /* we have that name already, */
  810             reply->error = EEXIST;
  811             reply->msg[0] = '\0';
  812             return;
  813         }
  814         sd = validsd(msg->index, reply);
  815         if (sd) {
  816             bcopy(msg->newname, sd->name, MAXSDNAME);
  817             update_sd_config(sd->sdno, 0);
  818             save_config();
  819             reply->error = 0;
  820         }
  821         return;
  822 
  823     case plex_object:                                       /* you can't attach a plex to anything */
  824         if (find_plex(msg->newname, 0) >= 0) {              /* we have that name already, */
  825             reply->error = EEXIST;
  826             reply->msg[0] = '\0';
  827             return;
  828         }
  829         plex = validplex(msg->index, reply);
  830         if (plex) {
  831             bcopy(msg->newname, plex->name, MAXPLEXNAME);
  832             update_plex_config(plex->plexno, 0);
  833             save_config();
  834             reply->error = 0;
  835         }
  836         return;
  837 
  838     case volume_object:                                     /* you can't attach a volume to anything */
  839         if (find_volume(msg->newname, 0) >= 0) {            /* we have that name already, */
  840             reply->error = EEXIST;
  841             reply->msg[0] = '\0';
  842             return;
  843         }
  844         vol = validvol(msg->index, reply);
  845         if (vol) {
  846             bcopy(msg->newname, vol->name, MAXVOLNAME);
  847             update_volume_config(msg->index, 0);
  848             save_config();
  849             reply->error = 0;
  850         }
  851         return;
  852 
  853     case invalid_object:
  854         reply->error = EINVAL;
  855         reply->msg[0] = '\0';
  856     }
  857 }
  858 
  859 /*
  860  * Replace one object with another.
  861  * Currently only for drives.
  862  * message->index is the drive number of the old drive
  863  * message->otherobject is the drive number of the new drive
  864  */
  865 void
  866 replaceobject(struct vinum_ioctl_msg *msg)
  867 {
  868     struct _ioctl_reply *reply = (struct _ioctl_reply *) msg;
  869 
  870     reply->error = ENODEV;                                  /* until I know how to do this */
  871     strcpy(reply->msg, "replace not implemented yet");
  872 /*      save_config (); */
  873 }
  874 
  875 void
  876 moveobject(struct vinum_ioctl_msg *msg)
  877 {
  878     struct _ioctl_reply *reply = (struct _ioctl_reply *) msg;
  879     struct drive *drive;
  880     struct sd *sd;
  881 
  882     /* Check that our objects are valid (i.e. they exist) */
  883     drive = validdrive(msg->index, (struct _ioctl_reply *) msg);
  884     if (drive == NULL)
  885         return;
  886     sd = validsd(msg->otherobject, (struct _ioctl_reply *) msg);
  887     if (sd == NULL)
  888         return;
  889     if (sd->driveno == msg->index)                          /* sd already belongs to drive */
  890         return;
  891 
  892     if (sd->state > sd_stale)
  893         set_sd_state(sd->sdno, sd_stale, setstate_force);   /* make the subdisk stale */
  894     else
  895         sd->state = sd_empty;
  896     if (sd->plexno >= 0)                                    /* part of a plex, */
  897         update_plex_state(sd->plexno);                      /* update its state */
  898 
  899     /* Return the space on the old drive */
  900     if ((sd->driveno >= 0)                                  /* we have a drive, */
  901     &&(sd->sectors > 0))                                    /* and some space on it */
  902         return_drive_space(sd->driveno,                     /* return the space */
  903             sd->driveoffset,
  904             sd->sectors);
  905 
  906     /* Reassign the old subdisk */
  907     sd->driveno = msg->index;
  908     sd->driveoffset = -1;                                   /* let the drive decide where to put us */
  909     give_sd_to_drive(sd->sdno);
  910     reply->error = 0;
  911 }
  912 
  913 /* Local Variables: */
  914 /* fill-column: 50 */
  915 /* End: */

Cache object: 726bc27550402bfea358b13ef64d5131


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