PERFORCE change 190457 for review
Zheng Liu
lz at FreeBSD.org
Thu Mar 24 04:52:57 UTC 2011
http://p4web.freebsd.org/@@190457?ac=10
Change 190457 by lz at 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 <sys/vnode.h>
#include <sys/stat.h>
#include <sys/mount.h>
+#include <sys/sysctl.h>
#include <sys/syslog.h>
#include <sys/buf.h>
@@ -52,6 +53,8 @@
#include <fs/ext4fs/ext4_extern.h>
#include <fs/ext4fs/ext4_rsv_win.h>
+#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 <sys/sysctl.h>
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 <sys/tree.h>
#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 <fs/ext4fs/ext4_extents.h>
#ifdef KDB
+#include <fs/ext4fs/ext4_mount.h>
+
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) <<<
More information about the p4-projects
mailing list