diff options
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r-- | fs/ext4/extents.c | 70 |
1 files changed, 53 insertions, 17 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 91ae46098ea4..765a4826b118 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -296,29 +296,44 @@ static inline int ext4_ext_space_root_idx(struct inode *inode, int check) | |||
296 | * to allocate @blocks | 296 | * to allocate @blocks |
297 | * Worse case is one block per extent | 297 | * Worse case is one block per extent |
298 | */ | 298 | */ |
299 | int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks) | 299 | int ext4_ext_calc_metadata_amount(struct inode *inode, sector_t lblock) |
300 | { | 300 | { |
301 | int lcap, icap, rcap, leafs, idxs, num; | 301 | struct ext4_inode_info *ei = EXT4_I(inode); |
302 | int newextents = blocks; | 302 | int idxs, num = 0; |
303 | |||
304 | rcap = ext4_ext_space_root_idx(inode, 0); | ||
305 | lcap = ext4_ext_space_block(inode, 0); | ||
306 | icap = ext4_ext_space_block_idx(inode, 0); | ||
307 | 303 | ||
308 | /* number of new leaf blocks needed */ | 304 | idxs = ((inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header)) |
309 | num = leafs = (newextents + lcap - 1) / lcap; | 305 | / sizeof(struct ext4_extent_idx)); |
310 | 306 | ||
311 | /* | 307 | /* |
312 | * Worse case, we need separate index block(s) | 308 | * If the new delayed allocation block is contiguous with the |
313 | * to link all new leaf blocks | 309 | * previous da block, it can share index blocks with the |
310 | * previous block, so we only need to allocate a new index | ||
311 | * block every idxs leaf blocks. At ldxs**2 blocks, we need | ||
312 | * an additional index block, and at ldxs**3 blocks, yet | ||
313 | * another index blocks. | ||
314 | */ | 314 | */ |
315 | idxs = (leafs + icap - 1) / icap; | 315 | if (ei->i_da_metadata_calc_len && |
316 | do { | 316 | ei->i_da_metadata_calc_last_lblock+1 == lblock) { |
317 | num += idxs; | 317 | if ((ei->i_da_metadata_calc_len % idxs) == 0) |
318 | idxs = (idxs + icap - 1) / icap; | 318 | num++; |
319 | } while (idxs > rcap); | 319 | if ((ei->i_da_metadata_calc_len % (idxs*idxs)) == 0) |
320 | num++; | ||
321 | if ((ei->i_da_metadata_calc_len % (idxs*idxs*idxs)) == 0) { | ||
322 | num++; | ||
323 | ei->i_da_metadata_calc_len = 0; | ||
324 | } else | ||
325 | ei->i_da_metadata_calc_len++; | ||
326 | ei->i_da_metadata_calc_last_lblock++; | ||
327 | return num; | ||
328 | } | ||
320 | 329 | ||
321 | return num; | 330 | /* |
331 | * In the worst case we need a new set of index blocks at | ||
332 | * every level of the inode's extent tree. | ||
333 | */ | ||
334 | ei->i_da_metadata_calc_len = 1; | ||
335 | ei->i_da_metadata_calc_last_lblock = lblock; | ||
336 | return ext_depth(inode) + 1; | ||
322 | } | 337 | } |
323 | 338 | ||
324 | static int | 339 | static int |
@@ -3117,7 +3132,19 @@ out: | |||
3117 | unmap_underlying_metadata_blocks(inode->i_sb->s_bdev, | 3132 | unmap_underlying_metadata_blocks(inode->i_sb->s_bdev, |
3118 | newblock + max_blocks, | 3133 | newblock + max_blocks, |
3119 | allocated - max_blocks); | 3134 | allocated - max_blocks); |
3135 | allocated = max_blocks; | ||
3120 | } | 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_DELALLOC_RESERVE) | ||
3146 | ext4_da_update_reserve_space(inode, allocated, 0); | ||
3147 | |||
3121 | map_out: | 3148 | map_out: |
3122 | set_buffer_mapped(bh_result); | 3149 | set_buffer_mapped(bh_result); |
3123 | out1: | 3150 | out1: |
@@ -3353,9 +3380,18 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
3353 | /* previous routine could use block we allocated */ | 3380 | /* previous routine could use block we allocated */ |
3354 | newblock = ext_pblock(&newex); | 3381 | newblock = ext_pblock(&newex); |
3355 | allocated = ext4_ext_get_actual_len(&newex); | 3382 | allocated = ext4_ext_get_actual_len(&newex); |
3383 | if (allocated > max_blocks) | ||
3384 | allocated = max_blocks; | ||
3356 | set_buffer_new(bh_result); | 3385 | set_buffer_new(bh_result); |
3357 | 3386 | ||
3358 | /* | 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_DELALLOC_RESERVE) | ||
3392 | ext4_da_update_reserve_space(inode, allocated, 1); | ||
3393 | |||
3394 | /* | ||
3359 | * Cache the extent and update transaction to commit on fdatasync only | 3395 | * Cache the extent and update transaction to commit on fdatasync only |
3360 | * when it is _not_ an uninitialized extent. | 3396 | * when it is _not_ an uninitialized extent. |
3361 | */ | 3397 | */ |