Date: Sun, 22 Aug 2010 05:31:17 GMT From: Zheng Liu <lz@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 182714 for review Message-ID: <201008220531.o7M5VHFn012716@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@182714?ac=10 Change 182714 by lz@gnehzuil-freebsd on 2010/08/22 05:30:17 Recovery changelist @182462. Affected files ... .. //depot/projects/soc2010/ext4fs/src/sys/fs/ext2fs/ext2_alloc.c#4 edit .. //depot/projects/soc2010/ext4fs/src/sys/fs/ext2fs/ext2_balloc.c#4 edit .. //depot/projects/soc2010/ext4fs/src/sys/fs/ext2fs/ext2_inode.c#5 edit .. //depot/projects/soc2010/ext4fs/src/sys/fs/ext2fs/ext2_vfsops.c#12 edit .. //depot/projects/soc2010/ext4fs/src/sys/fs/ext2fs/ext2fs.h#9 edit .. //depot/projects/soc2010/ext4fs/src/sys/fs/ext2fs/inode.h#7 edit Differences ... ==== //depot/projects/soc2010/ext4fs/src/sys/fs/ext2fs/ext2_alloc.c#4 (text+ko) ==== @@ -50,7 +50,11 @@ #include <fs/ext2fs/ext2fs.h> #include <fs/ext2fs/fs.h> #include <fs/ext2fs/ext2_extern.h> +#include <fs/ext2fs/ext2_rsv_win.h> +/* Just for clear */ +#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 *); @@ -59,38 +63,520 @@ int)); static daddr_t ext2_nodealloccg(struct inode *, int, daddr_t, int); static daddr_t ext2_mapsearch(struct m_ext2fs *, char *, daddr_t); + +/* 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 void ext2_remove_rsv_win(struct m_ext2fs *, struct ext2_rsv_win *); +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); + /* * Allocate a block in the file system. * - * A preference may be optionally specified. If a preference is given - * the following hierarchy is used to allocate a block: - * 1) allocate the requested block. - * 2) allocate a rotationally optimal block in the same cylinder. - * 3) allocate a block in the same cylinder group. - * 4) quadradically rehash into other cylinder groups, until an - * available block is located. - * If no block preference is given the following hierarchy is used - * to allocate a block: - * 1) allocate a block in the cylinder group that contains the - * inode for the file. - * 2) quadradically rehash into other cylinder groups, until an - * available block is located. + * By given preference: + * It checks whether inode has a reservation window and preference + * is within it. If so, it will try to allocate a free block from + * this reservation window. + * Otherwise, it traverses RB tree to find a place, which is not + * in any window. then it inserts it to RB tree and tries to allocate + * a free block again. + * If fails, it will try to allocate a free block in other cylinder + * groups without perference. + */ + +/* + * Allocate a free block. + * + * Firstly it checks whether reservation window is used. + * If it use reservation window, it will try to allocate a free + * block from the reservation window. If failed, it will traverse + * the bitmap to find a free block. + * If it not use reservation window, it will try to allocate + * a free block by bpref. If failed, it will 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_lo == 0) + return (0); + + if (bpref < 0) + bpref = 0; + + /* Check whther it use reservation window */ + if (rp != NULL) { + /* + * If window's start is not in this cylinder group, + * try to allocate from the beginning of this group. + * Otherwise, try to allocate from the beginning of + * the window. + */ + if (dtog(fs, rp->rsv_start) != cg) + start = phy_blk(cg, fs); + else + start = rp->rsv_start; + + /* + * If window's end cross the end of this group, + * set end variable to the end of this group. + * Otherwise, set it to window's end. + */ + if (dtog(fs, rp->rsv_end) != cg) + end = fs->e2fs->e2fs_fpg; + 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 + bpref = dtogd(fs, rp->rsv_start); + } 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_lo--; + fs->e2fs_gd[cg].ext2bgd_nbfree_lo--; + fs->e2fs_fmod = 1; + EXT2_UNLOCK(ump); + bdwrite(bp); + bno = phy_blk(cg, fs) + bno; + ip->i_next_alloc_goal = bno; + return (bno); +} + +/* + * Initialize reservation window per inode. + */ +void +ext2_init_rsv(struct inode *ip) +{ + struct ext2_rsv_win *rp; + + 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 (rp == NULL) + return; + + rp->rsv_start = EXT2_RSV_NOT_ALLOCATED; + rp->rsv_end = EXT2_RSV_NOT_ALLOCATED; + + rp->rsv_goal_size = EXT2_RSV_DEFAULT_RESERVE_BLKS; + rp->rsv_alloc_hit = 0; + + ip->i_rsv = rp; +} + +/* + * Discard reservation window. + * + * It is called at following locations: + * 1. free an inode + * 2. sync inode + * 3. truncate a file + */ +void +ext2_discard_rsv(struct inode *ip) +{ + struct ext2_rsv_win *rp; + + if (ip->i_rsv == NULL) + return; + + rp = ip->i_rsv; + + /* If reservation window is empty, nothing to do */ + if (rp->rsv_end == EXT2_RSV_NOT_ALLOCATED) + return; + + EXT2_TREE_LOCK(ip->i_e2fs); + ext2_remove_rsv_win(ip->i_e2fs, rp); + EXT2_TREE_UNLOCK(ip->i_e2fs); + rp->rsv_goal_size = EXT2_RSV_DEFAULT_RESERVE_BLKS; +} + +/* + * Remove a ext2_rsv_win structure from RB tree. + */ +static void +ext2_remove_rsv_win(struct m_ext2fs *fs, struct ext2_rsv_win *rp) +{ + RB_REMOVE(ext2_rsv_win_tree, &fs->e2fs_rsv_tree, rp); + rp->rsv_start = EXT2_RSV_NOT_ALLOCATED; + rp->rsv_end = EXT2_RSV_NOT_ALLOCATED; + rp->rsv_alloc_hit = 0; +} + +/* + * 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 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. * - * A preference may be optionally specified. If a preference is given - * the following hierarchy is used to allocate a block: - * 1) allocate the requested block. - * 2) allocate a rotationally optimal block in the same cylinder. - * 3) allocate a block in the same cylinder group. - * 4) quadradically rehash into other cylinder groups, until an - * available block is located. - * If no block preference is given the following hierarchy is used - * to allocate a block: - * 1) allocate a block in the cylinder group that contains the - * inode for the file. - * 2) quadradically rehash into other cylinder groups, until an - * available block is located. + * NOTE: This function will replace the ext2_alloc() function. */ +int +ext2_alloc_rsv(struct inode *ip, int32_t lbn, int32_t bpref, + int size, struct ucred *cred, int32_t *bnp) +{ + struct m_ext2fs *fs; + struct ext2mount *ump; + struct buf *bp; + int32_t bno = 0; + int i, cg, error; + + *bnp = 0; + fs = ip->i_e2fs; + ump = ip->i_ump; + mtx_assert(EXT2_MTX(ump), MA_OWNED); + + if (size == fs->e2fs_bsize && fs->e2fs->e2fs_fbcount_lo == 0) + goto nospace; + if (cred->cr_uid != 0 && + fs->e2fs->e2fs_fbcount_lo < fs->e2fs->e2fs_rbcount_lo) + goto nospace; + + if (bpref >= fs->e2fs->e2fs_bcount_lo) + 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_lo > 0) { + /* Read block bitmap from buffer */ + EXT2_UNLOCK(ump); + error = bread(ip->i_devvp, + fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap_lo), + (int)fs->e2fs_bsize, NOCRED, &bp); + if (error) { + brelse(bp); + goto ioerror; + } + + 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_lo > 0) { + /* Read block bitmap from buffer */ + EXT2_UNLOCK(ump); + error = bread(ip->i_devvp, + fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap_lo), + (int)fs->e2fs_bsize, NOCRED, &bp); + if (error) { + brelse(bp); + goto ioerror; + } + + 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) { + ip->i_blocks += btodb(fs->e2fs_bsize); + ip->i_flag |= IN_CHANGE | IN_UPDATE; + *bnp = bno; + return (0); + } + +nospace: + EXT2_UNLOCK(ump); + ext2_fserr(fs, cred->cr_uid, "file system full"); + uprintf("\n%s: write failed, file system is full\n", fs->e2fs_fsmnt); + return (ENOSPC); + +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; +} + int ext2_alloc(ip, lbn, bpref, size, cred, bnp) struct inode *ip; @@ -146,7 +632,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 @@ -923,9 +1409,11 @@ start = 0; loc = skpc(0xff, len, &bbp[start]); if (loc == 0) { - printf("start = %d, len = %d, fs = %s\n", - start, len, fs->e2fs_fsmnt); - panic("ext2fs_alloccg: map corrupted"); + /* XXX: just for reservation window */ + return -1; + /*printf("start = %d, len = %d, fs = %s\n",*/ + /*start, len, fs->e2fs_fsmnt);*/ + /*panic("ext2fs_alloccg: map corrupted");*/ /* NOTREACHED */ } } ==== //depot/projects/soc2010/ext4fs/src/sys/fs/ext2fs/ext2_balloc.c#4 (text+ko) ==== @@ -49,6 +49,7 @@ #include <fs/ext2fs/fs.h> #include <fs/ext2fs/ext2_extern.h> #include <fs/ext2fs/ext2_mount.h> +#include <fs/ext2fs/ext2_rsv_win.h> /* * Balloc defines the structure of file system storage * by allocating the physical blocks on a device given @@ -136,9 +137,14 @@ else nsize = fs->e2fs_bsize; EXT2_LOCK(ump); +/* error = ext2_alloc(ip, lbn, ext2_blkpref(ip, lbn, (int)lbn, &ip->i_db[0], 0), nsize, cred, &newb); +*/ + error = ext2_alloc_rsv(ip, lbn, + ext2_blkpref(ip, lbn, (int)lbn, &ip->i_db[0], 0), + nsize, cred, &newb); if (error) return (error); bp = getblk(vp, lbn, nsize, 0, 0, 0); @@ -170,9 +176,14 @@ EXT2_LOCK(ump); pref = ext2_blkpref(ip, lbn, indirs[0].in_off + EXT2_NDIR_BLOCKS, &ip->i_db[0], 0); +/* if ((error = ext2_alloc(ip, lbn, pref, (int)fs->e2fs_bsize, cred, &newb))) return (error); +*/ + if ((error = ext2_alloc_rsv(ip, lbn, pref, + (int)fs->e2fs_bsize, cred, &newb))) + return (error); nb = newb; bp = getblk(vp, indirs[1].in_lbn, fs->e2fs_bsize, 0, 0, 0); bp->b_blkno = fsbtodb(fs, newb); @@ -211,7 +222,10 @@ if (pref == 0) pref = ext2_blkpref(ip, lbn, indirs[i].in_off, bap, bp->b_lblkno); +/* error = ext2_alloc(ip, lbn, pref, (int)fs->e2fs_bsize, cred, &newb); +*/ + error = ext2_alloc_rsv(ip, lbn, pref, (int)fs->e2fs_bsize, cred, &newb); if (error) { brelse(bp); return (error); @@ -250,11 +264,18 @@ EXT2_LOCK(ump); pref = ext2_blkpref(ip, lbn, indirs[i].in_off, &bap[0], bp->b_lblkno); +/* if ((error = ext2_alloc(ip, lbn, pref, (int)fs->e2fs_bsize, cred, &newb)) != 0) { brelse(bp); return (error); } +*/ + if ((error = ext2_alloc_rsv(ip, lbn, pref, + (int)fs->e2fs_bsize, cred, &newb)) != 0) { + brelse(bp); + return (error); + } nb = newb; nbp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0, 0); nbp->b_blkno = fsbtodb(fs, nb); ==== //depot/projects/soc2010/ext4fs/src/sys/fs/ext2fs/ext2_inode.c#5 (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 *); @@ -154,6 +155,10 @@ fs = oip->i_e2fs; osize = oip->i_size; + EXT2_RSV_LOCK(oip); + ext2_discard_rsv(oip); + EXT2_RSV_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_RSV_LOCK(ip); + ext2_discard_rsv(ip); + EXT2_RSV_UNLOCK(ip); + /* * Ignore inodes related to stale file handles. */ @@ -533,6 +542,14 @@ } vfs_hash_remove(vp); + EXT2_RSV_LOCK(ip); + if (ip->i_rsv != NULL) { + free(ip->i_rsv, M_EXT2NODE); + ip->i_rsv = NULL; + } + EXT2_RSV_UNLOCK(ip); + mtx_destroy(&ip->i_rsv_lock); + mtx_destroy(&ip->i_ext_lock); free(vp->v_data, M_EXT2NODE); ==== //depot/projects/soc2010/ext4fs/src/sys/fs/ext2fs/ext2_vfsops.c#12 (text+ko) ==== @@ -98,8 +98,6 @@ int ronly); static int compute_sb_data(struct vnode * devvp, struct ext2fs * es, struct m_ext2fs * fs); -static int ext4_init_fg(struct m_ext2fs *); -static int find_most_set_bit(int64_t n); static const char *ext2_opts[] = { "from", "export", "acls", "noexec", "noatime", "union", "suiddir", "multilabel", "nosymfollow", @@ -355,7 +353,6 @@ fs->e2fs_ipb = fs->e2fs_bsize / EXT2_INODE_SIZE(fs); fs->e2fs_itpg = fs->e2fs_ipg /fs->e2fs_ipb; fs->e2fs_descpb = fs->e2fs_bsize / sizeof (struct ext2_gd); - fs->e2fs_descpbbits = find_most_set_bit(fs->e2fs_descpb); /* s_resuid / s_resgid ? */ fs->e2fs_gcount = (((int64_t)(es->e2fs_bcount_hi) << 32 | es->e2fs_bcount_lo) - es->e2fs_first_dblock + EXT2_BLOCKS_PER_GROUP(fs) - 1) / @@ -392,9 +389,6 @@ bp = NULL; } - /* initialize flex groups */ - ext4_init_fg(fs); - fs->e2fs_total_dir = 0; for (i=0; i < fs->e2fs_gcount; i++){ fs->e2fs_total_dir += (fs->e2fs_gd[i].ext2bgd_ndirs_lo); @@ -427,71 +421,6 @@ } /* - * Initialize flex groups data structure. - */ -static int -ext4_init_fg(struct m_ext2fs *fs) -{ - struct ext2fs *es = fs->e2fs; - int i, gpf = 0; - unsigned int fgcount, fg; - long nifree, nbfree, ndirs; - - fs->e2fs_log_gpf = es->e2fs_log_gpf; - gpf = 1 << fs->e2fs_log_gpf; - - if (gpf < 2) { - fs->e2fs_log_gpf = 0; - return (0); - } - - fgcount = ((fs->e2fs_gcount + gpf - 1) + - ((es->e2fs_reserved_ngdb + 1) << fs->e2fs_descpbbits)) / gpf; - - fs->e2fs_fg = malloc(fgcount * sizeof(struct ext4_flex_groups), - M_EXT2MNT, M_WAITOK | M_ZERO); - - for (i = 0; i < fs->e2fs_gcount; i++) { - nifree = 0; - nbfree = 0; - ndirs = 0; - fg = i >> fs->e2fs_log_gpf; - - /* XXX: need to support 64 bits. */ - nifree = fs->e2fs_gd[i].ext2bgd_nifree_lo; - nbfree = fs->e2fs_gd[i].ext2bgd_nbfree_lo; - ndirs = fs->e2fs_gd[i].ext2bgd_ndirs_lo; - - atomic_add_long(&fs->e2fs_fg[fg].e2fg_nifree, nifree); - atomic_add_long(&fs->e2fs_fg[fg].e2fg_nbfree, nbfree); - atomic_add_long(&fs->e2fs_fg[fg].e2fg_ndirs, ndirs); - } - - return (0); -} - -/* - * Find most significant set bit. - * - * TODO: Maybe it need to rewrite by assembly language for - * improving the performance. - */ -static int -find_most_set_bit(int64_t n) -{ - int64_t num, i; - unsigned int pos, res = 0; - - for (num = 1; num <= n; num++) { - for (i = (num >> 1), pos = 0; i != 0; pos++) - i >>= 1; - res = pos; - } - - return res; -} - -/* * Reload all incore data for a filesystem (used after running fsck on * the root filesystem and finding things to fix). The filesystem must * be mounted read-only. @@ -775,7 +704,6 @@ g_topology_unlock(); PICKUP_GIANT(); vrele(ump->um_devvp); - free(fs->e2fs_fg, M_EXT2MNT); free(fs->e2fs_gd, M_EXT2MNT); free(fs->e2fs_contigdirs, M_EXT2MNT); free(fs->e2fs, M_EXT2MNT); ==== //depot/projects/soc2010/ext4fs/src/sys/fs/ext2fs/ext2fs.h#9 (text+ko) ==== @@ -92,15 +92,6 @@ */ #define MAXMNTLEN 512 -/* ext4 flex block group data structure */ -struct ext4_flex_groups { - long e2fg_nifree; - long e2fg_nbfree; - long e2fg_ndirs; -}; - -#define EXT4_FLEX_ALLOC_DIR_SIZE 4 - /* * Super block for an ext2fs file system. */ @@ -214,10 +205,6 @@ off_t e2fs_maxfilesize; struct ext2_gd *e2fs_gd; /* Group Descriptors */ - u_int8_t e2fs_log_gpf; /* FLEX_BG group size */ - int e2fs_descpbbits; - struct ext4_flex_groups *e2fs_fg; - u_int16_t e2fs_min_extra_isize; /* all inodes have at least some bytes */ u_int16_t e2fs_want_extra_isize; /* new inodes should reserve some bytes */ }; ==== //depot/projects/soc2010/ext4fs/src/sys/fs/ext2fs/inode.h#7 (text+ko) ==== @@ -43,6 +43,7 @@ #include <sys/mutex.h> #include <sys/queue.h> +#include <fs/ext2fs/ext2_rsv_win.h> #include <fs/ext2fs/ext2_extents.h> #define ROOTINO ((ino_t)2) @@ -105,6 +106,10 @@ u_int32_t i_uid; /* File owner. */ u_int32_t i_gid; /* File group. */ + /* reservation window */ + struct mtx i_rsv_lock; /* Protects i_rsv */ + struct ext2_rsv_win *i_rsv; /* Reservation window */ + /* ext4 extents support */ struct mtx i_ext_lock; /* this lock only is required in read/write mode but we still use it in read-only mode. */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201008220531.o7M5VHFn012716>