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

📄 vinumconfig.c

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