aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/inode.c
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2010-01-25 04:00:31 -0500
committerTheodore Ts'o <tytso@mit.edu>2010-01-25 04:00:31 -0500
commit5f634d064c709ea02c3cdaa850a08323a4a4bf28 (patch)
tree3f81e9c56cd8348b7bb94f1d54efff696374c929 /fs/ext4/inode.c
parent1db913823c0f8360fccbd24ca67eb073966a5ffd (diff)
ext4: Fix quota accounting error with fallocate
When we fallocate a region of the file which we had recently written, and which is still in the page cache marked as delayed allocated blocks we need to make sure we don't do the quota update on writepage path. This is because the needed quota updated would have already be done by fallocate. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r--fs/ext4/inode.c44
1 files changed, 31 insertions, 13 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 60b3a19e9927..c955f6490b78 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1053,11 +1053,12 @@ static int ext4_calc_metadata_amount(struct inode *inode, sector_t lblock)
1053 * Called with i_data_sem down, which is important since we can call 1053 * Called with i_data_sem down, which is important since we can call
1054 * ext4_discard_preallocations() from here. 1054 * ext4_discard_preallocations() from here.
1055 */ 1055 */
1056static void ext4_da_update_reserve_space(struct inode *inode, int used) 1056void ext4_da_update_reserve_space(struct inode *inode,
1057 int used, int quota_claim)
1057{ 1058{
1058 struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); 1059 struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
1059 struct ext4_inode_info *ei = EXT4_I(inode); 1060 struct ext4_inode_info *ei = EXT4_I(inode);
1060 int mdb_free = 0; 1061 int mdb_free = 0, allocated_meta_blocks = 0;
1061 1062
1062 spin_lock(&ei->i_block_reservation_lock); 1063 spin_lock(&ei->i_block_reservation_lock);
1063 if (unlikely(used > ei->i_reserved_data_blocks)) { 1064 if (unlikely(used > ei->i_reserved_data_blocks)) {
@@ -1073,6 +1074,7 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
1073 ei->i_reserved_data_blocks -= used; 1074 ei->i_reserved_data_blocks -= used;
1074 used += ei->i_allocated_meta_blocks; 1075 used += ei->i_allocated_meta_blocks;
1075 ei->i_reserved_meta_blocks -= ei->i_allocated_meta_blocks; 1076 ei->i_reserved_meta_blocks -= ei->i_allocated_meta_blocks;
1077 allocated_meta_blocks = ei->i_allocated_meta_blocks;
1076 ei->i_allocated_meta_blocks = 0; 1078 ei->i_allocated_meta_blocks = 0;
1077 percpu_counter_sub(&sbi->s_dirtyblocks_counter, used); 1079 percpu_counter_sub(&sbi->s_dirtyblocks_counter, used);
1078 1080
@@ -1090,9 +1092,23 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used)
1090 spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); 1092 spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
1091 1093
1092 /* Update quota subsystem */ 1094 /* Update quota subsystem */
1093 vfs_dq_claim_block(inode, used); 1095 if (quota_claim) {
1094 if (mdb_free) 1096 vfs_dq_claim_block(inode, used);
1095 vfs_dq_release_reservation_block(inode, mdb_free); 1097 if (mdb_free)
1098 vfs_dq_release_reservation_block(inode, mdb_free);
1099 } else {
1100 /*
1101 * We did fallocate with an offset that is already delayed
1102 * allocated. So on delayed allocated writeback we should
1103 * not update the quota for allocated blocks. But then
1104 * converting an fallocate region to initialized region would
1105 * have caused a metadata allocation. So claim quota for
1106 * that
1107 */
1108 if (allocated_meta_blocks)
1109 vfs_dq_claim_block(inode, allocated_meta_blocks);
1110 vfs_dq_release_reservation_block(inode, mdb_free + used);
1111 }
1096 1112
1097 /* 1113 /*
1098 * If we have done all the pending block allocations and if 1114 * If we have done all the pending block allocations and if
@@ -1292,18 +1308,20 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block,
1292 */ 1308 */
1293 EXT4_I(inode)->i_state &= ~EXT4_STATE_EXT_MIGRATE; 1309 EXT4_I(inode)->i_state &= ~EXT4_STATE_EXT_MIGRATE;
1294 } 1310 }
1295 }
1296 1311
1312 /*
1313 * Update reserved blocks/metadata blocks after successful
1314 * block allocation which had been deferred till now. We don't
1315 * support fallocate for non extent files. So we can update
1316 * reserve space here.
1317 */
1318 if ((retval > 0) &&
1319 (flags & EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE))
1320 ext4_da_update_reserve_space(inode, retval, 1);
1321 }
1297 if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) 1322 if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
1298 EXT4_I(inode)->i_delalloc_reserved_flag = 0; 1323 EXT4_I(inode)->i_delalloc_reserved_flag = 0;
1299 1324
1300 /*
1301 * Update reserved blocks/metadata blocks after successful
1302 * block allocation which had been deferred till now.
1303 */
1304 if ((retval > 0) && (flags & EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE))
1305 ext4_da_update_reserve_space(inode, retval);
1306
1307 up_write((&EXT4_I(inode)->i_data_sem)); 1325 up_write((&EXT4_I(inode)->i_data_sem));
1308 if (retval > 0 && buffer_mapped(bh)) { 1326 if (retval > 0 && buffer_mapped(bh)) {
1309 int ret = check_block_validity(inode, "file system " 1327 int ret = check_block_validity(inode, "file system "