aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/extents.c19
-rw-r--r--fs/ext4/inode.c50
2 files changed, 57 insertions, 12 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index e40332158340..e3a55eb8b26a 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1841,11 +1841,13 @@ ext4_ext_put_in_cache(struct inode *inode, ext4_lblk_t block,
1841{ 1841{
1842 struct ext4_ext_cache *cex; 1842 struct ext4_ext_cache *cex;
1843 BUG_ON(len == 0); 1843 BUG_ON(len == 0);
1844 spin_lock(&EXT4_I(inode)->i_block_reservation_lock);
1844 cex = &EXT4_I(inode)->i_cached_extent; 1845 cex = &EXT4_I(inode)->i_cached_extent;
1845 cex->ec_type = type; 1846 cex->ec_type = type;
1846 cex->ec_block = block; 1847 cex->ec_block = block;
1847 cex->ec_len = len; 1848 cex->ec_len = len;
1848 cex->ec_start = start; 1849 cex->ec_start = start;
1850 spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
1849} 1851}
1850 1852
1851/* 1853/*
@@ -1902,12 +1904,17 @@ ext4_ext_in_cache(struct inode *inode, ext4_lblk_t block,
1902 struct ext4_extent *ex) 1904 struct ext4_extent *ex)
1903{ 1905{
1904 struct ext4_ext_cache *cex; 1906 struct ext4_ext_cache *cex;
1907 int ret = EXT4_EXT_CACHE_NO;
1905 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);
1906 cex = &EXT4_I(inode)->i_cached_extent; 1913 cex = &EXT4_I(inode)->i_cached_extent;
1907 1914
1908 /* has cache valid data? */ 1915 /* has cache valid data? */
1909 if (cex->ec_type == EXT4_EXT_CACHE_NO) 1916 if (cex->ec_type == EXT4_EXT_CACHE_NO)
1910 return EXT4_EXT_CACHE_NO; 1917 goto errout;
1911 1918
1912 BUG_ON(cex->ec_type != EXT4_EXT_CACHE_GAP && 1919 BUG_ON(cex->ec_type != EXT4_EXT_CACHE_GAP &&
1913 cex->ec_type != EXT4_EXT_CACHE_EXTENT); 1920 cex->ec_type != EXT4_EXT_CACHE_EXTENT);
@@ -1918,11 +1925,11 @@ ext4_ext_in_cache(struct inode *inode, ext4_lblk_t block,
1918 ext_debug("%u cached by %u:%u:%llu\n", 1925 ext_debug("%u cached by %u:%u:%llu\n",
1919 block, 1926 block,
1920 cex->ec_block, cex->ec_len, cex->ec_start); 1927 cex->ec_block, cex->ec_len, cex->ec_start);
1921 return cex->ec_type; 1928 ret = cex->ec_type;
1922 } 1929 }
1923 1930errout:
1924 /* not in cache */ 1931 spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
1925 return EXT4_EXT_CACHE_NO; 1932 return ret;
1926} 1933}
1927 1934
1928/* 1935/*
@@ -2875,6 +2882,8 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
2875 if (allocated > max_blocks) 2882 if (allocated > max_blocks)
2876 allocated = max_blocks; 2883 allocated = max_blocks;
2877 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;
2878 goto out2; 2887 goto out2;
2879 } 2888 }
2880 2889
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))) {