diff options
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/inode.c | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 25f809dc45a3..89b59cb7f9b8 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -1182,6 +1182,17 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock) | |||
1182 | struct ext4_inode_info *ei = EXT4_I(inode); | 1182 | struct ext4_inode_info *ei = EXT4_I(inode); |
1183 | unsigned int md_needed; | 1183 | unsigned int md_needed; |
1184 | int ret; | 1184 | int ret; |
1185 | ext4_lblk_t save_last_lblock; | ||
1186 | int save_len; | ||
1187 | |||
1188 | /* | ||
1189 | * We will charge metadata quota at writeout time; this saves | ||
1190 | * us from metadata over-estimation, though we may go over by | ||
1191 | * a small amount in the end. Here we just reserve for data. | ||
1192 | */ | ||
1193 | ret = dquot_reserve_block(inode, EXT4_C2B(sbi, 1)); | ||
1194 | if (ret) | ||
1195 | return ret; | ||
1185 | 1196 | ||
1186 | /* | 1197 | /* |
1187 | * recalculate the amount of metadata blocks to reserve | 1198 | * recalculate the amount of metadata blocks to reserve |
@@ -1190,32 +1201,31 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock) | |||
1190 | */ | 1201 | */ |
1191 | repeat: | 1202 | repeat: |
1192 | spin_lock(&ei->i_block_reservation_lock); | 1203 | spin_lock(&ei->i_block_reservation_lock); |
1204 | /* | ||
1205 | * ext4_calc_metadata_amount() has side effects, which we have | ||
1206 | * to be prepared undo if we fail to claim space. | ||
1207 | */ | ||
1208 | save_len = ei->i_da_metadata_calc_len; | ||
1209 | save_last_lblock = ei->i_da_metadata_calc_last_lblock; | ||
1193 | md_needed = EXT4_NUM_B2C(sbi, | 1210 | md_needed = EXT4_NUM_B2C(sbi, |
1194 | ext4_calc_metadata_amount(inode, lblock)); | 1211 | ext4_calc_metadata_amount(inode, lblock)); |
1195 | trace_ext4_da_reserve_space(inode, md_needed); | 1212 | trace_ext4_da_reserve_space(inode, md_needed); |
1196 | spin_unlock(&ei->i_block_reservation_lock); | ||
1197 | 1213 | ||
1198 | /* | 1214 | /* |
1199 | * We will charge metadata quota at writeout time; this saves | ||
1200 | * us from metadata over-estimation, though we may go over by | ||
1201 | * a small amount in the end. Here we just reserve for data. | ||
1202 | */ | ||
1203 | ret = dquot_reserve_block(inode, EXT4_C2B(sbi, 1)); | ||
1204 | if (ret) | ||
1205 | return ret; | ||
1206 | /* | ||
1207 | * We do still charge estimated metadata to the sb though; | 1215 | * We do still charge estimated metadata to the sb though; |
1208 | * we cannot afford to run out of free blocks. | 1216 | * we cannot afford to run out of free blocks. |
1209 | */ | 1217 | */ |
1210 | if (ext4_claim_free_clusters(sbi, md_needed + 1, 0)) { | 1218 | if (ext4_claim_free_clusters(sbi, md_needed + 1, 0)) { |
1211 | dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1)); | 1219 | ei->i_da_metadata_calc_len = save_len; |
1220 | ei->i_da_metadata_calc_last_lblock = save_last_lblock; | ||
1221 | spin_unlock(&ei->i_block_reservation_lock); | ||
1212 | if (ext4_should_retry_alloc(inode->i_sb, &retries)) { | 1222 | if (ext4_should_retry_alloc(inode->i_sb, &retries)) { |
1213 | yield(); | 1223 | yield(); |
1214 | goto repeat; | 1224 | goto repeat; |
1215 | } | 1225 | } |
1226 | dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1)); | ||
1216 | return -ENOSPC; | 1227 | return -ENOSPC; |
1217 | } | 1228 | } |
1218 | spin_lock(&ei->i_block_reservation_lock); | ||
1219 | ei->i_reserved_data_blocks++; | 1229 | ei->i_reserved_data_blocks++; |
1220 | ei->i_reserved_meta_blocks += md_needed; | 1230 | ei->i_reserved_meta_blocks += md_needed; |
1221 | spin_unlock(&ei->i_block_reservation_lock); | 1231 | spin_unlock(&ei->i_block_reservation_lock); |