📄 vinumconfig.c
字号:
* threaded manner */int parse_user_config(char *cptr, struct keywordset *keyset){ int status; ioctl_reply = (struct _ioctl_reply *) cptr; status = parse_config(cptr, keyset, 0); if (status == ENOENT) /* from scandisk, but it can't tell us */ strcpy(ioctl_reply->msg, "no drives found"); ioctl_reply = NULL; /* don't do this again */ return status;}/* Remove an object */void remove(struct vinum_ioctl_msg *msg){ struct vinum_ioctl_msg message = *msg; /* make a copy to hand on */ ioctl_reply = (struct _ioctl_reply *) msg; /* reinstate the address to reply to */ ioctl_reply->error = 0; /* no error, */ ioctl_reply->msg[0] = '\0'; /* no message */ switch (message.type) { case drive_object: remove_drive_entry(message.index, message.force, message.recurse); updateconfig(0); return; case sd_object: remove_sd_entry(message.index, message.force, message.recurse); updateconfig(0); return; case plex_object: remove_plex_entry(message.index, message.force, message.recurse); updateconfig(0); return; case volume_object: remove_volume_entry(message.index, message.force, message.recurse); updateconfig(0); return; default: ioctl_reply->error = EINVAL; strcpy(ioctl_reply->msg, "Invalid object type"); }}/* Remove a drive. */void remove_drive_entry(int driveno, int force, int recurse){ struct drive *drive = &DRIVE[driveno]; if ((driveno > vinum_conf.drives_allocated) /* not a valid drive */ ||(drive->state == drive_unallocated)) { /* or nothing there */ ioctl_reply->error = EINVAL; strcpy(ioctl_reply->msg, "No such drive"); } else if (drive->opencount > 0) { /* we have subdisks */ if (force) { /* do it at any cost */ int sdno; struct vinum_ioctl_msg sdmsg; for (sdno = 0; sdno < vinum_conf.subdisks_allocated; sdno++) { if ((SD[sdno].state != sd_unallocated) /* subdisk is allocated */ &&(SD[sdno].driveno == driveno)) { /* and it belongs to this drive */ sdmsg.index = sdno; sdmsg.type = sd_object; sdmsg.recurse = 1; sdmsg.force = force; remove(&sdmsg); /* remove the subdisk by force */ } } remove_drive(driveno); /* now remove it */ vinum_conf.drives_used--; /* one less drive */ } else ioctl_reply->error = EBUSY; /* can't do that */ } else { remove_drive(driveno); /* just remove it */ vinum_conf.drives_used--; /* one less drive */ }}/* remove a subdisk */void remove_sd_entry(int sdno, int force, int recurse){ struct sd *sd = &SD[sdno]; if ((sdno > vinum_conf.subdisks_allocated) /* not a valid sd */ ||(sd->state == sd_unallocated)) { /* or nothing there */ ioctl_reply->error = EINVAL; strcpy(ioctl_reply->msg, "No such subdisk"); } else if (sd->flags & VF_OPEN) { /* we're open */ ioctl_reply->error = EBUSY; /* no getting around that */ return; } else if (sd->plexno >= 0) { /* we have a plex */ if (force) { /* do it at any cost */ struct plex *plex = &PLEX[sd->plexno]; /* point to our plex */ int mysdno; for (mysdno = 0; /* look for ourselves */ mysdno < plex->subdisks && &SD[plex->sdnos[mysdno]] != sd; mysdno++); if (mysdno == plex->subdisks) /* didn't find it */ throw_rude_remark(ENOENT, "plex %s does not contain subdisk %s", plex->name, sd->name); if (mysdno < (plex->subdisks - 1)) /* not the last subdisk */ bcopy(&plex->sdnos[mysdno + 1], &plex->sdnos[mysdno], (plex->subdisks - 1 - mysdno) * sizeof(int)); plex->subdisks--; /* * removing a subdisk from a striped or * RAID-5 plex really tears the hell out * of the structure, and it needs to be * reinitialized */ /* * XXX Think about this. Maybe we should just * leave a hole */ if (plex->organization != plex_concat) /* not concatenated, */ set_plex_state(plex->plexno, plex_faulty, setstate_force); /* need to reinitialize */ log(LOG_INFO, "vinum: removing %s\n", sd->name); free_sd(sdno); vinum_conf.subdisks_used--; /* one less sd */ } else ioctl_reply->error = EBUSY; /* can't do that */ } else { log(LOG_INFO, "vinum: removing %s\n", sd->name); free_sd(sdno); vinum_conf.subdisks_used--; /* one less sd */ }}/* remove a plex */void remove_plex_entry(int plexno, int force, int recurse){ struct plex *plex = &PLEX[plexno]; int sdno; if ((plexno > vinum_conf.plexes_allocated) /* not a valid plex */ ||(plex->state == plex_unallocated)) { /* or nothing there */ ioctl_reply->error = EINVAL; strcpy(ioctl_reply->msg, "No such plex"); } else if (plex->flags & VF_OPEN) { /* we're open */ ioctl_reply->error = EBUSY; /* no getting around that */ return; } if (plex->subdisks) { if (force) { /* do it anyway */ if (recurse) { /* remove all below */ for (sdno = 0; sdno < plex->subdisks; sdno++) { free_sd(plex->sdnos[sdno]); /* free all subdisks */ vinum_conf.subdisks_used--; /* one less sd */ } } else { /* just tear them out */ for (sdno = 0; sdno < plex->subdisks; sdno++) SD[plex->sdnos[sdno]].plexno = -1; /* no plex any more */ } } else { /* can't do it without force */ ioctl_reply->error = EBUSY; /* can't do that */ return; } } if (plex->volno >= 0) { /* we are part of a volume */ /* * XXX This should be more intelligent. We should * be able to remove a plex as long as the volume * does not lose any data, which is normally the * case when it has more than one plex. To do it * right we must compare the completeness of the * mapping of all the plexes in the volume */ if (force) { /* do it at any cost */ struct volume *vol = &VOL[plex->volno]; int myplexno; for (myplexno = 0; myplexno < vol->plexes; myplexno++) if (vol->plex[myplexno] == plexno) /* found it */ break; if (myplexno == vol->plexes) { /* didn't find it. Huh? */ if (force) log(LOG_ERR, "volume %s does not contain plex %s", vol->name, plex->name); else throw_rude_remark(ENOENT, "volume %s does not contain plex %s", vol->name, plex->name); } if (myplexno < (vol->plexes - 1)) /* not the last plex in the list */ bcopy(&vol->plex[myplexno + 1], &vol->plex[myplexno], vol->plexes - 1 - myplexno); vol->plexes--; } else { ioctl_reply->error = EBUSY; /* can't do that */ return; } } log(LOG_INFO, "vinum: removing %s\n", plex->name); free_plex(plexno); vinum_conf.plexes_used--; /* one less plex */}/* remove a volume */void remove_volume_entry(int volno, int force, int recurse){ struct volume *vol = &VOL[volno]; int plexno; if ((volno > vinum_conf.volumes_allocated) /* not a valid volume */ ||(vol->state == volume_unallocated)) { /* or nothing there */ ioctl_reply->error = EINVAL; strcpy(ioctl_reply->msg, "No such volume"); } else if (vol->flags & VF_OPEN) /* we're open */ ioctl_reply->error = EBUSY; /* no getting around that */ else if (vol->plexes) { if (recurse && force) { /* remove all below */ struct vinum_ioctl_msg plexmsg; plexmsg.type = plex_object; plexmsg.recurse = 1; plexmsg.force = force; for (plexno = 0; plexno < vol->plexes; plexno++) { plexmsg.index = vol->plex[plexno]; /* plex number */ remove(&plexmsg); } log(LOG_INFO, "vinum: removing %s\n", vol->name); free_volume(volno); vinum_conf.volumes_used--; /* one less volume */ } else ioctl_reply->error = EBUSY; /* can't do that */ } else { log(LOG_INFO, "vinum: removing %s\n", vol->name); free_volume(volno); vinum_conf.volumes_used--; /* one less volume */ }}/* Currently called only from ioctl */void update_sd_config(int sdno, int diskconfig){ if (!diskconfig) set_sd_state(sdno, sd_up, setstate_configuring); SD[sdno].flags &= ~VF_NEWBORN;}void update_plex_config(int plexno, int diskconfig){ u_int64_t size; int sdno; struct plex *plex = &PLEX[plexno]; enum plexstate state = plex_up; /* state we want the plex in */ int remainder; /* size of fractional stripe at end */ int added_plex; /* set if we add a plex to a volume */ int required_sds; /* number of subdisks we need */ struct sd *sd; struct volume *vol; int data_sds; /* number of sds carrying data, for RAID-5 */ if (plex->state < plex_init) /* not a real plex, */ return; added_plex = 0; if (plex->volno >= 0) { /* we have a volume */ vol = &VOL[plex->volno]; if ((plex->flags & VF_NEWBORN) /* we're newly born */&&((vol->flags & VF_NEWBORN) == 0) /* and the volume isn't */ &&(vol->plexes > 0) /* and it has other plexes, */ &&(diskconfig == 0)) { /* and we didn't read this mess from disk */ added_plex = 1; /* we were added later */ state = plex_down; /* so take ourselves down */ } } /* * Check that our subdisks make sense. For * striped and RAID5 plexes, we need at least * two subdisks, and they must all be the same * size */ if (plex->organization == plex_striped) { data_sds = plex->subdisks; required_sds = 2; } else if (plex->organization == plex_raid5) { data_sds = plex->subdisks - 1; required_sds = 3; } else required_sds = 0; if (required_sds > 0) { /* striped or RAID-5 */ if (plex->subdisks < required_sds) { log(LOG_ERR, "vinum: plex %s does not have at least %d subdisks\n", plex->name, required_sds); state = plex_faulty; } /* * Now see if the plex size is a multiple of * the stripe size. If not, trim off the end * of each subdisk and return it to the drive. */ if (plex->length > 0) { if (data_sds > 0) { if (plex->stripesize > 0) { remainder = (int) (plex->length % ((u_int64_t) plex->stripesize * data_sds)); /* are we exact? */ if (remainder) { /* no */ log(LOG_INFO, "vinum: removing %d blocks of partial stripe at the end of %s\n", remainder, plex->name); plex->length -= remainder; /* shorten the plex */ remainder /= data_sds; /* spread the remainder amongst the sds */ for (sdno = 0; sdno < plex->subdisks; sdno++) { sd = &SD[plex->sdnos[sdno]]; /* point to the subdisk */ return_drive_space(sd->driveno, /* return the space */ sd->driveoffset + sd->sectors - remainder, remainder); sd->sectors -= remainder; /* and shorten it */ } } } else /* no data sds, */ plex->length = 0; /* reset length */ } } } size = 0; for (sdno = 0; sdno < plex->subdisks; sdno++) { sd = &SD[plex->sdnos[sdno]]; if (((plex->organization == plex_striped) || (plex->organization == plex_raid5)) && (sdno > 0) && (sd->sectors != SD[plex->sdnos[sdno - 1]].sectors)) { log(LOG_ERR, "vinum: %s must have equal sized subdisks\n", plex->name); state = plex_down; } size += sd->sectors; if (added_plex) /* we were added later */ sd->state = sd_stale; /* stale until proven otherwise */ } if (plex->subdisks) { /* plex has subdisks, calculate size */ /* * XXX We shouldn't need to calculate the size any * more. Check this some time */ if (plex->organization == plex_raid5) size = size / plex->subdisks * (plex->subdisks - 1); /* less space for RAID-5 */ if (plex->length != size) log(LOG_INFO, "Correcting length of %s: was %lld, is %lld\n", plex->name, plex->length, size); plex->length = size; } else { /* no subdisks, */ plex->length = 0; /* no size */ state = plex_down; /* take it down */ } if (diskconfig) sdstatemap(plex); /* set the sddowncount */ else set_plex_state(plexno, state, setstate_none | setstate_configuring); /* set all the state */ plex->flags &= ~VF_NEWBORN;}void update_volume_config(int volno, int diskconfig){ struct volume *vol = &VOL[volno]; struct plex *plex; int plexno; if (vol->state != volume_unallocated) /* * Recalculate the size of the volume, * which might change if the original * plexes were not a multiple of the * stripe size. */ { vol->size = 0; for (plexno = 0; plexno < vol->plexes; plexno++) { plex = &PLEX[vol->plex[p
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -