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