Date: Tue, 26 Apr 2011 02:45:51 GMT From: Zheng Liu <lz@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 192115 for review Message-ID: <201104260245.p3Q2jplp061446@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@192115?ac=10 Change 192115 by lz@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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201104260245.p3Q2jplp061446>