vinumio.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 1,103 行 · 第 1/3 页

C
1,103
字号
	if (error) {	    brelse(bp);	    return error;	}	error = uiomove((char *) bp->b_data + blockoff, count, &uio); /* move the data */	brelse(bp);    }    while (error == 0 && uio.uio_resid > 0 && count != 0);    return error;}/* * Write data to a drive * * Return error number */int write_drive(struct drive *drive, void *buf, size_t length, off_t offset){    int error;    struct buf *bp;    struct uio uio;    struct iovec iov;    daddr_t blocknum;					    /* block number */    int blockoff;					    /* offset in block */    int count;						    /* amount to transfer */    int blockshift;    if (drive->state == drive_down)			    /* currently down */	return 0;					    /* ignore */    if (drive->vp == NULL) {	drive->lasterror = ENODEV;	return ENODEV;					    /* not configured yet */    }    iov.iov_base = buf;    iov.iov_len = length;    uio.uio_iov = &iov;    uio.uio_iovcnt = length;    uio.uio_offset = offset;    uio.uio_resid = length;    uio.uio_segflg = UIO_SYSSPACE;    uio.uio_rw = UIO_WRITE;    uio.uio_procp = curproc;    error = 0;    blockshift = btodb(drive->blocksize) - 1;		    /* amount to shift block number							    * to get sector number */    do {	blocknum = btodb(uio.uio_offset) & ~blockshift;	    /* get the block number */	blockoff = uio.uio_offset % drive->blocksize;	    /* offset in block */	count = min((unsigned) (drive->blocksize - blockoff), /* amount to transfer in this block */	    uio.uio_resid);	if (count == drive->blocksize)			    /* the whole block */	    bp = getblk(drive->vp, blocknum, drive->blocksize, 0, 0); /* just transfer it */	else						    /* partial block: */	    error = bread(drive->vp,			    /* read it first */		blocknum,		drive->blocksize,		NOCRED,		&bp);	count = min(count, drive->blocksize - bp->b_resid); /* how much will we transfer now? */	if (error == 0)	    error = uiomove((char *) bp->b_data + blockoff, /* move the data to the block */		count,		&uio);	if (error) {	    brelse(bp);	    drive->lasterror = error;	    switch (error) {	    case EIO:		set_drive_state(drive->driveno, drive_down, setstate_force);		break;		/* XXX Add other possibilities here */	    default:	    }	    return error;	}	if (count + blockoff == drive->blocksize)	    /*	     * The transfer goes to the end of the block.  There's	     * no need to wait for any more data to arrive. 	     */	    bawrite(bp);				    /* start the write now */	else	    bdwrite(bp);				    /* do a delayed write */    }    while (error == 0 && uio.uio_resid > 0 && count != 0);    if (error)	drive->lasterror = error;    return error;					    /* OK */}/* Wake up on completion */void drive_io_done(struct buf *bp){    wakeup((caddr_t) bp);				    /* Wachet auf! */    bp->b_flags &= ~B_CALL;				    /* don't do this again */}/* * Check a drive for a vinum header.  If found,  * update the drive information.  We come here * with a partially populated drive structure * which includes the device name. * * Return information on what we found. * * This function is called from two places: check_drive, * which wants to find out whether the drive is a * Vinum drive, and config_drive, which asserts that * it is a vinum drive.  In the first case, we don't * print error messages (verbose==0), in the second * we do (verbose==1). */enum drive_label_info read_drive_label(struct drive *drive, int verbose){    int error;    int result;						    /* result of our search */    struct vinum_hdr *vhdr;				    /* and as header */    error = init_drive(drive, 0);			    /* find the drive */    if (error)						    /* find the drive */	return DL_CANT_OPEN;				    /* not ours */    vhdr = (struct vinum_hdr *) Malloc(VINUMHEADERLEN);	    /* allocate buffers */    CHECKALLOC(vhdr, "Can't allocate memory");    error = read_drive(drive, (void *) vhdr, VINUMHEADERLEN, VINUM_LABEL_OFFSET);    if (vhdr->magic == VINUM_MAGIC) {			    /* ours! */	if (drive->label.name[0]			    /* we have a name for this drive */	&&(strcmp(drive->label.name, vhdr->label.name))) {  /* but it doesn't match the real name */	    drive->lasterror = EINVAL;	    result = DL_WRONG_DRIVE;			    /* it's the wrong drive */	} else {	    drive->state = drive_up;			    /* it's OK by us */	    result = DL_OURS;	}	/*	 * We copy the drive anyway so that we have	 * the correct name in the drive info.  This	 * may not be the name specified 	 */	drive->label = vhdr->label;			    /* put in the label information */    } else if (vhdr->magic == VINUM_NOMAGIC)		    /* was ours, but we gave it away */	result = DL_DELETED_LABEL;			    /* and return the info */    else	result = DL_NOT_OURS;				    /* we could have it, but we don't yet */    Free(vhdr);						    /* that's all. */    return result;}/* * Check a drive for a vinum header.  If found,  * read configuration information from the drive and * incorporate the data into the configuration. * * Return drive number. */struct drive *check_drive(char *devicename){    int driveno;    int i;    struct drive *drive;    driveno = find_drive_by_dev(devicename, 1);		    /* if entry doesn't exist, create it */    drive = &vinum_conf.drive[driveno];			    /* and get a pointer */    if (read_drive_label(drive, 0) == DL_OURS) {	    /* not ours */	for (i = 0; i < vinum_conf.drives_allocated; i++) { /* see if the name already exists */	    if ((i != driveno)				    /* not this drive */&&(DRIVE[i].state != drive_unallocated)			    /* and it's allocated */	    &&(strcmp(DRIVE[i].label.name,			DRIVE[driveno].label.name) == 0)) { /* and it has the same name */		struct drive *mydrive = &DRIVE[i];		if (mydrive->devicename[0] == '/') {	    /* we know a device name for it */		    /*		     * set an error, but don't take the drive down:		     * that would cause unneeded error messages.		     */		    drive->lasterror = EEXIST;		    break;		} else {				    /* it's just a place holder, */		    int sdno;		    for (sdno = 0; sdno < vinum_conf.subdisks_allocated; sdno++) { /* look at each subdisk */			if ((SD[sdno].driveno == i)	    /* it's pointing to this one, */			&&(SD[sdno].state != sd_unallocated)) {	/* and it's a real subdisk */			    SD[sdno].driveno = drive->driveno; /* point to the one we found */			    update_sd_state(sdno);	    /* and update its state */			}		    }		    bzero(mydrive, sizeof(struct drive));   /* don't deallocate it, just remove it */		}	    }	}    } else {	if (drive->lasterror == 0)	    drive->lasterror = ENODEV;	set_drive_state(drive->driveno, drive_down, setstate_force);    }    return drive;}static char *sappend(char *txt, char *s){    while ((*s++ = *txt++) != 0);    return s - 1;}/* Kludge: kernel printf doesn't handle quads correctly XXX */static char *lltoa(long long l, char *s);static char *lltoa(long long l, char *s){    if (l < 0) {	*s++ = '-';	l = -l;    }    if (l > 9) {	s = lltoa(l / 10, s);	l %= 10;    }    *s++ = l + '0';    return s;}/* * Format the configuration in text form into the buffer * at config.  Don't go beyond len bytes * XXX this stinks.  Fix soon.  */void format_config(char *config, int len){    int i;    int j;    char *s = config;    bzero(config, len);    /* First, the volume configuration */    for (i = 0; i < vinum_conf.volumes_allocated; i++) {	struct volume *vol;	vol = &vinum_conf.volume[i];	if ((vol->state > volume_uninit)	    && (vol->name[0] != '\0')) {		    /* paranoia */	    if (vol->preferred_plex >= 0)		    /* preferences, */		sprintf(s,		    "volume %s state %s readpol prefer %s",		    vol->name,		    volume_state(vol->state),		    vinum_conf.plex[vol->preferred_plex].name);	    else					    /* default round-robin */		sprintf(s,		    "volume %s state %s",		    vol->name,		    volume_state(vol->state));	    while (*s)		s++;					    /* find the end */	    s = sappend("\n", s);	    if (s > &config[len - 80]) {		log(LOG_ERR, "vinum: configuration data overflow\n");		return;	    }	}    }    /* Then the plex configuration */    for (i = 0; i < vinum_conf.plexes_allocated; i++) {	struct plex *plex;	plex = &vinum_conf.plex[i];	if ((plex->state != plex_referenced)	    && (plex->name[0] != '\0')) {		    /* paranoia */	    sprintf(s, "plex name %s state %s org %s ",		plex->name,		plex_state(plex->state),		plex_org(plex->organization));	    while (*s)		s++;					    /* find the end */	    if ((plex->organization == plex_striped)		|| (plex->organization == plex_raid5)) {		sprintf(s, "%db ", (int) plex->stripesize);		while (*s)		    s++;				    /* find the end */	    }	    if (plex->volno >= 0)			    /* we have a volume */		sprintf(s, "vol %s ", vinum_conf.volume[plex->volno].name);	    while (*s)		s++;					    /* find the end */	    for (j = 0; j < plex->subdisks; j++) {		sprintf(s, " sd %s", vinum_conf.sd[plex->sdnos[j]].name);	    }	    s = sappend("\n", s);	    if (s > &config[len - 80]) {		log(LOG_ERR, "vinum: configuration data overflow\n");		return;	    }	}    }    /* And finally the subdisk configuration */    for (i = 0; i < vinum_conf.subdisks_allocated; i++) {	struct sd *sd;	sd = &SD[i];	if ((sd->state != sd_referenced)	    && (sd->name[0] != '\0')) {			    /* paranoia */	    sprintf(s,		"sd name %s drive %s plex %s state %s len ",		sd->name,		vinum_conf.drive[sd->driveno].label.name,		vinum_conf.plex[sd->plexno].name,		sd_state(sd->state));	    while (*s)		s++;					    /* find the end */	    s = lltoa(sd->sectors, s);	    s = sappend("b driveoffset ", s);	    s = lltoa(sd->driveoffset, s);	    s = sappend("b plexoffset ", s);	    s = lltoa(sd->plexoffset, s);	    s = sappend("b\n", s);	    if (s > &config[len - 80]) {		log(LOG_ERR, "vinum: configuration data overflow\n");		return;	    }	}    }}/* * issue a save config request to the d鎚on.  The actual work * is done in process context by daemon_save_config  */void save_config(void){    queue_daemon_request(daemonrq_saveconfig, (union daemoninfo) NULL);}/* * Write the configuration to all vinum slices.  This * is performed by the d鎚on only  */void daemon_save_config(void){    int error;    int written_config;					    /* set when we first write the config to disk */    int driveno;    struct drive *drive;				    /* point to current drive info */    struct vinum_hdr *vhdr;				    /* and as header */    char *config;					    /* point to config data */    int wlabel_on;					    /* to set writing label on/off */    /* don't save the configuration while we're still working on it */    if (vinum_conf.flags & VF_CONFIGURING)	return;    written_config = 0;					    /* no config written yet */    /* Build a volume header */

⌨️ 快捷键说明

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