diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/extents.c | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index ded3d469f978..77146b826a13 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -1107,7 +1107,7 @@ static int | |||
1107 | ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1, | 1107 | ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1, |
1108 | struct ext4_extent *ex2) | 1108 | struct ext4_extent *ex2) |
1109 | { | 1109 | { |
1110 | unsigned short ext1_ee_len, ext2_ee_len; | 1110 | unsigned short ext1_ee_len, ext2_ee_len, max_len; |
1111 | 1111 | ||
1112 | /* | 1112 | /* |
1113 | * Make sure that either both extents are uninitialized, or | 1113 | * Make sure that either both extents are uninitialized, or |
@@ -1116,6 +1116,11 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1, | |||
1116 | if (ext4_ext_is_uninitialized(ex1) ^ ext4_ext_is_uninitialized(ex2)) | 1116 | if (ext4_ext_is_uninitialized(ex1) ^ ext4_ext_is_uninitialized(ex2)) |
1117 | return 0; | 1117 | return 0; |
1118 | 1118 | ||
1119 | if (ext4_ext_is_uninitialized(ex1)) | ||
1120 | max_len = EXT_UNINIT_MAX_LEN; | ||
1121 | else | ||
1122 | max_len = EXT_INIT_MAX_LEN; | ||
1123 | |||
1119 | ext1_ee_len = ext4_ext_get_actual_len(ex1); | 1124 | ext1_ee_len = ext4_ext_get_actual_len(ex1); |
1120 | ext2_ee_len = ext4_ext_get_actual_len(ex2); | 1125 | ext2_ee_len = ext4_ext_get_actual_len(ex2); |
1121 | 1126 | ||
@@ -1128,7 +1133,7 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1, | |||
1128 | * as an RO_COMPAT feature, refuse to merge to extents if | 1133 | * as an RO_COMPAT feature, refuse to merge to extents if |
1129 | * this can result in the top bit of ee_len being set. | 1134 | * this can result in the top bit of ee_len being set. |
1130 | */ | 1135 | */ |
1131 | if (ext1_ee_len + ext2_ee_len > EXT_MAX_LEN) | 1136 | if (ext1_ee_len + ext2_ee_len > max_len) |
1132 | return 0; | 1137 | return 0; |
1133 | #ifdef AGGRESSIVE_TEST | 1138 | #ifdef AGGRESSIVE_TEST |
1134 | if (le16_to_cpu(ex1->ee_len) >= 4) | 1139 | if (le16_to_cpu(ex1->ee_len) >= 4) |
@@ -1815,7 +1820,11 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, | |||
1815 | 1820 | ||
1816 | ex->ee_block = cpu_to_le32(block); | 1821 | ex->ee_block = cpu_to_le32(block); |
1817 | ex->ee_len = cpu_to_le16(num); | 1822 | ex->ee_len = cpu_to_le16(num); |
1818 | if (uninitialized) | 1823 | /* |
1824 | * Do not mark uninitialized if all the blocks in the | ||
1825 | * extent have been removed. | ||
1826 | */ | ||
1827 | if (uninitialized && num) | ||
1819 | ext4_ext_mark_uninitialized(ex); | 1828 | ext4_ext_mark_uninitialized(ex); |
1820 | 1829 | ||
1821 | err = ext4_ext_dirty(handle, inode, path + depth); | 1830 | err = ext4_ext_dirty(handle, inode, path + depth); |
@@ -2308,6 +2317,19 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
2308 | /* allocate new block */ | 2317 | /* allocate new block */ |
2309 | goal = ext4_ext_find_goal(inode, path, iblock); | 2318 | goal = ext4_ext_find_goal(inode, path, iblock); |
2310 | 2319 | ||
2320 | /* | ||
2321 | * See if request is beyond maximum number of blocks we can have in | ||
2322 | * a single extent. For an initialized extent this limit is | ||
2323 | * EXT_INIT_MAX_LEN and for an uninitialized extent this limit is | ||
2324 | * EXT_UNINIT_MAX_LEN. | ||
2325 | */ | ||
2326 | if (max_blocks > EXT_INIT_MAX_LEN && | ||
2327 | create != EXT4_CREATE_UNINITIALIZED_EXT) | ||
2328 | max_blocks = EXT_INIT_MAX_LEN; | ||
2329 | else if (max_blocks > EXT_UNINIT_MAX_LEN && | ||
2330 | create == EXT4_CREATE_UNINITIALIZED_EXT) | ||
2331 | max_blocks = EXT_UNINIT_MAX_LEN; | ||
2332 | |||
2311 | /* Check if we can really insert (iblock)::(iblock+max_blocks) extent */ | 2333 | /* Check if we can really insert (iblock)::(iblock+max_blocks) extent */ |
2312 | newex.ee_block = cpu_to_le32(iblock); | 2334 | newex.ee_block = cpu_to_le32(iblock); |
2313 | newex.ee_len = cpu_to_le16(max_blocks); | 2335 | newex.ee_len = cpu_to_le16(max_blocks); |