diff options
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/extents.c | 37 | ||||
-rw-r--r-- | fs/ext4/ialloc.c | 6 | ||||
-rw-r--r-- | fs/ext4/inode.c | 50 |
3 files changed, 73 insertions, 20 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 2a1cb0979768..e3a55eb8b26a 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -326,11 +326,14 @@ ext4_ext_max_entries(struct inode *inode, int depth) | |||
326 | 326 | ||
327 | static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext) | 327 | static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext) |
328 | { | 328 | { |
329 | ext4_fsblk_t block = ext_pblock(ext); | 329 | ext4_fsblk_t block = ext_pblock(ext), valid_block; |
330 | int len = ext4_ext_get_actual_len(ext); | 330 | int len = ext4_ext_get_actual_len(ext); |
331 | struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es; | 331 | struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es; |
332 | if (unlikely(block < le32_to_cpu(es->s_first_data_block) || | 332 | |
333 | ((block + len) > ext4_blocks_count(es)))) | 333 | valid_block = le32_to_cpu(es->s_first_data_block) + |
334 | EXT4_SB(inode->i_sb)->s_gdb_count; | ||
335 | if (unlikely(block <= valid_block || | ||
336 | ((block + len) > ext4_blocks_count(es)))) | ||
334 | return 0; | 337 | return 0; |
335 | else | 338 | else |
336 | return 1; | 339 | return 1; |
@@ -339,10 +342,13 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext) | |||
339 | static int ext4_valid_extent_idx(struct inode *inode, | 342 | static int ext4_valid_extent_idx(struct inode *inode, |
340 | struct ext4_extent_idx *ext_idx) | 343 | struct ext4_extent_idx *ext_idx) |
341 | { | 344 | { |
342 | ext4_fsblk_t block = idx_pblock(ext_idx); | 345 | ext4_fsblk_t block = idx_pblock(ext_idx), valid_block; |
343 | struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es; | 346 | struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es; |
344 | if (unlikely(block < le32_to_cpu(es->s_first_data_block) || | 347 | |
345 | (block >= ext4_blocks_count(es)))) | 348 | valid_block = le32_to_cpu(es->s_first_data_block) + |
349 | EXT4_SB(inode->i_sb)->s_gdb_count; | ||
350 | if (unlikely(block <= valid_block || | ||
351 | (block >= ext4_blocks_count(es)))) | ||
346 | return 0; | 352 | return 0; |
347 | else | 353 | else |
348 | return 1; | 354 | return 1; |
@@ -1835,11 +1841,13 @@ ext4_ext_put_in_cache(struct inode *inode, ext4_lblk_t block, | |||
1835 | { | 1841 | { |
1836 | struct ext4_ext_cache *cex; | 1842 | struct ext4_ext_cache *cex; |
1837 | BUG_ON(len == 0); | 1843 | BUG_ON(len == 0); |
1844 | spin_lock(&EXT4_I(inode)->i_block_reservation_lock); | ||
1838 | cex = &EXT4_I(inode)->i_cached_extent; | 1845 | cex = &EXT4_I(inode)->i_cached_extent; |
1839 | cex->ec_type = type; | 1846 | cex->ec_type = type; |
1840 | cex->ec_block = block; | 1847 | cex->ec_block = block; |
1841 | cex->ec_len = len; | 1848 | cex->ec_len = len; |
1842 | cex->ec_start = start; | 1849 | cex->ec_start = start; |
1850 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); | ||
1843 | } | 1851 | } |
1844 | 1852 | ||
1845 | /* | 1853 | /* |
@@ -1896,12 +1904,17 @@ ext4_ext_in_cache(struct inode *inode, ext4_lblk_t block, | |||
1896 | struct ext4_extent *ex) | 1904 | struct ext4_extent *ex) |
1897 | { | 1905 | { |
1898 | struct ext4_ext_cache *cex; | 1906 | struct ext4_ext_cache *cex; |
1907 | int ret = EXT4_EXT_CACHE_NO; | ||
1899 | 1908 | ||
1909 | /* | ||
1910 | * We borrow i_block_reservation_lock to protect i_cached_extent | ||
1911 | */ | ||
1912 | spin_lock(&EXT4_I(inode)->i_block_reservation_lock); | ||
1900 | cex = &EXT4_I(inode)->i_cached_extent; | 1913 | cex = &EXT4_I(inode)->i_cached_extent; |
1901 | 1914 | ||
1902 | /* has cache valid data? */ | 1915 | /* has cache valid data? */ |
1903 | if (cex->ec_type == EXT4_EXT_CACHE_NO) | 1916 | if (cex->ec_type == EXT4_EXT_CACHE_NO) |
1904 | return EXT4_EXT_CACHE_NO; | 1917 | goto errout; |
1905 | 1918 | ||
1906 | BUG_ON(cex->ec_type != EXT4_EXT_CACHE_GAP && | 1919 | BUG_ON(cex->ec_type != EXT4_EXT_CACHE_GAP && |
1907 | cex->ec_type != EXT4_EXT_CACHE_EXTENT); | 1920 | cex->ec_type != EXT4_EXT_CACHE_EXTENT); |
@@ -1912,11 +1925,11 @@ ext4_ext_in_cache(struct inode *inode, ext4_lblk_t block, | |||
1912 | ext_debug("%u cached by %u:%u:%llu\n", | 1925 | ext_debug("%u cached by %u:%u:%llu\n", |
1913 | block, | 1926 | block, |
1914 | cex->ec_block, cex->ec_len, cex->ec_start); | 1927 | cex->ec_block, cex->ec_len, cex->ec_start); |
1915 | return cex->ec_type; | 1928 | ret = cex->ec_type; |
1916 | } | 1929 | } |
1917 | 1930 | errout: | |
1918 | /* not in cache */ | 1931 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); |
1919 | return EXT4_EXT_CACHE_NO; | 1932 | return ret; |
1920 | } | 1933 | } |
1921 | 1934 | ||
1922 | /* | 1935 | /* |
@@ -2869,6 +2882,8 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
2869 | if (allocated > max_blocks) | 2882 | if (allocated > max_blocks) |
2870 | allocated = max_blocks; | 2883 | allocated = max_blocks; |
2871 | set_buffer_unwritten(bh_result); | 2884 | set_buffer_unwritten(bh_result); |
2885 | bh_result->b_bdev = inode->i_sb->s_bdev; | ||
2886 | bh_result->b_blocknr = newblock; | ||
2872 | goto out2; | 2887 | goto out2; |
2873 | } | 2888 | } |
2874 | 2889 | ||
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 47b84e8df568..f18e0a08a6b5 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -585,6 +585,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, | |||
585 | fallback: | 585 | fallback: |
586 | ngroups = sbi->s_groups_count; | 586 | ngroups = sbi->s_groups_count; |
587 | avefreei = freei / ngroups; | 587 | avefreei = freei / ngroups; |
588 | fallback_retry: | ||
588 | parent_group = EXT4_I(parent)->i_block_group; | 589 | parent_group = EXT4_I(parent)->i_block_group; |
589 | for (i = 0; i < ngroups; i++) { | 590 | for (i = 0; i < ngroups; i++) { |
590 | grp = (parent_group + i) % ngroups; | 591 | grp = (parent_group + i) % ngroups; |
@@ -602,7 +603,7 @@ fallback: | |||
602 | * filesystems the above test can fail to find any blockgroups | 603 | * filesystems the above test can fail to find any blockgroups |
603 | */ | 604 | */ |
604 | avefreei = 0; | 605 | avefreei = 0; |
605 | goto fallback; | 606 | goto fallback_retry; |
606 | } | 607 | } |
607 | 608 | ||
608 | return -1; | 609 | return -1; |
@@ -831,11 +832,12 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode) | |||
831 | ret2 = find_group_flex(sb, dir, &group); | 832 | ret2 = find_group_flex(sb, dir, &group); |
832 | if (ret2 == -1) { | 833 | if (ret2 == -1) { |
833 | ret2 = find_group_other(sb, dir, &group, mode); | 834 | ret2 = find_group_other(sb, dir, &group, mode); |
834 | if (ret2 == 0 && once) | 835 | if (ret2 == 0 && once) { |
835 | once = 0; | 836 | once = 0; |
836 | printk(KERN_NOTICE "ext4: find_group_flex " | 837 | printk(KERN_NOTICE "ext4: find_group_flex " |
837 | "failed, fallback succeeded dir %lu\n", | 838 | "failed, fallback succeeded dir %lu\n", |
838 | dir->i_ino); | 839 | dir->i_ino); |
840 | } | ||
839 | } | 841 | } |
840 | goto got_group; | 842 | goto got_group; |
841 | } | 843 | } |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index c6bd6ced3bb7..2a9ffd528dd1 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -1149,6 +1149,7 @@ int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block, | |||
1149 | int retval; | 1149 | int retval; |
1150 | 1150 | ||
1151 | clear_buffer_mapped(bh); | 1151 | clear_buffer_mapped(bh); |
1152 | clear_buffer_unwritten(bh); | ||
1152 | 1153 | ||
1153 | /* | 1154 | /* |
1154 | * Try to see if we can get the block without requesting | 1155 | * Try to see if we can get the block without requesting |
@@ -1179,6 +1180,18 @@ int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block, | |||
1179 | return retval; | 1180 | return retval; |
1180 | 1181 | ||
1181 | /* | 1182 | /* |
1183 | * When we call get_blocks without the create flag, the | ||
1184 | * BH_Unwritten flag could have gotten set if the blocks | ||
1185 | * requested were part of a uninitialized extent. We need to | ||
1186 | * clear this flag now that we are committed to convert all or | ||
1187 | * part of the uninitialized extent to be an initialized | ||
1188 | * extent. This is because we need to avoid the combination | ||
1189 | * of BH_Unwritten and BH_Mapped flags being simultaneously | ||
1190 | * set on the buffer_head. | ||
1191 | */ | ||
1192 | clear_buffer_unwritten(bh); | ||
1193 | |||
1194 | /* | ||
1182 | * New blocks allocate and/or writing to uninitialized extent | 1195 | * New blocks allocate and/or writing to uninitialized extent |
1183 | * will possibly result in updating i_data, so we take | 1196 | * will possibly result in updating i_data, so we take |
1184 | * the write lock of i_data_sem, and call get_blocks() | 1197 | * the write lock of i_data_sem, and call get_blocks() |
@@ -2297,6 +2310,10 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock, | |||
2297 | struct buffer_head *bh_result, int create) | 2310 | struct buffer_head *bh_result, int create) |
2298 | { | 2311 | { |
2299 | int ret = 0; | 2312 | int ret = 0; |
2313 | sector_t invalid_block = ~((sector_t) 0xffff); | ||
2314 | |||
2315 | if (invalid_block < ext4_blocks_count(EXT4_SB(inode->i_sb)->s_es)) | ||
2316 | invalid_block = ~0; | ||
2300 | 2317 | ||
2301 | BUG_ON(create == 0); | 2318 | BUG_ON(create == 0); |
2302 | BUG_ON(bh_result->b_size != inode->i_sb->s_blocksize); | 2319 | BUG_ON(bh_result->b_size != inode->i_sb->s_blocksize); |
@@ -2318,11 +2335,18 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock, | |||
2318 | /* not enough space to reserve */ | 2335 | /* not enough space to reserve */ |
2319 | return ret; | 2336 | return ret; |
2320 | 2337 | ||
2321 | map_bh(bh_result, inode->i_sb, 0); | 2338 | map_bh(bh_result, inode->i_sb, invalid_block); |
2322 | set_buffer_new(bh_result); | 2339 | set_buffer_new(bh_result); |
2323 | set_buffer_delay(bh_result); | 2340 | set_buffer_delay(bh_result); |
2324 | } else if (ret > 0) { | 2341 | } else if (ret > 0) { |
2325 | bh_result->b_size = (ret << inode->i_blkbits); | 2342 | bh_result->b_size = (ret << inode->i_blkbits); |
2343 | /* | ||
2344 | * With sub-block writes into unwritten extents | ||
2345 | * we also need to mark the buffer as new so that | ||
2346 | * the unwritten parts of the buffer gets correctly zeroed. | ||
2347 | */ | ||
2348 | if (buffer_unwritten(bh_result)) | ||
2349 | set_buffer_new(bh_result); | ||
2326 | ret = 0; | 2350 | ret = 0; |
2327 | } | 2351 | } |
2328 | 2352 | ||
@@ -4357,11 +4381,9 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
4357 | ei->i_flags = le32_to_cpu(raw_inode->i_flags); | 4381 | ei->i_flags = le32_to_cpu(raw_inode->i_flags); |
4358 | inode->i_blocks = ext4_inode_blocks(raw_inode, ei); | 4382 | inode->i_blocks = ext4_inode_blocks(raw_inode, ei); |
4359 | ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl_lo); | 4383 | ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl_lo); |
4360 | if (EXT4_SB(inode->i_sb)->s_es->s_creator_os != | 4384 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT)) |
4361 | cpu_to_le32(EXT4_OS_HURD)) { | ||
4362 | ei->i_file_acl |= | 4385 | ei->i_file_acl |= |
4363 | ((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32; | 4386 | ((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32; |
4364 | } | ||
4365 | inode->i_size = ext4_isize(raw_inode); | 4387 | inode->i_size = ext4_isize(raw_inode); |
4366 | ei->i_disksize = inode->i_size; | 4388 | ei->i_disksize = inode->i_size; |
4367 | inode->i_generation = le32_to_cpu(raw_inode->i_generation); | 4389 | inode->i_generation = le32_to_cpu(raw_inode->i_generation); |
@@ -4409,9 +4431,23 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
4409 | (__u64)(le32_to_cpu(raw_inode->i_version_hi)) << 32; | 4431 | (__u64)(le32_to_cpu(raw_inode->i_version_hi)) << 32; |
4410 | } | 4432 | } |
4411 | 4433 | ||
4412 | if (ei->i_flags & EXT4_EXTENTS_FL) { | 4434 | ret = 0; |
4413 | /* Validate extent which is part of inode */ | 4435 | if (ei->i_file_acl && |
4414 | ret = ext4_ext_check_inode(inode); | 4436 | ((ei->i_file_acl < |
4437 | (le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) + | ||
4438 | EXT4_SB(sb)->s_gdb_count)) || | ||
4439 | (ei->i_file_acl >= ext4_blocks_count(EXT4_SB(sb)->s_es)))) { | ||
4440 | ext4_error(sb, __func__, | ||
4441 | "bad extended attribute block %llu in inode #%lu", | ||
4442 | ei->i_file_acl, inode->i_ino); | ||
4443 | ret = -EIO; | ||
4444 | goto bad_inode; | ||
4445 | } else if (ei->i_flags & EXT4_EXTENTS_FL) { | ||
4446 | if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | ||
4447 | (S_ISLNK(inode->i_mode) && | ||
4448 | !ext4_inode_is_fast_symlink(inode))) | ||
4449 | /* Validate extent which is part of inode */ | ||
4450 | ret = ext4_ext_check_inode(inode); | ||
4415 | } else if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | 4451 | } else if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || |
4416 | (S_ISLNK(inode->i_mode) && | 4452 | (S_ISLNK(inode->i_mode) && |
4417 | !ext4_inode_is_fast_symlink(inode))) { | 4453 | !ext4_inode_is_fast_symlink(inode))) { |