Skip to contentSkip to conversation

basic delayed allocation in ext4

RFC In review Alex Tomas 2 participants 3 messages Jul 26, 2007

Subsystems (2)
lore
Share & tools
lore

Alex Tomas

author
#0 lore raw

RFC 1/1 basic delayed allocation in ext4

Good day,

please review ...

thanks, Alex

Basic delayed allocation in ext4

Two special ->get_block() methods are introduced:

* ext4_da_get_block_prep()
to be used with ->prepare_write(), defers allocation till flush
* ext4_da_get_block_write()
to be used with mpage_da_writepages(), allocate blocks and correct on-disk size

Current implementation works with data=writeback only, you should mount filesystem with delalloc,data=writeback options.

TODO:
* reservation
* data=ordered
* quota
* bmap

include/linux/ext4_fs.h +1 -0
Index: linux-2.6.22/include/linux/ext4_fs.h
===================================================================
@@ -488,6 +488,7 @@ do {									       \
 #define EXT4_MOUNT_EXTENTS		0x400000 /* Extents support */
 #define EXT4_MOUNT_JOURNAL_CHECKSUM	0x800000 /* Journal checksums */
 #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT	0x1000000 /* Journal Async Commit */
+#define EXT4_MOUNT_DELALLOC		0x2000000 /* Delalloc support */
 /* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */
 #ifndef _LINUX_EXT2_FS_H
 #define clear_opt(o, opt)		o &= ~EXT4_MOUNT_##opt
fs/ext4/super.c +5 -1
Index: linux-2.6.22/fs/ext4/super.c
===================================================================
@@ -728,7 +728,7 @@ enum {
 	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
 	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
 	Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
-	Opt_grpquota, Opt_extents, Opt_noextents,
+	Opt_grpquota, Opt_extents, Opt_noextents, Opt_delalloc,
 };
 
 static match_table_t tokens = {
@@ -782,6 +782,7 @@ static match_table_t tokens = {
 	{Opt_barrier, "barrier=%u"},
 	{Opt_extents, "extents"},
 	{Opt_noextents, "noextents"},
+	{Opt_delalloc, "delalloc"},
 	{Opt_err, NULL},
 	{Opt_resize, "resize"},
 };
@@ -1127,6 +1128,9 @@ clear_qf_name:
 		case Opt_noextents:
 			clear_opt (sbi->s_mount_opt, EXTENTS);
 			break;
+		case Opt_delalloc:
+			set_opt (sbi->s_mount_opt, DELALLOC);
+			break;
 		default:
 			printk (KERN_ERR
 				"EXT4-fs: Unrecognized mount option \"%s\" "
fs/ext4/inode.c +156 -0

178 lines not on this page · raw message

#1 lore raw
Quoted 27 lines · Alex Tomas

Good day,

please review ...

thanks, Alex

Basic delayed allocation in ext4

Two special ->get_block() methods are introduced:

* ext4_da_get_block_prep()
to be used with ->prepare_write(), defers allocation till flush
* ext4_da_get_block_write()
to be used with mpage_da_writepages(), allocate blocks and correct
on-disk size

Current implementation works with data=writeback only, you should mount filesystem with delalloc,data=writeback options.

TODO:
* reservation
* data=ordered
* quota
* bmap

[.. snip...]

Quoted 13 lines

/*
* Test whether an inode is a fast symlink.
*/

fs/ext4/inode.c +6 -0
@@ -1291,6 +1293,142 @@ static int ext4_journalled_commit_write(
 }
 
 /*
+ * this is a special callback for ->prepare_write() only
+ * it's intention is to return mapped block or reserve space
+ */
+static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
+                struct buffer_head *bh_result, int create)
+{

fs/ext4/inode.c static int ext4_journalled_commit_write( · line 1311

Quoted 10 lines
fs/ext4/inode.c +10 -0
+    int ret = 0;
+
+    BUG_ON(create == 0);
+    BUG_ON(bh_result->b_size != inode->i_sb->s_blocksize);
+
+    /* first, we need to know whether the block is allocated already
+     * XXX: when the filesystem has a lot of free blocks, we could
+     * reserve even allocated blocks to save this lookup */
+    ret = ext4_get_blocks_wrap(NULL, inode, iblock, 1,  bh_result, 0, 0);
+    if (ret >= 0) {

I guess this should be (ret > 0)

fs/ext4/inode.c static int ext4_journalled_commit_write( · line 1316

Quoted 5 lines
fs/ext4/inode.c +5 -0
+        if (buffer_mapped(bh_result)) {
+            bh_result->b_size = (ret << inode->i_blkbits);
+        } else {
+            /* OK, the block isn't allocated yet, let's reserve space */
+            /* XXX: call reservation here */

[...snip..]

epare_write(struct file *file, struct page *page,

fs/ext4/inode.c static int ext4_journalled_commit_write( · line 1395

Quoted 13 lines
fs/ext4/inode.c +13 -0
+                          unsigned from, unsigned to)
+{
+    return block_prepare_write(page, from, to, ext4_da_get_block_prep);
+}
+
+    return ret;
+}
+
+static int ext4_da_writepages(struct address_space *mapping,
+                struct writeback_control *wbc)
+{
+    return mpage_da_writepages(mapping, wbc, ext4_da_get_block_write);
+}

I was not able to find mpage_da_writepages()..

-aneesh

author
#2 lore raw
Quoted 9 lines · Aneesh Kumar K.V
Quoted 6 lines
fs/ext4/inode.c +4 -0
+    /* first, we need to know whether the block is allocated already
+     * XXX: when the filesystem has a lot of free blocks, we could
+     * reserve even allocated blocks to save this lookup */
+    ret = ext4_get_blocks_wrap(NULL, inode, iblock, 1,  bh_result, 0, 

0);
+ if (ret >= 0) {

I guess this should be (ret > 0)

well, no. it has to catch allocated and non-allocated blocks (though can be written more clear, probably)

Quoted 1 line

I was not able to find mpage_da_writepages()..

sorry, it's part of vfs delayed allocation patch, should be on the list now.

thanks, Alex