summaryrefslogtreecommitdiff
path: root/sys/dev/vinum/vinumstate.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/vinum/vinumstate.c')
-rw-r--r--sys/dev/vinum/vinumstate.c843
1 files changed, 0 insertions, 843 deletions
diff --git a/sys/dev/vinum/vinumstate.c b/sys/dev/vinum/vinumstate.c
deleted file mode 100644
index 8d44fecfcdf2d..0000000000000
--- a/sys/dev/vinum/vinumstate.c
+++ /dev/null
@@ -1,843 +0,0 @@
-/*-
- * Copyright (c) 1997, 1998
- * Nan Yang Computer Services Limited. All rights reserved.
- *
- * This software is distributed under the so-called ``Berkeley
- * License'':
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Nan Yang Computer
- * Services Limited.
- * 4. Neither the name of the Company nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * This software is provided ``as is'', and any express or implied
- * warranties, including, but not limited to, the implied warranties of
- * merchantability and fitness for a particular purpose are disclaimed.
- * In no event shall the company or contributors be liable for any
- * direct, indirect, incidental, special, exemplary, or consequential
- * damages (including, but not limited to, procurement of substitute
- * goods or services; loss of use, data, or profits; or business
- * interruption) however caused and on any theory of liability, whether
- * in contract, strict liability, or tort (including negligence or
- * otherwise) arising in any way out of the use of this software, even if
- * advised of the possibility of such damage.
- *
- * $Id: vinumstate.c,v 2.10 1999/01/17 06:19:23 grog Exp grog $
- */
-
-#define REALLYKERNEL
-#include "opt_vinum.h"
-#include <dev/vinum/vinumhdr.h>
-#include <dev/vinum/request.h>
-
-/* Update drive state */
-/* Return 1 if the state changes, otherwise 0 */
-int
-set_drive_state(int driveno, enum drivestate newstate, enum setstateflags flags)
-{
- struct drive *drive = &DRIVE[driveno];
- int oldstate = drive->state;
- int sdno;
-
- if (drive->state == drive_unallocated) /* no drive to do anything with, */
- return 0;
-
- if (newstate != oldstate) { /* don't change it if it's not different */
- if ((newstate == drive_down) /* the drive's going down */
- &&(!(flags & setstate_force))
- && (drive->opencount != 0)) /* we can't do it */
- return 0; /* don't do it */
- drive->state = newstate; /* set the state */
- if (drive->label.name[0] != '\0') /* we have a name, */
- printf("vinum: drive %s is %s\n", drive->label.name, drive_state(drive->state));
- if ((drive->state == drive_up)
- && (drive->vp == NULL)) /* should be open, but we're not */
- init_drive(drive, 1); /* which changes the state again */
- if (newstate != oldstate) { /* state has changed */
- for (sdno = 0; sdno < vinum_conf.subdisks_used; sdno++) { /* find this drive's subdisks */
- if (SD[sdno].driveno == driveno) /* belongs to this drive */
- update_sd_state(sdno); /* update the state */
- }
- }
- if ((flags & setstate_configuring) == 0) /* configuring? */
- save_config(); /* no: save the updated configuration now */
- return 1;
- }
- return 0;
-}
-
-/* Try to set the subdisk state. Return 1 if state changed to
- * what we wanted, -1 if it changed to something else, and 0
- * if no change.
- *
- * This routine is called both from the user (up, down states
- * only) and internally.
- */
-int
-set_sd_state(int sdno, enum sdstate newstate, enum setstateflags flags)
-{
- struct sd *sd = &SD[sdno];
- struct plex *plex;
- struct volume *vol;
- int oldstate = sd->state;
- int status = 1; /* status to return */
-
- if ((newstate == oldstate)
- || (sd->state == sd_unallocated)) /* no subdisk to do anything with, */
- return 0;
-
- if (sd->driveoffset < 0) { /* not allocated space */
- sd->state = sd_down;
- if (newstate != sd_down) {
- if (sd->plexno >= 0)
- sdstatemap(&PLEX[sd->plexno]); /* count up subdisks */
- return -1;
- }
- } else { /* space allocated */
- switch (newstate) {
- case sd_down:
- if ((!flags & setstate_force) /* but gently */
- &&(sd->plexno >= 0)) /* and we're attached to a plex, */
- return 0; /* don't do it */
- break;
-
- case sd_up:
- if (DRIVE[sd->driveno].state != drive_up) /* can't bring the sd up if the drive isn't, */
- return 0; /* not even by force */
- switch (sd->state) {
- case sd_crashed:
- case sd_down: /* been down, no data lost */
- if ((sd->plexno >= 0) /* we're associated with a plex */
- &&(((PLEX[sd->plexno].state < plex_firstup) /* and it's not up */
- ||(PLEX[sd->plexno].subdisks > 1)))) /* or it's the only one */
- break; /* do it */
- /* XXX Get this right: make sure that other plexes in
- * the volume cover this address space, otherwise
- * we make this one sd_up.
- *
- * Do we even want this any more?
- */
- sd->state = sd_reborn; /* here it is again */
- printf("vinum: subdisk %s is %s, not %s\n", sd->name, sd_state(sd->state), sd_state(newstate));
- status = -1;
- break;
-
- case sd_init: /* brand new */
- if (flags & setstate_configuring) /* we're doing this while configuring */
- break;
- /* otherwise it's like being empty */
- /* FALLTHROUGH */
-
- case sd_empty:
- if ((sd->plexno >= 0) /* we're associated with a plex */
- &&(((PLEX[sd->plexno].state < plex_firstup) /* and it's not up */
- ||(PLEX[sd->plexno].subdisks > 1)))) /* or it's the only one */
- break;
- /* Otherwise it's just out of date */
- /* FALLTHROUGH */
-
- case sd_stale: /* out of date info, need reviving */
- case sd_obsolete:
- /* 1. If the subdisk is not part of a plex, bring it up, don't revive.
-
- * 2. If the subdisk is part of a one-plex volume or an unattached plex,
- * and it's not RAID-5, we *can't revive*. The subdisk doesn't
- * change its state.
- *
- * 3. If the subdisk is part of a one-plex volume or an unattached plex,
- * and it's RAID-5, but more than one subdisk is down, we *still
- * can't revive*. The subdisk doesn't change its state.
- *
- * 4. If the subdisk is part of a multi-plex volume, we'll change to
- * reviving and let the revive routines find out whether it will work
- * or not. If they don't, the revive stops with an error message,
- * but the state doesn't change (FWIW).*/
- if (sd->plexno < 0) /* no plex associated, */
- break; /* bring it up */
- plex = &PLEX[sd->plexno];
- if (plex->volno >= 0) /* have a volume */
- vol = &VOL[plex->volno];
- else
- vol = NULL;
- if (((vol == NULL) /* no volume */ ||(vol->plexes == 1)) /* or only one plex in volume */
- &&((plex->organization != plex_raid5) /* or it's a RAID-5 plex */
- ||(plex->sddowncount > 1))) /* with more than one subdisk down, */
- return 0; /* can't do it */
- sd->state = sd_reviving; /* put in reviving state */
- sd->revived = 0; /* nothing done yet */
- status = EAGAIN; /* need to repeat */
- break;
-
- /* XXX This is silly. We need to be able to
- * bring the subdisk up when it's finished
- * initializing, but not from the user. We
- * use the same ioctl in each case, but Vinum(8)
- * doesn't supply the -f flag, so we use that
- * to decide whether to do it or not */
- case sd_initializing:
- if (flags & setstate_force)
- break; /* do it if we have to */
- return 0; /* no */
-
- case sd_reviving:
- if (flags & setstate_force) /* insist, */
- break;
- return EAGAIN; /* no, try again */
-
- default: /* can't do it */
- /* There's no way to bring subdisks up directly from
- * other states. First they need to be initialized
- * or revived */
- return 0;
- }
- break;
-
- default: /* other ones, only internal with force */
- if (flags & setstate_force == 0) /* no force? What's this? */
- return 0; /* don't do it */
- }
- }
- if (status == 1) { /* we can do it, */
- sd->state = newstate;
- printf("vinum: %s is %s\n", sd->name, sd_state(sd->state));
- } else /* we don't get here with status 0 */
- printf("vinum: %s is %s, not %s\n", sd->name, sd_state(sd->state), sd_state(newstate));
- if (sd->plexno >= 0) /* we belong to a plex */
- update_plex_state(sd->plexno); /* update plex state */
- if ((flags & setstate_configuring) == 0) /* save config now */
- save_config();
- return status;
-}
-
-/* Set the state of a plex dependent on its subdisks.
- * This time round, we'll let plex state just reflect
- * aggregate subdisk state, so this becomes an order of
- * magnitude less complicated. In particular, ignore
- * the requested state.
- */
-int
-set_plex_state(int plexno, enum plexstate state, enum setstateflags flags)
-{
- struct plex *plex; /* point to our plex */
- enum plexstate oldstate;
- enum volplexstate vps; /* how do we compare with the other plexes? */
-
- plex = &PLEX[plexno]; /* point to our plex */
- oldstate = plex->state;
-
- if ((plex->state == plex_unallocated) /* or no plex to do anything with, */
- ||((state == oldstate) /* or we're already there */
- &&(state != plex_up))) /* and it's not up */
- return 0;
-
- vps = vpstate(plex); /* how do we compare with the other plexes? */
-
- switch (state) {
- /* We can't bring the plex up, even by force,
- * unless it's ready. update_plex_state
- * checks that */
- case plex_up: /* bring the plex up */
- update_plex_state(plex->plexno); /* it'll come up if it can */
- break;
-
- case plex_down: /* want to take it down */
- if (((vps == volplex_onlyus) /* we're the only one up */
- ||(vps == volplex_onlyusup)) /* we're the only one up */
- &&(!(flags & setstate_force))) /* and we don't want to use force */
- return 0; /* can't do it */
- plex->state = state; /* do it */
- invalidate_subdisks(plex, sd_down); /* and down all up subdisks */
- break;
-
- /* This is only requested internally.
- * Trust ourselves */
- case plex_faulty:
- plex->state = state; /* do it */
- invalidate_subdisks(plex, sd_crashed); /* and crash all up subdisks */
- break;
-
- case plex_initializing:
- /* XXX consider what safeguards we need here */
- if ((flags & setstate_force) == 0)
- return 0;
- plex->state = state; /* do it */
- break;
-
- /* What's this? */
- default:
- return 0;
- }
- if (plex->state != oldstate) /* we've changed, */
- printf("vinum: %s is %s\n", plex->name, plex_state(plex->state)); /* tell them about it */
- /* Now see what we have left, and whether
- * we're taking the volume down */
- if (plex->volno >= 0) /* we have a volume */
- update_volume_state(plex->volno); /* update its state */
- if ((flags & setstate_configuring) == 0) /* save config now */
- save_config(); /* yes: save the updated configuration */
- return 1;
-}
-
-/* Update the state of a plex dependent on its plexes. */
-int
-set_volume_state(int volno, enum volumestate state, enum setstateflags flags)
-{
- struct volume *vol = &VOL[volno]; /* point to our volume */
-
- if ((vol->state == state) /* we're there already */
- ||(vol->state == volume_unallocated)) /* or no volume to do anything with, */
- return 0;
-
- if (state == volume_up) /* want to come up */
- update_volume_state(volno);
- else if (state == volume_down) { /* want to go down */
- if ((vol->opencount == 0) /* not open */
- ||((flags & setstate_force) != 0)) { /* or we're forcing */
- vol->state = volume_down;
- printf("vinum: volume %s is %s\n", vol->name, volume_state(vol->state));
- if ((flags & setstate_configuring) == 0) /* save config now */
- save_config(); /* yes: save the updated configuration */
- return 1;
- }
- }
- return 0; /* no change */
-}
-
-/* Set the state of a subdisk based on its environment */
-void
-update_sd_state(int sdno)
-{
- struct sd *sd;
- struct drive *drive;
- enum sdstate oldstate;
-
- sd = &SD[sdno];
- oldstate = sd->state;
- drive = &DRIVE[sd->driveno];
-
- if (drive->state == drive_up) {
- switch (sd->state) {
- case sd_down:
- case sd_crashed:
- sd->state = sd_reborn; /* back up again with no loss */
- break;
-
- default:
- break;
- }
- } else { /* down or worse */
- switch (sd->state) {
- case sd_up:
- case sd_reborn:
- case sd_reviving:
- sd->state = sd_crashed; /* lost our drive */
- break;
-
- default:
- break;
- }
- }
- if (sd->state != oldstate) /* state has changed, */
- printf("vinum: %s is %s\n", sd->name, sd_state(sd->state)); /* say so */
- if (sd->plexno >= 0) /* we're part of a plex, */
- update_plex_state(sd->plexno); /* update its state */
-}
-
-/* Set the state of a plex based on its environment */
-void
-update_plex_state(int plexno)
-{
- struct plex *plex; /* point to our plex */
- enum plexstate oldstate;
- enum volplexstate vps; /* how do we compare with the other plexes? */
- enum sdstates statemap; /* get a map of the subdisk states */
-
- plex = &PLEX[plexno]; /* point to our plex */
- oldstate = plex->state;
-
- vps = vpstate(plex); /* how do we compare with the other plexes? */
- statemap = sdstatemap(plex); /* get a map of the subdisk states */
-
- if (statemap == sd_upstate) /* all subdisks ready for action */
- /* All the subdisks are up. This also means that
- * they are consistent, so we can just bring
- * the plex up */
- plex->state = plex_up; /* go for it */
- else if (statemap == sd_emptystate) { /* nothing done yet */
- if (((vps & (volplex_otherup | volplex_onlyus)) == 0) /* nothing is up */ &&(plex->state == plex_init) /* we're brand spanking new */
- &&(plex->volno >= 0) /* and we have a volume */
- &&(VOL[plex->volno].flags & VF_CONFIG_SETUPSTATE)) { /* and we consider that up */
- /* Conceptually, an empty plex does not contain valid data,
- * but normally we'll see this state when we have just
- * created a plex, and it's either consistent from earlier,
- * or we don't care about the previous contents (we're going
- * to create a file system or use it for swap).
- *
- * We need to do this in one swell foop: on the next call
- * we will no longer be just empty.
- *
- * This code assumes that all the other plexes are also
- * capable of coming up (i.e. all the sds are up), but
- * that's OK: we'll come back to this function for the remaining
- * plexes in the volume. */
- struct volume *vol = &VOL[plex->volno];
- int plexno;
-
- for (plexno = 0; plexno < vol->plexes; plexno++)
- PLEX[vol->plex[plexno]].state = plex_up;
- } else if (vps & volplex_otherup == 0) { /* no other plexes up */
- int sdno;
-
- plex->state = plex_up; /* we can call that up */
- for (sdno = 0; sdno < plex->subdisks; sdno++) { /* change the subdisks to up state */
- SD[plex->sdnos[sdno]].state = sd_up;
- printf("vinum: %s is up\n", SD[plex->sdnos[sdno]].name); /* tell them about it */
- }
- } else
- plex->state = plex_faulty; /* no, it's down */
- } else if (statemap & (sd_upstate | sd_rebornstate) == statemap) /* all up or reborn */
- plex->state = plex_flaky;
- else if (statemap & (sd_upstate | sd_rebornstate)) /* some up or reborn */
- plex->state = plex_corrupt; /* corrupt */
- else if (statemap & sd_initstate) /* some subdisks initializing */
- plex->state = plex_initializing;
- else /* nothing at all up */
- plex->state = plex_faulty;
-
- if (plex->state != oldstate) /* state has changed, */
- printf("vinum: %s is %s\n", plex->name, plex_state(plex->state)); /* tell them about it */
- if (plex->volno >= 0) /* we're part of a volume, */
- update_volume_state(plex->volno); /* update its state */
-}
-
-/* Set volume state based on its components */
-void
-update_volume_state(int volno)
-{
- struct volume *vol; /* our volume */
- int plexno;
- enum volumestate oldstate;
-
- vol = &VOL[volno]; /* point to our volume */
- oldstate = vol->state;
-
- for (plexno = 0; plexno < vol->plexes; plexno++) {
- struct plex *plex = &PLEX[vol->plex[plexno]]; /* point to the plex */
- if (plex->state >= plex_corrupt) { /* something accessible, */
- vol->state = volume_up;
- break;
- }
- }
- if (plexno == vol->plexes) /* didn't find an up plex */
- vol->state = volume_down;
-
- if (vol->state != oldstate) { /* state changed */
- printf("vinum: %s is %s\n", vol->name, volume_state(vol->state));
- save_config(); /* save the updated configuration */
- }
-}
-
-/* Called from request routines when they find
- * a subdisk which is not kosher. Decide whether
- * it warrants changing the state. Return
- * REQUEST_DOWN if we can't use the subdisk,
- * REQUEST_OK if we can. */
-/* A prior version of this function checked the plex
- * state as well. At the moment, consider plex states
- * information for the user only. We'll ignore them
- * and use the subdisk state only. The last version of
- * this file with the old logic was 2.7. XXX */
-enum requeststatus
-checksdstate(struct sd *sd, struct request *rq, daddr_t diskaddr, daddr_t diskend)
-{
- struct plex *plex = &PLEX[sd->plexno];
- int writeop = (rq->bp->b_flags & B_READ) == 0; /* note if we're writing */
-
- switch (sd->state) {
- /* We shouldn't get called if the subdisk is up */
- case sd_up:
- return REQUEST_OK;
-
- case sd_reviving:
- /* Access to a reviving subdisk depends on the
- * organization of the plex:
-
- * - If it's concatenated, access the subdisk up to its current
- * revive point. If we want to write to the subdisk overlapping the
- * current revive block, set the conflict flag in the request, asking
- * the caller to put the request on the wait list, which will be
- * attended to by revive_block when it's done.
- * - if it's striped, we can't do it (we could do some hairy
- * calculations, but it's unlikely to work).
- * - if it's RAID-5, we can do it as long as only one
- * subdisk is down */
- if (plex->state == plex_striped) /* plex is striped, */
- return REQUEST_DOWN; /* can't access it now */
- if (diskaddr > (sd->revived
- + sd->plexoffset
- + (sd->revive_blocksize >> DEV_BSHIFT))) /* we're beyond the end */
- return REQUEST_DOWN; /* don't take the sd down again... */
- else if (diskend > (sd->revived + sd->plexoffset)) { /* we finish beyond the end */
- if (writeop) {
- rq->flags |= XFR_REVIVECONFLICT; /* note a potential conflict */
- rq->sdno = sd->sdno; /* and which sd last caused it */
- } else
- return REQUEST_DOWN; /* can't read this yet */
- }
- return REQUEST_OK;
-
- case sd_reborn:
- if (writeop)
- return REQUEST_OK; /* always write to a reborn disk */
- else /* don't allow a read */
- /* Handle the mapping. We don't want to reject
- * a read request to a reborn subdisk if that's
- * all we have. XXX */
- return REQUEST_DOWN;
-
- case sd_down:
- if (writeop) /* writing to a consistent down disk */
- set_sd_state(sd->sdno, sd_obsolete, setstate_force); /* it's not consistent now */
- return REQUEST_DOWN; /* and it's down one way or another */
-
- case sd_crashed:
- if (writeop) /* writing to a consistent down disk */
- set_sd_state(sd->sdno, sd_stale, setstate_force); /* it's not consistent now */
- return REQUEST_DOWN; /* and it's down one way or another */
-
- default:
- return REQUEST_DOWN;
- }
-}
-
-/* return a state map for the subdisks of a plex */
-enum sdstates
-sdstatemap(struct plex *plex)
-{
- int sdno;
- enum sdstates statemap = 0; /* note the states we find */
-
- plex->sddowncount = 0; /* no subdisks down yet */
- for (sdno = 0; sdno < plex->subdisks; sdno++) {
- struct sd *sd = &SD[plex->sdnos[sdno]]; /* point to the subdisk */
-
- switch (sd->state) {
- case sd_empty:
- statemap |= sd_emptystate;
- (plex->sddowncount)++; /* another unusable subdisk */
- break;
-
- case sd_init:
- statemap |= sd_initstate;
- (plex->sddowncount)++; /* another unusable subdisk */
- break;
-
- case sd_down:
- statemap |= sd_downstate;
- (plex->sddowncount)++; /* another unusable subdisk */
- break;
-
- case sd_crashed:
- statemap |= sd_crashedstate;
- (plex->sddowncount)++; /* another unusable subdisk */
- break;
-
- case sd_obsolete:
- statemap |= sd_obsolete;
- (plex->sddowncount)++; /* another unusable subdisk */
- break;
-
- case sd_stale:
- statemap |= sd_stalestate;
- (plex->sddowncount)++; /* another unusable subdisk */
- break;
-
- case sd_reborn:
- statemap |= sd_rebornstate;
- break;
-
- case sd_up:
- statemap |= sd_upstate;
- break;
-
- case sd_initializing:
- statemap |= sd_initstate;
- (plex->sddowncount)++; /* another unusable subdisk */
- break;
-
- case sd_unallocated:
- case sd_uninit:
- case sd_reviving:
- statemap |= sd_otherstate;
- (plex->sddowncount)++; /* another unusable subdisk */
- }
- }
- return statemap;
-}
-
-/* determine the state of the volume relative to this plex */
-enum volplexstate
-vpstate(struct plex *plex)
-{
- struct volume *vol;
- enum volplexstate state = volplex_onlyusdown; /* state to return */
- int plexno;
-
- if (plex->volno < 0) /* not associated with a volume */
- return volplex_onlyusdown; /* assume the worst */
-
- vol = &VOL[plex->volno]; /* point to our volume */
- for (plexno = 0; plexno < vol->plexes; plexno++) {
- if (&PLEX[vol->plex[plexno]] == plex) { /* us */
-#if RAID5
- if (PLEX[vol->plex[plexno]].state >= plex_degraded) /* are we up? */
- state |= volplex_onlyus; /* yes */
-#else
- if (PLEX[vol->plex[plexno]].state >= plex_flaky) /* are we up? */
- state |= volplex_onlyus; /* yes */
-#endif
- } else {
-#if RAID5
- if (PLEX[vol->plex[plexno]].state >= plex_degraded) /* not us */
- state |= volplex_otherup; /* and when they were up, they were up */
- else
- state |= volplex_alldown; /* and when they were down, they were down */
-#else
- if (PLEX[vol->plex[plexno]].state >= plex_flaky) /* not us */
- state |= volplex_otherup; /* and when they were up, they were up */
- else
- state |= volplex_alldown; /* and when they were down, they were down */
-#endif
- }
- }
- return state; /* and when they were only halfway up */
-} /* they were neither up nor down */
-
-/* Check if all bits b are set in a */
-int allset(int a, int b);
-
-int
-allset(int a, int b)
-{
- return (a & b) == b;
-}
-
-/* Invalidate the subdisks belonging to a plex */
-void
-invalidate_subdisks(struct plex *plex, enum sdstate state)
-{
- int sdno;
-
- for (sdno = 0; sdno < plex->subdisks; sdno++) { /* for each subdisk */
- struct sd *sd = &SD[plex->sdnos[sdno]];
-
- switch (sd->state) {
- case sd_unallocated:
- case sd_uninit:
- case sd_init:
- case sd_initializing:
- case sd_empty:
- case sd_obsolete:
- case sd_stale:
- case sd_crashed:
- case sd_down:
- break;
-
- case sd_reviving:
- case sd_reborn:
- case sd_up:
- set_sd_state(plex->sdnos[sdno], state, setstate_force);
- }
- }
-}
-
-/* Start an object, in other words do what we can to get it up.
- * This is called from vinumioctl (VINUMSTART).
- * Return error indications via ioctl_reply
- */
-void
-start_object(struct vinum_ioctl_msg *data)
-{
- int status;
- int objindex = data->index; /* data gets overwritten */
- struct _ioctl_reply *ioctl_reply = (struct _ioctl_reply *) data; /* format for returning replies */
- enum setstateflags flags;
-
- if (data->force != 0) /* are we going to use force? */
- flags = setstate_force; /* yes */
- else
- flags = setstate_none; /* no */
-
- switch (data->type) {
- case drive_object:
- status = set_drive_state(objindex, drive_up, flags);
- if (DRIVE[objindex].state != drive_up) /* set status on whether we really did it */
- ioctl_reply->error = EINVAL;
- else
- ioctl_reply->error = 0;
- break;
-
- case sd_object:
- if (SD[objindex].state == sd_reviving) { /* reviving, */
- ioctl_reply->error = revive_block(objindex); /* revive another block */
- ioctl_reply->msg[0] = '\0'; /* no comment */
- return;
- }
- status = set_sd_state(objindex, sd_up, flags); /* set state */
- if (status == EAGAIN) { /* first revive, */
- ioctl_reply->error = revive_block(objindex); /* revive the first block */
- ioctl_reply->error = EAGAIN;
- } else {
- if (SD[objindex].state != sd_up) /* set status on whether we really did it */
- ioctl_reply->error = EINVAL;
- else
- ioctl_reply->error = 0;
- }
- break;
-
- case plex_object:
- status = set_plex_state(objindex, plex_up, flags);
- if (PLEX[objindex].state != plex_up) /* set status on whether we really did it */
- ioctl_reply->error = EINVAL;
- else
- ioctl_reply->error = 0;
- break;
-
- case volume_object:
- status = set_volume_state(objindex, volume_up, flags);
- if (VOL[objindex].state != volume_up) /* set status on whether we really did it */
- ioctl_reply->error = EINVAL;
- else
- ioctl_reply->error = 0;
- break;
-
- default:
- ioctl_reply->error = EINVAL;
- strcpy(ioctl_reply->msg, "Invalid object type");
- return;
- }
- /* There's no point in saying anything here:
- * the userland program does it better */
- ioctl_reply->msg[0] = '\0';
-}
-
-/* Stop an object, in other words do what we can to get it down
- * This is called from vinumioctl (VINUMSTOP).
- * Return error indications via ioctl_reply.
- */
-void
-stop_object(struct vinum_ioctl_msg *data)
-{
- int status = 1;
- int objindex = data->index; /* save the number from change */
- struct _ioctl_reply *ioctl_reply = (struct _ioctl_reply *) data; /* format for returning replies */
-
- switch (data->type) {
- case drive_object:
- status = set_drive_state(objindex, drive_down, data->force);
- break;
-
- case sd_object:
- status = set_sd_state(objindex, sd_down, data->force);
- break;
-
- case plex_object:
- status = set_plex_state(objindex, plex_down, data->force);
- break;
-
- case volume_object:
- status = set_volume_state(objindex, volume_down, data->force);
- break;
-
- default:
- ioctl_reply->error = EINVAL;
- strcpy(ioctl_reply->msg, "Invalid object type");
- return;
- }
- ioctl_reply->msg[0] = '\0';
- if (status == 0) /* couldn't do it */
- ioctl_reply->error = EINVAL;
- else
- ioctl_reply->error = 0;
-}
-
-/* VINUM_SETSTATE ioctl: set an object state
- * msg is the message passed by the user */
-void
-setstate(struct vinum_ioctl_msg *msg)
-{
- int sdno;
- struct sd *sd;
- struct plex *plex;
- struct _ioctl_reply *ioctl_reply = (struct _ioctl_reply *) msg; /* format for returning replies */
-
- switch (msg->state) {
- case object_down:
- stop_object(msg);
- break;
-
- case object_initializing:
- switch (msg->type) {
- case sd_object:
- sd = &SD[msg->index];
- if ((msg->index >= vinum_conf.subdisks_used)
- || (sd->state == sd_unallocated)) {
- sprintf(ioctl_reply->msg, "Invalid subdisk %d", msg->index);
- ioctl_reply->error = EFAULT;
- return;
- }
- set_sd_state(msg->index, sd_initializing, msg->force);
- if (sd->state != sd_initializing) {
- strcpy(ioctl_reply->msg, "Can't set state");
- ioctl_reply->error = EINVAL;
- } else
- ioctl_reply->error = 0;
- break;
-
- case plex_object:
- plex = &PLEX[msg->index];
- if ((msg->index >= vinum_conf.plexes_used)
- || (plex->state == plex_unallocated)) {
- sprintf(ioctl_reply->msg, "Invalid subdisk %d", msg->index);
- ioctl_reply->error = EFAULT;
- return;
- }
- set_plex_state(msg->index, plex_initializing, msg->force);
- if (plex->state != plex_initializing) {
- strcpy(ioctl_reply->msg, "Can't set state");
- ioctl_reply->error = EINVAL;
- } else {
- ioctl_reply->error = 0;
- for (sdno = 0; sdno < plex->subdisks; sdno++) {
- sd = &SD[plex->sdnos[sdno]];
- set_sd_state(plex->sdnos[sdno], sd_initializing, msg->force);
- if (sd->state != sd_initializing) {
- strcpy(ioctl_reply->msg, "Can't set state");
- ioctl_reply->error = EINVAL;
- break;
- }
- }
- }
- break;
-
- default:
- strcpy(ioctl_reply->msg, "Invalid object");
- ioctl_reply->error = EINVAL;
- }
- break;
-
- case object_up:
- start_object(msg);
- }
-}