[PATCH] ext4: uninitialised extent handling
authorSuparna Bhattacharya <suparna@in.ibm.com>
Wed, 11 Oct 2006 08:21:06 +0000 (01:21 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Wed, 11 Oct 2006 18:14:16 +0000 (11:14 -0700)
Make it possible to add file preallocation support in future as an RO_COMPAT
feature by recognizing uninitialized extents as holes and limiting extent
length to keep the top bit of ee_len free for marking uninitialized extents.

Signed-off-by: Suparna Bhattacharya <suparna@in.ibm.com>
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/ext4/extents.c
include/linux/ext4_fs_extents.h

index 4a13b56e1540dbadc375c8226c31b7568069bf5e..32526061a17d14e76db4f2d355532b3c2d945d7d 100644 (file)
@@ -1082,6 +1082,13 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
            != le32_to_cpu(ex2->ee_block))
                return 0;
 
+       /*
+        * To allow future support for preallocated extents to be added
+        * as an RO_COMPAT feature, refuse to merge to extents if
+        * can result in the top bit of ee_len being set
+        */
+       if (le16_to_cpu(ex1->ee_len) + le16_to_cpu(ex2->ee_len) > EXT_MAX_LEN)
+               return 0;
 #ifdef AGRESSIVE_TEST
        if (le16_to_cpu(ex1->ee_len) >= 4)
                return 0;
@@ -1944,6 +1951,15 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
                unsigned long ee_block = le32_to_cpu(ex->ee_block);
                ext4_fsblk_t ee_start = ext_pblock(ex);
                unsigned short ee_len  = le16_to_cpu(ex->ee_len);
+
+               /*
+                * Allow future support for preallocated extents to be added
+                * as an RO_COMPAT feature:
+                * Uninitialized extents are treated as holes, except that
+                * we avoid (fail) allocating new blocks during a write.
+                */
+               if (ee_len > EXT_MAX_LEN)
+                       goto out2;
                /* if found exent covers block, simple return it */
                if (iblock >= ee_block && iblock < ee_block + ee_len) {
                        newblock = iblock - ee_block + ee_start;
index facc76684d4fdc54b603758b718c3b6173555c7a..0eba0acf6ba68077ff68852f1e5fc7286d847c53 100644 (file)
@@ -141,6 +141,8 @@ typedef int (*ext_prepare_callback)(struct inode *, struct ext4_ext_path *,
 
 #define EXT_MAX_BLOCK  0xffffffff
 
+#define EXT_MAX_LEN    ((1UL << 15) - 1)
+
 
 #define EXT_FIRST_EXTENT(__hdr__) \
        ((struct ext4_extent *) (((char *) (__hdr__)) +         \