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