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

Cache object: e77adbcef6ff31f8770c6e239783deb2


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