PERFORCE change 177944 for review
Zheng Liu
lz at FreeBSD.org
Sat May 8 08:03:56 UTC 2010
http://p4web.freebsd.org/@@177944?ac=10
Change 177944 by lz at 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");
More information about the p4-projects
mailing list