From owner-p4-projects@FreeBSD.ORG Thu Mar 24 04:52:57 2011 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 1DEEA1065673; Thu, 24 Mar 2011 04:52:57 +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 D1F471065670 for ; Thu, 24 Mar 2011 04:52:56 +0000 (UTC) (envelope-from lz@FreeBSD.org) Received: from skunkworks.freebsd.org (skunkworks.freebsd.org [IPv6:2001:4f8:fff6::2d]) by mx1.freebsd.org (Postfix) with ESMTP id BD7608FC13 for ; Thu, 24 Mar 2011 04:52:56 +0000 (UTC) Received: from skunkworks.freebsd.org (localhost [127.0.0.1]) by skunkworks.freebsd.org (8.14.4/8.14.4) with ESMTP id p2O4quYd022694 for ; Thu, 24 Mar 2011 04:52:56 GMT (envelope-from lz@FreeBSD.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.4/8.14.4/Submit) id p2O4quqd022691 for perforce@freebsd.org; Thu, 24 Mar 2011 04:52:56 GMT (envelope-from lz@FreeBSD.org) Date: Thu, 24 Mar 2011 04:52:56 GMT Message-Id: <201103240452.p2O4quqd022691@skunkworks.freebsd.org> X-Authentication-Warning: skunkworks.freebsd.org: perforce set sender to lz@FreeBSD.org using -f From: Zheng Liu To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 190457 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: Thu, 24 Mar 2011 04:52:57 -0000 http://p4web.freebsd.org/@@190457?ac=10 Change 190457 by lz@freebsd-dev on 2011/03/24 04:52:09 Merge reallocblks from ext2fs. Affected files ... .. //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_alloc.c#3 edit .. //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_balloc.c#3 edit .. //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_dinode.h#3 edit .. //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_extern.h#3 edit .. //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_inode.c#4 edit .. //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_readwrite.c#3 edit .. //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_rsv_win.h#3 edit .. //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_subr.c#3 edit .. //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_vfsops.c#4 edit .. //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4fs.h#3 edit .. //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/inode.h#3 edit Differences ... ==== //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_alloc.c#3 (text+ko) ==== @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -52,6 +53,8 @@ #include #include +#define FANCY_REALLOC 1 + /* Just for clear */ #define phy_blk(cg, fs) (((cg) * (fs->e2fs->e2fs_fpg)) + fs->e2fs->e2fs_first_dblock) @@ -64,6 +67,11 @@ static daddr_t ext2_nodealloccg(struct inode *, int, daddr_t, int); static daddr_t ext2_mapsearch(struct m_ext2fs *, char *, daddr_t); +/* For reallocblks */ +#ifdef FANCY_REALLOC +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); @@ -82,25 +90,33 @@ * Allocate a block in the file system. * * 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 + * Check whether inode has a reservation window and preference + * is within it and 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. + * If not, traverse RB tree to find a place, which is not in + * any window and insert it to RB tree to try to allocate a + * free block again. + * If it fails, try to allocate a free block in other cylinder + * groups without preference. */ +SYSCTL_NODE(_vfs, OID_AUTO, ext2fs, CTLFLAG_RW, 0, "EXT2FS filesystem"); + +static int rsv = 0; +SYSCTL_INT(_vfs_ext2fs, OID_AUTO, rsv, CTLFLAG_RW, &rsv, 0, ""); + +static int rsv_winsize = 8; +SYSCTL_UINT(_vfs_ext2fs, OID_AUTO, rsv_winsize, CTLFLAG_RW, &rsv_winsize, 0, ""); + /* * 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 + * 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 it not use reservation window, it will try to allocate - * a free block by bpref. If failed, it will traverse the bitmap + * 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 @@ -122,26 +138,26 @@ if (bpref < 0) bpref = 0; - /* Check whther it use reservation window */ + /* 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 of this group. - * Otherwise, try to allocate from the beginning of - * the window. + * try to allocate from the beginning, otherwise + * try to allocate from the beginning of the + * window. */ - if (dtog(fs, rp->rsv_start) != cg) - start = phy_blk(cg, fs); + if (dtog(fs, rp->rsv_start) < cg) + start = 0; else start = rp->rsv_start; /* - * If window's end cross the end of this group, + * If window's end crosses the end of this group, * set end variable to the end of this group. - * Otherwise, set it to window's end. + * Otherwise, set it to the window's end. */ - if (dtog(fs, rp->rsv_end) != cg) - end = fs->e2fs->e2fs_fpg; + if (dtog(fs, rp->rsv_end) > cg) + end = phy_blk(cg + 1, fs) - 1; else end = rp->rsv_end; @@ -154,7 +170,10 @@ goto gotit; } } else - bpref = dtogd(fs, rp->rsv_start); + if (dtog(fs, rp->rsv_start) == cg) + bpref = dtogd(fs, rp->rsv_start); + else + bpref = 0; } else { if (dtog(fs, bpref) != cg) bpref = 0; @@ -196,7 +215,7 @@ M_EXT2NODE, M_WAITOK | M_ZERO); /* - * If malloc failed, we just do not use + * If malloc failed, we just do not use the * reservation window mechanism. */ if (rp == NULL) @@ -205,7 +224,10 @@ rp->rsv_start = EXT2_RSV_NOT_ALLOCATED; rp->rsv_end = EXT2_RSV_NOT_ALLOCATED; - rp->rsv_goal_size = EXT2_RSV_DEFAULT_RESERVE_BLKS; + if (rsv_winsize < EXT2_RSV_MAX_RESERVE_BLKS) + rp->rsv_goal_size = rsv_winsize; + else + rp->rsv_goal_size = EXT2_RSV_DEFAULT_RESERVE_BLKS; rp->rsv_alloc_hit = 0; ip->i_rsv = rp; @@ -214,10 +236,9 @@ /* * Discard reservation window. * - * It is called at following locations: + * It is called during the following situations: * 1. free an inode - * 2. sync inode - * 3. truncate a file + * 2. truncate a file */ void ext2_discard_rsv(struct inode *ip) @@ -236,7 +257,10 @@ 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; + if (rsv_winsize < EXT2_RSV_MAX_RESERVE_BLKS) + rp->rsv_goal_size = rsv_winsize; + else + rp->rsv_goal_size = EXT2_RSV_DEFAULT_RESERVE_BLKS; } /* @@ -245,7 +269,7 @@ 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); + 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; @@ -312,7 +336,7 @@ rp->rsv_end = start + size - 1; rp->rsv_alloc_hit = 0; - RB_INSERT(ext2_rsv_win_tree, &fs->e2fs_rsv_tree, rp); + RB_INSERT(ext2_rsv_win_tree, fs->e2fs_rsv_tree, rp); return (0); } @@ -320,7 +344,7 @@ /* * 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. + * in the ext2_search_next_block() function. */ cur = start & ~7; rsv = search; @@ -334,7 +358,7 @@ return (-1); prev = rsv; - rsv = RB_NEXT(ext2_rsv_win_tree, &fs->e2fs_rsv_tree, rsv); + rsv = RB_NEXT(ext2_rsv_win_tree, fs->e2fs_rsv_tree, rsv); if (rsv == NULL) break; @@ -351,7 +375,7 @@ rp->rsv_alloc_hit = 0; if (prev != rp) - RB_INSERT(ext2_rsv_win_tree, &fs->e2fs_rsv_tree, rp); + RB_INSERT(ext2_rsv_win_tree, fs->e2fs_rsv_tree, rp); return (0); } @@ -417,7 +441,7 @@ EXT2_TREE_LOCK(fs); - search = ext2_search_rsv(&fs->e2fs_rsv_tree, start); + search = ext2_search_rsv(fs->e2fs_rsv_tree, start); repeat: ret = ext2_find_rsv(search, rp, fs, start, cg); @@ -475,7 +499,7 @@ /* * Allocate a block using reservation window in ext2 file system. * - * NOTE: This function will replace the ext2_alloc() function. + * XXX: This function will replace the ext2_alloc() function. */ int ext2_alloc_rsv(struct inode *ip, int32_t lbn, int32_t bpref, @@ -559,6 +583,9 @@ allocated: if (bno > 0) { + ip->i_next_alloc_block = lbn; + ip->i_next_alloc_goal = bno; + ip->i_blocks += btodb(fs->e2fs_bsize); ip->i_flag |= IN_CHANGE | IN_UPDATE; *bnp = bno; @@ -574,7 +601,7 @@ 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; + return (EIO); } int @@ -609,13 +636,17 @@ goto nospace; if (bpref >= fs->e2fs->e2fs_bcount_lo) bpref = 0; - if (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) { + /* set next_alloc fields as done in block_getblk */ + ip->i_next_alloc_block = lbn; + ip->i_next_alloc_goal = bno; + ip->i_blocks += btodb(fs->e2fs_bsize); ip->i_flag |= IN_CHANGE | IN_UPDATE; *bnp = bno; @@ -632,7 +663,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 - * logicar blocks to be made contiguous is given. The allocator attempts + * logical 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 @@ -644,13 +675,13 @@ */ #ifdef FANCY_REALLOC -#include static int doasyncfree = 1; + +SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, + "Use asychronous writes to update block pointers when freeing blocks"); + static int doreallocblks = 1; - -#ifdef OPT_DEBUG -SYSCTL_INT(_debug, 14, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, ""); -#endif /* OPT_DEBUG */ +SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doreallocblks, CTLFLAG_RW, &doreallocblks, 0, ""); #endif int @@ -664,7 +695,6 @@ /* printf("ext2_reallocblks not implemented\n"); */ return ENOSPC; #else - struct m_ext2fs *fs; struct inode *ip; struct vnode *vp; @@ -673,13 +703,17 @@ struct ext2mount *ump; struct cluster_save *buflist; struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp; - int32_t start_lbn, end_lbn, soff, newblk, blkno =0; + int32_t start_lbn, end_lbn, soff, newblk, blkno; int i, len, start_lvl, end_lvl, pref, ssize; vp = ap->a_vp; ip = VTOI(vp); fs = ip->i_e2fs; ump = ip->i_ump; + + if (doreallocblks == 0) + return (ENOSPC); + #ifdef UNKLAR if (fs->fs_contigsumsize <= 0) return (ENOSPC); @@ -720,11 +754,6 @@ soff = idp->in_off; } /* - * Find the preferred location for the cluster. - */ - EXT2_LOCK(ump); - pref = ext2_blkpref(ip, start_lbn, soff, sbap, blkno); - /* * If the block range spans two block maps, get the second map. */ if (end_lvl == 0 || (idp = &end_ap[end_lvl - 1])->in_off + 1 >= len) { @@ -735,17 +764,20 @@ panic("ext2_reallocblk: start == end"); #endif ssize = len - (idp->in_off + 1); - if (bread(vp, idp->in_lbn, (int)fs->e2fs_bsize, NOCRED, &ebp)){ - EXT2_UNLOCK(ump); + if (bread(vp, idp->in_lbn, (int)fs->e2fs_bsize, NOCRED, &ebp)) goto fail; - } ebap = (int32_t *)ebp->b_data; } /* + * Find the preferred location for the cluster. + */ + EXT2_LOCK(ump); + pref = ext2_blkpref(ip, start_lbn, soff, sbap, 0); + /* * Search the block map looking for an allocation of the desired size. */ if ((newblk = (int32_t)ext2_hashalloc(ip, dtog(fs, pref), pref, - len, ext2_clusteralloc)) == 0){ + len, ext2_clusteralloc)) == 0) { EXT2_UNLOCK(ump); goto fail; } @@ -756,15 +788,23 @@ * block pointers in the inode and indirect blocks associated * with the file. */ +#ifdef DEBUG + printf("realloc: ino %d, lbns %jd-%jd\n\told:", ip->i_number, + (intmax_t)start_lbn, (intmax_t)end_lbn); +#endif /* DEBUG */ blkno = newblk; for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->e2fs_fpb) { - if (i == ssize) + if (i == ssize) { bap = ebap; soff = -i; + } #ifdef DIAGNOSTIC if (buflist->bs_children[i]->b_blkno != fsbtodb(fs, *bap)) panic("ext2_reallocblks: alloc mismatch"); #endif +#ifdef DEBUG + printf(" %d,", *bap); +#endif /* DEBUG */ *bap++ = blkno; } /* @@ -800,11 +840,20 @@ /* * Last, free the old blocks and assign the new blocks to the buffers. */ +#ifdef DEBUG + printf("\n\tnew:"); +#endif for (blkno = newblk, i = 0; i < len; i++, blkno += fs->e2fs_fpb) { ext2_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->e2fs_bsize); buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno); +#ifdef DEBUG + printf(" %d,", blkno); +#endif } +#ifdef DEBUG + printf("\n"); +#endif return (0); fail: @@ -1125,7 +1174,8 @@ struct m_ext2fs *fs; struct buf *bp; struct ext2mount *ump; - int error, bno, start, end, loc; + daddr_t bno, runstart, runlen; + int bit, loc, end, error, start; char *bbp; /* XXX ondisk32 */ fs = ip->i_e2fs; @@ -1141,6 +1191,15 @@ EXT2_LOCK(ump); return (0); } + if (fs->e2fs_gd[cg].ext2bgd_nbfree_lo == 0) { + /* + * Another thread allocated the last block in this + * group while we were waiting for the buffer. + */ + brelse(bp); + EXT2_LOCK(ump); + return (0); + } bbp = (char *)bp->b_data; if (dtog(fs, bpref) != cg) @@ -1166,18 +1225,52 @@ else start = 0; end = howmany(fs->e2fs->e2fs_fpg, NBBY) - start; - for (loc = start; loc < end; loc++) { - if (bbp[loc] == 0) { - bno = loc * NBBY; - goto gotit; - } - } - for (loc = 0; loc < start; loc++) { - if (bbp[loc] == 0) { - bno = loc * NBBY; - goto gotit; - } - } +retry: + runlen = 0; + runstart = 0; + for (loc = start; loc < end; loc++) { + if (bbp[loc] == (char)0xff) { + runlen = 0; + continue; + } + + /* Start of a run, find the number of high clear bits. */ + if (runlen == 0) { + bit = fls(bbp[loc]); + runlen = NBBY - bit; + runstart = loc * NBBY + bit; + } else if (bbp[loc] == 0) { + /* Contunue a run. */ + runlen += NBBY; + } else { + /* + * Finish the current run. If it isn't long + * enough, start a new one. + */ + bit = ffs(bbp[loc]) - 1; + runlen += bit; + if (runlen >= 8) { + bno = runstart; + goto gotit; + } + + /* Run was too short, start a new one. */ + bit = fls(bbp[loc]); + runlen = NBBY - bit; + runstart = loc * NBBY + bit; + } + + /* If the current run is long enough, use it. */ + if (runlen >= 8) { + bno = runstart; + goto gotit; + } + } + if (start != 0) { + end = start; + start = 0; + goto retry; + } bno = ext2_mapsearch(fs, bbp, bpref); if (bno < 0){ @@ -1187,14 +1280,15 @@ } gotit: #ifdef DIAGNOSTIC - if (isset(bbp, (daddr_t)bno)) { + if (isset(bbp, bno)) { printf("ext2fs_alloccgblk: cg=%d bno=%d fs=%s\n", - cg, bno, fs->e2fs_fsmnt); + cg, (intmax_t)bno, fs->e2fs_fsmnt); panic("ext2fs_alloccg: dup alloc"); } #endif - setbit(bbp, (daddr_t)bno); + setbit(bbp, bno); EXT2_LOCK(ump); + ext2_clusteracct(fs, bbp, cg, bno, -1); fs->e2fs->e2fs_fbcount_lo--; fs->e2fs_gd[cg].ext2bgd_nbfree_lo--; fs->e2fs_fmod = 1; @@ -1203,6 +1297,117 @@ return (cg * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock + bno); } +#ifdef FANCY_REALLOC +static daddr_t +ext2_clusteralloc(struct inode *ip, int cg, daddr_t bpref, int len) +{ + struct m_ext2fs *fs; + struct ext2mount *ump; + struct buf *bp; + char *bbp; + int error, i, bit, got, loc, run; + daddr_t bno; + int32_t *lp; + + fs = ip->i_e2fs; + ump = ip->i_ump; + + if (fs->e2fs_maxcluster[cg] < len) + return (0); + + 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) + goto fail_lock; + + bbp = (char *)bp->b_data; + bp->b_xflags |= BX_BKGRDWRITE; + + EXT2_LOCK(ump); + /* + * Check to see if a cluster of the needed size (or bigger) is + * available in this cylinder group. + */ + lp = &fs->e2fs_clustersum[cg].cs_sum[len]; + for (i = len; i <= fs->e2fs_contigsumsize; i++) + if (*lp++ > 0) + break; + if (i > fs->e2fs_contigsumsize) { + /* + * Update the cluster summary information to reflect + * the true maximum sized cluster so that future cluster + * allocation requests can avoid reading the bitmap only + * to find no clusters. + */ + lp = &fs->e2fs_clustersum[cg].cs_sum[len - 1]; + for (i = len - 1; i > 0; i--) + if (*lp-- > 0) + break; + fs->e2fs_maxcluster[cg] = i; + goto fail; + } + EXT2_UNLOCK(ump); + + /* Search the cluster map to find a big enough cluster like ffs. */ + if (dtog(fs, bpref) != cg) + bpref = 0; + if (bpref != 0) + bpref = dtogd(fs, bpref); + loc = bpref / NBBY; + bit = 1 << (bpref % NBBY); + for (run = 0, got = bpref; got < fs->e2fs->e2fs_fpg; got++) { + if ((bbp[loc] & bit) != 0) { + run = 0; + } else { + run++; + if (run == len) + break; + } + if ((got & (NBBY - 1)) != (NBBY - 1)) + bit <<= 1; + else { + loc++; + bit = 1; + } + } + + if (got >= fs->e2fs->e2fs_fpg) + goto fail_lock; + + /* + * Allocate the cluster that we have found. + */ + for (i = 1; i < len; i++) + if (!isclr(bbp, got - run + i)) + panic("ext2_clusteralloc: map mismatch"); + + bno = got - run + 1; + if (bno >= fs->e2fs->e2fs_fpg) + panic("ext2_clusteralloc: allocated out of group"); + + EXT2_LOCK(ump); + for (i = 0; i < len; i += fs->e2fs_fpb) { + setbit(bbp, bno + i); + ext2_clusteracct(fs, bbp, cg, bno + i, -1); + fs->e2fs->e2fs_fbcount_lo--; + fs->e2fs_gd[cg].ext2bgd_nbfree_lo--; + } + fs->e2fs_fmod = 1; + EXT2_UNLOCK(ump); + + bdwrite(bp); + return (phy_blk(cg, fs) + bno); + +fail_lock: + EXT2_LOCK(ump); +fail: + brelse(bp); + return (0); +} +#endif /* FANCY_REALLOC */ + /* * Determine whether an inode can be allocated. * @@ -1233,6 +1438,15 @@ EXT2_LOCK(ump); return (0); } + if (fs->e2fs_gd[cg].ext2bgd_nifree_lo == 0) { + /* + * Another thread allocated the last i-node in this + * group while we were waiting for the buffer. + */ + brelse(bp); + EXT2_LOCK(ump); + return (0); + } ibp = (char *)bp->b_data; if (ipref) { ipref %= fs->e2fs->e2fs_ipg; @@ -1254,16 +1468,12 @@ } } i = start + len - loc; - map = ibp[i]; - ipref = i * NBBY; - for (i = 1; i < (1 << NBBY); i <<= 1, ipref++) { - if ((map & i) == 0) { - goto gotit; - } + map = ibp[i] ^ 0xff; + if (map == 0) { + printf("fs = %s\n", fs->e2fs_fsmnt); + panic("ext2fs_nodealloccg: block not in map"); } - printf("fs = %s\n", fs->e2fs_fsmnt); - panic("ext2fs_nodealloccg: block not in map"); - /* NOTREACHED */ + ipref = i * NBBY + ffs(map) - 1; gotit: setbit(ibp, ipref); EXT2_LOCK(ump); @@ -1320,6 +1530,7 @@ } clrbit(bbp, bno); EXT2_LOCK(ump); + ext2_clusteracct(fs, bbp, cg, bno, 1); fs->e2fs->e2fs_fbcount_lo++; fs->e2fs_gd[cg].ext2bgd_nbfree_lo++; fs->e2fs_fmod = 1; @@ -1391,7 +1602,6 @@ static daddr_t ext2_mapsearch(struct m_ext2fs *fs, char *bbp, daddr_t bpref) { - daddr_t bno; int start, len, loc, i, map; /* @@ -1410,23 +1620,23 @@ loc = skpc(0xff, len, &bbp[start]); if (loc == 0) { /* 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 */ + if (rsv == 1) + return (-1); + else { + printf("start = %d, len = %d, fs = %s\n", + start, len, fs->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 (bno); + map = bbp[i] ^ 0xff; + if (map == 0) { + printf("fs = %s\n", fs->e2fs_fsmnt); + panic("ext2fs_mapsearch: block not in map"); } - printf("fs = %s\n", fs->e2fs_fsmnt); - panic("ext2fs_mapsearch: block not in map"); - /* NOTREACHED */ + return (i * NBBY + ffs(map) - 1); } /* ==== //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_balloc.c#3 (text+ko) ==== @@ -79,6 +79,8 @@ fs = ip->i_e2fs; ump = ip->i_ump; + if (ip->i_rsv == NULL) + ext2_init_rsv(ip); /* * check if this is a sequential block allocation. * If so, increment next_alloc fields to allow ext2_blkpref @@ -137,11 +139,6 @@ 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); @@ -176,11 +173,6 @@ 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); @@ -222,9 +214,6 @@ 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); @@ -264,13 +253,6 @@ 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); ==== //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_dinode.h#3 (text+ko) ==== @@ -29,6 +29,25 @@ #ifndef _FS_EXT4FS_EXT4_DINODE_H_ #define _FS_EXT4FS_EXT4_DINODE_H_ +#define e2di_size_high e2di_dacl + +/* + * Special inode numbers + * The root inode is the root of the file system. Inode 0 can't be used for + * normal purposes and bad blocks are normally linked to inode 1, thus + * the root inode is 2. + * Inode 3 to 10 are reserved in ext2fs. + */ +#define EXT2_BADBLKINO ((ino_t)1) +#define EXT2_ROOTINO ((ino_t)2) +#define EXT2_ACLIDXINO ((ino_t)3) +#define EXT2_ACLDATAINO ((ino_t)4) +#define EXT2_BOOTLOADERINO ((ino_t)5) +#define EXT2_UNDELDIRINO ((ino_t)6) +#define EXT2_RESIZEINO ((ino_t)7) +#define EXT2_JOURNALINO ((ino_t)8) +#define EXT2_FIRSTINO ((ino_t)11) + /* * Inode flags * The current implementation uses only EXT2_IMMUTABLE and EXT2_APPEND flags ==== //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_extern.h#3 (text+ko) ==== @@ -55,6 +55,7 @@ int32_t ext2_blkpref(struct inode *, int32_t, int, int32_t *, int32_t); int ext2_bmap(struct vop_bmap_args *); int ext2_bmaparray(struct vnode *, int32_t, int64_t *, int *, int *); +void ext2_clusteracct(struct m_ext2fs *, char *, int, daddr_t, int); void ext2_dirbad(struct inode *ip, doff_t offset, char *how); void ext2_ei2i(struct ext2fs_dinode *, struct inode *); int ext2_getlbns(struct vnode *, int32_t, struct indir *, int *); ==== //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_inode.c#4 (text+ko) ==== @@ -545,8 +545,6 @@ EXT2_RSV_UNLOCK(ip); mtx_destroy(&ip->i_rsv_lock); - mtx_destroy(&ip->i_ext_lock); - free(vp->v_data, M_EXT2NODE); vp->v_data = 0; vnode_destroy_vobject(vp); ==== //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_readwrite.c#3 (text+ko) ==== @@ -307,7 +307,6 @@ struct inode *ip; FS *fs; struct buf *bp; - struct thread *td; daddr_t lbn; off_t osize; int blkoffset, error, flags, ioflag, resid, size, seqcount, xfersize; @@ -352,17 +351,8 @@ * Maybe this should be above the vnode op call, but so long as * file servers have no limits, I don't think it matters. */ - td = uio->uio_td; - if (vp->v_type == VREG && td != NULL) { - PROC_LOCK(td->td_proc); - if (uio->uio_offset + uio->uio_resid > - lim_cur(td->td_proc, RLIMIT_FSIZE)) { - psignal(td->td_proc, SIGXFSZ); - PROC_UNLOCK(td->td_proc); - return (EFBIG); - } - PROC_UNLOCK(td->td_proc); - } + if (vn_rlimit_fsize(vp, uio, uio->uio_td)) + return (EFBIG); resid = uio->uio_resid; osize = ip->i_size; ==== //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_rsv_win.h#3 (text+ko) ==== @@ -31,8 +31,8 @@ #include #define EXT2_RSV_DEFAULT_RESERVE_BLKS 8 -#define EXT2_RSV_MAX_RESERVE_BLKS 1024 -#define EXT2_RSV_NOT_ALLOCATED 0 +#define EXT2_RSV_MAX_RESERVE_BLKS 1024 +#define EXT2_RSV_NOT_ALLOCATED 0 #define EXT2_RSV_LOCK(ip) mtx_lock(&ip->i_rsv_lock) #define EXT2_RSV_UNLOCK(ip) mtx_unlock(&ip->i_rsv_lock) @@ -60,11 +60,11 @@ const struct ext2_rsv_win *b) { if (a->rsv_start < b->rsv_start) - return -1; + return (-1); if (a->rsv_start == b->rsv_start) - return 0; + return (0); - return 1; + return (1); } RB_PROTOTYPE(ext2_rsv_win_tree, ext2_rsv_win, rsv_link, ext2_rsv_win_cmp); @@ -73,7 +73,6 @@ /* ext2_alloc.c */ void ext2_init_rsv(struct inode *ip); void ext2_discard_rsv(struct inode *ip); -int ext2_alloc_rsv(struct inode *, int32_t, int32_t, - int, struct ucred *, int32_t *); +int ext2_alloc_rsv(struct inode *, int32_t, int32_t, int, struct ucred *, int32_t *); #endif /* !_FS_EXT4FS_EXT4_RSV_WIN_H_ */ ==== //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_subr.c#3 (text+ko) ==== @@ -53,6 +53,8 @@ #include #ifdef KDB +#include + void ext2_checkoverlap(struct buf *, struct inode *); #endif @@ -103,7 +105,7 @@ brelse(path.ep_bp); path.ep_bp = NULL; } - if ((error = bread(ip->i_devvp, fsbtodb(fs, newblk), bsize, NOCRED, &bp)) != 0) { + if ((error = bread(vp, fsbtodb(fs, newblk), bsize, NOCRED, &bp)) != 0) { brelse(bp); return (error); } @@ -141,7 +143,7 @@ for (ep = buf; ep < ebp; ep++) { if (ep == bp || (ep->b_flags & B_INVAL)) continue; - vp = ip->i_devvp; + vp = ip->i_ump->um_devvp; /* look for overlap */ if (ep->b_bcount == 0 || ep->b_blkno > last || ep->b_blkno + btodb(ep->b_bcount) <= start) @@ -154,3 +156,107 @@ } } #endif /* KDB */ + +/* + * Update the cluster map because of an allocation or free like ffs. + * + * cnt == 1 means free; cnt == -1 means allocating. + */ +void +ext2_clusteracct(struct m_ext2fs *fs, char *bbp, int cg, daddr_t bno, int cnt) +{ + int32_t *sump = fs->e2fs_clustersum[cg].cs_sum; + int32_t *lp; + int i, forw, back, start, end, bit, loc; + + /* Initialize the cluster summary array. */ + if (fs->e2fs_clustersum[cg].cs_init == 0) { + int run = 0; + bit = 1; + loc = 0; + + for (i = 0; i < fs->e2fs->e2fs_fpg; i++) { + if ((bbp[loc] & bit) == 0) + run++; + else if (run != 0) { + if (run > fs->e2fs_contigsumsize) + run = fs->e2fs_contigsumsize; + sump[run]++; + run = 0; + } + if ((i & (NBBY - 1)) != (NBBY - 1)) { + bit <<= 1; + } else { + loc++; + bit = 1; + } + } >>> TRUNCATED FOR MAIL (1000 lines) <<<