diff options
| -rw-r--r-- | fs/ext4/ext4_extents.h | 7 | ||||
| -rw-r--r-- | fs/ext4/extents.c | 34 | ||||
| -rw-r--r-- | fs/ext4/move_extent.c | 10 | ||||
| -rw-r--r-- | fs/ext4/super.c | 15 |
4 files changed, 39 insertions, 27 deletions
diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h index 2e29abb30f76..476414644387 100644 --- a/fs/ext4/ext4_extents.h +++ b/fs/ext4/ext4_extents.h | |||
| @@ -133,8 +133,11 @@ typedef int (*ext_prepare_callback)(struct inode *, struct ext4_ext_path *, | |||
| 133 | #define EXT_BREAK 1 | 133 | #define EXT_BREAK 1 |
| 134 | #define EXT_REPEAT 2 | 134 | #define EXT_REPEAT 2 |
| 135 | 135 | ||
| 136 | /* Maximum logical block in a file; ext4_extent's ee_block is __le32 */ | 136 | /* |
| 137 | #define EXT_MAX_BLOCK 0xffffffff | 137 | * Maximum number of logical blocks in a file; ext4_extent's ee_block is |
| 138 | * __le32. | ||
| 139 | */ | ||
| 140 | #define EXT_MAX_BLOCKS 0xffffffff | ||
| 138 | 141 | ||
| 139 | /* | 142 | /* |
| 140 | * EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an | 143 | * EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 5199bac7fc62..41575704600a 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -1408,7 +1408,7 @@ got_index: | |||
| 1408 | 1408 | ||
| 1409 | /* | 1409 | /* |
| 1410 | * ext4_ext_next_allocated_block: | 1410 | * ext4_ext_next_allocated_block: |
| 1411 | * returns allocated block in subsequent extent or EXT_MAX_BLOCK. | 1411 | * returns allocated block in subsequent extent or EXT_MAX_BLOCKS. |
| 1412 | * NOTE: it considers block number from index entry as | 1412 | * NOTE: it considers block number from index entry as |
| 1413 | * allocated block. Thus, index entries have to be consistent | 1413 | * allocated block. Thus, index entries have to be consistent |
| 1414 | * with leaves. | 1414 | * with leaves. |
| @@ -1422,7 +1422,7 @@ ext4_ext_next_allocated_block(struct ext4_ext_path *path) | |||
| 1422 | depth = path->p_depth; | 1422 | depth = path->p_depth; |
| 1423 | 1423 | ||
| 1424 | if (depth == 0 && path->p_ext == NULL) | 1424 | if (depth == 0 && path->p_ext == NULL) |
| 1425 | return EXT_MAX_BLOCK; | 1425 | return EXT_MAX_BLOCKS; |
| 1426 | 1426 | ||
| 1427 | while (depth >= 0) { | 1427 | while (depth >= 0) { |
| 1428 | if (depth == path->p_depth) { | 1428 | if (depth == path->p_depth) { |
| @@ -1439,12 +1439,12 @@ ext4_ext_next_allocated_block(struct ext4_ext_path *path) | |||
| 1439 | depth--; | 1439 | depth--; |
| 1440 | } | 1440 | } |
| 1441 | 1441 | ||
| 1442 | return EXT_MAX_BLOCK; | 1442 | return EXT_MAX_BLOCKS; |
| 1443 | } | 1443 | } |
| 1444 | 1444 | ||
| 1445 | /* | 1445 | /* |
| 1446 | * ext4_ext_next_leaf_block: | 1446 | * ext4_ext_next_leaf_block: |
| 1447 | * returns first allocated block from next leaf or EXT_MAX_BLOCK | 1447 | * returns first allocated block from next leaf or EXT_MAX_BLOCKS |
| 1448 | */ | 1448 | */ |
| 1449 | static ext4_lblk_t ext4_ext_next_leaf_block(struct inode *inode, | 1449 | static ext4_lblk_t ext4_ext_next_leaf_block(struct inode *inode, |
| 1450 | struct ext4_ext_path *path) | 1450 | struct ext4_ext_path *path) |
| @@ -1456,7 +1456,7 @@ static ext4_lblk_t ext4_ext_next_leaf_block(struct inode *inode, | |||
| 1456 | 1456 | ||
| 1457 | /* zero-tree has no leaf blocks at all */ | 1457 | /* zero-tree has no leaf blocks at all */ |
| 1458 | if (depth == 0) | 1458 | if (depth == 0) |
| 1459 | return EXT_MAX_BLOCK; | 1459 | return EXT_MAX_BLOCKS; |
| 1460 | 1460 | ||
| 1461 | /* go to index block */ | 1461 | /* go to index block */ |
| 1462 | depth--; | 1462 | depth--; |
| @@ -1469,7 +1469,7 @@ static ext4_lblk_t ext4_ext_next_leaf_block(struct inode *inode, | |||
| 1469 | depth--; | 1469 | depth--; |
| 1470 | } | 1470 | } |
| 1471 | 1471 | ||
| 1472 | return EXT_MAX_BLOCK; | 1472 | return EXT_MAX_BLOCKS; |
| 1473 | } | 1473 | } |
| 1474 | 1474 | ||
| 1475 | /* | 1475 | /* |
| @@ -1677,13 +1677,13 @@ static unsigned int ext4_ext_check_overlap(struct inode *inode, | |||
| 1677 | */ | 1677 | */ |
| 1678 | if (b2 < b1) { | 1678 | if (b2 < b1) { |
| 1679 | b2 = ext4_ext_next_allocated_block(path); | 1679 | b2 = ext4_ext_next_allocated_block(path); |
| 1680 | if (b2 == EXT_MAX_BLOCK) | 1680 | if (b2 == EXT_MAX_BLOCKS) |
| 1681 | goto out; | 1681 | goto out; |
| 1682 | } | 1682 | } |
| 1683 | 1683 | ||
| 1684 | /* check for wrap through zero on extent logical start block*/ | 1684 | /* check for wrap through zero on extent logical start block*/ |
| 1685 | if (b1 + len1 < b1) { | 1685 | if (b1 + len1 < b1) { |
| 1686 | len1 = EXT_MAX_BLOCK - b1; | 1686 | len1 = EXT_MAX_BLOCKS - b1; |
| 1687 | newext->ee_len = cpu_to_le16(len1); | 1687 | newext->ee_len = cpu_to_le16(len1); |
| 1688 | ret = 1; | 1688 | ret = 1; |
| 1689 | } | 1689 | } |
| @@ -1767,7 +1767,7 @@ repeat: | |||
| 1767 | fex = EXT_LAST_EXTENT(eh); | 1767 | fex = EXT_LAST_EXTENT(eh); |
| 1768 | next = ext4_ext_next_leaf_block(inode, path); | 1768 | next = ext4_ext_next_leaf_block(inode, path); |
| 1769 | if (le32_to_cpu(newext->ee_block) > le32_to_cpu(fex->ee_block) | 1769 | if (le32_to_cpu(newext->ee_block) > le32_to_cpu(fex->ee_block) |
| 1770 | && next != EXT_MAX_BLOCK) { | 1770 | && next != EXT_MAX_BLOCKS) { |
| 1771 | ext_debug("next leaf block - %d\n", next); | 1771 | ext_debug("next leaf block - %d\n", next); |
| 1772 | BUG_ON(npath != NULL); | 1772 | BUG_ON(npath != NULL); |
| 1773 | npath = ext4_ext_find_extent(inode, next, NULL); | 1773 | npath = ext4_ext_find_extent(inode, next, NULL); |
| @@ -1887,7 +1887,7 @@ static int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block, | |||
| 1887 | BUG_ON(func == NULL); | 1887 | BUG_ON(func == NULL); |
| 1888 | BUG_ON(inode == NULL); | 1888 | BUG_ON(inode == NULL); |
| 1889 | 1889 | ||
| 1890 | while (block < last && block != EXT_MAX_BLOCK) { | 1890 | while (block < last && block != EXT_MAX_BLOCKS) { |
| 1891 | num = last - block; | 1891 | num = last - block; |
| 1892 | /* find extent for this block */ | 1892 | /* find extent for this block */ |
| 1893 | down_read(&EXT4_I(inode)->i_data_sem); | 1893 | down_read(&EXT4_I(inode)->i_data_sem); |
| @@ -2020,7 +2020,7 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path, | |||
| 2020 | if (ex == NULL) { | 2020 | if (ex == NULL) { |
| 2021 | /* there is no extent yet, so gap is [0;-] */ | 2021 | /* there is no extent yet, so gap is [0;-] */ |
| 2022 | lblock = 0; | 2022 | lblock = 0; |
| 2023 | len = EXT_MAX_BLOCK; | 2023 | len = EXT_MAX_BLOCKS; |
| 2024 | ext_debug("cache gap(whole file):"); | 2024 | ext_debug("cache gap(whole file):"); |
| 2025 | } else if (block < le32_to_cpu(ex->ee_block)) { | 2025 | } else if (block < le32_to_cpu(ex->ee_block)) { |
| 2026 | lblock = block; | 2026 | lblock = block; |
| @@ -2350,7 +2350,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, | |||
| 2350 | * never happen because at least one of the end points | 2350 | * never happen because at least one of the end points |
| 2351 | * needs to be on the edge of the extent. | 2351 | * needs to be on the edge of the extent. |
| 2352 | */ | 2352 | */ |
| 2353 | if (end == EXT_MAX_BLOCK) { | 2353 | if (end == EXT_MAX_BLOCKS - 1) { |
| 2354 | ext_debug(" bad truncate %u:%u\n", | 2354 | ext_debug(" bad truncate %u:%u\n", |
| 2355 | start, end); | 2355 | start, end); |
| 2356 | block = 0; | 2356 | block = 0; |
| @@ -2398,7 +2398,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, | |||
| 2398 | * If this is a truncate, this condition | 2398 | * If this is a truncate, this condition |
| 2399 | * should never happen | 2399 | * should never happen |
| 2400 | */ | 2400 | */ |
| 2401 | if (end == EXT_MAX_BLOCK) { | 2401 | if (end == EXT_MAX_BLOCKS - 1) { |
| 2402 | ext_debug(" bad truncate %u:%u\n", | 2402 | ext_debug(" bad truncate %u:%u\n", |
| 2403 | start, end); | 2403 | start, end); |
| 2404 | err = -EIO; | 2404 | err = -EIO; |
| @@ -2478,7 +2478,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, | |||
| 2478 | * we need to remove it from the leaf | 2478 | * we need to remove it from the leaf |
| 2479 | */ | 2479 | */ |
| 2480 | if (num == 0) { | 2480 | if (num == 0) { |
| 2481 | if (end != EXT_MAX_BLOCK) { | 2481 | if (end != EXT_MAX_BLOCKS - 1) { |
| 2482 | /* | 2482 | /* |
| 2483 | * For hole punching, we need to scoot all the | 2483 | * For hole punching, we need to scoot all the |
| 2484 | * extents up when an extent is removed so that | 2484 | * extents up when an extent is removed so that |
| @@ -3699,7 +3699,7 @@ void ext4_ext_truncate(struct inode *inode) | |||
| 3699 | 3699 | ||
| 3700 | last_block = (inode->i_size + sb->s_blocksize - 1) | 3700 | last_block = (inode->i_size + sb->s_blocksize - 1) |
| 3701 | >> EXT4_BLOCK_SIZE_BITS(sb); | 3701 | >> EXT4_BLOCK_SIZE_BITS(sb); |
| 3702 | err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCK); | 3702 | err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1); |
| 3703 | 3703 | ||
| 3704 | /* In a multi-transaction truncate, we only make the final | 3704 | /* In a multi-transaction truncate, we only make the final |
| 3705 | * transaction synchronous. | 3705 | * transaction synchronous. |
| @@ -4347,8 +4347,8 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
| 4347 | 4347 | ||
| 4348 | start_blk = start >> inode->i_sb->s_blocksize_bits; | 4348 | start_blk = start >> inode->i_sb->s_blocksize_bits; |
| 4349 | last_blk = (start + len - 1) >> inode->i_sb->s_blocksize_bits; | 4349 | last_blk = (start + len - 1) >> inode->i_sb->s_blocksize_bits; |
| 4350 | if (last_blk >= EXT_MAX_BLOCK) | 4350 | if (last_blk >= EXT_MAX_BLOCKS) |
| 4351 | last_blk = EXT_MAX_BLOCK-1; | 4351 | last_blk = EXT_MAX_BLOCKS-1; |
| 4352 | len_blks = ((ext4_lblk_t) last_blk) - start_blk + 1; | 4352 | len_blks = ((ext4_lblk_t) last_blk) - start_blk + 1; |
| 4353 | 4353 | ||
| 4354 | /* | 4354 | /* |
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 2b8304bf3c50..f57455a1b1b2 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c | |||
| @@ -1002,12 +1002,12 @@ mext_check_arguments(struct inode *orig_inode, | |||
| 1002 | return -EINVAL; | 1002 | return -EINVAL; |
| 1003 | } | 1003 | } |
| 1004 | 1004 | ||
| 1005 | if ((orig_start > EXT_MAX_BLOCK) || | 1005 | if ((orig_start >= EXT_MAX_BLOCKS) || |
| 1006 | (donor_start > EXT_MAX_BLOCK) || | 1006 | (donor_start >= EXT_MAX_BLOCKS) || |
| 1007 | (*len > EXT_MAX_BLOCK) || | 1007 | (*len > EXT_MAX_BLOCKS) || |
| 1008 | (orig_start + *len > EXT_MAX_BLOCK)) { | 1008 | (orig_start + *len >= EXT_MAX_BLOCKS)) { |
| 1009 | ext4_debug("ext4 move extent: Can't handle over [%u] blocks " | 1009 | ext4_debug("ext4 move extent: Can't handle over [%u] blocks " |
| 1010 | "[ino:orig %lu, donor %lu]\n", EXT_MAX_BLOCK, | 1010 | "[ino:orig %lu, donor %lu]\n", EXT_MAX_BLOCKS, |
| 1011 | orig_inode->i_ino, donor_inode->i_ino); | 1011 | orig_inode->i_ino, donor_inode->i_ino); |
| 1012 | return -EINVAL; | 1012 | return -EINVAL; |
| 1013 | } | 1013 | } |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index cc5c157aa11d..9ea71aa864b3 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -2243,6 +2243,12 @@ static void ext4_orphan_cleanup(struct super_block *sb, | |||
| 2243 | * in the vfs. ext4 inode has 48 bits of i_block in fsblock units, | 2243 | * in the vfs. ext4 inode has 48 bits of i_block in fsblock units, |
| 2244 | * so that won't be a limiting factor. | 2244 | * so that won't be a limiting factor. |
| 2245 | * | 2245 | * |
| 2246 | * However there is other limiting factor. We do store extents in the form | ||
| 2247 | * of starting block and length, hence the resulting length of the extent | ||
| 2248 | * covering maximum file size must fit into on-disk format containers as | ||
| 2249 | * well. Given that length is always by 1 unit bigger than max unit (because | ||
| 2250 | * we count 0 as well) we have to lower the s_maxbytes by one fs block. | ||
| 2251 | * | ||
| 2246 | * Note, this does *not* consider any metadata overhead for vfs i_blocks. | 2252 | * Note, this does *not* consider any metadata overhead for vfs i_blocks. |
| 2247 | */ | 2253 | */ |
| 2248 | static loff_t ext4_max_size(int blkbits, int has_huge_files) | 2254 | static loff_t ext4_max_size(int blkbits, int has_huge_files) |
| @@ -2264,10 +2270,13 @@ static loff_t ext4_max_size(int blkbits, int has_huge_files) | |||
| 2264 | upper_limit <<= blkbits; | 2270 | upper_limit <<= blkbits; |
| 2265 | } | 2271 | } |
| 2266 | 2272 | ||
| 2267 | /* 32-bit extent-start container, ee_block */ | 2273 | /* |
| 2268 | res = 1LL << 32; | 2274 | * 32-bit extent-start container, ee_block. We lower the maxbytes |
| 2275 | * by one fs block, so ee_len can cover the extent of maximum file | ||
| 2276 | * size | ||
| 2277 | */ | ||
| 2278 | res = (1LL << 32) - 1; | ||
| 2269 | res <<= blkbits; | 2279 | res <<= blkbits; |
| 2270 | res -= 1; | ||
| 2271 | 2280 | ||
| 2272 | /* Sanity check against vm- & vfs- imposed limits */ | 2281 | /* Sanity check against vm- & vfs- imposed limits */ |
| 2273 | if (res > upper_limit) | 2282 | if (res > upper_limit) |
