PERFORCE change 192115 for review

Zheng Liu lz at FreeBSD.org
Tue Apr 26 02:45:52 UTC 2011


http://p4web.freebsd.org/@@192115?ac=10

Change 192115 by lz at freebsd-dev on 2011/04/26 02:44:59

	Move preallocation's functions to ext2_prealloc.c.

Affected files ...

.. //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_alloc.c#44 edit
.. //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_prealloc.c#3 edit

Differences ...

==== //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_alloc.c#44 (text+ko) ====

@@ -55,8 +55,6 @@
 
 #define FANCY_REALLOC 1
 
-#define phy_blk(cg, fs) (((cg) * (fs->e2fs->e2fs_fpg)) + fs->e2fs->e2fs_first_dblock)
-
 static daddr_t	ext2_alloccg(struct inode *, int, daddr_t, int);
 static u_long	ext2_dirpref(struct inode *);
 static void	ext2_fserr(struct m_ext2fs *, uid_t, char *);
@@ -71,17 +69,6 @@
 static daddr_t  ext2_clusteralloc(struct inode *, int, daddr_t, int);
 #endif
 
-/* For reservation window */
-static u_long   ext2_alloc_blk(struct inode *, int, struct buf *, int32_t, struct ext2_rsv_win *);
-static int      ext2_alloc_new_rsv(struct inode *, int, struct buf *, int32_t);
-static int      ext2_bpref_in_rsv(struct ext2_rsv_win *, int32_t);
-static int      ext2_find_rsv(struct ext2_rsv_win *, struct ext2_rsv_win *,
-                              struct m_ext2fs *, int32_t, int);
-static u_long   ext2_rsvalloc(struct m_ext2fs *, struct inode *,
-                              int, struct buf *, int32_t, int);
-static daddr_t  ext2_search_next_block(struct m_ext2fs *, char *, int, int);
-static struct ext2_rsv_win *ext2_search_rsv(struct ext2_rsv_win_tree *, int32_t);
-
 /*
  * Allocate a block in the file system.
  *
@@ -101,411 +88,6 @@
 static int doprealloc = 0;
 SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doprealloc, CTLFLAG_RW, &doprealloc, 0, "");
 
-/*
- * Allocate a free block.
- *
- * First check whether reservation window is used.
- * If reservation window is used, try to allocate a free
- * block from the reservation window. If it fails, traverse
- * the bitmap to find a free block.
- * If reservation window is not used, try to allocate
- * a free block by bpref. If it fails, traverse the bitmap
- * to find a free block.
- */
-static u_long
-ext2_alloc_blk(struct inode *ip, int cg, struct buf *bp,
-    int32_t bpref, struct ext2_rsv_win *rp)
-{
-	struct m_ext2fs *fs;
-	struct ext2mount *ump;
-	int bno, start, end;
-	char *bbp;
-
-	fs = ip->i_e2fs;
-	ump = ip->i_ump;
-	bbp = (char *)bp->b_data;
-
-	if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0)
-		return (0);
-
-        if (bpref < 0)
-                bpref = 0;
-
-        /* Check whether it use reservation window */
-        if (rp != NULL) {
-                /*
-                 * If window's start is not in this cylinder group,
-                 * try to allocate from the beginning, otherwise
-                 * try to allocate from the beginning of the
-                 * window.
-                 */
-                if (dtog(fs, rp->rsv_start) < cg)
-                        start = 0;
-                else
-                        start = rp->rsv_start;
-
-                /*
-                 * If window's end crosses the end of this group,
-                 * set end variable to the end of this group.
-                 * Otherwise, set it to the window's end.
-                 */
-                if (dtog(fs, rp->rsv_end) > cg)
-                        end = phy_blk(cg + 1, fs) - 1;
-                else
-                        end = rp->rsv_end;
-
-                /* If preference block is within the window, try to allocate it. */
-                if (start <= bpref && bpref <= end) {
-                        bpref = dtogd(fs, bpref);
-                        if (isclr(bbp, bpref)) {
-                                rp->rsv_alloc_hit++;
-                                bno = bpref;
-                                goto gotit;
-                        }
-                } else
-                        if (dtog(fs, rp->rsv_start) == cg)
-                                bpref = dtogd(fs, rp->rsv_start);
-                        else
-                                bpref = 0;
-        } else {
-                if (dtog(fs, bpref) != cg)
-                        bpref = 0;
-                if (bpref != 0) {
-                        bpref = dtogd(fs, bpref);
-                        if (isclr(bbp, bpref)) {
-                                bno = bpref;
-                                goto gotit;
-                        }
-                }
-        }
-
-	bno = ext2_mapsearch(fs, bbp, bpref);
-	if (bno < 0)
-		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);
-	bno = phy_blk(cg, fs) + bno;
-        return (bno);
-}
-
-/*
- * Check bpref is in the reservation window.
- */
-static int
-ext2_bpref_in_rsv(struct ext2_rsv_win *rp, int32_t bpref)
-{
-        if (bpref >= 0 && (bpref < rp->rsv_start || bpref > rp->rsv_end))
-                return (0);
-
-        return (1);
-}
-
-/*
- * Search a tree node from RB tree. It includes the bpref or
- * the previous one if bpref is not in any window.
- */
-static struct ext2_rsv_win *
-ext2_search_rsv(struct ext2_rsv_win_tree *root, int32_t start)
-{
-        struct ext2_rsv_win *prev, *next;
-
-        if (RB_EMPTY(root))
-                return (NULL);
-
-        next = RB_ROOT(root);
-        do {
-                prev = next;
-                if (start < next->rsv_start)
-                        next = RB_LEFT(next, rsv_link);
-                else if (start > next->rsv_end)
-                        next = RB_RIGHT(next, rsv_link);
-                else
-                        return (next);
-        } while (next != NULL);
-
-        if (prev->rsv_start > start) {
-                next = RB_PREV(ext2_rsv_win_tree, root, prev);
-                if (next != NULL)
-                        prev = next;
-        }
-
-        return (prev);
-}
-
-/*
- * Find a reservation window by given range from start to
- * the end of this cylinder group.
- */
-static int
-ext2_find_rsv(struct ext2_rsv_win *search, struct ext2_rsv_win *rp,
-    struct m_ext2fs *fs, int32_t start, int cg)
-{
-        struct ext2_rsv_win *rsv, *prev;
-        int32_t cur;
-        int size = rp->rsv_goal_size;
-
-        if (search == NULL) {
-                rp->rsv_start = start & ~7;
-                rp->rsv_end = start + size - 1;
-                rp->rsv_alloc_hit = 0;
-
-                RB_INSERT(ext2_rsv_win_tree, fs->e2fs_rsv_tree, rp);
-
-                return (0);
-        }
-
-        /*
-         * Make the start of reservation window byte-aligned
-         * in order to can find a free block with bit operations
-         * in the ext2_search_next_block() function.
-         */
-        cur = start & ~7;
-        rsv = search;
-        prev = NULL;
-
-        while (1) {
-                if (cur <= rsv->rsv_end)
-                        cur = rsv->rsv_end + 1;
-
-                if (dtog(fs, cur) != cg)
-                        return (-1);
-
-                prev = rsv;
-                rsv = RB_NEXT(ext2_rsv_win_tree, fs->e2fs_rsv_tree, rsv);
-
-                if (rsv == NULL)
-                        break;
-
-                if (cur + size <= rsv->rsv_start)
-                        break;
-        }
-
-        if (prev != rp && rp->rsv_end != EXT2_RSV_NOT_ALLOCATED)
-                ext2_remove_rsv_win(fs, rp);
-
-        rp->rsv_start = cur;
-        rp->rsv_end = cur + size - 1;
-        rp->rsv_alloc_hit = 0;
-
-        if (prev != rp)
-                RB_INSERT(ext2_rsv_win_tree, fs->e2fs_rsv_tree, rp);
-
-        return (0);
-}
-
-/*
- * Find a free block by given range from bpref to
- * the end of this cylinder group.
- */
-static daddr_t
-ext2_search_next_block(struct m_ext2fs *fs, char *bbp, int bpref, int cg)
-{
-        daddr_t bno;
-        int start, loc, len, map, i;
-
-        start = bpref / NBBY;
-        len = howmany(fs->e2fs->e2fs_fpg, NBBY) - start;
-        loc = skpc(0xff, len, &bbp[start]);
-        if (loc == 0)
-                return (-1);
-
-        i = start + len - loc;
-        map = bbp[i];
-        bno = i * NBBY;
-        for (i = 1; i < (1 << NBBY); i <<= 1, bno++) {
-                if ((map & i) == 0)
-                        return (bno);
-        }
-
-        return (-1);
-}
-
-/*
- * Allocate a new reservation window.
- */
-static int
-ext2_alloc_new_rsv(struct inode *ip, int cg, struct buf *bp, int32_t bpref)
-{
-        struct m_ext2fs *fs;
-        struct ext2_rsv_win *rp, *search;
-        char *bbp;
-        int start, size, ret;
-
-        fs = ip->i_e2fs;
-        rp = ip->i_rsv;
-        bbp = bp->b_data;
-        size = rp->rsv_goal_size;
-
-        if (bpref <= 0)
-                start = phy_blk(cg, fs);
-        else
-                start = bpref;
-
-        /* Dynamically increase the size of window */
-        if (rp->rsv_end != EXT2_RSV_NOT_ALLOCATED) {
-                if (rp->rsv_alloc_hit >
-                    ((rp->rsv_end - rp->rsv_start + 1) / 2)) {
-                        size = size * 2;
-                        if (size > EXT2_RSV_MAX_RESERVE_BLKS)
-                                size = EXT2_RSV_MAX_RESERVE_BLKS;
-                        rp->rsv_goal_size = size;
-                }
-        }
-
-        EXT2_TREE_LOCK(fs);
-
-        search = ext2_search_rsv(fs->e2fs_rsv_tree, start);
-
-repeat:
-        ret = ext2_find_rsv(search, rp, fs, start, cg);
-        if (ret < 0) {
-                if (rp->rsv_end != EXT2_RSV_NOT_ALLOCATED)
-                        ext2_remove_rsv_win(fs, rp);
-                EXT2_TREE_UNLOCK(fs);
-                return (-1);
-        }
-        EXT2_TREE_UNLOCK(fs);
-
-        start = dtogd(fs, rp->rsv_start);
-        start = ext2_search_next_block(fs, bbp, start, cg);
-        if (start < 0) {
-                EXT2_TREE_LOCK(fs);
-                if (rp->rsv_end != EXT2_RSV_NOT_ALLOCATED)
-                        ext2_remove_rsv_win(fs, rp);
-                EXT2_TREE_UNLOCK(fs);
-                return (-1);
-        }
-
-        start = phy_blk(cg, fs) + start;
-        if (start >= rp->rsv_start && start <= rp->rsv_end)
-                return (0);
-
-        search = rp;
-        EXT2_TREE_LOCK(fs);
-        goto repeat;
-}
-
-/*
- * 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;
-        int ret;
-
-        rp = ip->i_rsv;
-        if (rp == NULL)
-                return (ext2_alloc_blk(ip, cg, bp, bpref, NULL));
-
-        if (rp->rsv_end == EXT2_RSV_NOT_ALLOCATED ||
-            !ext2_bpref_in_rsv(rp, bpref)) {
-                ret = ext2_alloc_new_rsv(ip, cg, bp, bpref);
-                if (ret < 0)
-                        return (0);
-        }
-
-        return (ext2_alloc_blk(ip, cg, bp, bpref, rp));
-}
-
-/*
- * Allocate a block using reservation window in ext2 file system.
- */
-int
-ext2_prealloc(struct inode *ip, int32_t lbn, int32_t bpref,
-    int size, struct ucred *cred)
-{
-	struct m_ext2fs *fs;
-	struct ext2mount *ump;
-        struct buf *bp;
-	int32_t bno = 0;
-	int i, cg, error;
-
-	fs = ip->i_e2fs;
-	ump = ip->i_ump;
-	mtx_assert(EXT2_MTX(ump), MA_OWNED);
-
-	if (size == fs->e2fs_bsize && fs->e2fs->e2fs_fbcount == 0)
-		goto fail;
-	if (cred->cr_uid != 0 && 
-	    fs->e2fs->e2fs_fbcount < fs->e2fs->e2fs_rbcount)
-		goto fail;
-
-	if (bpref >= fs->e2fs->e2fs_bcount)
-		bpref = 0;
-	if (bpref == 0)
-		cg = ino_to_cg(fs, ip->i_number);
-	else
-		cg = dtog(fs, bpref);
-
-        /* 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 fail;
-                }
-
-                EXT2_RSV_LOCK(ip);
-                /* Try to allocate from reservation window */
-                bno = ext2_rsvalloc(fs, ip, cg, bp, bpref, size);
-                EXT2_RSV_UNLOCK(ip);
-                if (bno > 0)
-                        goto allocated;
-
-                brelse(bp);
-                EXT2_LOCK(ump);
-        }
-
-        /* Just need to try to allocate a free block from rest groups. */
-        cg = (cg + 1) % fs->e2fs_gcount;
-        for (i = 1; i < fs->e2fs_gcount; i++) {
-                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 fail;
-                        }
-
-                        EXT2_RSV_LOCK(ip);
-                        bno = ext2_rsvalloc(fs, ip, cg, bp, -1, size);
-                        EXT2_RSV_UNLOCK(ip);
-                        if (bno > 0)
-                                goto allocated;
-
-                        brelse(bp);
-                        EXT2_LOCK(ump);
-                }
-
-                cg++;
-                if (cg == fs->e2fs_gcount)
-                        cg = 0;
-        }
-
-allocated:
-        if (bno > 0)
-                return (bno);
-
-fail:
-	return (0);
-}
-
 int
 ext2_alloc(ip, lbn, bpref, size, cred, bnp)
 	struct inode *ip;
@@ -1303,7 +885,7 @@
         EXT2_UNLOCK(ump);
 
         bdwrite(bp);
-        return (phy_blk(cg, fs) + bno);
+        return ((cg * fs->e2fs->e2fs_fpg) + fs->e2fs->e2fs_first_dblock + bno);
 
 fail_lock:
         EXT2_LOCK(ump);
@@ -1524,15 +1106,10 @@
 		start = 0;
 		loc = skpc(0xff, len, &bbp[start]);
 		if (loc == 0) {
-                        /* XXX: just for reservation window */
-                        if (doprealloc == 1)
-                                return (-1);
-                        else {
-                                printf("start = %d, len = %d, fs = %s\n",
-                                        start, len, fs->e2fs_fsmnt);
-                                panic("ext2fs_alloccg: map corrupted");
-                                /* NOTREACHED */
-                        }
+			printf("start = %d, len = %d, fs = %s\n",
+				start, len, fs->e2fs_fsmnt);
+			panic("ext2fs_alloccg: map corrupted");
+			/* NOTREACHED */
 		}
 	}
 	i = start + len - loc;

==== //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_prealloc.c#3 (text+ko) ====

@@ -43,12 +43,461 @@
 #include <fs/ext2fs/ext2_extern.h>
 #include <fs/ext2fs/ext2_prealloc.h>
 
+static u_long   ext2_alloc_blk(struct inode *, int, struct buf *, int32_t, struct ext2_rsv_win *);
+static int      ext2_alloc_new_rsv(struct inode *, int, struct buf *, int32_t);
+static int      ext2_bpref_in_rsv(struct ext2_rsv_win *, int32_t);
+static int      ext2_find_rsv(struct ext2_rsv_win *, struct ext2_rsv_win *,
+                              struct m_ext2fs *, int32_t, int);
+static daddr_t  ext2_mapsearch(struct m_ext2fs *, char *, daddr_t);
+static u_long   ext2_rsvalloc(struct m_ext2fs *, struct inode *,
+                              int, struct buf *, int32_t, int);
+static daddr_t  ext2_search_next_block(struct m_ext2fs *, char *, int, int);
+static struct	ext2_rsv_win *ext2_search_rsv(struct ext2_rsv_win_tree *, int32_t);
+
 RB_GENERATE(ext2_rsv_win_tree, ext2_rsv_win, rsv_link, ext2_rsv_win_cmp);
 
 static int prealloc_size = 8;
 SYSCTL_UINT(_vfs_ext2fs, OID_AUTO, prealloc_size, CTLFLAG_RW, &prealloc_size, 0, "");
 
 /*
+ * Allocate a free block.
+ *
+ * First check whether reservation window is used.
+ * If reservation window is used, try to allocate a free
+ * block from the reservation window. If it fails, traverse
+ * the bitmap to find a free block.
+ * If reservation window is not used, try to allocate
+ * a free block by bpref. If it fails, traverse the bitmap
+ * to find a free block.
+ */
+static u_long
+ext2_alloc_blk(struct inode *ip, int cg, struct buf *bp,
+    int32_t bpref, struct ext2_rsv_win *rp)
+{
+	struct m_ext2fs *fs;
+	struct ext2mount *ump;
+	int bno, start, end;
+	char *bbp;
+
+	fs = ip->i_e2fs;
+	ump = ip->i_ump;
+	bbp = (char *)bp->b_data;
+
+	if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0)
+		return (0);
+
+        if (bpref < 0)
+                bpref = 0;
+
+        /* Check whether it use reservation window */
+        if (rp != NULL) {
+                /*
+                 * If window's start is not in this cylinder group,
+                 * try to allocate from the beginning, otherwise
+                 * try to allocate from the beginning of the
+                 * window.
+                 */
+                if (dtog(fs, rp->rsv_start) < cg)
+                        start = 0;
+                else
+                        start = rp->rsv_start;
+
+                /*
+                 * If window's end crosses the end of this group,
+                 * set end variable to the end of this group.
+                 * Otherwise, set it to the window's end.
+                 */
+                if (dtog(fs, rp->rsv_end) > cg)
+                        end = cg * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock - 1;
+                else
+                        end = rp->rsv_end;
+
+                /* If preference block is within the window, try to allocate it. */
+                if (start <= bpref && bpref <= end) {
+                        bpref = dtogd(fs, bpref);
+                        if (isclr(bbp, bpref)) {
+                                rp->rsv_alloc_hit++;
+                                bno = bpref;
+                                goto gotit;
+                        }
+                } else
+                        if (dtog(fs, rp->rsv_start) == cg)
+                                bpref = dtogd(fs, rp->rsv_start);
+                        else
+                                bpref = 0;
+        } else {
+                if (dtog(fs, bpref) != cg)
+                        bpref = 0;
+                if (bpref != 0) {
+                        bpref = dtogd(fs, bpref);
+                        if (isclr(bbp, bpref)) {
+                                bno = bpref;
+                                goto gotit;
+                        }
+                }
+        }
+
+	bno = ext2_mapsearch(fs, bbp, bpref);
+	if (bno < 0)
+		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);
+}
+
+/*
+ * Check bpref is in the reservation window.
+ */
+static int
+ext2_bpref_in_rsv(struct ext2_rsv_win *rp, int32_t bpref)
+{
+        if (bpref >= 0 && (bpref < rp->rsv_start || bpref > rp->rsv_end))
+                return (0);
+
+        return (1);
+}
+
+/*
+ * Search a tree node from RB tree. It includes the bpref or
+ * the previous one if bpref is not in any window.
+ */
+static struct ext2_rsv_win *
+ext2_search_rsv(struct ext2_rsv_win_tree *root, int32_t start)
+{
+        struct ext2_rsv_win *prev, *next;
+
+        if (RB_EMPTY(root))
+                return (NULL);
+
+        next = RB_ROOT(root);
+        do {
+                prev = next;
+                if (start < next->rsv_start)
+                        next = RB_LEFT(next, rsv_link);
+                else if (start > next->rsv_end)
+                        next = RB_RIGHT(next, rsv_link);
+                else
+                        return (next);
+        } while (next != NULL);
+
+        if (prev->rsv_start > start) {
+                next = RB_PREV(ext2_rsv_win_tree, root, prev);
+                if (next != NULL)
+                        prev = next;
+        }
+
+        return (prev);
+}
+
+/*
+ * Find a reservation window by given range from start to
+ * the end of this cylinder group.
+ */
+static int
+ext2_find_rsv(struct ext2_rsv_win *search, struct ext2_rsv_win *rp,
+    struct m_ext2fs *fs, int32_t start, int cg)
+{
+        struct ext2_rsv_win *rsv, *prev;
+        int32_t cur;
+        int size = rp->rsv_goal_size;
+
+        if (search == NULL) {
+                rp->rsv_start = start & ~7;
+                rp->rsv_end = start + size - 1;
+                rp->rsv_alloc_hit = 0;
+
+                RB_INSERT(ext2_rsv_win_tree, fs->e2fs_rsv_tree, rp);
+
+                return (0);
+        }
+
+        /*
+         * Make the start of reservation window byte-aligned
+         * in order to can find a free block with bit operations
+         * in the ext2_search_next_block() function.
+         */
+        cur = start & ~7;
+        rsv = search;
+        prev = NULL;
+
+        while (1) {
+                if (cur <= rsv->rsv_end)
+                        cur = rsv->rsv_end + 1;
+
+                if (dtog(fs, cur) != cg)
+                        return (-1);
+
+                prev = rsv;
+                rsv = RB_NEXT(ext2_rsv_win_tree, fs->e2fs_rsv_tree, rsv);
+
+                if (rsv == NULL)
+                        break;
+
+                if (cur + size <= rsv->rsv_start)
+                        break;
+        }
+
+        if (prev != rp && rp->rsv_end != EXT2_RSV_NOT_ALLOCATED)
+                ext2_remove_rsv_win(fs, rp);
+
+        rp->rsv_start = cur;
+        rp->rsv_end = cur + size - 1;
+        rp->rsv_alloc_hit = 0;
+
+        if (prev != rp)
+                RB_INSERT(ext2_rsv_win_tree, fs->e2fs_rsv_tree, rp);
+
+        return (0);
+}
+
+/*
+ * Find a free block by given range from bpref to
+ * the end of this cylinder group.
+ */
+static daddr_t
+ext2_search_next_block(struct m_ext2fs *fs, char *bbp, int bpref, int cg)
+{
+        daddr_t bno;
+        int start, loc, len, map, i;
+
+        start = bpref / NBBY;
+        len = howmany(fs->e2fs->e2fs_fpg, NBBY) - start;
+        loc = skpc(0xff, len, &bbp[start]);
+        if (loc == 0)
+                return (-1);
+
+        i = start + len - loc;
+        map = bbp[i];
+        bno = i * NBBY;
+        for (i = 1; i < (1 << NBBY); i <<= 1, bno++) {
+                if ((map & i) == 0)
+                        return (bno);
+        }
+
+        return (-1);
+}
+
+/*
+ * Allocate a new reservation window.
+ */
+static int
+ext2_alloc_new_rsv(struct inode *ip, int cg, struct buf *bp, int32_t bpref)
+{
+        struct m_ext2fs *fs;
+        struct ext2_rsv_win *rp, *search;
+        char *bbp;
+        int start, size, ret;
+
+        fs = ip->i_e2fs;
+        rp = ip->i_rsv;
+        bbp = bp->b_data;
+        size = rp->rsv_goal_size;
+
+        if (bpref <= 0)
+                start = cg * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock;
+        else
+                start = bpref;
+
+        /* Dynamically increase the size of window */
+        if (rp->rsv_end != EXT2_RSV_NOT_ALLOCATED) {
+                if (rp->rsv_alloc_hit >
+                    ((rp->rsv_end - rp->rsv_start + 1) / 2)) {
+                        size = size * 2;
+                        if (size > EXT2_RSV_MAX_RESERVE_BLKS)
+                                size = EXT2_RSV_MAX_RESERVE_BLKS;
+                        rp->rsv_goal_size = size;
+                }
+        }
+
+        EXT2_TREE_LOCK(fs);
+
+        search = ext2_search_rsv(fs->e2fs_rsv_tree, start);
+
+repeat:
+        ret = ext2_find_rsv(search, rp, fs, start, cg);
+        if (ret < 0) {
+                if (rp->rsv_end != EXT2_RSV_NOT_ALLOCATED)
+                        ext2_remove_rsv_win(fs, rp);
+                EXT2_TREE_UNLOCK(fs);
+                return (-1);
+        }
+        EXT2_TREE_UNLOCK(fs);
+
+        start = dtogd(fs, rp->rsv_start);
+        start = ext2_search_next_block(fs, bbp, start, cg);
+        if (start < 0) {
+                EXT2_TREE_LOCK(fs);
+                if (rp->rsv_end != EXT2_RSV_NOT_ALLOCATED)
+                        ext2_remove_rsv_win(fs, rp);
+                EXT2_TREE_UNLOCK(fs);
+                return (-1);
+        }
+
+        start = cg * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock + start;
+        if (start >= rp->rsv_start && start <= rp->rsv_end)
+                return (0);
+
+        search = rp;
+        EXT2_TREE_LOCK(fs);
+        goto repeat;
+}
+
+/*
+ * 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;
+        int ret;
+
+        rp = ip->i_rsv;
+        if (rp == NULL)
+                return (ext2_alloc_blk(ip, cg, bp, bpref, NULL));
+
+        if (rp->rsv_end == EXT2_RSV_NOT_ALLOCATED ||
+            !ext2_bpref_in_rsv(rp, bpref)) {
+                ret = ext2_alloc_new_rsv(ip, cg, bp, bpref);
+                if (ret < 0)
+                        return (0);
+        }
+
+        return (ext2_alloc_blk(ip, cg, bp, bpref, rp));
+}
+
+/*
+ * Allocate a block using reservation window in ext2 file system.
+ */
+int
+ext2_prealloc(struct inode *ip, int32_t lbn, int32_t bpref,
+    int size, struct ucred *cred)
+{
+	struct m_ext2fs *fs;
+	struct ext2mount *ump;
+        struct buf *bp;
+	int32_t bno = 0;
+	int i, cg, error;
+
+	fs = ip->i_e2fs;
+	ump = ip->i_ump;
+	mtx_assert(EXT2_MTX(ump), MA_OWNED);
+
+	if (size == fs->e2fs_bsize && fs->e2fs->e2fs_fbcount == 0)
+		goto fail;
+	if (cred->cr_uid != 0 && 
+	    fs->e2fs->e2fs_fbcount < fs->e2fs->e2fs_rbcount)
+		goto fail;
+
+	if (bpref >= fs->e2fs->e2fs_bcount)
+		bpref = 0;
+	if (bpref == 0)
+		cg = ino_to_cg(fs, ip->i_number);
+	else
+		cg = dtog(fs, bpref);
+
+        /* 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 fail;
+                }
+
+                EXT2_RSV_LOCK(ip);
+                /* Try to allocate from reservation window */
+                bno = ext2_rsvalloc(fs, ip, cg, bp, bpref, size);
+                EXT2_RSV_UNLOCK(ip);
+                if (bno > 0)
+                        goto allocated;
+
+                brelse(bp);
+                EXT2_LOCK(ump);
+        }
+
+        /* Just need to try to allocate a free block from rest groups. */
+        cg = (cg + 1) % fs->e2fs_gcount;
+        for (i = 1; i < fs->e2fs_gcount; i++) {
+                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 fail;
+                        }
+
+                        EXT2_RSV_LOCK(ip);
+                        bno = ext2_rsvalloc(fs, ip, cg, bp, -1, size);
+                        EXT2_RSV_UNLOCK(ip);
+                        if (bno > 0)
+                                goto allocated;
+
+                        brelse(bp);
+                        EXT2_LOCK(ump);
+                }
+
+                cg++;
+                if (cg == fs->e2fs_gcount)
+                        cg = 0;
+        }
+
+allocated:
+        if (bno > 0)
+                return (bno);
+
+fail:
+	return (0);
+}
+
+/*
+ * Find a block in the specified cylinder group.
+ */
+static daddr_t
+ext2_mapsearch(struct m_ext2fs *fs, char *bbp, daddr_t bpref)
+{
+	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(fs, bpref) / NBBY;
+	else
+		start = 0;
+	len = howmany(fs->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)
+			return (-1);
+	}
+	i = start + len - loc;
+	map = bbp[i] ^ 0xff;
+	if (map == 0) {
+		printf("fs = %s\n", fs->e2fs_fsmnt);
+		panic("ext2fs_mapsearch: block not in map");
+	}
+	return (i * NBBY + ffs(map) - 1);
+}
+
+/*
  * Remove a ext2_rsv_win structure from RB tree.
  */
 void


More information about the p4-projects mailing list