diff options
-rw-r--r-- | fs/ext4/ext4.h | 2 | ||||
-rw-r--r-- | fs/ext4/extents.c | 21 | ||||
-rw-r--r-- | fs/ext4/inode.c | 44 |
3 files changed, 54 insertions, 13 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index af7b62699ea9..b98de17e542a 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1443,6 +1443,8 @@ extern int ext4_block_truncate_page(handle_t *handle, | |||
1443 | extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); | 1443 | extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); |
1444 | extern qsize_t *ext4_get_reserved_space(struct inode *inode); | 1444 | extern qsize_t *ext4_get_reserved_space(struct inode *inode); |
1445 | extern int flush_aio_dio_completed_IO(struct inode *inode); | 1445 | extern int flush_aio_dio_completed_IO(struct inode *inode); |
1446 | extern void ext4_da_update_reserve_space(struct inode *inode, | ||
1447 | int used, int quota_claim); | ||
1446 | /* ioctl.c */ | 1448 | /* ioctl.c */ |
1447 | extern long ext4_ioctl(struct file *, unsigned int, unsigned long); | 1449 | extern long ext4_ioctl(struct file *, unsigned int, unsigned long); |
1448 | extern long ext4_compat_ioctl(struct file *, unsigned int, unsigned long); | 1450 | extern long ext4_compat_ioctl(struct file *, unsigned int, unsigned long); |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 7d7b74e94687..3b6ff72026f0 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -3132,7 +3132,19 @@ out: | |||
3132 | unmap_underlying_metadata_blocks(inode->i_sb->s_bdev, | 3132 | unmap_underlying_metadata_blocks(inode->i_sb->s_bdev, |
3133 | newblock + max_blocks, | 3133 | newblock + max_blocks, |
3134 | allocated - max_blocks); | 3134 | allocated - max_blocks); |
3135 | allocated = max_blocks; | ||
3135 | } | 3136 | } |
3137 | |||
3138 | /* | ||
3139 | * If we have done fallocate with the offset that is already | ||
3140 | * delayed allocated, we would have block reservation | ||
3141 | * and quota reservation done in the delayed write path. | ||
3142 | * But fallocate would have already updated quota and block | ||
3143 | * count for this offset. So cancel these reservation | ||
3144 | */ | ||
3145 | if (flags & EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE) | ||
3146 | ext4_da_update_reserve_space(inode, allocated, 0); | ||
3147 | |||
3136 | map_out: | 3148 | map_out: |
3137 | set_buffer_mapped(bh_result); | 3149 | set_buffer_mapped(bh_result); |
3138 | out1: | 3150 | out1: |
@@ -3368,9 +3380,18 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
3368 | /* previous routine could use block we allocated */ | 3380 | /* previous routine could use block we allocated */ |
3369 | newblock = ext_pblock(&newex); | 3381 | newblock = ext_pblock(&newex); |
3370 | allocated = ext4_ext_get_actual_len(&newex); | 3382 | allocated = ext4_ext_get_actual_len(&newex); |
3383 | if (allocated > max_blocks) | ||
3384 | allocated = max_blocks; | ||
3371 | set_buffer_new(bh_result); | 3385 | set_buffer_new(bh_result); |
3372 | 3386 | ||
3373 | /* | 3387 | /* |
3388 | * Update reserved blocks/metadata blocks after successful | ||
3389 | * block allocation which had been deferred till now. | ||
3390 | */ | ||
3391 | if (flags & EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE) | ||
3392 | ext4_da_update_reserve_space(inode, allocated, 1); | ||
3393 | |||
3394 | /* | ||
3374 | * Cache the extent and update transaction to commit on fdatasync only | 3395 | * Cache the extent and update transaction to commit on fdatasync only |
3375 | * when it is _not_ an uninitialized extent. | 3396 | * when it is _not_ an uninitialized extent. |
3376 | */ | 3397 | */ |
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 | */ |
1056 | static void ext4_da_update_reserve_space(struct inode *inode, int used) | 1056 | void 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 " |