⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vinumconfig.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    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 + -