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

📄 vinumconfig.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * To do: * * Don't store drive configuration on the config DB: read each drive's header * to decide where it is. * * Accept any old crap in the config_<foo> functions, and complain when * we try to bring it up. * * When trying to bring volumes up, check that the complete address range * is covered. *//*- * Copyright (c) 1997, 1998 *	Nan Yang Computer Services Limited.  All rights reserved. * *  This software is distributed under the so-called ``Berkeley *  License'': * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by Nan Yang Computer *      Services Limited. * 4. Neither the name of the Company nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * This software is provided ``as is'', and any express or implied * warranties, including, but not limited to, the implied warranties of * merchantability and fitness for a particular purpose are disclaimed. * In no event shall the company or contributors be liable for any * direct, indirect, incidental, special, exemplary, or consequential * damages (including, but not limited to, procurement of substitute * goods or services; loss of use, data, or profits; or business * interruption) however caused and on any theory of liability, whether * in contract, strict liability, or tort (including negligence or * otherwise) arising in any way out of the use of this software, even if * advised of the possibility of such damage. * * $Id: vinumconfig.c,v 1.8.2.4 1999/05/05 05:16:20 grog Exp $ */#define STATIC static#define REALLYKERNEL#include "opt_vinum.h"#include <dev/vinum/vinumhdr.h>#include <dev/vinum/request.h>#define MAXTOKEN 64					    /* maximum number of tokens in a line *//* * We can afford the luxury of global variables here, * since start_config ensures that these functions * are single-threaded. *//* These are indices in vinum_conf of the last-mentioned of each kind of object */static int current_drive = -1;				    /* note the last drive we mention, for							    * some defaults */static int current_plex = -1;				    /* and the same for the last plex */static int current_volume = -1;				    /* and the last volme */static struct _ioctl_reply *ioctl_reply;		    /* struct to return via ioctl *//* These values are used by most of these routines, so set them as globals */static char *token[MAXTOKEN];				    /* pointers to individual tokens */static int tokens;					    /* number of tokens */#define TOCONS	0x01#define TOTTY	0x02#define TOLOG	0x04struct putchar_arg {    int flags;    struct tty *tty;};#define MSG_MAX 1024					    /* maximum length of a formatted message *//* * Format an error message and return to the user in the reply. * CARE: This routine is designed to be called only from the * configuration routines, so it assumes it's the owner of * the configuration lock, and unlocks it on exit */void throw_rude_remark(int error, char *msg,...){    int retval;    va_list ap;    char *text;    static int finishing;				    /* don't recurse */    int was_finishing;    va_start(ap, msg);    if ((ioctl_reply != NULL)				    /* we're called from the user */    &&(!(vinum_conf.flags & VF_READING_CONFIG))) {	    /* and not reading from disk: return msg */	/*	 * We can't just format to ioctl_reply, since it	 * may contain our input parameters	 */	text = Malloc(MSG_MAX);	if (text == NULL) {	    log(LOG_ERR, "vinum: can't allocate error message buffer\n");	    printf("vinum: ");	    vprintf(msg, ap);				    /* print to the console */	    printf("\n");	} else {	    retval = kvprintf(msg, NULL, (void *) text, 10, ap);	    text[retval] = '\0';			    /* delimit */	    strcpy(ioctl_reply->msg, text);	    ioctl_reply->error = error;			    /* first byte is the error number */	    Free(text);	}    } else {	printf("vinum: ");	vprintf(msg, ap);				    /* print to the console */	printf("\n");    }    va_end(ap);    if (vinum_conf.flags & VF_READING_CONFIG) {		    /* go through to the bitter end, */	if ((vinum_conf.flags & VF_READING_CONFIG)	    /* we're reading from disk, */	&&((daemon_options & daemon_noupdate) == 0)) {	    log(LOG_NOTICE, "Disabling configuration updates\n");	    daemon_options |= daemon_noupdate;	}	return;    }    /*     * We have a problem here: we want to unlock the     * configuration, which implies tidying up, but     * if we find an error while tidying up, we could     * recurse for ever.  Use this kludge to only try     * once     */    was_finishing = finishing;    finishing = 1;    finish_config(was_finishing);			    /* unlock anything we may be holding */    finishing = was_finishing;    longjmp(command_fail, error);}/* Function declarations */int atoi(char *);					    /* no atoi in the kernel *//* Minimal version of atoi */int atoi(char *s){							    /* no atoi in the kernel */    int r = 0;    int sign = 1;    while (((*s >= '0') && (*s <= '9')) || (*s == '-')) {	if (*s == '-')	    sign = -sign;	else	    r = r * 10 + (*s - '0');    }    return r;}/* * Check a volume to see if the plex is already assigned to it. * Return index in volume->plex, or -1 if not assigned */int my_plex(int volno, int plexno){    int i;    struct volume *vol;    vol = &VOL[volno];					    /* point to volno */    for (i = 0; i < vol->plexes; i++)	if (vol->plex[i] == plexno)	    return i;    return -1;						    /* not found */}/* * Check a plex to see if the subdisk is already assigned to it. * Return index in plex->sd, or -1 if not assigned */int my_sd(int plexno, int sdno){    int i;    struct plex *plex;    plex = &PLEX[plexno];    for (i = 0; i < plex->subdisks; i++)	if (plex->sdnos[i] == sdno)	    return i;    return -1;						    /* not found */}/* * Check that this operation is being done from the config * saved on disk. * longjmp out if not.  op is the name of the operation. */void checkdiskconfig(char *op){    if ((vinum_conf.flags & VF_READING_CONFIG) == 0)	throw_rude_remark(EPERM, "Can't perform '%s' from config file", op);}/* Add plex to the volume if possible */int give_plex_to_volume(int volno, int plexno){    struct volume *vol;    /*     * It's not an error for the plex to already     * belong to the volume, but we need to check a     * number of things to make sure it's done right.     * Some day.     */    if (my_plex(volno, plexno) >= 0)	return plexno;					    /* that's it */    vol = &VOL[volno];					    /* point to volume */    if (vol->plexes == MAXPLEX)				    /* all plexes allocated */	throw_rude_remark(ENOSPC,	    "Too many plexes for volume %s",	    vol->name);    else if ((vol->plexes > 0)				    /* we have other plexes */    &&((vol->flags & VF_CONFIG_SETUPSTATE) == 0))	    /* and we're not setting up state */	invalidate_subdisks(&PLEX[plexno], sd_stale);	    /* make the subdisks invalid */    vol->plex[vol->plexes] = plexno;			    /* this one */    vol->plexes++;					    /* add another plex */    PLEX[plexno].volno = volno;				    /* note the number of our volume */    return vol->plexes - 1;				    /* and return its index */}/* * Add subdisk to a plex if possible */int give_sd_to_plex(int plexno, int sdno){    int i;    struct plex *plex;    struct sd *sd;    /*     * It's not an error for the sd to already     * belong to the plex, but we need to check a     * number of things to make sure it's done right.     * Some day.     */    i = my_sd(plexno, sdno);    if (i >= 0)						    /* does it already belong to us? */	return i;					    /* that's it */    plex = &PLEX[plexno];				    /* point to the plex */    sd = &SD[sdno];					    /* and the subdisk */    /* Do we have an offset?  Otherwise put it after the last one */    if (sd->plexoffset < 0) {				    /* no offset specified */	if (plex->subdisks > 0) {	    struct sd *lastsd = &SD[plex->sdnos[plex->subdisks - 1]]; /* last subdisk */	    if (plex->organization == plex_concat)	    /* concat, */		sd->plexoffset = lastsd->sectors + lastsd->plexoffset; /* starts here */	    else					    /* striped or RAID-5, */		sd->plexoffset = plex->stripesize * plex->subdisks; /* starts here */	} else						    /* first subdisk */	    sd->plexoffset = 0;				    /* start at the beginning */    }    if (plex->subdisks == MAXSD)			    /* we already have our maximum */	throw_rude_remark(ENOSPC,			    /* crap out */	    "Can't add %s to %s: plex full",	    sd->name,	    plex->name);    plex->subdisks++;					    /* another entry */    if (plex->subdisks >= plex->subdisks_allocated)	    /* need more space */	EXPAND(plex->sdnos, int, plex->subdisks_allocated, INITIAL_SUBDISKS_IN_PLEX);    /* Adjust size of plex and volume. */    if (plex->organization == plex_raid5)	plex->length = (plex->subdisks - 1) * sd->sectors;  /* size is one disk short */    else	plex->length += sd->sectors;			    /* plex gets this much bigger */    if (plex->volno >= 0)				    /* we have a volume */	VOL[plex->volno].size = max(VOL[plex->volno].size, plex->length); /* adjust its size */    /*     * We need to check that the subdisks don't overlap,     * but we can't do that until a point where we *must*     * know the size of all the subdisks.  That's not     * here.  But we need to sort them by offset     */    for (i = 0; i < plex->subdisks - 1; i++) {	if (sd->plexoffset < SD[plex->sdnos[i]].plexoffset) { /* it fits before this one */	    /* First move any remaining subdisks by one */	    int j;	    for (j = plex->subdisks - 1; j > i; j--)	    /* move up one at a time */		plex->sdnos[j] = plex->sdnos[j - 1];	    plex->sdnos[i] = sdno;	    sd->plexsdno = i;				    /* note where we are in the subdisk */	    return i;	}    }    /*     * The plex doesn't have any subdisk with a larger     * offset.  Insert it     */    plex->sdnos[i] = sdno;    sd->plexsdno = i;					    /* note where we are in the subdisk */    return i;}/* * Add a subdisk to drive if possible.  The pointer to the drive * must already be stored in the sd structure, but the drive * doesn't know about the subdisk yet. */static void give_sd_to_drive(int sdno){    struct sd *sd;					    /* pointer to subdisk */    struct drive *drive;				    /* and drive */    int fe;						    /* index in free list */    int sfe;						    /* and index of subdisk when assigning max */    sd = &SD[sdno];					    /* point to sd */    drive = &DRIVE[sd->driveno];			    /* and drive */    if (drive->state != drive_up) {	update_sd_state(sdno);				    /* that crashes the subdisk */	return;    }    if ((drive->sectors_available == 0)			    /* no space left */    ||(sd->sectors > drive->sectors_available)) {	    /* or too big, */	sd->driveoffset = -1;				    /* don't be confusing */	sd->state = sd_down;				    /* make it down */	throw_rude_remark(ENOSPC, "No space for %s on %s", sd->name, drive->label.name);	return;						    /* in case we come back here */    }    drive->subdisks_used++;				    /* one more subdisk */    if (sd->sectors == 0) {				    /* take the largest chunk */	sfe = 0;					    /* to keep the compiler happy */	for (fe = 0; fe < drive->freelist_entries; fe++) {	    if (drive->freelist[fe].sectors >= sd->sectors) { /* more space here */		sd->sectors = drive->freelist[fe].sectors;  /* take it */		sd->driveoffset = drive->freelist[fe].offset;		sfe = fe;				    /* and note the index for later */	    }	}	if (sd->sectors == 0)				    /* no luck, */	    throw_rude_remark(ENOSPC,			    /* give up */		"No space for %s on %s",		sd->name,		drive->label.name);	if (sfe < (drive->freelist_entries - 1))	    /* not the last one, */	    bcopy(&drive->freelist[sfe + 1],		&drive->freelist[sfe],		(drive->freelist_entries - sfe) * sizeof(struct drive_freelist));	drive->freelist_entries--;			    /* one less entry */	drive->sectors_available -= sd->sectors;	    /* and note how much less space we have */    } else if (sd->driveoffset < 0) {			    /* no offset specified, find one */	for (fe = 0; fe < drive->freelist_entries; fe++) {	    if (drive->freelist[fe].sectors >= sd->sectors) { /* it'll fit here */		sd->driveoffset = drive->freelist[fe].offset;		if (sd->sectors == drive->freelist[fe].sectors) { /* used up the entire entry */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -