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.14 2000/10/27 03:07:53 grog Exp grog $
   45  * $FreeBSD: releng/5.0/sys/dev/vinum/vinumioctl.c 108907 2003-01-07 22:59:50Z grog $
   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 thread *td)
   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             break;
  314         }
  315 
  316     case VINUM_DRIVE_TYPE:
  317     default:
  318         log(LOG_WARNING,
  319             "vinumioctl: invalid ioctl from process %d (%s): %lx\n",
  320             curthread->td_proc->p_pid,
  321             curthread->td_proc->p_comm,
  322             cmd);
  323         return EINVAL;
  324 
  325     case VINUM_SD_TYPE:
  326     case VINUM_RAWSD_TYPE:
  327         objno = Sdno(dev);
  328 
  329         sd = &SD[objno];
  330 
  331         switch (cmd) {
  332       case DIOCGDINFO:                              /* get disk label */
  333             get_volume_label(sd->name, 1, sd->sectors, (struct disklabel *) data);
  334             break;
  335 
  336             /*
  337              * We don't have this stuff on hardware,
  338              * so just pretend to do it so that
  339              * utilities don't get upset.
  340              */
  341         case DIOCWDINFO:                                    /* write partition info */
  342         case DIOCSDINFO:                                    /* set partition info */
  343             return 0;                                       /* not a titty */
  344 
  345         default:
  346             return ENOTTY;                                  /* not my kind of ioctl */
  347         }
  348 
  349         return 0;                                           /* pretend we did it */
  350 
  351     case VINUM_RAWPLEX_TYPE:
  352     case VINUM_PLEX_TYPE:
  353         objno = Plexno(dev);
  354 
  355         plex = &PLEX[objno];
  356 
  357         switch (cmd) {
  358         case DIOCGDINFO:                                    /* get disk label */
  359             get_volume_label(plex->name, 1, plex->length, (struct disklabel *) data);
  360             break;
  361 
  362             /*
  363              * We don't have this stuff on hardware,
  364              * so just pretend to do it so that
  365              * utilities don't get upset.
  366              */
  367         case DIOCWDINFO:                                    /* write partition info */
  368         case DIOCSDINFO:                                    /* set partition info */
  369             return 0;                                       /* not a titty */
  370 
  371         default:
  372             return ENOTTY;                                  /* not my kind of ioctl */
  373         }
  374 
  375         return 0;                                           /* pretend we did it */
  376 
  377     case VINUM_VOLUME_TYPE:
  378         objno = Volno(dev);
  379 
  380         if ((unsigned) objno >= (unsigned) vinum_conf.volumes_allocated) /* not a valid volume */
  381             return ENXIO;
  382         vol = &VOL[objno];
  383         if (vol->state != volume_up)                        /* not up, */
  384             return EIO;                                     /* I/O error */
  385 
  386         switch (cmd) {
  387 
  388         case DIOCGMEDIASIZE:
  389             *(off_t *)data = vol->size << DEV_BSHIFT;
  390             break;
  391 
  392         case DIOCGSECTORSIZE:
  393             *(u_int *)data = DEV_BSIZE;
  394             break;
  395 
  396             /*
  397              * We don't have this stuff on hardware,
  398              * so just pretend to do it so that
  399              * utilities don't get upset.
  400              */
  401         case DIOCWDINFO:                                    /* write partition info */
  402         case DIOCSDINFO:                                    /* set partition info */
  403             return 0;                                       /* not a titty */
  404 
  405         case DIOCWLABEL:                                    /* set or reset label writeable */
  406             if ((flag & FWRITE) == 0)                       /* not writeable? */
  407                 return EACCES;                              /* no, die */
  408             if (*(int *) data != 0)                         /* set it? */
  409                 vol->flags |= VF_WLABEL;                    /* yes */
  410             else
  411                 vol->flags &= ~VF_WLABEL;                   /* no, reset */
  412             break;
  413 
  414         default:
  415             return ENOTTY;                                  /* not my kind of ioctl */
  416         }
  417         break;
  418     }
  419     return 0;                                               /* XXX */
  420 }
  421 
  422 /*
  423  * The following four functions check the supplied
  424  * object index and return a pointer to the object
  425  * if it exists.  Otherwise they longjump out via
  426  * throw_rude_remark.
  427  */
  428 struct drive *
  429 validdrive(int driveno, struct _ioctl_reply *reply)
  430 {
  431     if ((driveno < vinum_conf.drives_allocated)
  432         && (DRIVE[driveno].state > drive_referenced))
  433         return &DRIVE[driveno];
  434     strcpy(reply->msg, "No such drive");
  435     reply->error = ENOENT;
  436     return NULL;
  437 }
  438 
  439 struct sd *
  440 validsd(int sdno, struct _ioctl_reply *reply)
  441 {
  442     if ((sdno < vinum_conf.subdisks_allocated)
  443         && (SD[sdno].state > sd_referenced))
  444         return &SD[sdno];
  445     strcpy(reply->msg, "No such subdisk");
  446     reply->error = ENOENT;
  447     return NULL;
  448 }
  449 
  450 struct plex *
  451 validplex(int plexno, struct _ioctl_reply *reply)
  452 {
  453     if ((plexno < vinum_conf.plexes_allocated)
  454         && (PLEX[plexno].state > plex_referenced))
  455         return &PLEX[plexno];
  456     strcpy(reply->msg, "No such plex");
  457     reply->error = ENOENT;
  458     return NULL;
  459 }
  460 
  461 struct volume *
  462 validvol(int volno, struct _ioctl_reply *reply)
  463 {
  464     if ((volno < vinum_conf.volumes_allocated)
  465         && (VOL[volno].state > volume_uninit))
  466         return &VOL[volno];
  467     strcpy(reply->msg, "No such volume");
  468     reply->error = ENOENT;
  469     return NULL;
  470 }
  471 
  472 /* reset an object's stats */
  473 void
  474 resetstats(struct vinum_ioctl_msg *msg)
  475 {
  476     struct _ioctl_reply *reply = (struct _ioctl_reply *) msg;
  477 
  478     switch (msg->type) {
  479     case drive_object:
  480         if (msg->index < vinum_conf.drives_allocated) {
  481             struct drive *drive = &DRIVE[msg->index];
  482             if (drive->state > drive_referenced) {
  483                 drive->reads = 0;                           /* number of reads on this drive */
  484                 drive->writes = 0;                          /* number of writes on this drive */
  485                 drive->bytes_read = 0;                      /* number of bytes read */
  486                 drive->bytes_written = 0;                   /* number of bytes written */
  487                 reply->error = 0;
  488                 return;
  489             }
  490             reply->error = EINVAL;
  491             return;
  492         }
  493     case sd_object:
  494         if (msg->index < vinum_conf.subdisks_allocated) {
  495             struct sd *sd = &SD[msg->index];
  496             if (sd->state > sd_referenced) {
  497                 sd->reads = 0;                              /* number of reads on this subdisk */
  498                 sd->writes = 0;                             /* number of writes on this subdisk */
  499                 sd->bytes_read = 0;                         /* number of bytes read */
  500                 sd->bytes_written = 0;                      /* number of bytes written */
  501                 reply->error = 0;
  502                 return;
  503             }
  504             reply->error = EINVAL;
  505             return;
  506         }
  507         break;
  508 
  509     case plex_object:
  510         if (msg->index < vinum_conf.plexes_allocated) {
  511             struct plex *plex = &PLEX[msg->index];
  512             if (plex->state > plex_referenced) {
  513                 plex->reads = 0;
  514                 plex->writes = 0;                           /* number of writes on this plex */
  515                 plex->bytes_read = 0;                       /* number of bytes read */
  516                 plex->bytes_written = 0;                    /* number of bytes written */
  517                 plex->recovered_reads = 0;                  /* number of recovered read operations */
  518                 plex->degraded_writes = 0;                  /* number of degraded writes */
  519                 plex->parityless_writes = 0;                /* number of parityless writes */
  520                 plex->multiblock = 0;                       /* requests that needed more than one block */
  521                 plex->multistripe = 0;                      /* requests that needed more than one stripe */
  522                 reply->error = 0;
  523                 return;
  524             }
  525             reply->error = EINVAL;
  526             return;
  527         }
  528         break;
  529 
  530     case volume_object:
  531         if (msg->index < vinum_conf.volumes_allocated) {
  532             struct volume *vol = &VOL[msg->index];
  533             if (vol->state > volume_uninit) {
  534                 vol->bytes_read = 0;                        /* number of bytes read */
  535                 vol->bytes_written = 0;                     /* number of bytes written */
  536                 vol->reads = 0;                             /* number of reads on this volume */
  537                 vol->writes = 0;                            /* number of writes on this volume */
  538                 vol->recovered_reads = 0;                   /* reads recovered from another plex */
  539                 reply->error = 0;
  540                 return;
  541             }
  542             reply->error = EINVAL;
  543             return;
  544         }
  545     case invalid_object:                                    /* can't get this */
  546         reply->error = EINVAL;
  547         return;
  548     }
  549 }
  550 
  551 /* attach an object to a superior object */
  552 void
  553 attachobject(struct vinum_ioctl_msg *msg)
  554 {
  555     struct _ioctl_reply *reply = (struct _ioctl_reply *) msg;
  556     int sdno;
  557     struct sd *sd;
  558     struct plex *plex;
  559     struct volume *vol;
  560 
  561     switch (msg->type) {
  562     case drive_object:                                      /* you can't attach a drive to anything */
  563     case volume_object:                                     /* nor a volume */
  564     case invalid_object:                                    /* "this can't happen" */
  565         reply->error = EINVAL;
  566         reply->msg[0] = '\0';                               /* vinum(8) doesn't do this */
  567         return;
  568 
  569     case sd_object:
  570         sd = validsd(msg->index, reply);
  571         if (sd == NULL)                                     /* not a valid subdisk  */
  572             return;
  573         plex = validplex(msg->otherobject, reply);
  574         if (plex) {
  575             /*
  576              * We should be more intelligent about this.
  577              * We should be able to reattach a dead
  578              * subdisk, but if we want to increase the total
  579              * number of subdisks, we have a lot of reshuffling
  580              * to do. XXX
  581              */
  582             if ((plex->organization != plex_concat)         /* can't attach to striped and RAID-4/5 */
  583             &&(!msg->force)) {                              /* without using force */
  584                 reply->error = EINVAL;                      /* no message, the user should check */
  585                 strcpy(reply->msg, "Can't attach to this plex organization");
  586                 return;
  587             }
  588             if (sd->plexno >= 0) {                          /* already belong to a plex */
  589                 reply->error = EBUSY;                       /* no message, the user should check */
  590                 reply->msg[0] = '\0';
  591                 return;
  592             }
  593             sd->plexoffset = msg->offset;                   /* this is where we want it */
  594             set_sd_state(sd->sdno, sd_stale, setstate_force); /* make sure it's stale */
  595             give_sd_to_plex(plex->plexno, sd->sdno);        /* and give it to the plex */
  596             update_sd_config(sd->sdno, 0);
  597             save_config();
  598         }
  599         if (sd->state == sd_reviving)
  600             reply->error = EAGAIN;                          /* need to revive it */
  601         else
  602             reply->error = 0;
  603         break;
  604 
  605     case plex_object:
  606         plex = validplex(msg->index, reply);                /* get plex */
  607         if (plex == NULL)
  608             return;
  609         vol = validvol(msg->otherobject, reply);            /* and volume information */
  610         if (vol) {
  611             if ((vol->plexes == MAXPLEX)                    /* we have too many already */
  612             ||(plex->volno >= 0)) {                         /* or the plex has an owner */
  613                 reply->error = EINVAL;                      /* no message, the user should check */
  614                 reply->msg[0] = '\0';
  615                 return;
  616             }
  617             for (sdno = 0; sdno < plex->subdisks; sdno++) {
  618                 sd = &SD[plex->sdnos[sdno]];
  619 
  620                 if (sd->state > sd_down)                    /* real subdisk, vaguely accessible */
  621                     set_sd_state(plex->sdnos[sdno], sd_stale, setstate_force); /* make it stale */
  622             }
  623             set_plex_state(plex->plexno, plex_up, setstate_none); /* update plex state */
  624             give_plex_to_volume(msg->otherobject, msg->index); /* and give it to the volume */
  625             update_plex_config(plex->plexno, 0);
  626             save_config();
  627             reply->error = 0;                               /* all went well */
  628         }
  629     }
  630 }
  631 
  632 /* detach an object from a superior object */
  633 void
  634 detachobject(struct vinum_ioctl_msg *msg)
  635 {
  636     struct _ioctl_reply *reply = (struct _ioctl_reply *) msg;
  637     struct sd *sd;
  638     struct plex *plex;
  639     struct volume *vol;
  640     int sdno;
  641     int plexno;
  642 
  643     switch (msg->type) {
  644     case drive_object:                                      /* you can't detach a drive from anything */
  645     case volume_object:                                     /* nor a volume */
  646     case invalid_object:                                    /* "this can't happen" */
  647         reply->error = EINVAL;
  648         reply->msg[0] = '\0';                               /* vinum(8) doesn't do this */
  649         return;
  650 
  651     case sd_object:
  652         sd = validsd(msg->index, reply);
  653         if (sd == NULL)
  654             return;
  655         if (sd->plexno < 0) {                               /* doesn't belong to a plex */
  656             reply->error = ENOENT;
  657             strcpy(reply->msg, "Subdisk is not attached");
  658             return;
  659         } else {                                            /* valid plex number */
  660             plex = &PLEX[sd->plexno];
  661             if ((!msg->force)                               /* don't force things */
  662             &&((plex->state == plex_up)                     /* and the plex is up */
  663             ||((plex->state == plex_flaky) && sd->state == sd_up))) { /* or flaky with this sd up */
  664                 reply->error = EBUSY;                       /* we need this sd */
  665                 reply->msg[0] = '\0';
  666                 return;
  667             }
  668             sd->plexno = -1;                                /* anonymous sd */
  669             if (plex->subdisks == 1) {                      /* this was the only subdisk */
  670                 Free(plex->sdnos);                          /* free the subdisk array */
  671                 plex->sdnos = NULL;                         /* and note the fact */
  672                 plex->subdisks_allocated = 0;               /* no subdisk space */
  673             } else {
  674                 for (sdno = 0; sdno < plex->subdisks; sdno++) {
  675                     if (plex->sdnos[sdno] == msg->index)    /* found our subdisk */
  676                         break;
  677                 }
  678                 if (sdno < (plex->subdisks - 1))            /* not the last one, compact */
  679                     bcopy(&plex->sdnos[sdno + 1],
  680                         &plex->sdnos[sdno],
  681                         (plex->subdisks - 1 - sdno) * sizeof(int));
  682             }
  683             plex->subdisks--;
  684             if (!bcmp(plex->name, sd->name, strlen(plex->name) + 1))
  685                 /* this subdisk is named after the plex */
  686             {
  687                 bcopy(sd->name,
  688                     &sd->name[3],
  689                     min(strlen(sd->name) + 1, MAXSDNAME - 3));
  690                 bcopy("ex-", sd->name, 3);
  691                 sd->name[MAXSDNAME - 1] = '\0';
  692             }
  693             update_plex_config(plex->plexno, 0);
  694             if (isstriped(plex))                            /* we've just mutilated our plex, */
  695                 set_plex_state(plex->plexno,
  696                     plex_down,
  697                     setstate_force | setstate_configuring);
  698             save_config();
  699             reply->error = 0;
  700         }
  701         return;
  702 
  703     case plex_object:
  704         plex = validplex(msg->index, reply);                /* get plex */
  705         if (plex == NULL)
  706             return;
  707         if (plex->volno >= 0) {
  708             int volno = plex->volno;
  709 
  710             vol = &VOL[volno];
  711             if ((!msg->force)                               /* don't force things */
  712             &&((vol->state == volume_up)                    /* and the volume is up */
  713             &&(vol->plexes == 1))) {                        /* and this is the last plex */
  714                 /*
  715                    * XXX As elsewhere, check whether we will lose
  716                    * mapping by removing this plex
  717                  */
  718                 reply->error = EBUSY;                       /* we need this plex */
  719                 reply->msg[0] = '\0';
  720                 return;
  721             }
  722             plex->volno = -1;                               /* anonymous plex */
  723             for (plexno = 0; plexno < vol->plexes; plexno++) {
  724                 if (vol->plex[plexno] == msg->index)        /* found our plex */
  725                     break;
  726             }
  727             if (plexno < (vol->plexes - 1))                 /* not the last one, compact */
  728                 bcopy(&vol->plex[plexno + 1],
  729                     &vol->plex[plexno],
  730                     (vol->plexes - 1 - plexno) * sizeof(int));
  731             vol->plexes--;
  732             vol->last_plex_read = 0;                        /* don't go beyond the end */
  733             if (!bcmp(vol->name, plex->name, strlen(vol->name) + 1))
  734                 /* this plex is named after the volume */
  735             {
  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) + 1))
  744                                                             /* subdisk is named after the plex */
  745                         {
  746                             bcopy(sd->name,
  747                                 &sd->name[3],
  748                                 min(strlen(sd->name) + 1, MAXSDNAME - 3));
  749                             bcopy("ex-", sd->name, 3);
  750                             sd->name[MAXSDNAME - 1] = '\0';
  751                         }
  752                     }
  753                 }
  754                 bcopy(plex->name,
  755                     &plex->name[3],
  756                     min(strlen(plex->name) + 1, MAXPLEXNAME - 3));
  757                 bcopy("ex-", plex->name, 3);
  758                 plex->name[MAXPLEXNAME - 1] = '\0';
  759             }
  760             update_volume_config(volno, 0);
  761             save_config();
  762             reply->error = 0;
  763         } else {
  764             reply->error = ENOENT;
  765             strcpy(reply->msg, "Plex is not attached");
  766         }
  767     }
  768 }
  769 
  770 void
  771 renameobject(struct vinum_rename_msg *msg)
  772 {
  773     struct _ioctl_reply *reply = (struct _ioctl_reply *) msg;
  774     struct drive *drive;
  775     struct sd *sd;
  776     struct plex *plex;
  777     struct volume *vol;
  778 
  779     switch (msg->type) {
  780     case drive_object:                                      /* you can't attach a drive to anything */
  781         if (find_drive(msg->newname, 0) >= 0) {             /* we have that name already, */
  782             reply->error = EEXIST;
  783             reply->msg[0] = '\0';
  784             return;
  785         }
  786         drive = validdrive(msg->index, reply);
  787         if (drive) {
  788             bcopy(msg->newname, drive->label.name, MAXDRIVENAME);
  789             save_config();
  790             reply->error = 0;
  791         }
  792         return;
  793 
  794     case sd_object:                                         /* you can't attach a subdisk to anything */
  795         if (find_subdisk(msg->newname, 0) >= 0) {           /* we have that name already, */
  796             reply->error = EEXIST;
  797             reply->msg[0] = '\0';
  798             return;
  799         }
  800         sd = validsd(msg->index, reply);
  801         if (sd) {
  802             bcopy(msg->newname, sd->name, MAXSDNAME);
  803             update_sd_config(sd->sdno, 0);
  804             save_config();
  805             reply->error = 0;
  806         }
  807         return;
  808 
  809     case plex_object:                                       /* you can't attach a plex to anything */
  810         if (find_plex(msg->newname, 0) >= 0) {              /* we have that name already, */
  811             reply->error = EEXIST;
  812             reply->msg[0] = '\0';
  813             return;
  814         }
  815         plex = validplex(msg->index, reply);
  816         if (plex) {
  817             bcopy(msg->newname, plex->name, MAXPLEXNAME);
  818             update_plex_config(plex->plexno, 0);
  819             save_config();
  820             reply->error = 0;
  821         }
  822         return;
  823 
  824     case volume_object:                                     /* you can't attach a volume to anything */
  825         if (find_volume(msg->newname, 0) >= 0) {            /* we have that name already, */
  826             reply->error = EEXIST;
  827             reply->msg[0] = '\0';
  828             return;
  829         }
  830         vol = validvol(msg->index, reply);
  831         if (vol) {
  832             bcopy(msg->newname, vol->name, MAXVOLNAME);
  833             update_volume_config(msg->index, 0);
  834             save_config();
  835             reply->error = 0;
  836         }
  837         return;
  838 
  839     case invalid_object:
  840         reply->error = EINVAL;
  841         reply->msg[0] = '\0';
  842     }
  843 }
  844 
  845 /*
  846  * Replace one object with another.
  847  * Currently only for drives.
  848  * message->index is the drive number of the old drive
  849  * message->otherobject is the drive number of the new drive
  850  */
  851 void
  852 replaceobject(struct vinum_ioctl_msg *msg)
  853 {
  854     struct _ioctl_reply *reply = (struct _ioctl_reply *) msg;
  855 
  856     reply->error = ENODEV;                                  /* until I know how to do this */
  857     strcpy(reply->msg, "replace not implemented yet");
  858 /*      save_config (); */
  859 }
  860 
  861 void
  862 moveobject(struct vinum_ioctl_msg *msg)
  863 {
  864     struct _ioctl_reply *reply = (struct _ioctl_reply *) msg;
  865     struct drive *drive;
  866     struct sd *sd;
  867 
  868     /* Check that our objects are valid (i.e. they exist) */
  869     drive = validdrive(msg->index, (struct _ioctl_reply *) msg);
  870     if (drive == NULL)
  871         return;
  872     sd = validsd(msg->otherobject, (struct _ioctl_reply *) msg);
  873     if (sd == NULL)
  874         return;
  875     if (sd->driveno == msg->index)                          /* sd already belongs to drive */
  876         return;
  877 
  878     if (sd->state > sd_stale)
  879         set_sd_state(sd->sdno, sd_stale, setstate_force);   /* make the subdisk stale */
  880     else
  881         sd->state = sd_empty;
  882     if (sd->plexno >= 0)                                    /* part of a plex, */
  883         update_plex_state(sd->plexno);                      /* update its state */
  884 
  885     /* Return the space on the old drive */
  886     if ((sd->driveno >= 0)                                  /* we have a drive, */
  887     &&(sd->sectors > 0))                                    /* and some space on it */
  888         return_drive_space(sd->driveno,                     /* return the space */
  889             sd->driveoffset,
  890             sd->sectors);
  891 
  892     /* Reassign the old subdisk */
  893     sd->driveno = msg->index;
  894     sd->driveoffset = -1;                                   /* let the drive decide where to put us */
  895     give_sd_to_drive(sd->sdno);
  896     reply->error = 0;
  897 }
  898 
  899 /* Local Variables: */
  900 /* fill-column: 50 */
  901 /* End: */

Cache object: 4d3129d88167ff87d74c3bb001877792


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