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

📄 vinumconfig.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		    if (fe < (drive->freelist_entries - 1)) /* not the last one, */			bcopy(&drive->freelist[fe + 1],			    &drive->freelist[fe],			    (drive->freelist_entries - fe) * sizeof(struct drive_freelist));		    drive->freelist_entries--;		    /* one less entry */		} else {		    drive->freelist[fe].sectors -= sd->sectors;	/* this much less space */		    drive->freelist[fe].offset += sd->sectors; /* this much further on */		}		drive->sectors_available -= sd->sectors;    /* and note how much less space we have */		break;	    }	}	if (sd->driveoffset < 0)	    /*	     * Didn't find anything.  Although the drive has	     * enough space, it's too fragmented	     */	    throw_rude_remark(ENOSPC, "No space for %s on %s", sd->name, drive->label.name);    } else {						    /* specific offset */	/*	 * For a specific offset to work, the space must be	 * entirely in a single freelist entry.  Look for it.	 */	u_int64_t sdend = sd->driveoffset + sd->sectors;    /* end of our subdisk */	for (fe = 0; fe < drive->freelist_entries; fe++) {	    u_int64_t dend = drive->freelist[fe].offset + drive->freelist[fe].sectors; /* end of entry */	    if (dend >= sdend) {			    /* fits before here */		if (drive->freelist[fe].offset > sd->driveoffset) /* starts after the beginning of sd area */		    throw_rude_remark(ENOSPC,			"No space for subdisk %s on drive %s at offset %lld",			sd->name,			drive->label.name);		/*		 * We've found the space, and we can allocate it.		 * We don't need to say that to the subdisk, which		 * already knows about it.  We need to tell it to		 * the free list, though.  We have four possibilities:		 *		 * 1.  The subdisk exactly eats up the entry.  That's the		 *     same as above.		 * 2.  The subdisk starts at the beginning and leaves space		 *     at the end.		 * 3.  The subdisk starts after the beginning and leaves		 *     space at the end as well: we end up with another		 *     fragment.		 * 4.  The subdisk leaves space at the beginning and finishes		 *     at the end.		 */		drive->sectors_available -= sd->sectors;    /* note how much less space we have */		if (sd->driveoffset == drive->freelist[fe].offset) { /* 1 or 2 */		    if (sd->sectors == drive->freelist[fe].sectors) { /* 1: used up the entire entry */			if (fe < (drive->freelist_entries - 1))	/* not the last one, */			    bcopy(&drive->freelist[fe + 1],				&drive->freelist[fe],				(drive->freelist_entries - fe) * sizeof(struct drive_freelist));			drive->freelist_entries--;	    /* one less entry */		    } else {				    /* 2: space at the end */			drive->freelist[fe].sectors -= sd->sectors; /* this much less space */			drive->freelist[fe].offset += sd->sectors; /* this much further on */		    }		} else {				    /* 3 or 4 */		    drive->freelist[fe].sectors = sd->driveoffset - drive->freelist[fe].offset;		    if (dend > sdend) {			    /* 3: space at the end as well */			if (fe < (drive->freelist_entries - 1))	/* not the last one */			    bcopy(&drive->freelist[fe],	    /* move the rest down */				&drive->freelist[fe + 1],				(drive->freelist_entries - fe) * sizeof(struct drive_freelist));			drive->freelist_entries++;	    /* one less entry */			drive->freelist[fe + 1].offset = sdend;	/* second entry starts after sd */			drive->freelist[fe + 1].sectors = dend - sdend;	/* and is this long */		    }		}		break;	    }	}    }    drive->opencount++;					    /* one more subdisk attached */}/* Get an empty drive entry from the drive table */int get_empty_drive(void){    int driveno;    struct drive *drive;    /* first see if we have one which has been deallocated */    for (driveno = 0; driveno < vinum_conf.drives_allocated; driveno++) {	if (DRIVE[driveno].state == drive_unallocated)	    /* bingo */	    break;    }    if (driveno >= vinum_conf.drives_allocated)		    /* we've used all our allocation */	EXPAND(DRIVE, struct drive, vinum_conf.drives_allocated, INITIAL_DRIVES);    /* got a drive entry.  Make it pretty */    drive = &DRIVE[driveno];    bzero(drive, sizeof(struct drive));    drive->driveno = driveno;				    /* put number in structure */    drive->flags |= VF_NEWBORN;				    /* newly born drive */    strcpy("unknown", drive->devicename);		    /* and make the name ``unknown'' */    return driveno;					    /* return the index */}/* * Find the named drive in vinum_conf.drive, return a pointer * return the index in vinum_conf.drive. * Don't mark the drive as allocated (XXX SMP) * If create != 0, create an entry if it doesn't exist *//* XXX check if we have it open from attach */int find_drive(const char *name, int create){    int driveno;    struct drive *drive;    if (name != NULL) {	for (driveno = 0; driveno < vinum_conf.drives_allocated; driveno++) {	    drive = &DRIVE[driveno];			    /* point to drive */	    if ((drive->label.name[0] != '\0')		    /* it has a name */&&(strcmp(drive->label.name, name) == 0)		    /* and it's this one */	    &&(drive->state > drive_unallocated))	    /* and it's a real one: found */		return driveno;	}    }    /* the drive isn't in the list.  Add it if he wants */    if (create == 0)					    /* don't want to create */	return -1;					    /* give up */    driveno = get_empty_drive();    drive = &DRIVE[driveno];    if (name != NULL)	bcopy(name,					    /* put in its name */	    drive->label.name,	    min(sizeof(drive->label.name),		strlen(name)));    drive->state = drive_referenced;			    /* in use, nothing worthwhile there */    return driveno;					    /* return the index */}/* * Find a drive given its device name. * devname must be valid. * Otherwise the same as find_drive above */int find_drive_by_dev(const char *devname, int create){    int driveno;    struct drive *drive;    for (driveno = 0; driveno < vinum_conf.drives_allocated; driveno++) {	drive = &DRIVE[driveno];			    /* point to drive */	if ((strcmp(drive->devicename, devname) == 0)	    /* it's this device */	&&(drive->state > drive_unallocated))		    /* and it's a real one: found */	    return driveno;    }    /* the drive isn't in the list.  Add it if he wants */    if (create == 0)					    /* don't want to create */	return -1;					    /* give up */    driveno = get_empty_drive();    drive = &DRIVE[driveno];    bcopy(devname,					    /* put in its name */	drive->devicename,	min(sizeof(drive->devicename),	    strlen(devname)));    drive->state = drive_referenced;			    /* in use, nothing worthwhile there */    return driveno;					    /* return the index */}/* Find an empty subdisk in the subdisk table */int get_empty_sd(void){    int sdno;    struct sd *sd;    /* first see if we have one which has been deallocated */    for (sdno = 0; sdno < vinum_conf.subdisks_allocated; sdno++) {	if (SD[sdno].state == sd_unallocated)		    /* bingo */	    break;    }    if (sdno >= vinum_conf.subdisks_allocated)	/*	 * We've run out of space.  sdno is pointing	 * where we want it, but at the moment we	 * don't have the space.  Get it.	 */	EXPAND(SD, struct sd, vinum_conf.subdisks_allocated, INITIAL_SUBDISKS);    /* initialize some things */    sd = &SD[sdno];					    /* point to it */    bzero(sd, sizeof(struct sd));			    /* initialize */    sd->flags |= VF_NEWBORN;				    /* newly born subdisk */    sd->plexno = -1;					    /* no plex */    sd->driveno = -1;					    /* and no drive */    sd->plexoffset = -1;				    /* and no offsets */    sd->driveoffset = -1;    return sdno;					    /* return the index */}/* return a drive to the free pool */void free_drive(struct drive *drive){    if (drive->state > drive_referenced) {		    /* real drive */	LOCKDRIVE(drive);	if (drive->vp != NULL)				    /* device open */	    vn_close(drive->vp, FREAD | FWRITE, FSCRED, drive->p);	if (drive->freelist)	    Free(drive->freelist);	bzero(drive, sizeof(struct drive));		    /* this also sets drive_unallocated */	unlockdrive(drive);    }}/* * Find the named subdisk in vinum_conf.sd. * * If create != 0, create an entry if it doesn't exist * * Return index in vinum_conf.sd */int find_subdisk(const char *name, int create){    int sdno;    struct sd *sd;    for (sdno = 0; sdno < vinum_conf.subdisks_allocated; sdno++) {	if (strcmp(SD[sdno].name, name) == 0)		    /* found it */	    return sdno;    }    /* the subdisk 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 */    sdno = get_empty_sd();    sd = &SD[sdno];    bcopy(name, sd->name, min(sizeof(sd->name), strlen(name)));	/* put in its name */    return sdno;					    /* return the pointer */}/* Return space to a drive */void return_drive_space(int driveno, int64_t offset, int length){    struct drive *drive;    int fe;						    /* free list entry */    u_int64_t sdend;					    /* end of our subdisk */    u_int64_t dend;					    /* end of our freelist entry */    drive = &DRIVE[driveno];    if (drive->state == drive_up) {	sdend = offset + length;			    /* end of our subdisk */	/* Look for where to return the sd address space */	for (fe = 0;	    (fe < drive->freelist_entries) && (drive->freelist[fe].offset < offset);	    fe++);	/*	 * Now we are pointing to the last entry, the first	 * with a higher offset than the subdisk, or both.	 */	if ((fe > 1)					    /* not the first entry */&&((fe == drive->freelist_entries)			    /* gone past the end */	||(drive->freelist[fe].offset > offset)))	    /* or past the block were looking for */	    fe--;					    /* point to the block before */	dend = drive->freelist[fe].offset + drive->freelist[fe].sectors; /* end of the entry */	/*	 * At this point, we are pointing to the correct	 * place in the free list.  A number of possibilities	 * exist:	 *	 * 1.  The block to be freed starts at the end of the	 *     block to which we are pointing.  This has two	 *     subcases:	 *	 * a.  The block to be freed ends at the beginning	 *     of the following block.  Merge the three	 *     areas into a single block.	 *	 * b.  The block is shorter than the space between	 *     the current block and the next one.  Enlarge	 *     the current block.	 *	 * 2.  The block to be freed starts after the end	 *     of the block.  Again, we have two cases:	 *	 * a.  It ends before the start of the following block.	 *     Create a new free block.	 *	 * b.  It ends at the start of the following block.	 *     Enlarge the following block downwards.	 *	 * When there is only one free space block, and the	 * space to be returned is before it, the pointer is	 * to a non-existent zeroth block. XXX check this	 */	if (offset == dend) {				    /* Case 1: it starts at the end of this block */	    if ((fe < drive->freelist_entries - 1)	    /* we're not the last block in the free list */	    &&(sdend == drive->freelist[fe + 1].offset)) {  /* and the subdisk ends at the start of the																			   * next block */		drive->freelist[fe].sectors = drive->freelist[fe + 1].sectors; /* 1a: merge all three blocks */		if (fe < drive->freelist_entries - 2)	    /* still more blocks after next */		    bcopy(&drive->freelist[fe + 2],	    /* move down one */			&drive->freelist[fe + 1],			(drive->freelist_entries - 2 - fe) * sizeof(struct drive_freelist));		drive->freelist_entries--;		    /* one less entry in the free list */	    } else					    /* 1b: just enlarge this block */		drive->freelist[fe].sectors += length;	} else {					    /* Case 2 */	    if (offset > dend)				    /* it starts after this block */		fe++;					    /* so look at the next block */	    if ((fe < drive->freelist_entries)		    /* we're not the last block in the free list */	    &&(sdend == drive->freelist[fe].offset)) {	    /* and the subdisk ends at the start of																		   * this block: case 4 */		drive->freelist[fe].offset = offset;	    /* it starts where the sd was */		drive->freelist[fe].sectors += length;	    /* and it's this much bigger */	    } else {					    /* case 3: non-contiguous */		if (fe < drive->freelist_entries)	    /* not after the last block, */		    bcopy(&drive->freelist[fe],		    /* move the rest up one entry */			&drive->freelist[fe + 1],			(drive->freelist_entries - fe) * sizeof(struct drive_freelist));		drive->freelist_entries++;		    /* one less entry */		drive->freelist[fe].offset = offset;	    /* this entry represents the sd */		drive->freelist[fe].sectors = length;	    }	}	drive->sectors_available += length;		    /* the sectors are now available */    }}/* * Free an allocated sd entry * This performs memory management only.  remove() * is responsible for checking relationships. */void free_sd(int sdno){    struct sd *sd;    sd = &SD[sdno];    if ((sd->driveno >= 0)				    /* we have a drive, */    &&(sd->sectors > 0))				    /* and some space on it */	return_drive_space(sd->driveno,			    /* return the space */	    sd->driveoffset,	    sd->sectors);    bzero(sd, sizeof(struct sd));			    /* and clear it out */    sd->state = sd_unallocated;}/* Find an empty plex in the plex table */int get_empty_plex(void){    int plexno;    struct plex *plex;					    /* if we allocate one */    /* first see if we have one which has been deallocated */    for (plexno = 0; plexno < vinum_conf.plexes_allocated; plexno++) {	if (PLEX[plexno].state == plex_unallocated)	    /* bingo */	    break;					    /* and get out of here */    }    if (plexno >= vinum_conf.plexes_allocated)	EXPAND(PLEX, struct plex, vinum_conf.plexes_allocated, INITIAL_PLEXES);    /* Found a plex.  Give it an sd structure */    plex = &PLEX[plexno];				    /* this one is ours */    bzero(plex, sizeof(struct plex));			    /* polish it up */    plex->sdnos = (int *) Malloc(sizeof(int) * INITIAL_SUBDISKS_IN_PLEX); /* allocate sd table */

⌨️ 快捷键说明

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