diff options
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r-- | fs/ext4/extents.c | 37 |
1 files changed, 26 insertions, 11 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 | ||