Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 8 May 2010 08:03:56 GMT
From:      Zheng Liu <lz@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 177944 for review
Message-ID:  <201005080803.o4883uJr055199@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@177944?ac=10

Change 177944 by lz@gnehzuil-freebsd on 2010/05/08 08:03:55

	Add some allocation functions.

Affected files ...

.. //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_alloc.c#4 edit

Differences ...

==== //depot/projects/soc2010/extfs/src/sys/fs/ext2fs/ext2_alloc.c#4 (text+ko) ====

@@ -62,6 +62,11 @@
 static daddr_t  ext2_mapsearch(struct m_ext2fs *, char *, daddr_t);
 
 static void ext2_rsv_win_remove(struct m_ext2fs *, struct ext2_rsv_win *);
+static int ext2_in_rsv(struct ext2_rsv_win *, int32_t);
+static u_long ext2_try_alloc_rsv(struct ext2_rsv_win *rwp, struct inode *, int, int32_t, int,
+					daddr_t (*allocator)(struct inode *, int, daddr_t, int));
+static daddr_t ext2_alloccg_rsv(struct inode *, int, daddr_t, int);
+static int ext2_alloc_new_rsv(struct ext2_rsv_win *, struct m_ext2fs *, int, int32_t);
 
 RB_GENERATE(ext2_rsv_win_tree, ext2_rsv_win, rw_link, ext2_rsv_win_cmp);
 
@@ -138,6 +143,97 @@
 }
 
 /*
+ * Check bpref in reservation window.
+ */
+static int
+ext2_in_rsv(struct ext2_rsv_win *rwp, int32_t bpref)
+{
+	if (bpref < rwp->rw_start ||
+		bpref > rwp->rw_end)
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Determine whether a block can be allocated.
+ *
+ * Check to see if a block of the appropriate size is available,
+ * and if it is, allocate it.
+ */
+static daddr_t
+ext2_alloccg_rsv(struct inode *ip, int cg, daddr_t bpref, int size)
+{
+	struct m_ext2fs *fs;
+	struct buf *bp;
+	struct ext2mount *ump;
+	int error, bno;
+	char *bbp;
+
+	fs = ip->i_e2fs;
+	ump = ip->i_ump;
+	if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0)
+		return (0);
+	EXT2_UNLOCK(ump);
+	error = bread(ip->i_devvp, fsbtodb(fs,
+		fs->e2fs_gd[cg].ext2bgd_b_bitmap),
+		(int)fs->e2fs_bsize, NOCRED, &bp);
+	if (error) {
+		brelse(bp);
+		EXT2_LOCK(ump);
+		return (0);
+	}
+	bbp = (char *)bp->b_data;
+
+	if (dtog(fs, bpref) != cg)
+		bpref = 0;
+	if (bpref != 0) {
+		bpref = dtogd(fs, bpref);
+		/*
+		 * if the requested block is available, use it
+		 */
+		if (isclr(bbp, bpref)) {
+			bno = bpref;
+			goto gotit;
+		}
+	}
+
+	brelse(bp);
+	EXT2_LOCK(ump);
+	return (0);
+
+gotit:
+	setbit(bbp, (daddr_t)bno);
+	EXT2_LOCK(ump);
+	fs->e2fs->e2fs_fbcount--;
+	fs->e2fs_gd[cg].ext2bgd_nbfree--;
+	fs->e2fs_fmod = 1;
+	EXT2_UNLOCK(ump);
+	bdwrite(bp);
+	return (cg * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock + bno);
+}
+
+/*
+ * Allocate a block in reservation window.
+ */
+static u_long 
+ext2_try_alloc_rsv(struct ext2_rsv_win *rwp, struct inode *ip, int cg, int32_t bpref, int size,
+			daddr_t (*allocator)(struct inode *, int, daddr_t, int))
+{
+	mtx_assert(EXT2_MTX(ip->i_ump), MA_OWNED);
+	return (*allocator)(ip, cg, bpref, size);
+}
+
+/*
+ * Allocate a new reservation window.
+ */
+static int
+ext2_alloc_new_rsv(struct ext2_rsv_win *rwp, struct m_ext2fs *sbp, int cg, int32_t bpref)
+{
+	return -1;
+}
+
+/*
  * Allocate a block using reservation window in ext2 file system.
  */
 int
@@ -146,40 +242,48 @@
 {
 	struct m_ext2fs *fs;
 	struct ext2mount *ump;
+	struct ext2_rsv_win_info *rwip;
 	int32_t bno;
-	int cg;	
+	int cg, ret;	
+
 	*bnp = 0;
 	fs = ip->i_e2fs;
 	ump = ip->i_ump;
+	rwip = ip->i_rsv_winp;
 	mtx_assert(EXT2_MTX(ump), MA_OWNED);
-#ifdef DIAGNOSTIC
-	if ((u_int)size > fs->e2fs_bsize || blkoff(fs, size) != 0) {
-		vn_printf(ip->i_devvp, "bsize = %lu, size = %d, fs = %s\n",
-		    (long unsigned int)fs->e2fs_bsize, size, fs->e2fs_fsmnt);
-		panic("ext2_alloc: bad size");
-	}
-	if (cred == NOCRED)
-		panic("ext2_alloc: missing credential");
-#endif /* DIAGNOSTIC */
+
 	if (size == fs->e2fs_bsize && fs->e2fs->e2fs_fbcount == 0)
 		goto nospace;
 	if (cred->cr_uid != 0 && 
-		fs->e2fs->e2fs_fbcount < fs->e2fs->e2fs_rbcount)
+			fs->e2fs->e2fs_fbcount < fs->e2fs->e2fs_rbcount)
 		goto nospace;
+
 	if (bpref >= fs->e2fs->e2fs_bcount)
 		bpref = 0;
-	 if (bpref == 0)
-                cg = ino_to_cg(fs, ip->i_number);
-        else
-                cg = dtog(fs, bpref);
-        bno = (daddr_t)ext2_hashalloc(ip, cg, bpref, fs->e2fs_bsize,
-                                                 ext2_alloccg);
-        if (bno > 0) {
-                ip->i_blocks += btodb(fs->e2fs_bsize);
-                ip->i_flag |= IN_CHANGE | IN_UPDATE;
-                *bnp = bno;
-                return (0);
-        }
+	if (bpref == 0)
+		cg = ino_to_cg(fs, ip->i_number);
+	else
+		cg = dtog(fs, bpref);
+
+	/* If bpref is in reservation window and window has free block, then alloc it.
+	 * Otherwise, try to allocate a new reservation window.
+	 */
+	if (rwip->rwi_entry.rw_end == EXT2_RWI_NOT_ALLOCATED ||
+		!ext2_in_rsv(&rwip->rwi_entry, bpref)) {
+		ret = ext2_alloc_new_rsv(&rwip->rwi_entry, fs, cg, bpref);
+	} else {
+		bno = ext2_try_alloc_rsv(&rwip->rwi_entry,
+			ip, cg, bpref, size, ext2_alloccg_rsv);
+	}
+
+	bno = (daddr_t)ext2_hashalloc(ip, cg, bpref, fs->e2fs_bsize,
+			ext2_alloccg);
+	if (bno > 0) {
+		ip->i_blocks += btodb(fs->e2fs_bsize);
+		ip->i_flag |= IN_CHANGE | IN_UPDATE;
+		*bnp = bno;
+		return (0);
+	}
 nospace:
 	EXT2_UNLOCK(ump);
 	ext2_fserr(fs, cred->cr_uid, "file system full");



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201005080803.o4883uJr055199>