📄 vinumconfig.c
字号:
if (autosize != 0) /* need to find a size, */ give_sd_to_drive(sdno); /* do it before the plex */ /* Check for a plex name */ if ((sd->plexno < 0) /* didn't specify a plex */ &&(!detached)) /* and didn't say not to, */ sd->plexno = current_plex; /* set to the current plex */ if (sd->plexno >= 0) sdindex = give_sd_to_plex(sd->plexno, sdno); /* now tell the plex that it has this sd */ sd->sdno = sdno; /* point to our entry in the table */ /* Does the subdisk have a name? If not, give it one */ if (sd->name[0] == '\0') { /* no name */ char sdsuffix[8]; /* form sd name suffix here */ /* Do we have a plex name? */ if (sdindex >= 0) /* we have a plex */ strcpy(sd->name, PLEX[sd->plexno].name); /* take it from there */ else /* no way */ throw_rude_remark(EINVAL, "Unnamed sd is not associated with a plex"); sprintf(sdsuffix, ".s%d", sdindex); /* form the suffix */ strcat(sd->name, sdsuffix); /* and add it to the name */ } /* do we have complete info for this subdisk? */ if (sd->sectors < 0) throw_rude_remark(EINVAL, "sd %s has no length spec", sd->name); if (state != sd_unallocated) /* we had a specific state to set */ sd->state = state; /* do it now */ else if (sd->state == sd_unallocated) /* no, nothing set yet, */ sd->state = sd_empty; /* must be empty */ if (autosize == 0) /* no autoconfig, do the drive now */ give_sd_to_drive(sdno); vinum_conf.subdisks_used++; /* one more in use */}/* * Handle a plex definition. */void config_plex(int update){ int parameter; int plexno; /* index of plex in vinum_conf */ struct plex *plex; /* and pointer to it */ int pindex = MAXPLEX; /* index in volume's plex list */ int detached = 0; /* don't give it to a volume */ int namedplexno; enum plexstate state = plex_init; /* state to set at end */ current_plex = -1; /* forget the previous plex */ plexno = get_empty_plex(); /* allocate a plex */ plex = &PLEX[plexno]; /* and point to it */ plex->plexno = plexno; /* and back to the config */ for (parameter = 1; parameter < tokens; parameter++) { /* look at the other tokens */ switch (get_keyword(token[parameter], &keyword_set)) { /* * If we have a 'name' parameter, it must * come first, because we're too lazy to tidy * up dangling refs if it comes later. */ case kw_name: namedplexno = find_plex(token[++parameter], 0); /* find an existing plex with this name */ if (namedplexno >= 0) { /* plex exists already, */ if (PLEX[namedplexno].state == plex_referenced) { /* we've been told about this one */ if (parameter > 2) /* we've done other things first, */ throw_rude_remark(EINVAL, "plex %s: name parameter must come first\n", /* no go */ token[parameter]); else { int i; struct volume *vol; /* for tidying up dangling references */ *plex = PLEX[namedplexno]; /* get the info */ PLEX[namedplexno].state = plex_unallocated; /* and deallocate the other one */ vol = &VOL[plex->volno]; /* point to the volume */ for (i = 0; i < MAXPLEX; i++) { /* for each plex */ if (vol->plex[i] == namedplexno) vol->plex[i] = plexno; /* bend the pointer */ } } break; /* use this one */ } if (update) /* are we updating? */ return; /* yes: that's OK, just return */ else throw_rude_remark(EINVAL, "Duplicate plex %s", token[parameter]); } else bcopy(token[parameter], /* put in the name */ plex->name, min(MAXPLEXNAME, strlen(token[parameter]))); break; case kw_detached: detached = 1; break; case kw_org: /* plex organization */ switch (get_keyword(token[++parameter], &keyword_set)) { case kw_concat: plex->organization = plex_concat; break; case kw_striped: { int stripesize = sizespec(token[++parameter]); plex->organization = plex_striped; if (stripesize % DEV_BSIZE != 0) /* not a multiple of block size, */ throw_rude_remark(EINVAL, "plex %s: stripe size %d not a multiple of sector size", plex->name, stripesize); else plex->stripesize = stripesize / DEV_BSIZE; break; } case kw_raid5: { int stripesize = sizespec(token[++parameter]); plex->organization = plex_raid5; if (stripesize % DEV_BSIZE != 0) /* not a multiple of block size, */ throw_rude_remark(EINVAL, "plex %s: stripe size %d not a multiple of sector size", plex->name, stripesize); else plex->stripesize = stripesize / DEV_BSIZE; break; } default: throw_rude_remark(EINVAL, "Invalid plex organization"); } if (((plex->organization == plex_striped) || (plex->organization == plex_raid5)) && (plex->stripesize == 0)) /* didn't specify a valid stripe size */ throw_rude_remark(EINVAL, "Need a stripe size parameter"); break; case kw_volume: plex->volno = find_volume(token[++parameter], 1); /* insert a pointer to the volume */ break; case kw_sd: /* add a subdisk */ { int sdno; sdno = find_subdisk(token[++parameter], 1); /* find a subdisk */ SD[sdno].plexoffset = sizespec(token[++parameter]); /* get the offset */ give_sd_to_plex(plexno, sdno); /* and insert it there */ break; } case kw_state: checkdiskconfig(token[++parameter]); /* must be a kernel user */ state = PlexState(token[parameter]); /* set the state */ break; default: throw_rude_remark(EINVAL, "plex %s, invalid keyword: %s", plex->name, token[parameter]); } } if ((plex->volno < 0) /* we don't have a volume */ &&(!detached)) /* and we wouldn't object */ plex->volno = current_volume; if (plex->volno >= 0) pindex = give_plex_to_volume(plex->volno, plexno); /* Now tell the volume that it has this plex */ /* Does the plex have a name? If not, give it one */ if (plex->name[0] == '\0') { /* no name */ char plexsuffix[8]; /* form plex name suffix here */ /* Do we have a volume name? */ if (plex->volno >= 0) /* we have a volume */ strcpy(plex->name, /* take it from there */ VOL[plex->volno].name); else /* no way */ throw_rude_remark(EINVAL, "Unnamed plex is not associated with a volume"); sprintf(plexsuffix, ".p%d", pindex); /* form the suffix */ strcat(plex->name, plexsuffix); /* and add it to the name */ } /* Note the last plex we configured */ current_plex = plexno; plex->state = state; /* set whatever state we chose */ vinum_conf.plexes_used++; /* one more in use */}/* * Handle a volume definition. * If we find an error, print a message, deallocate the nascent volume, and return */void config_volume(int update){ int parameter; int volno; struct volume *vol; /* collect volume info here */ int i; if (tokens < 2) /* not enough tokens */ throw_rude_remark(EINVAL, "Volume has no name"); current_volume = -1; /* forget the previous volume */ volno = find_volume(token[1], 1); /* allocate a volume to initialize */ vol = &VOL[volno]; /* and get a pointer */ if (update && ((vol->flags & VF_CREATED) == 0)) /* this volume exists already */ return; /* don't do anything */ vol->flags &= ~VF_CREATED; /* it exists now */ for (parameter = 2; parameter < tokens; parameter++) { /* look at all tokens */ switch (get_keyword(token[parameter], &keyword_set)) { case kw_plex: { int plexno; /* index of this plex */ int myplexno; /* and index if it's already ours */ plexno = find_plex(token[++parameter], 1); /* find a plex */ if (plexno < 0) /* couldn't */ break; /* we've already had an error message */ myplexno = my_plex(volno, plexno); /* does it already belong to us? */ if (myplexno > 0) /* yes, shouldn't get it again */ throw_rude_remark(EINVAL, "Plex %s already belongs to volume %s", token[parameter], vol->name); else if (++vol->plexes > 8) /* another entry */ throw_rude_remark(EINVAL, "Too many plexes for volume %s", vol->name); vol->plex[vol->plexes - 1] = plexno; PLEX[plexno].state = plex_referenced; /* we know something about it */ PLEX[plexno].volno = volno; /* and this volume references it */ } break; case kw_readpol: switch (get_keyword(token[++parameter], &keyword_set)) { /* decide what to do */ case kw_round: vol->preferred_plex = ROUND_ROBIN_READPOL; /* default */ break; case kw_prefer: { int myplexno; /* index of this plex */ myplexno = find_plex(token[++parameter], 1); /* find a plex */ if (myplexno < 0) /* couldn't */ break; /* we've already had an error message */ myplexno = my_plex(volno, myplexno); /* does it already belong to us? */ if (myplexno > 0) /* yes */ vol->preferred_plex = myplexno; /* just note the index */ else if (++vol->plexes > 8) /* another entry */ throw_rude_remark(EINVAL, "Too many plexes"); else { /* space for the new plex */ vol->plex[vol->plexes - 1] = myplexno; /* add it to our list */ vol->preferred_plex = vol->plexes - 1; /* and note the index */ } } break; default: throw_rude_remark(EINVAL, "Invalid read policy"); } case kw_setupstate: vol->flags |= VF_CONFIG_SETUPSTATE; /* set the volume up later on */ break; case kw_state: checkdiskconfig(token[++parameter]); /* must be on disk */ vol->state = VolState(token[parameter]); /* set the state */ break; /* * XXX experimental ideas. These are not * documented, and will not be until I * decide they're worth keeping */ case kw_writethrough: /* set writethrough mode */ vol->flags |= VF_WRITETHROUGH; break; case kw_writeback: /* set writeback mode */ vol->flags &= ~VF_WRITETHROUGH; break; case kw_raw: vol->flags |= VF_RAW; /* raw volume (no label) */ break; default: throw_rude_remark(EINVAL, "volume %s, invalid keyword: %s", vol->name, token[parameter]); } } current_volume = volno; /* note last referred volume */ vol->devno = VINUMBDEV(volno, 0, 0, VINUM_VOLUME_TYPE); /* also note device number */ /* * Before we can actually use the volume, we need * a volume label. We could start to fake one here, * but it will be a lot easier when we have some * to copy from the drives, so defer it until we * set up the configuration. XXX */ if (vol->state == volume_unallocated) vol->state = volume_down; /* now ready to bring up at the end */ /* Find out how big our volume is */ for (i = 0; i < vol->plexes; i++) vol->size = max(vol->size, PLEX[vol->plex[i]].length); vinum_conf.volumes_used++; /* one more in use */}/* * Parse a config entry. CARE! This destroys the original contents of the * config entry, which we don't really need after this. More specifically, it * places \0 characters at the end of each token. * * Return 0 if all is well, otherwise EINVAL for invalid keyword, * or ENOENT if 'read' command doesn't find any drives. */int parse_config(char *cptr, struct keywordset *keyset, int update){ int status; status = 0; /* until proven otherwise */ tokens = tokenize(cptr, token); /* chop up into tokens */ if (tokens <= 0) /* screwed up or empty line */ return tokens; /* give up */ if (token[0][0] == '#') /* comment line */ return 0; switch (get_keyword(token[0], keyset)) { /* decide what to do */ case kw_read: /* read config from a specified drive */ status = vinum_scandisk(&token[1], tokens - 1); /* read the config from disk */ break; case kw_drive: config_drive(update); break; case kw_subdisk: config_subdisk(update); break; case kw_plex: config_plex(update); break; case kw_volume: config_volume(update); break; /* Anything else is invalid in this context */ default: throw_rude_remark(EINVAL, /* should we die? */ "Invalid configuration information: %s", token[0]); } return status;}/* * parse a line handed in from userland via ioctl. * This differs only by the error reporting mechanism: * we return the error indication in the reply to the * ioctl, so we need to set a global static pointer in * this file. This technique works because we have * ensured that configuration is performed in a single-
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -