Date: Sat, 8 May 2010 08:03:56 GMT From: Zheng Liu <lz@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 177944 for review Message-ID: <201005080803.o4883uJr055199@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@177944?ac=10 Change 177944 by lz@gnehzuil-freebsd on 2010/05/08 08:03:55 Add some allocation functions. Affected files ... .. //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_alloc.c#4 edit Differences ... ==== //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_alloc.c#4 (text+ko) ==== @@ -62,6 +62,11 @@ static daddr_t ext2_mapsearch(struct m_ext2fs *, char *, daddr_t); static void ext2_rsv_win_remove(struct m_ext2fs *, struct ext2_rsv_win *); +static int ext2_in_rsv(struct ext2_rsv_win *, int32_t); +static u_long ext2_try_alloc_rsv(struct ext2_rsv_win *rwp, struct inode *, int, int32_t, int, + daddr_t (*allocator)(struct inode *, int, daddr_t, int)); +static daddr_t ext2_alloccg_rsv(struct inode *, int, daddr_t, int); +static int ext2_alloc_new_rsv(struct ext2_rsv_win *, struct m_ext2fs *, int, int32_t); RB_GENERATE(ext2_rsv_win_tree, ext2_rsv_win, rw_link, ext2_rsv_win_cmp); @@ -138,6 +143,97 @@ } /* + * Check bpref in reservation window. + */ +static int +ext2_in_rsv(struct ext2_rsv_win *rwp, int32_t bpref) +{ + if (bpref < rwp->rw_start || + bpref > rwp->rw_end) + return 0; + + return 1; +} + +/* + * Determine whether a block can be allocated. + * + * Check to see if a block of the appropriate size is available, + * and if it is, allocate it. + */ +static daddr_t +ext2_alloccg_rsv(struct inode *ip, int cg, daddr_t bpref, int size) +{ + struct m_ext2fs *fs; + struct buf *bp; + struct ext2mount *ump; + int error, bno; + char *bbp; + + fs = ip->i_e2fs; + ump = ip->i_ump; + if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0) + return (0); + EXT2_UNLOCK(ump); + error = bread(ip->i_devvp, fsbtodb(fs, + fs->e2fs_gd[cg].ext2bgd_b_bitmap), + (int)fs->e2fs_bsize, NOCRED, &bp); + if (error) { + brelse(bp); + EXT2_LOCK(ump); + return (0); + } + bbp = (char *)bp->b_data; + + if (dtog(fs, bpref) != cg) + bpref = 0; + if (bpref != 0) { + bpref = dtogd(fs, bpref); + /* + * if the requested block is available, use it + */ + if (isclr(bbp, bpref)) { + bno = bpref; + goto gotit; + } + } + + brelse(bp); + EXT2_LOCK(ump); + return (0); + +gotit: + setbit(bbp, (daddr_t)bno); + EXT2_LOCK(ump); + fs->e2fs->e2fs_fbcount--; + fs->e2fs_gd[cg].ext2bgd_nbfree--; + fs->e2fs_fmod = 1; + EXT2_UNLOCK(ump); + bdwrite(bp); + return (cg * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock + bno); +} + +/* + * Allocate a block in reservation window. + */ +static u_long +ext2_try_alloc_rsv(struct ext2_rsv_win *rwp, struct inode *ip, int cg, int32_t bpref, int size, + daddr_t (*allocator)(struct inode *, int, daddr_t, int)) +{ + mtx_assert(EXT2_MTX(ip->i_ump), MA_OWNED); + return (*allocator)(ip, cg, bpref, size); +} + +/* + * Allocate a new reservation window. + */ +static int +ext2_alloc_new_rsv(struct ext2_rsv_win *rwp, struct m_ext2fs *sbp, int cg, int32_t bpref) +{ + return -1; +} + +/* * Allocate a block using reservation window in ext2 file system. */ int @@ -146,40 +242,48 @@ { struct m_ext2fs *fs; struct ext2mount *ump; + struct ext2_rsv_win_info *rwip; int32_t bno; - int cg; + int cg, ret; + *bnp = 0; fs = ip->i_e2fs; ump = ip->i_ump; + rwip = ip->i_rsv_winp; mtx_assert(EXT2_MTX(ump), MA_OWNED); -#ifdef DIAGNOSTIC - if ((u_int)size > fs->e2fs_bsize || blkoff(fs, size) != 0) { - vn_printf(ip->i_devvp, "bsize = %lu, size = %d, fs = %s\n", - (long unsigned int)fs->e2fs_bsize, size, fs->e2fs_fsmnt); - panic("ext2_alloc: bad size"); - } - if (cred == NOCRED) - panic("ext2_alloc: missing credential"); -#endif /* DIAGNOSTIC */ + if (size == fs->e2fs_bsize && fs->e2fs->e2fs_fbcount == 0) goto nospace; if (cred->cr_uid != 0 && - fs->e2fs->e2fs_fbcount < fs->e2fs->e2fs_rbcount) + fs->e2fs->e2fs_fbcount < fs->e2fs->e2fs_rbcount) goto nospace; + if (bpref >= fs->e2fs->e2fs_bcount) bpref = 0; - if (bpref == 0) - cg = ino_to_cg(fs, ip->i_number); - else - cg = dtog(fs, bpref); - bno = (daddr_t)ext2_hashalloc(ip, cg, bpref, fs->e2fs_bsize, - ext2_alloccg); - if (bno > 0) { - ip->i_blocks += btodb(fs->e2fs_bsize); - ip->i_flag |= IN_CHANGE | IN_UPDATE; - *bnp = bno; - return (0); - } + if (bpref == 0) + cg = ino_to_cg(fs, ip->i_number); + else + cg = dtog(fs, bpref); + + /* If bpref is in reservation window and window has free block, then alloc it. + * Otherwise, try to allocate a new reservation window. + */ + if (rwip->rwi_entry.rw_end == EXT2_RWI_NOT_ALLOCATED || + !ext2_in_rsv(&rwip->rwi_entry, bpref)) { + ret = ext2_alloc_new_rsv(&rwip->rwi_entry, fs, cg, bpref); + } else { + bno = ext2_try_alloc_rsv(&rwip->rwi_entry, + ip, cg, bpref, size, ext2_alloccg_rsv); + } + + bno = (daddr_t)ext2_hashalloc(ip, cg, bpref, fs->e2fs_bsize, + ext2_alloccg); + 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");
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201005080803.o4883uJr055199>