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