From owner-p4-projects@FreeBSD.ORG Sat May 8 08:03:56 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 7A73B1065673; Sat, 8 May 2010 08:03:56 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 3F142106566B for ; Sat, 8 May 2010 08:03:56 +0000 (UTC) (envelope-from lz@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.freebsd.org (Postfix) with ESMTP id 2D15A8FC0A for ; Sat, 8 May 2010 08:03:56 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id o4883ucW055201 for ; Sat, 8 May 2010 08:03:56 GMT (envelope-from lz@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id o4883uJr055199 for perforce@freebsd.org; Sat, 8 May 2010 08:03:56 GMT (envelope-from lz@FreeBSD.org) Date: Sat, 8 May 2010 08:03:56 GMT Message-Id: <201005080803.o4883uJr055199@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to lz@FreeBSD.org using -f From: Zheng Liu To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 177944 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 08 May 2010 08:03:56 -0000 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");