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

Cache object: f94cb5d4385093e95e1be16857253b10


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