PERFORCE change 178234 for review
Zheng Liu
lz at FreeBSD.org
Fri May 14 04:16:20 UTC 2010
http://p4web.freebsd.org/@@178234?ac=10
Change 178234 by lz at gnehzuil-freebsd on 2010/05/14 04:16:10
Implement reservation window mechanism.
* Algorithm:
1. When a file need to allocate a block with a uninitialized reservation
window, we will first initialize this file's reservation window, try
to allocate a window and add it to rb tree according to bpref. Then
allocate a block.
2. If a file which has a window, then we will ignore bpref and try to
allocate a block according to window's start and hit.
3. If a file's window has no free block, then window will be remove from
rb tree and try to allocate a new window according to bpref.
4. If above attempts failed, we try to allocate using old hashalloc algorithm.
* Problem:
1. dbench -D dir 4 and copy a large file, such as 600MB, it prints vm_fault. I
think there are some errors in synchronization.
* To be done:
1. Dynamically increase the window size.
2. Do not use old hashalloc algorithm when we try to allocate a block in reservation
window. It just need to allocate a free block in other cylinder groups.
Affected files ...
.. //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_alloc.c#7 edit
.. //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_balloc.c#4 edit
.. //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_inode.c#3 edit
.. //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_rsv_win.h#6 edit
.. //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/inode.h#4 edit
Differences ...
==== //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_alloc.c#7 (text+ko) ====
@@ -63,12 +63,16 @@
/* For reservation window */
static void ext2_add_rsv_win(struct m_ext2fs *, struct ext2_rsv_win *);
-static int ext2_alloc_new_rsv(struct inode *, struct m_ext2fs *, int, int32_t, int);
-static daddr_t ext2_alloccg_rsv(struct inode *, int, daddr_t, int);
-static u_long ext2_mapsearch_rsv(struct m_ext2fs *, char *, daddr_t);
-static int ext2_in_rsv(struct ext2_rsv_win *, int32_t);
+static u_long ext2_alloc_blk(struct m_ext2fs *, struct inode *, int cg,
+ struct buf *, int32_t, struct ext2_rsv_win *);
+static int ext2_alloc_new_rsv_win(struct inode *, struct ext2_rsv_win *, int32_t,
+ struct m_ext2fs *, int, struct buf *);
+static int ext2_find_next_rsv_win(struct ext2_rsv_win *, struct ext2_rsv_win *,
+ struct m_ext2fs *, int32_t, int);
static void ext2_remove_rsv_win(struct m_ext2fs *, struct ext2_rsv_win *);
-static int ext2_search_rsv_win(struct inode *, struct m_ext2fs *, int, int32_t, int);
+static u_long ext2_rsvalloc(struct m_ext2fs *, struct inode *, int,
+ struct buf *, int32_t, int);
+struct ext2_rsv_win *ext2_search_rsv_win(struct ext2_rsv_win_tree *, int32_t);
RB_GENERATE(ext2_rsv_win_tree, ext2_rsv_win, rw_link, ext2_rsv_win_cmp);
@@ -79,28 +83,26 @@
* info structure will be initialized.
*/
void
-ext2_init_rsv_win_info(struct inode *ip)
+ext2_init_rsv(struct inode *ip)
{
- struct ext2_rsv_win *rwp;
- struct ext2_rsv_win_info *rwip;
+ struct ext2_rsv_win *rp;
- rwip = malloc(sizeof(struct ext2_rsv_win_info),
- M_EXT2NODE, M_NOWAIT | M_ZERO);
+ rp = malloc(sizeof(struct ext2_rsv_win),
+ M_EXT2NODE, M_WAITOK | M_ZERO);
/* If malloc failed, we just do not use
* reservation window mechanism
*/
- if (rwip == NULL)
+ if (rp == NULL)
return;
- rwp = &rwip->rwi_entry;
- rwp->rw_start = EXT2_RWI_NOT_ALLOCATED;
- rwp->rw_end = EXT2_RWI_NOT_ALLOCATED;
+ rp->rw_start = EXT2_RWI_NOT_ALLOCATED;
+ rp->rw_end = EXT2_RWI_NOT_ALLOCATED;
- rwp->rw_goal_size = EXT2_RWI_DEFAULT_RESERVE_BLKS;
- rwp->rw_alloc_hit = 0;
+ rp->rw_goal_size = EXT2_RWI_DEFAULT_RESERVE_BLKS;
+ rp->rw_alloc_hit = 0;
- ip->i_rsv_winp = rwip;
+ ip->i_rsv = rp;
}
/*
@@ -112,186 +114,282 @@
* 3. truncate a file
*/
void
-ext2_discard_rsv_win(struct inode *ip)
+ext2_discard_rsv(struct inode *ip)
{
- struct ext2_rsv_win *rwp;
+ struct ext2_rsv_win *rp;
/* do not use reservation window */
- if (ip->i_rsv_winp == NULL)
- return;
+ if (ip->i_rsv == NULL)
+ return;
+ rp = ip->i_rsv;
- rwp = &ip->i_rsv_winp->rwi_entry;
- if (rwp->rw_end == EXT2_RWI_NOT_ALLOCATED)
- /* reservation window is empty */
- return;
+ /* If reservation window is empty, nothing to do */
+ if (rp->rw_end == EXT2_RWI_NOT_ALLOCATED)
+ return;
- mtx_lock_spin(&ip->i_e2fs->e2fs_rsv_win_lock);
- if (rwp->rw_end != EXT2_RWI_NOT_ALLOCATED)
- ext2_remove_rsv_win(ip->i_e2fs, rwp);
- mtx_unlock_spin(&ip->i_e2fs->e2fs_rsv_win_lock);
+ if (rp->rw_end != EXT2_RWI_NOT_ALLOCATED)
+ ext2_remove_rsv_win(ip->i_e2fs, rp);
}
/*
* Add a ext2_rsv_win struct to RB tree.
*/
-static void ext2_add_rsv_win(struct m_ext2fs *sbp, struct ext2_rsv_win *rwp)
+static void
+ext2_add_rsv_win(struct m_ext2fs *fs, struct ext2_rsv_win *rp)
{
- RB_INSERT(ext2_rsv_win_tree, &sbp->e2fs_tree, rwp);
+ RB_INSERT(ext2_rsv_win_tree, &fs->e2fs_rsv_tree, rp);
}
/*
* Remove a ext2_rsv_win structure from RB tree.
*/
static void
-ext2_remove_rsv_win(struct m_ext2fs *sbp, struct ext2_rsv_win *rwp)
+ext2_remove_rsv_win(struct m_ext2fs *fs, struct ext2_rsv_win *rp)
{
- rwp->rw_start = EXT2_RWI_NOT_ALLOCATED;
- rwp->rw_end = EXT2_RWI_NOT_ALLOCATED;
- rwp->rw_alloc_hit = 0;
- RB_REMOVE(ext2_rsv_win_tree, &sbp->e2fs_tree, rwp);
+ rp->rw_start = EXT2_RWI_NOT_ALLOCATED;
+ rp->rw_end = EXT2_RWI_NOT_ALLOCATED;
+ rp->rw_alloc_hit = 0;
+ RB_REMOVE(ext2_rsv_win_tree, &fs->e2fs_rsv_tree, rp);
}
/*
- * Check bpref in reservation window.
+ * Find a reservation window which can includes the bpref,
+ * or the previous one if bpref is not in any window.
*/
-static int
-ext2_in_rsv(struct ext2_rsv_win *rwp, int32_t bpref)
+struct ext2_rsv_win *
+ext2_search_rsv_win(struct ext2_rsv_win_tree *root, int32_t bpref)
{
- if (bpref < rwp->rw_start || bpref > rwp->rw_end)
- return 0;
+ struct ext2_rsv_win *next, *prev;
+
+ next = RB_ROOT(root);
+ do {
+ prev = next;
+ if (bpref < next->rw_start)
+ next = RB_LEFT(next, rw_link);
+ else if (bpref > next->rw_end)
+ next = RB_RIGHT(next, rw_link);
+ else
+ return next;
+ } while(next != NULL);
+
+ if (next == NULL || next->rw_start > bpref)
+ next = prev;
- return 1;
+ return next;
}
/*
- * Find a reservation window which includes bpref.
+ * Find a space to store a reservation window.
*/
static int
-ext2_search_rsv_win(struct inode *ip, struct m_ext2fs *sbp, int cg, int32_t bpref, int size)
+ext2_find_next_rsv_win(struct ext2_rsv_win *search, struct ext2_rsv_win *rp,
+ struct m_ext2fs *fs, int32_t bpref, int cg)
{
- struct buf *bp;
- struct ext2mount *ump;
- struct ext2_rsv_win *rwp;
- int error;
- char *bbp;
+ struct ext2_rsv_win *rsv, *prev, *next;
+ int32_t cur;
+ int size = EXT2_RWI_DEFAULT_RESERVE_BLKS;
+
+ cur = bpref;
+ rsv = search;
+ prev = NULL;
+ if (search == NULL)
+ return -1;
+
+ while (1) {
+ if (cur <= rsv->rw_end)
+ cur = rsv->rw_end + 1;
- ump = ip->i_ump;
- if (sbp->e2fs_gd[cg].ext2bgd_nbfree == 0)
- return (0);
- EXT2_UNLOCK(ump);
- error = bread(ip->i_devvp, fsbtodb(sbp,
- sbp->e2fs_gd[cg].ext2bgd_b_bitmap),
- (int)sbp->e2fs_bsize, NOCRED, &bp);
- if (error) {
- brelse(bp);
- EXT2_LOCK(ump);
- return (0);
- }
+ if (dtog(fs, cur) != cg)
+ return -1;
- bbp = (char *)bp->b_data;
+ prev = rsv;
+ next = RB_NEXT(ext2_rsv_win_tree, &fs->e2fs_rsv_tree, rsv);
+ rsv = next;
- mtx_lock_spin(&sbp->e2fs_rsv_win_lock);
+ if (next == NULL);
+ break;
- /* If RB tree is empty, then it just need to search a free block and allocate it.
- * else we need to traverse tree to find a space.
- */
- if (RB_EMPTY(&sbp->e2fs_tree)) {
- if (!ext2_mapsearch_rsv(sbp, bbp, bpref))
- goto failed;
+ if (cur + size <= rsv->rw_start)
+ break;
+ }
- rwp = &ip->i_rsv_winp->rwi_entry;
- rwp->rw_start = bpref;
- rwp->rw_end = bpref + rwp->rw_goal_size - 1;
- ext2_add_rsv_win(sbp, rwp);
+ if (prev != rp && rp->rw_end != EXT2_RWI_NOT_ALLOCATED)
+ ext2_remove_rsv_win(fs, rp);
- goto success;
- } else {
- int32_t curr;
- struct ext2_rsv_win *search;
- struct ext2_rsv_win *prev;
+ rp->rw_start = cur;
+ rp->rw_end = cur + size - 1;
+ rp->rw_alloc_hit = 0;
- search = RB_ROOT(&sbp->e2fs_tree);
- do {
- prev = search;
- if (bpref < search->rw_start)
- search = RB_LEFT(search, rw_link);
- else if (bpref > search->rw_end)
- search = RB_RIGHT(search, rw_link);
- else
- break;
- } while (search);
+ if (prev != rp) {
+ ext2_add_rsv_win(fs, rp);
+ }
- /* get bpref's previous reservation window */
- if (search == NULL)
- search = prev;
+ return 0;
+}
- curr = bpref;
- while (1) {
- if (curr <= search->rw_end)
- curr = search->rw_end + 1;
+/*
+ * Try to allocate a new reservation window.
+ */
+static int
+ext2_alloc_new_rsv_win(struct inode *ip, struct ext2_rsv_win *rp, int32_t bpref,
+ struct m_ext2fs *fs, int cg, struct buf *bp)
+{
+ struct ext2_rsv_win *search_rsv;
+ int size, ret;
+ int start, end, loc;
+ char *bbp;
- if (curr > sbp->e2fs->e2fs_first_dblock +
- cg * EXT2_BLOCKS_PER_GROUP(sbp))
- goto failed;
+ bbp = (char *)bp->b_data;
+ bpref = bpref;
+ size = rp->rw_goal_size;
- search = RB_NEXT(ext2_rsv_win_tree, &sbp->e2fs_tree, search);
+ mtx_lock_spin(&fs->e2fs_rsv_lock);
- /* reach the last reservation window */
- if (search == NULL)
- break;
+ /* If tree is empty, then try to alloc according to bpref */
+ if (RB_EMPTY(&fs->e2fs_rsv_tree)) {
+ mtx_unlock_spin(&fs->e2fs_rsv_lock);
+ /* bpref is not in this cylinder group.
+ * So try to allocate it in other group.
+ */
+ if (dtog(fs, bpref) != cg)
+ return -1;
+ if (bpref != 0) {
+ bpref = dtogd(fs, bpref);
+ if (isclr(bbp, bpref))
+ goto gotit;
+ }
+ if (bpref)
+ start = dtogd(fs, bpref) / NBBY;
+ else
+ start = 0;
+ end = howmany(fs->e2fs->e2fs_fpg, NBBY) - start;
+ for (loc = start; loc < end; loc++) {
+ if (bbp[loc] == 0) {
+ bpref = loc * NBBY;
+ goto gotit;
+ }
+ }
- /* found a space */
- if (curr + size < search->rw_start)
- break;
- }
+ for (loc = start; loc < start; loc++) {
+ if (bbp[loc] == 0) {
+ bpref = loc * NBBY;
+ goto gotit;
+ }
+ }
+ } else {
+repeat:
+ search_rsv = ext2_search_rsv_win(&fs->e2fs_rsv_tree, bpref);
- if (!ext2_mapsearch_rsv(sbp, bbp, bpref))
- goto failed;
+ ret = ext2_find_next_rsv_win(search_rsv, rp, fs, bpref, cg);
+ if (ret < 0) {
+ if (rp->rw_end != EXT2_RWI_NOT_ALLOCATED)
+ ext2_remove_rsv_win(fs, rp);
+ mtx_unlock_spin(&fs->e2fs_rsv_lock);
+ return 0;
+ }
+ mtx_unlock_spin(&fs->e2fs_rsv_lock);
- rwp = &ip->i_rsv_winp->rwi_entry;
- rwp->rw_start = bpref;
- rwp->rw_end = bpref + rwp->rw_goal_size - 1;
- ext2_add_rsv_win(sbp, rwp);
+ if (isclr(bbp, bpref) &&
+ bpref >= rp->rw_start &&
+ bpref < rp->rw_end)
+ return 0;
- goto success;
- }
+ start = dtogd(fs, bpref) / NBBY;
+ end = howmany(fs->e2fs->e2fs_fpg, NBBY) - start;
+ for (loc = start; loc < end; loc++) {
+ if (bbp[loc] == 0 &&
+ loc * NBBY >= rp->rw_start &&
+ loc * NBBY < rp->rw_end) {
+ return 0;
+ }
+ }
-success:
- mtx_unlock_spin(&sbp->e2fs_rsv_win_lock);
- EXT2_LOCK(ump);
- return 1;
+ if (loc == end) {
+ mtx_lock_spin(&fs->e2fs_rsv_lock);
+ search_rsv = rp;
+ goto repeat;
+ }
+ }
-failed:
- mtx_unlock_spin(&sbp->e2fs_rsv_win_lock);
- EXT2_LOCK(ump);
- return 0;
+gotit:
+ rp->rw_start = bpref + cg * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock;
+ rp->rw_end = rp->rw_start + size - 1;
+ rp->rw_alloc_hit = 0;
+ mtx_lock_spin(&fs->e2fs_rsv_lock);
+ ext2_add_rsv_win(fs, rp);
+ mtx_unlock_spin(&fs->e2fs_rsv_lock);
+ return 0;
}
/*
- * Allocate a new reservation window.
+ * Allocate a free block.
*/
-static int
-ext2_alloc_new_rsv(struct inode *ip, struct m_ext2fs *sbp, int cg, int32_t bpref, int size)
+static u_long
+ext2_alloc_blk(struct m_ext2fs *fs, struct inode *ip, int cg,
+ struct buf *bp, int32_t bpref, struct ext2_rsv_win *rp)
{
- struct ext2_rsv_win *rwp;
+ struct ext2mount *ump;
+ u_long start, end;
+ char *bbp;
+ u_long bno;
+
+ ump = ip->i_ump;
+ bbp = (char *)bp->b_data;
+ if (rp != NULL && rp->rw_end != EXT2_RWI_NOT_ALLOCATED) {
+ start = dtogd(fs, rp->rw_start + rp->rw_alloc_hit) / NBBY;
+ end = dtogd(fs, rp->rw_end) / NBBY;
+ } else {
+ start = dtogd(fs, bpref) / NBBY;
+ end = howmany(fs->e2fs->e2fs_fpg, NBBY) - start;
+ }
+
+ if (bbp[start * NBBY] == 0) {
+ bno = start * NBBY;
+ goto gotit;
+ }
+
+ return 0;
- rwp = &ip->i_rsv_winp->rwi_entry;
+gotit:
+ bno += rp->rw_alloc_hit++;
+ setbit(bbp, (daddr_t)bno);
+ EXT2_LOCK(ump);
+ fs->e2fs->e2fs_fbcount--;
+ fs->e2fs_gd[cg].ext2bgd_nbfree--;
+ fs->e2fs_fmod = 1;
+ EXT2_UNLOCK(ump);
+ bdwrite(bp);
+ return cg * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock + bno;
+}
- /* delete old reservation window */
- if (rwp->rw_end != EXT2_RWI_NOT_ALLOCATED) {
- mtx_lock_spin(&sbp->e2fs_rsv_win_lock);
- ext2_remove_rsv_win(sbp, &ip->i_rsv_winp->rwi_entry);
- mtx_unlock_spin(&sbp->e2fs_rsv_win_lock);
- }
+/*
+ * Allocate a free block from reservation window.
+ */
+static u_long
+ext2_rsvalloc(struct m_ext2fs *fs, struct inode *ip, int cg,
+ struct buf *bp, int32_t bpref, int size)
+{
+ struct ext2_rsv_win *rp;
+ int32_t ret;
- /* try to allocate a new reservation window in cg's group */
- if (ext2_search_rsv_win(ip, sbp, cg, bpref, size))
- return 1;
+ rp = ip->i_rsv;
- /* TODO: force to allocate a new reservation window in next group */
+ /* If window is empty or bpref is not in reservation window,
+ * we will try to allocate a new reservation window.
+ * Then we try to allocate a free block.
+ */
+ if (rp->rw_end == EXT2_RWI_NOT_ALLOCATED) {
+ ret = ext2_alloc_new_rsv_win(ip, rp, bpref, fs, cg, bp);
+ if (ret < 0)
+ return 0;
+ } else if (rp->rw_start + rp->rw_alloc_hit - 1 == rp->rw_end) {
+ ret = ext2_alloc_new_rsv_win(ip, rp, rp->rw_end, fs, cg, bp);
+ if (ret < 0)
+ return 0;
+ }
- return 0;
+ return ext2_alloc_blk(fs, ip, cg, bp, bpref, rp);
}
/*
@@ -301,24 +399,23 @@
*/
int
ext2_alloc_rsv(struct inode *ip, int32_t lbn, int32_t bpref,
- int size, struct ucred *cred, int32_t *bnp)
+ int size, struct ucred *cred, int32_t *bnp)
{
struct m_ext2fs *fs;
struct ext2mount *ump;
- struct ext2_rsv_win_info *rwip;
- int32_t bno;
- int cg;
+ struct buf *bp;
+ int32_t bno = 0;
+ int i, cg, error;
*bnp = 0;
fs = ip->i_e2fs;
ump = ip->i_ump;
- rwip = ip->i_rsv_winp;
mtx_assert(EXT2_MTX(ump), MA_OWNED);
if (size == fs->e2fs_bsize && fs->e2fs->e2fs_fbcount == 0)
goto nospace;
if (cred->cr_uid != 0 &&
- fs->e2fs->e2fs_fbcount < fs->e2fs->e2fs_rbcount)
+ fs->e2fs->e2fs_fbcount < fs->e2fs->e2fs_rbcount)
goto nospace;
if (bpref >= fs->e2fs->e2fs_bcount)
@@ -328,22 +425,53 @@
else
cg = dtog(fs, bpref);
- /* If bpref is in reservation window and window has free block, then alloc it.
- * Otherwise, try to allocate a new reservation window.
- */
- if (rwip->rwi_entry.rw_end == EXT2_RWI_NOT_ALLOCATED ||
- !ext2_in_rsv(&rwip->rwi_entry, bpref))
- if (!ext2_alloc_new_rsv(ip, fs, cg, bpref, size))
- goto nospace;
+ /* TODO: If cg doesn't have enought blocks, do not use reservation window */
+
+ /* If cg has some free blocks, then try to allocate a free block from this cg */
+ if (fs->e2fs_gd[cg].ext2bgd_nbfree > 0) {
+ /* Read block bitmap from buffer */
+ EXT2_UNLOCK(ump);
+ error = bread(ip->i_devvp,
+ fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap),
+ (int)fs->e2fs_bsize, NOCRED, &bp);
+ if (error) {
+ brelse(bp);
+ goto ioerror;
+ }
+
+ EXT2_IRSV_LOCK(ip);
+ /* Try to allocate from reservation window */
+ bno = ext2_rsvalloc(fs, ip, cg, bp, bpref, size);
+ EXT2_IRSV_UNLOCK(ip);
+ if (bno > 0)
+ goto allocated;
+
+ brelse(bp);
+ EXT2_LOCK(ump);
+ }
+
+ /* TODO: Just need to try to allocate a free block from rest groups.
+ * Now just use old allocation algorihtm.
+ */
+/*
+ for (i = cg + 1; i < fs->e2fs_gcount; i++) {
+ }
+*/
+ i = 1;
+ bno = (daddr_t)ext2_hashalloc(ip, cg, bpref, fs->e2fs_bsize, ext2_alloccg);
- bno = ext2_alloccg_rsv(ip, cg, bpref, size);
+allocated:
+ if (bno > 0) {
+ ip->i_blocks += btodb(fs->e2fs_bsize);
+ ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ *bnp = bno;
+ return (0);
+ }
- if (bno > 0) {
- ip->i_blocks += btodb(fs->e2fs_bsize);
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
- *bnp = bno;
- return (0);
- }
+ioerror:
+ ext2_fserr(fs, cred->cr_uid, "file system IO error");
+ uprintf("\n%s: write failed, file system IO error\n", fs->e2fs_fsmnt);
+ return EIO;
nospace:
EXT2_UNLOCK(ump);
@@ -439,7 +567,7 @@
* Reallocate a sequence of blocks into a contiguous sequence of blocks.
*
* The vnode and an array of buffer pointers for a range of sequential
- * logical blocks to be made contiguous is given. The allocator attempts
+ * logicar blocks to be made contiguous is given. The allocator attempts
* to find a range of sequential blocks starting as close as possible to
* an fs_rotdelay offset from the end of the allocation for the logical
* block immediately preceding the current range. If successful, the
@@ -925,66 +1053,6 @@
*
* Check to see if a block of the appropriate size is available,
* and if it is, allocate it.
- *
- * NOTE: This function will replace the ext2_alloccg() function.
- */
-static daddr_t
-ext2_alloccg_rsv(struct inode *ip, int cg, daddr_t bpref, int size)
-{
- struct m_ext2fs *fs;
- struct buf *bp;
- struct ext2mount *ump;
- int error, bno;
- char *bbp;
-
- fs = ip->i_e2fs;
- ump = ip->i_ump;
- if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0)
- return (0);
- EXT2_UNLOCK(ump);
- error = bread(ip->i_devvp, fsbtodb(fs,
- fs->e2fs_gd[cg].ext2bgd_b_bitmap),
- (int)fs->e2fs_bsize, NOCRED, &bp);
- if (error) {
- brelse(bp);
- EXT2_LOCK(ump);
- return (0);
- }
- bbp = (char *)bp->b_data;
-
- if (dtog(fs, bpref) != cg)
- bpref = 0;
- if (bpref != 0) {
- bpref = dtogd(fs, bpref);
- /*
- * if the requested block is available, use it
- */
- if (isclr(bbp, bpref)) {
- bno = bpref;
- goto gotit;
- }
- }
-
- brelse(bp);
- EXT2_LOCK(ump);
- return (0);
-
-gotit:
- setbit(bbp, (daddr_t)bno);
- EXT2_LOCK(ump);
- fs->e2fs->e2fs_fbcount--;
- fs->e2fs_gd[cg].ext2bgd_nbfree--;
- fs->e2fs_fmod = 1;
- EXT2_UNLOCK(ump);
- bdwrite(bp);
- return (cg * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock + bno);
-}
-
-/*
- * Determine whether a block can be allocated.
- *
- * Check to see if a block of the appropriate size is available,
- * and if it is, allocate it.
*/
static daddr_t
ext2_alloccg(struct inode *ip, int cg, daddr_t bpref, int size)
@@ -1219,9 +1287,11 @@
panic("ext2_vfree: range: devvp = %p, ino = %d, fs = %s",
pip->i_devvp, ino, fs->e2fs_fsmnt);
- ext2_discard_rsv_win(pip);
- free(pip->i_rsv_winp, M_EXT2NODE);
- pip->i_rsv_winp = NULL;
+ EXT2_IRSV_LOCK(pip);
+ ext2_discard_rsv(pip);
+ /*free(pip->i_rsv, M_EXT2NODE);*/
+ /*pip->i_rsv = NULL;*/
+ EXT2_IRSV_UNLOCK(pip);
cg = ino_to_cg(fs, ino);
error = bread(pip->i_devvp,
@@ -1254,47 +1324,6 @@
}
/*
- * Search a free block from bpref.
- *
- * NOTE: This function will replace the ext2_mapsearch() function.
- */
-static u_long ext2_mapsearch_rsv(struct m_ext2fs *sbp, char *bbp, daddr_t bpref)
-{
- daddr_t bno;
- int start, len, loc, i, map;
-
- /*
- * find the fragment by searching through the free block
- * map for an appropriate bit pattern
- */
- if (bpref)
- start = dtogd(sbp, bpref) / NBBY;
- else
- start = 0;
- len = howmany(sbp->e2fs->e2fs_fpg, NBBY) - start;
- loc = skpc(0xff, len, &bbp[start]);
- if (loc == 0) {
- len = start + 1;
- start = 0;
- loc = skpc(0xff, len, &bbp[start]);
- if (loc == 0) {
- printf("start = %d, len = %d, fs = %s\n",
- start, len, sbp->e2fs_fsmnt);
- panic("ext2fs_alloccg: map corrupted");
- /* NOTREACHED */
- }
- }
- i = start + len - loc;
- map = bbp[i];
- bno = i * NBBY;
- for (i = 1; i < (1 << NBBY); i <<= 1, bno++) {
- if ((map & i) == 0)
- return 1;
- }
- return 0;
-}
-
-/*
* Find a block in the specified cylinder group.
*
* It is a panic if a request is made to find a block if none are
==== //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_balloc.c#4 (text+ko) ====
@@ -79,11 +79,11 @@
fs = ip->i_e2fs;
ump = ip->i_ump;
- /*
- * lazily initialize the reservation window info in inode
- */
- if (ip->i_rsv_winp == NULL)
- ext2_init_rsv_win_info(ip);
+ /* lazily initialize the reservation window info in inode */
+ EXT2_IRSV_LOCK(ip);
+ if (ip->i_rsv == NULL)
+ ext2_init_rsv(ip);
+ EXT2_IRSV_UNLOCK(ip);
/*
* check if this is a sequential block allocation.
==== //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_inode.c#3 (text+ko) ====
@@ -52,6 +52,7 @@
#include <fs/ext2fs/ext2fs.h>
#include <fs/ext2fs/fs.h>
#include <fs/ext2fs/ext2_extern.h>
+#include <fs/ext2fs/ext2_rsv_win.h>
static int ext2_indirtrunc(struct inode *, int32_t, int32_t, int32_t, int,
long *);
@@ -153,7 +154,11 @@
}
fs = oip->i_e2fs;
osize = oip->i_size;
- ext2_discard_rsv_win(oip);
+
+ EXT2_IRSV_LOCK(oip);
+ ext2_discard_rsv(oip);
+ EXT2_IRSV_UNLOCK(oip);
+
/*
* Lengthen the size of the file. We must ensure that the
* last byte of the file is allocated. Since the smallest
@@ -485,6 +490,10 @@
if (prtactive && vrefcnt(vp) != 0)
vprint("ext2_inactive: pushing active", vp);
+ EXT2_IRSV_LOCK(ip);
+ ext2_discard_rsv(ip);
+ EXT2_IRSV_UNLOCK(ip);
+
/*
* Ignore inodes related to stale file handles.
*/
@@ -527,11 +536,15 @@
vprint("ufs_reclaim: pushing active", vp);
ip = VTOI(vp);
- ext2_discard_rsv_win(ip);
- if (ip->i_rsv_winp != NULL) {
- free(ip->i_rsv_winp, M_EXT2NODE);
- ip->i_rsv_winp = NULL;
+#if 0
+ EXT2_IRSV_LOCK(ip);
+ if (ip->i_rsv != NULL) {
+ free(ip->i_rsv, M_EXT2NODE);
+ ip->i_rsv = NULL;
}
+ EXT2_IRSV_UNLOCK(ip);
+ mtx_destroy(&ip->i_rsv_lock);
+#endif
if (ip->i_flag & IN_LAZYMOD) {
ip->i_flag |= IN_MODIFIED;
==== //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_rsv_win.h#6 (text+ko) ====
@@ -35,6 +35,9 @@
#define EXT2_MAX_RSV_WIN_BLKS 1027
+#define EXT2_IRSV_LOCK(ip) mtx_lock(&ip->i_rsv_lock)
+#define EXT2_IRSV_UNLOCK(ip) mtx_unlock(&ip->i_rsv_lock)
+
/*
* Reservation window entry
*/
==== //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/inode.h#4 (text+ko) ====
@@ -103,7 +103,7 @@
u_int32_t i_gid; /* File group. */
struct mtx i_rsv_lock; /* Protects i_rsv */
- struct ext2_rsv_win i_rsv; /* Reservation window */
+ struct ext2_rsv_win *i_rsv; /* Reservation window */
};
/*
More information about the p4-projects
mailing list