📄 vinumconfig.c
字号:
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 + -