From owner-p4-projects@FreeBSD.ORG Fri May 14 04:16:20 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 54E7E1065678; Fri, 14 May 2010 04:16:20 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 10A65106566C for ; Fri, 14 May 2010 04:16:20 +0000 (UTC) (envelope-from lz@FreeBSD.org) Received: from repoman.freebsd.org (unknown [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id F1D6D8FC1D for ; Fri, 14 May 2010 04:16:19 +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 o4E4GJrW025527 for ; Fri, 14 May 2010 04:16:19 GMT (envelope-from lz@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id o4E4GJ09025525 for perforce@freebsd.org; Fri, 14 May 2010 04:16:19 GMT (envelope-from lz@FreeBSD.org) Date: Fri, 14 May 2010 04:16:19 GMT Message-Id: <201005140416.o4E4GJ09025525@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 178234 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: Fri, 14 May 2010 04:16:20 -0000 http://p4web.freebsd.org/@@178234?ac=10 Change 178234 by lz@gnehzuil-freebsd on 2010/05/14 04:16:10 Implement reservation window mechanism. * Algorithm: 1. When a file need to allocate a block with a uninitialized reservation window, we will first initialize this file's reservation window, try to allocate a window and add it to rb tree according to bpref. Then allocate a block. 2. If a file which has a window, then we will ignore bpref and try to allocate a block according to window's start and hit. 3. If a file's window has no free block, then window will be remove from rb tree and try to allocate a new window according to bpref. 4. If above attempts failed, we try to allocate using old hashalloc algorithm. * Problem: 1. dbench -D dir 4 and copy a large file, such as 600MB, it prints vm_fault. I think there are some errors in synchronization. * To be done: 1. Dynamically increase the window size. 2. Do not use old hashalloc algorithm when we try to allocate a block in reservation window. It just need to allocate a free block in other cylinder groups. Affected files ... .. //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_alloc.c#7 edit .. //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_balloc.c#4 edit .. //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_inode.c#3 edit .. //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_rsv_win.h#6 edit .. //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/inode.h#4 edit Differences ... ==== //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_alloc.c#7 (text+ko) ==== @@ -63,12 +63,16 @@ /* For reservation window */ static void ext2_add_rsv_win(struct m_ext2fs *, struct ext2_rsv_win *); -static int ext2_alloc_new_rsv(struct inode *, struct m_ext2fs *, int, int32_t, int); -static daddr_t ext2_alloccg_rsv(struct inode *, int, daddr_t, int); -static u_long ext2_mapsearch_rsv(struct m_ext2fs *, char *, daddr_t); -static int ext2_in_rsv(struct ext2_rsv_win *, int32_t); +static u_long ext2_alloc_blk(struct m_ext2fs *, struct inode *, int cg, + struct buf *, int32_t, struct ext2_rsv_win *); +static int ext2_alloc_new_rsv_win(struct inode *, struct ext2_rsv_win *, int32_t, + struct m_ext2fs *, int, struct buf *); +static int ext2_find_next_rsv_win(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 int ext2_search_rsv_win(struct inode *, struct m_ext2fs *, int, int32_t, int); +static u_long ext2_rsvalloc(struct m_ext2fs *, struct inode *, int, + struct buf *, int32_t, int); +struct ext2_rsv_win *ext2_search_rsv_win(struct ext2_rsv_win_tree *, int32_t); RB_GENERATE(ext2_rsv_win_tree, ext2_rsv_win, rw_link, ext2_rsv_win_cmp); @@ -79,28 +83,26 @@ * info structure will be initialized. */ void -ext2_init_rsv_win_info(struct inode *ip) +ext2_init_rsv(struct inode *ip) { - struct ext2_rsv_win *rwp; - struct ext2_rsv_win_info *rwip; + struct ext2_rsv_win *rp; - rwip = malloc(sizeof(struct ext2_rsv_win_info), - M_EXT2NODE, M_NOWAIT | M_ZERO); + 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 (rwip == NULL) + if (rp == NULL) return; - rwp = &rwip->rwi_entry; - rwp->rw_start = EXT2_RWI_NOT_ALLOCATED; - rwp->rw_end = EXT2_RWI_NOT_ALLOCATED; + rp->rw_start = EXT2_RWI_NOT_ALLOCATED; + rp->rw_end = EXT2_RWI_NOT_ALLOCATED; - rwp->rw_goal_size = EXT2_RWI_DEFAULT_RESERVE_BLKS; - rwp->rw_alloc_hit = 0; + rp->rw_goal_size = EXT2_RWI_DEFAULT_RESERVE_BLKS; + rp->rw_alloc_hit = 0; - ip->i_rsv_winp = rwip; + ip->i_rsv = rp; } /* @@ -112,186 +114,282 @@ * 3. truncate a file */ void -ext2_discard_rsv_win(struct inode *ip) +ext2_discard_rsv(struct inode *ip) { - struct ext2_rsv_win *rwp; + struct ext2_rsv_win *rp; /* do not use reservation window */ - if (ip->i_rsv_winp == NULL) - return; + if (ip->i_rsv == NULL) + return; + rp = ip->i_rsv; - rwp = &ip->i_rsv_winp->rwi_entry; - if (rwp->rw_end == EXT2_RWI_NOT_ALLOCATED) - /* reservation window is empty */ - return; + /* If reservation window is empty, nothing to do */ + if (rp->rw_end == EXT2_RWI_NOT_ALLOCATED) + return; - mtx_lock_spin(&ip->i_e2fs->e2fs_rsv_win_lock); - if (rwp->rw_end != EXT2_RWI_NOT_ALLOCATED) - ext2_remove_rsv_win(ip->i_e2fs, rwp); - mtx_unlock_spin(&ip->i_e2fs->e2fs_rsv_win_lock); + if (rp->rw_end != EXT2_RWI_NOT_ALLOCATED) + ext2_remove_rsv_win(ip->i_e2fs, rp); } /* * Add a ext2_rsv_win struct to RB tree. */ -static void ext2_add_rsv_win(struct m_ext2fs *sbp, struct ext2_rsv_win *rwp) +static void +ext2_add_rsv_win(struct m_ext2fs *fs, struct ext2_rsv_win *rp) { - RB_INSERT(ext2_rsv_win_tree, &sbp->e2fs_tree, rwp); + RB_INSERT(ext2_rsv_win_tree, &fs->e2fs_rsv_tree, rp); } /* * Remove a ext2_rsv_win structure from RB tree. */ static void -ext2_remove_rsv_win(struct m_ext2fs *sbp, struct ext2_rsv_win *rwp) +ext2_remove_rsv_win(struct m_ext2fs *fs, struct ext2_rsv_win *rp) { - rwp->rw_start = EXT2_RWI_NOT_ALLOCATED; - rwp->rw_end = EXT2_RWI_NOT_ALLOCATED; - rwp->rw_alloc_hit = 0; - RB_REMOVE(ext2_rsv_win_tree, &sbp->e2fs_tree, rwp); + rp->rw_start = EXT2_RWI_NOT_ALLOCATED; + rp->rw_end = EXT2_RWI_NOT_ALLOCATED; + rp->rw_alloc_hit = 0; + RB_REMOVE(ext2_rsv_win_tree, &fs->e2fs_rsv_tree, rp); } /* - * Check bpref in reservation window. + * Find a reservation window which can includes the bpref, + * or the previous one if bpref is not in any window. */ -static int -ext2_in_rsv(struct ext2_rsv_win *rwp, int32_t bpref) +struct ext2_rsv_win * +ext2_search_rsv_win(struct ext2_rsv_win_tree *root, int32_t bpref) { - if (bpref < rwp->rw_start || bpref > rwp->rw_end) - return 0; + struct ext2_rsv_win *next, *prev; + + next = RB_ROOT(root); + do { + prev = next; + if (bpref < next->rw_start) + next = RB_LEFT(next, rw_link); + else if (bpref > next->rw_end) + next = RB_RIGHT(next, rw_link); + else + return next; + } while(next != NULL); + + if (next == NULL || next->rw_start > bpref) + next = prev; - return 1; + return next; } /* - * Find a reservation window which includes bpref. + * Find a space to store a reservation window. */ static int -ext2_search_rsv_win(struct inode *ip, struct m_ext2fs *sbp, int cg, int32_t bpref, int size) +ext2_find_next_rsv_win(struct ext2_rsv_win *search, struct ext2_rsv_win *rp, + struct m_ext2fs *fs, int32_t bpref, int cg) { - struct buf *bp; - struct ext2mount *ump; - struct ext2_rsv_win *rwp; - int error; - char *bbp; + struct ext2_rsv_win *rsv, *prev, *next; + int32_t cur; + int size = EXT2_RWI_DEFAULT_RESERVE_BLKS; + + cur = bpref; + rsv = search; + prev = NULL; + if (search == NULL) + return -1; + + while (1) { + if (cur <= rsv->rw_end) + cur = rsv->rw_end + 1; - ump = ip->i_ump; - if (sbp->e2fs_gd[cg].ext2bgd_nbfree == 0) - return (0); - EXT2_UNLOCK(ump); - error = bread(ip->i_devvp, fsbtodb(sbp, - sbp->e2fs_gd[cg].ext2bgd_b_bitmap), - (int)sbp->e2fs_bsize, NOCRED, &bp); - if (error) { - brelse(bp); - EXT2_LOCK(ump); - return (0); - } + if (dtog(fs, cur) != cg) + return -1; - bbp = (char *)bp->b_data; + prev = rsv; + next = RB_NEXT(ext2_rsv_win_tree, &fs->e2fs_rsv_tree, rsv); + rsv = next; - mtx_lock_spin(&sbp->e2fs_rsv_win_lock); + if (next == NULL); + break; - /* If RB tree is empty, then it just need to search a free block and allocate it. - * else we need to traverse tree to find a space. - */ - if (RB_EMPTY(&sbp->e2fs_tree)) { - if (!ext2_mapsearch_rsv(sbp, bbp, bpref)) - goto failed; + if (cur + size <= rsv->rw_start) + break; + } - rwp = &ip->i_rsv_winp->rwi_entry; - rwp->rw_start = bpref; - rwp->rw_end = bpref + rwp->rw_goal_size - 1; - ext2_add_rsv_win(sbp, rwp); + if (prev != rp && rp->rw_end != EXT2_RWI_NOT_ALLOCATED) + ext2_remove_rsv_win(fs, rp); - goto success; - } else { - int32_t curr; - struct ext2_rsv_win *search; - struct ext2_rsv_win *prev; + rp->rw_start = cur; + rp->rw_end = cur + size - 1; + rp->rw_alloc_hit = 0; - search = RB_ROOT(&sbp->e2fs_tree); - do { - prev = search; - if (bpref < search->rw_start) - search = RB_LEFT(search, rw_link); - else if (bpref > search->rw_end) - search = RB_RIGHT(search, rw_link); - else - break; - } while (search); + if (prev != rp) { + ext2_add_rsv_win(fs, rp); + } - /* get bpref's previous reservation window */ - if (search == NULL) - search = prev; + return 0; +} - curr = bpref; - while (1) { - if (curr <= search->rw_end) - curr = search->rw_end + 1; +/* + * Try to allocate a new reservation window. + */ +static int +ext2_alloc_new_rsv_win(struct inode *ip, struct ext2_rsv_win *rp, int32_t bpref, + struct m_ext2fs *fs, int cg, struct buf *bp) +{ + struct ext2_rsv_win *search_rsv; + int size, ret; + int start, end, loc; + char *bbp; - if (curr > sbp->e2fs->e2fs_first_dblock + - cg * EXT2_BLOCKS_PER_GROUP(sbp)) - goto failed; + bbp = (char *)bp->b_data; + bpref = bpref; + size = rp->rw_goal_size; - search = RB_NEXT(ext2_rsv_win_tree, &sbp->e2fs_tree, search); + mtx_lock_spin(&fs->e2fs_rsv_lock); - /* reach the last reservation window */ - if (search == NULL) - break; + /* If tree is empty, then try to alloc according to bpref */ + if (RB_EMPTY(&fs->e2fs_rsv_tree)) { + mtx_unlock_spin(&fs->e2fs_rsv_lock); + /* bpref is not in this cylinder group. + * So try to allocate it in other group. + */ + if (dtog(fs, bpref) != cg) + return -1; + if (bpref != 0) { + bpref = dtogd(fs, bpref); + if (isclr(bbp, bpref)) + goto gotit; + } + if (bpref) + start = dtogd(fs, bpref) / NBBY; + else + start = 0; + end = howmany(fs->e2fs->e2fs_fpg, NBBY) - start; + for (loc = start; loc < end; loc++) { + if (bbp[loc] == 0) { + bpref = loc * NBBY; + goto gotit; + } + } - /* found a space */ - if (curr + size < search->rw_start) - break; - } + for (loc = start; loc < start; loc++) { + if (bbp[loc] == 0) { + bpref = loc * NBBY; + goto gotit; + } + } + } else { +repeat: + search_rsv = ext2_search_rsv_win(&fs->e2fs_rsv_tree, bpref); - if (!ext2_mapsearch_rsv(sbp, bbp, bpref)) - goto failed; + ret = ext2_find_next_rsv_win(search_rsv, rp, fs, bpref, cg); + if (ret < 0) { + if (rp->rw_end != EXT2_RWI_NOT_ALLOCATED) + ext2_remove_rsv_win(fs, rp); + mtx_unlock_spin(&fs->e2fs_rsv_lock); + return 0; + } + mtx_unlock_spin(&fs->e2fs_rsv_lock); - rwp = &ip->i_rsv_winp->rwi_entry; - rwp->rw_start = bpref; - rwp->rw_end = bpref + rwp->rw_goal_size - 1; - ext2_add_rsv_win(sbp, rwp); + if (isclr(bbp, bpref) && + bpref >= rp->rw_start && + bpref < rp->rw_end) + return 0; - goto success; - } + start = dtogd(fs, bpref) / NBBY; + end = howmany(fs->e2fs->e2fs_fpg, NBBY) - start; + for (loc = start; loc < end; loc++) { + if (bbp[loc] == 0 && + loc * NBBY >= rp->rw_start && + loc * NBBY < rp->rw_end) { + return 0; + } + } -success: - mtx_unlock_spin(&sbp->e2fs_rsv_win_lock); - EXT2_LOCK(ump); - return 1; + if (loc == end) { + mtx_lock_spin(&fs->e2fs_rsv_lock); + search_rsv = rp; + goto repeat; + } + } -failed: - mtx_unlock_spin(&sbp->e2fs_rsv_win_lock); - EXT2_LOCK(ump); - return 0; +gotit: + rp->rw_start = bpref + cg * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock; + rp->rw_end = rp->rw_start + size - 1; + rp->rw_alloc_hit = 0; + mtx_lock_spin(&fs->e2fs_rsv_lock); + ext2_add_rsv_win(fs, rp); + mtx_unlock_spin(&fs->e2fs_rsv_lock); + return 0; } /* - * Allocate a new reservation window. + * Allocate a free block. */ -static int -ext2_alloc_new_rsv(struct inode *ip, struct m_ext2fs *sbp, int cg, int32_t bpref, int size) +static u_long +ext2_alloc_blk(struct m_ext2fs *fs, struct inode *ip, int cg, + struct buf *bp, int32_t bpref, struct ext2_rsv_win *rp) { - struct ext2_rsv_win *rwp; + struct ext2mount *ump; + u_long start, end; + char *bbp; + u_long bno; + + ump = ip->i_ump; + bbp = (char *)bp->b_data; + if (rp != NULL && rp->rw_end != EXT2_RWI_NOT_ALLOCATED) { + start = dtogd(fs, rp->rw_start + rp->rw_alloc_hit) / NBBY; + end = dtogd(fs, rp->rw_end) / NBBY; + } else { + start = dtogd(fs, bpref) / NBBY; + end = howmany(fs->e2fs->e2fs_fpg, NBBY) - start; + } + + if (bbp[start * NBBY] == 0) { + bno = start * NBBY; + goto gotit; + } + + return 0; - rwp = &ip->i_rsv_winp->rwi_entry; +gotit: + bno += rp->rw_alloc_hit++; + 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; +} - /* delete old reservation window */ - if (rwp->rw_end != EXT2_RWI_NOT_ALLOCATED) { - mtx_lock_spin(&sbp->e2fs_rsv_win_lock); - ext2_remove_rsv_win(sbp, &ip->i_rsv_winp->rwi_entry); - mtx_unlock_spin(&sbp->e2fs_rsv_win_lock); - } +/* + * 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; + int32_t ret; - /* try to allocate a new reservation window in cg's group */ - if (ext2_search_rsv_win(ip, sbp, cg, bpref, size)) - return 1; + rp = ip->i_rsv; - /* TODO: force to allocate a new reservation window in next group */ + /* If window is empty or bpref is not in reservation window, + * we will try to allocate a new reservation window. + * Then we try to allocate a free block. + */ + if (rp->rw_end == EXT2_RWI_NOT_ALLOCATED) { + ret = ext2_alloc_new_rsv_win(ip, rp, bpref, fs, cg, bp); + if (ret < 0) + return 0; + } else if (rp->rw_start + rp->rw_alloc_hit - 1 == rp->rw_end) { + ret = ext2_alloc_new_rsv_win(ip, rp, rp->rw_end, fs, cg, bp); + if (ret < 0) + return 0; + } - return 0; + return ext2_alloc_blk(fs, ip, cg, bp, bpref, rp); } /* @@ -301,24 +399,23 @@ */ int ext2_alloc_rsv(struct inode *ip, int32_t lbn, int32_t bpref, - int size, struct ucred *cred, int32_t *bnp) + int size, struct ucred *cred, int32_t *bnp) { struct m_ext2fs *fs; struct ext2mount *ump; - struct ext2_rsv_win_info *rwip; - int32_t bno; - int cg; + struct buf *bp; + int32_t bno = 0; + int i, cg, error; *bnp = 0; fs = ip->i_e2fs; ump = ip->i_ump; - rwip = ip->i_rsv_winp; mtx_assert(EXT2_MTX(ump), MA_OWNED); 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) @@ -328,22 +425,53 @@ 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)) - if (!ext2_alloc_new_rsv(ip, fs, cg, bpref, size)) - goto nospace; + /* TODO: If cg doesn't have enought blocks, do not use reservation window */ + + /* 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 ioerror; + } + + EXT2_IRSV_LOCK(ip); + /* Try to allocate from reservation window */ + bno = ext2_rsvalloc(fs, ip, cg, bp, bpref, size); + EXT2_IRSV_UNLOCK(ip); + if (bno > 0) + goto allocated; + + brelse(bp); + EXT2_LOCK(ump); + } + + /* TODO: Just need to try to allocate a free block from rest groups. + * Now just use old allocation algorihtm. + */ +/* + for (i = cg + 1; i < fs->e2fs_gcount; i++) { + } +*/ + i = 1; + bno = (daddr_t)ext2_hashalloc(ip, cg, bpref, fs->e2fs_bsize, ext2_alloccg); - bno = ext2_alloccg_rsv(ip, cg, bpref, size); +allocated: + if (bno > 0) { + ip->i_blocks += btodb(fs->e2fs_bsize); + ip->i_flag |= IN_CHANGE | IN_UPDATE; + *bnp = bno; + return (0); + } - if (bno > 0) { - ip->i_blocks += btodb(fs->e2fs_bsize); - ip->i_flag |= IN_CHANGE | IN_UPDATE; - *bnp = bno; - return (0); - } +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; nospace: EXT2_UNLOCK(ump); @@ -439,7 +567,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 @@ -925,66 +1053,6 @@ * * Check to see if a block of the appropriate size is available, * and if it is, allocate it. - * - * NOTE: This function will replace the ext2_alloccg() function. - */ -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); -} - -/* - * 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(struct inode *ip, int cg, daddr_t bpref, int size) @@ -1219,9 +1287,11 @@ panic("ext2_vfree: range: devvp = %p, ino = %d, fs = %s", pip->i_devvp, ino, fs->e2fs_fsmnt); - ext2_discard_rsv_win(pip); - free(pip->i_rsv_winp, M_EXT2NODE); - pip->i_rsv_winp = NULL; + EXT2_IRSV_LOCK(pip); + ext2_discard_rsv(pip); + /*free(pip->i_rsv, M_EXT2NODE);*/ + /*pip->i_rsv = NULL;*/ + EXT2_IRSV_UNLOCK(pip); cg = ino_to_cg(fs, ino); error = bread(pip->i_devvp, @@ -1254,47 +1324,6 @@ } /* - * Search a free block from bpref. - * - * NOTE: This function will replace the ext2_mapsearch() function. - */ -static u_long ext2_mapsearch_rsv(struct m_ext2fs *sbp, char *bbp, daddr_t bpref) -{ - daddr_t bno; - 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(sbp, bpref) / NBBY; - else - start = 0; - len = howmany(sbp->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) { - printf("start = %d, len = %d, fs = %s\n", - start, len, sbp->e2fs_fsmnt); - panic("ext2fs_alloccg: map corrupted"); - /* NOTREACHED */ - } - } - i = start + len - loc; - map = bbp[i]; - bno = i * NBBY; - for (i = 1; i < (1 << NBBY); i <<= 1, bno++) { - if ((map & i) == 0) - return 1; - } - return 0; -} - -/* * Find a block in the specified cylinder group. * * It is a panic if a request is made to find a block if none are ==== //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_balloc.c#4 (text+ko) ==== @@ -79,11 +79,11 @@ fs = ip->i_e2fs; ump = ip->i_ump; - /* - * lazily initialize the reservation window info in inode - */ - if (ip->i_rsv_winp == NULL) - ext2_init_rsv_win_info(ip); + /* lazily initialize the reservation window info in inode */ + EXT2_IRSV_LOCK(ip); + if (ip->i_rsv == NULL) + ext2_init_rsv(ip); + EXT2_IRSV_UNLOCK(ip); /* * check if this is a sequential block allocation. ==== //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_inode.c#3 (text+ko) ==== @@ -52,6 +52,7 @@ #include #include #include +#include static int ext2_indirtrunc(struct inode *, int32_t, int32_t, int32_t, int, long *); @@ -153,7 +154,11 @@ } fs = oip->i_e2fs; osize = oip->i_size; - ext2_discard_rsv_win(oip); + + EXT2_IRSV_LOCK(oip); + ext2_discard_rsv(oip); + EXT2_IRSV_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_IRSV_LOCK(ip); + ext2_discard_rsv(ip); + EXT2_IRSV_UNLOCK(ip); + /* * Ignore inodes related to stale file handles. */ @@ -527,11 +536,15 @@ vprint("ufs_reclaim: pushing active", vp); ip = VTOI(vp); - ext2_discard_rsv_win(ip); - if (ip->i_rsv_winp != NULL) { - free(ip->i_rsv_winp, M_EXT2NODE); - ip->i_rsv_winp = NULL; +#if 0 + EXT2_IRSV_LOCK(ip); + if (ip->i_rsv != NULL) { + free(ip->i_rsv, M_EXT2NODE); + ip->i_rsv = NULL; } + EXT2_IRSV_UNLOCK(ip); + mtx_destroy(&ip->i_rsv_lock); +#endif if (ip->i_flag & IN_LAZYMOD) { ip->i_flag |= IN_MODIFIED; ==== //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_rsv_win.h#6 (text+ko) ==== @@ -35,6 +35,9 @@ #define EXT2_MAX_RSV_WIN_BLKS 1027 +#define EXT2_IRSV_LOCK(ip) mtx_lock(&ip->i_rsv_lock) +#define EXT2_IRSV_UNLOCK(ip) mtx_unlock(&ip->i_rsv_lock) + /* * Reservation window entry */ ==== //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/inode.h#4 (text+ko) ==== @@ -103,7 +103,7 @@ u_int32_t i_gid; /* File group. */ struct mtx i_rsv_lock; /* Protects i_rsv */ - struct ext2_rsv_win i_rsv; /* Reservation window */ + struct ext2_rsv_win *i_rsv; /* Reservation window */ }; /*