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

Cache object: 419f57f9d86d2f196c3035c86d3f246a


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