📄 vinumconfig.c
字号:
CHECKALLOC(plex->sdnos, "vinum: Can't allocate plex subdisk table"); bzero(plex->sdnos, (sizeof(int) * INITIAL_SUBDISKS_IN_PLEX)); /* do we need this? */ plex->flags |= VF_NEWBORN; /* newly born plex */ plex->subdisks = 0; /* no subdisks in use */ plex->subdisks_allocated = INITIAL_SUBDISKS_IN_PLEX; /* and we have space for this many */ plex->organization = plex_disorg; /* and it's not organized */ plex->volno = -1; /* no volume yet */ return plexno; /* return the index */}/* * Find the named plex in vinum_conf.plex * * If create != 0, create an entry if it doesn't exist * return index in vinum_conf.plex */int find_plex(const char *name, int create){ int plexno; struct plex *plex; for (plexno = 0; plexno < vinum_conf.plexes_allocated; plexno++) { if (strcmp(PLEX[plexno].name, name) == 0) /* found it */ return plexno; } /* the plex isn't in the list. Add it if he wants */ if (create == 0) /* don't want to create */ return -1; /* give up */ /* Allocate one and insert the name */ plexno = get_empty_plex(); plex = &PLEX[plexno]; /* point to it */ bcopy(name, plex->name, min(sizeof(plex->name), strlen(name))); /* put in its name */ return plexno; /* return the pointer */}/* * Free an allocated plex entry * and its associated memory areas */void free_plex(int plexno){ struct plex *plex; plex = &PLEX[plexno]; if (plex->sdnos) Free(plex->sdnos); if (plex->lock) Free(plex->lock); bzero(plex, sizeof(struct plex)); /* and clear it out */ plex->state = plex_unallocated;}/* Find an empty volume in the volume table */int get_empty_volume(void){ int volno; struct volume *vol; /* first see if we have one which has been deallocated */ for (volno = 0; volno < vinum_conf.volumes_allocated; volno++) { if (VOL[volno].state == volume_unallocated) /* bingo */ break; } if (volno >= vinum_conf.volumes_allocated) EXPAND(VOL, struct volume, vinum_conf.volumes_allocated, INITIAL_VOLUMES); /* Now initialize fields */ vol = &VOL[volno]; bzero(vol, sizeof(struct volume)); vol->flags |= VF_NEWBORN | VF_CREATED; /* newly born volume */ vol->preferred_plex = ROUND_ROBIN_READPOL; /* round robin */ return volno; /* return the index */}/* * Find the named volume in vinum_conf.volume. * * If create != 0, create an entry if it doesn't exist * return the index in vinum_conf */int find_volume(const char *name, int create){ int volno; struct volume *vol; for (volno = 0; volno < vinum_conf.volumes_allocated; volno++) { if (strcmp(VOL[volno].name, name) == 0) /* found it */ return volno; } /* the volume isn't in the list. Add it if he wants */ if (create == 0) /* don't want to create */ return -1; /* give up */ /* Allocate one and insert the name */ volno = get_empty_volume(); vol = &VOL[volno]; bcopy(name, vol->name, min(sizeof(vol->name), strlen(name))); /* put in its name */ vol->blocksize = DEV_BSIZE; /* block size of this volume */ return volno; /* return the pointer */}/* * Free an allocated volume entry * and its associated memory areas */void free_volume(int volno){ struct volume *vol; vol = &VOL[volno]; bzero(vol, sizeof(struct volume)); /* and clear it out */ vol->state = volume_unallocated;}/* * Handle a drive definition. We store the information in the global variable * drive, so we don't need to allocate. * * If we find an error, print a message and return */void config_drive(int update){ enum drive_label_info partition_status; /* info about the partition */ int parameter; int driveno; /* index of drive in vinum_conf */ struct drive *drive; /* and pointer to it */ if (tokens < 2) /* not enough tokens */ throw_rude_remark(EINVAL, "Drive has no name\n"); driveno = find_drive(token[1], 1); /* allocate a drive to initialize */ drive = &DRIVE[driveno]; /* and get a pointer */ if (update && ((drive->flags & VF_NEWBORN) == 0)) /* this drive exists already */ return; /* don't do anything */ drive->flags &= ~VF_NEWBORN; /* no longer newly born */ if (drive->state != drive_referenced) { /* we already know this drive */ /* * XXX Check which definition is more up-to-date. Give * preference for the definition on its own drive */ return; /* XXX */ } for (parameter = 2; parameter < tokens; parameter++) { /* look at the other tokens */ switch (get_keyword(token[parameter], &keyword_set)) { case kw_device: parameter++; if (drive->devicename[0] == '/') { /* we know this drive... */ if (strcmp(drive->devicename, token[parameter])) /* different name */ close_drive(drive); /* close it if it's open */ else /* no change */ break; } /* open the device and get the configuration */ bcopy(token[parameter], /* insert device information */ drive->devicename, min(sizeof(drive->devicename), strlen(token[parameter]))); partition_status = read_drive_label(drive, 1); switch (partition_status) { case DL_CANT_OPEN: /* not our kind */ close_drive(drive); if (drive->lasterror == EFTYPE) /* wrong kind of partition */ throw_rude_remark(drive->lasterror, "Drive %s has invalid partition type", drive->label.name); else /* I/O error of some kind */ throw_rude_remark(drive->lasterror, "Can't initialize drive %s", drive->label.name); break; case DL_WRONG_DRIVE: /* valid drive, not the name we expected */ if (vinum_conf.flags & VF_FORCECONFIG) { /* but we'll accept that */ bcopy(token[1], drive->label.name, sizeof(drive->label.name)); break; } close_drive(drive); /* * There's a potential race condition here: * the rude remark refers to a field in an * unallocated drive, which potentially could * be reused. This works because we're the only * thread accessing the config at the moment. */ drive->state = drive_unallocated; /* throw it away completely */ throw_rude_remark(drive->lasterror, "Incorrect drive name %s specified for drive %s", token[1], drive->label.name); break; case DL_DELETED_LABEL: /* it was a drive, but we deleted it */ break; case DL_NOT_OURS: /* nothing to do with the rest */ case DL_OURS: break; } /* * read_drive_label overwrites the device name. * If we get here, we can have the drive, * so put it back again */ bcopy(token[parameter], drive->devicename, min(sizeof(drive->devicename), strlen(token[parameter]))); break; case kw_state: checkdiskconfig(token[++parameter]); /* must be reading from disk */ drive->state = DriveState(token[parameter]); /* set the state */ break; default: close_drive(drive); throw_rude_remark(EINVAL, "Drive %s, invalid keyword: %s", token[1], token[parameter]); } } if (drive->devicename[0] != '/') { drive->state = drive_unallocated; /* deallocate the drive */ throw_rude_remark(EINVAL, "No device name for %s", drive->label.name); } vinum_conf.drives_used++; /* passed all hurdles: one more in use */}/* * Handle a subdisk definition. We store the information in the global variable * sd, so we don't need to allocate. * * If we find an error, print a message and return */void config_subdisk(int update){ int parameter; int sdno; /* index of sd in vinum_conf */ struct sd *sd; /* and pointer to it */ u_int64_t size; int detached = 0; /* set to 1 if this is a detached subdisk */ int sdindex = -1; /* index in plexes subdisk table */ enum sdstate state = sd_unallocated; /* state to set, if specified */ int autosize = 0; /* set if we autosize in give_sd_to_drive */ int namedsdno; /* index of another with this name */ sdno = get_empty_sd(); /* allocate an SD to initialize */ sd = &SD[sdno]; /* and get a pointer */ sd->sectors = -1; /* to distinguish from 0 */ 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: namedsdno = find_subdisk(token[++parameter], 0); /* find an existing sd with this name */ if (namedsdno >= 0) { /* got one */ if (SD[namedsdno].state == sd_referenced) { /* we've been told about this one */ if (parameter > 2) throw_rude_remark(EINVAL, "sd %s: name parameter must come first\n", /* no go */ token[parameter]); else { int i; struct plex *plex; /* for tidying up dangling references */ *sd = SD[namedsdno]; /* copy from the referenced one */ SD[namedsdno].state = sd_unallocated; /* and deallocate the referenced one */ plex = &PLEX[sd->plexno]; /* now take a look at our plex */ for (i = 0; i < plex->subdisks; i++) { /* look for the pointer */ if (plex->sdnos[i] == namedsdno) /* pointing to the old subdisk */ plex->sdnos[i] = sdno; /* bend it to point here */ } } } if (update) /* are we updating? */ return; /* that's OK, nothing more to do */ else throw_rude_remark(EINVAL, "Duplicate subdisk %s", token[parameter]); } else bcopy(token[parameter], sd->name, min(sizeof(sd->name), strlen(token[parameter]))); break; case kw_detached: detached = 1; break; case kw_plexoffset: size = sizespec(token[++parameter]); if ((size == -1) /* unallocated */ &&(vinum_conf.flags & VF_READING_CONFIG)) /* reading from disk */ break; /* invalid sd; just ignore it */ if ((size % DEV_BSIZE) != 0) throw_rude_remark(EINVAL, "sd %s, bad plex offset alignment: %lld", sd->name, size); else sd->plexoffset = size / DEV_BSIZE; break; case kw_driveoffset: size = sizespec(token[++parameter]); if ((size == -1) /* unallocated */ &&(vinum_conf.flags & VF_READING_CONFIG)) /* reading from disk */ break; /* invalid sd; just ignore it */ if ((size % DEV_BSIZE) != 0) throw_rude_remark(EINVAL, "sd %s, bad drive offset alignment: %lld", sd->name, size); else sd->driveoffset = size / DEV_BSIZE; break; case kw_len: if (get_keyword(token[++parameter], &keyword_set) == kw_max) /* select maximum size from drive */ size = 0; /* this is how we say it :-) */ else size = sizespec(token[parameter]); if ((size % DEV_BSIZE) != 0) throw_rude_remark(EINVAL, "sd %s, length %d not multiple of sector size", sd->name, size); else sd->sectors = size / DEV_BSIZE; /* * We have a problem with autosizing: we need to * give the drive to the plex before we give it * to the drive, in order to be clean if we give * up in the middle, but at this time the size hasn't * been set. Note that we have to fix up after * giving the subdisk to the drive. */ if (size == 0) autosize = 1; /* note that we're autosizing */ break; case kw_drive: sd->driveno = find_drive(token[++parameter], 1); /* insert drive information */ break; case kw_plex: sd->plexno = find_plex(token[++parameter], 1); /* insert plex information */ break; /* * Set the state. We can't do this directly, * because give_sd_to_plex may change it */ case kw_state: checkdiskconfig(token[++parameter]); /* must be reading from disk */ state = SdState(token[parameter]); /* set the state */ break; default: throw_rude_remark(EINVAL, "sd %s, invalid keyword: %s", sd->name, token[parameter]); } } /* Check we have a drive name */ if (sd->driveno < 0) { /* didn't specify a drive */ sd->driveno = current_drive; /* set to the current drive */ if (sd->driveno < 0) /* no current drive? */ throw_rude_remark(EINVAL, "Subdisk %s is not associated with a drive", sd->name); } /* * This is tacky. If something goes wrong * with the checks, we may end up losing drive * space. FIXME. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -