diff options
-rw-r--r-- | fs/ext4/extents.c | 16 | ||||
-rw-r--r-- | include/linux/ext4_fs_extents.h | 2 |
2 files changed, 18 insertions, 0 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 4a13b56e1540..32526061a17d 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -1082,6 +1082,13 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1, | |||
1082 | != le32_to_cpu(ex2->ee_block)) | 1082 | != le32_to_cpu(ex2->ee_block)) |
1083 | return 0; | 1083 | return 0; |
1084 | 1084 | ||
1085 | /* | ||
1086 | * To allow future support for preallocated extents to be added | ||
1087 | * as an RO_COMPAT feature, refuse to merge to extents if | ||
1088 | * can result in the top bit of ee_len being set | ||
1089 | */ | ||
1090 | if (le16_to_cpu(ex1->ee_len) + le16_to_cpu(ex2->ee_len) > EXT_MAX_LEN) | ||
1091 | return 0; | ||
1085 | #ifdef AGRESSIVE_TEST | 1092 | #ifdef AGRESSIVE_TEST |
1086 | if (le16_to_cpu(ex1->ee_len) >= 4) | 1093 | if (le16_to_cpu(ex1->ee_len) >= 4) |
1087 | return 0; | 1094 | return 0; |
@@ -1944,6 +1951,15 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
1944 | unsigned long ee_block = le32_to_cpu(ex->ee_block); | 1951 | unsigned long ee_block = le32_to_cpu(ex->ee_block); |
1945 | ext4_fsblk_t ee_start = ext_pblock(ex); | 1952 | ext4_fsblk_t ee_start = ext_pblock(ex); |
1946 | unsigned short ee_len = le16_to_cpu(ex->ee_len); | 1953 | unsigned short ee_len = le16_to_cpu(ex->ee_len); |
1954 | |||
1955 | /* | ||
1956 | * Allow future support for preallocated extents to be added | ||
1957 | * as an RO_COMPAT feature: | ||
1958 | * Uninitialized extents are treated as holes, except that | ||
1959 | * we avoid (fail) allocating new blocks during a write. | ||
1960 | */ | ||
1961 | if (ee_len > EXT_MAX_LEN) | ||
1962 | goto out2; | ||
1947 | /* if found exent covers block, simple return it */ | 1963 | /* if found exent covers block, simple return it */ |
1948 | if (iblock >= ee_block && iblock < ee_block + ee_len) { | 1964 | if (iblock >= ee_block && iblock < ee_block + ee_len) { |
1949 | newblock = iblock - ee_block + ee_start; | 1965 | newblock = iblock - ee_block + ee_start; |
diff --git a/include/linux/ext4_fs_extents.h b/include/linux/ext4_fs_extents.h index facc76684d4f..0eba0acf6ba6 100644 --- a/include/linux/ext4_fs_extents.h +++ b/include/linux/ext4_fs_extents.h | |||
@@ -141,6 +141,8 @@ typedef int (*ext_prepare_callback)(struct inode *, struct ext4_ext_path *, | |||
141 | 141 | ||
142 | #define EXT_MAX_BLOCK 0xffffffff | 142 | #define EXT_MAX_BLOCK 0xffffffff |
143 | 143 | ||
144 | #define EXT_MAX_LEN ((1UL << 15) - 1) | ||
145 | |||
144 | 146 | ||
145 | #define EXT_FIRST_EXTENT(__hdr__) \ | 147 | #define EXT_FIRST_EXTENT(__hdr__) \ |
146 | ((struct ext4_extent *) (((char *) (__hdr__)) + \ | 148 | ((struct ext4_extent *) (((char *) (__hdr__)) + \ |