diff options
Diffstat (limited to 'fs/ext4/balloc.c')
-rw-r--r-- | fs/ext4/balloc.c | 157 |
1 files changed, 19 insertions, 138 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index bd30799a43ed..264f6949511e 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include "ext4_jbd2.h" | 21 | #include "ext4_jbd2.h" |
22 | #include "mballoc.h" | 22 | #include "mballoc.h" |
23 | 23 | ||
24 | #include <trace/events/ext4.h> | ||
25 | |||
24 | /* | 26 | /* |
25 | * balloc.c contains the blocks allocation and deallocation routines | 27 | * balloc.c contains the blocks allocation and deallocation routines |
26 | */ | 28 | */ |
@@ -171,7 +173,8 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, | |||
171 | * less than the blocksize * 8 ( which is the size | 173 | * less than the blocksize * 8 ( which is the size |
172 | * of bitmap ), set rest of the block bitmap to 1 | 174 | * of bitmap ), set rest of the block bitmap to 1 |
173 | */ | 175 | */ |
174 | mark_bitmap_end(group_blocks, sb->s_blocksize * 8, bh->b_data); | 176 | ext4_mark_bitmap_end(group_blocks, sb->s_blocksize * 8, |
177 | bh->b_data); | ||
175 | } | 178 | } |
176 | return free_blocks - ext4_group_used_meta_blocks(sb, block_group, gdp); | 179 | return free_blocks - ext4_group_used_meta_blocks(sb, block_group, gdp); |
177 | } | 180 | } |
@@ -341,6 +344,7 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group) | |||
341 | * We do it here so the bitmap uptodate bit | 344 | * We do it here so the bitmap uptodate bit |
342 | * get set with buffer lock held. | 345 | * get set with buffer lock held. |
343 | */ | 346 | */ |
347 | trace_ext4_read_block_bitmap_load(sb, block_group); | ||
344 | set_bitmap_uptodate(bh); | 348 | set_bitmap_uptodate(bh); |
345 | if (bh_submit_read(bh) < 0) { | 349 | if (bh_submit_read(bh) < 0) { |
346 | put_bh(bh); | 350 | put_bh(bh); |
@@ -358,130 +362,6 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group) | |||
358 | } | 362 | } |
359 | 363 | ||
360 | /** | 364 | /** |
361 | * ext4_add_groupblocks() -- Add given blocks to an existing group | ||
362 | * @handle: handle to this transaction | ||
363 | * @sb: super block | ||
364 | * @block: start physcial block to add to the block group | ||
365 | * @count: number of blocks to free | ||
366 | * | ||
367 | * This marks the blocks as free in the bitmap. We ask the | ||
368 | * mballoc to reload the buddy after this by setting group | ||
369 | * EXT4_GROUP_INFO_NEED_INIT_BIT flag | ||
370 | */ | ||
371 | void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, | ||
372 | ext4_fsblk_t block, unsigned long count) | ||
373 | { | ||
374 | struct buffer_head *bitmap_bh = NULL; | ||
375 | struct buffer_head *gd_bh; | ||
376 | ext4_group_t block_group; | ||
377 | ext4_grpblk_t bit; | ||
378 | unsigned int i; | ||
379 | struct ext4_group_desc *desc; | ||
380 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
381 | int err = 0, ret, blk_free_count; | ||
382 | ext4_grpblk_t blocks_freed; | ||
383 | struct ext4_group_info *grp; | ||
384 | |||
385 | ext4_debug("Adding block(s) %llu-%llu\n", block, block + count - 1); | ||
386 | |||
387 | ext4_get_group_no_and_offset(sb, block, &block_group, &bit); | ||
388 | grp = ext4_get_group_info(sb, block_group); | ||
389 | /* | ||
390 | * Check to see if we are freeing blocks across a group | ||
391 | * boundary. | ||
392 | */ | ||
393 | if (bit + count > EXT4_BLOCKS_PER_GROUP(sb)) { | ||
394 | goto error_return; | ||
395 | } | ||
396 | bitmap_bh = ext4_read_block_bitmap(sb, block_group); | ||
397 | if (!bitmap_bh) | ||
398 | goto error_return; | ||
399 | desc = ext4_get_group_desc(sb, block_group, &gd_bh); | ||
400 | if (!desc) | ||
401 | goto error_return; | ||
402 | |||
403 | if (in_range(ext4_block_bitmap(sb, desc), block, count) || | ||
404 | in_range(ext4_inode_bitmap(sb, desc), block, count) || | ||
405 | in_range(block, ext4_inode_table(sb, desc), sbi->s_itb_per_group) || | ||
406 | in_range(block + count - 1, ext4_inode_table(sb, desc), | ||
407 | sbi->s_itb_per_group)) { | ||
408 | ext4_error(sb, "Adding blocks in system zones - " | ||
409 | "Block = %llu, count = %lu", | ||
410 | block, count); | ||
411 | goto error_return; | ||
412 | } | ||
413 | |||
414 | /* | ||
415 | * We are about to add blocks to the bitmap, | ||
416 | * so we need undo access. | ||
417 | */ | ||
418 | BUFFER_TRACE(bitmap_bh, "getting undo access"); | ||
419 | err = ext4_journal_get_undo_access(handle, bitmap_bh); | ||
420 | if (err) | ||
421 | goto error_return; | ||
422 | |||
423 | /* | ||
424 | * We are about to modify some metadata. Call the journal APIs | ||
425 | * to unshare ->b_data if a currently-committing transaction is | ||
426 | * using it | ||
427 | */ | ||
428 | BUFFER_TRACE(gd_bh, "get_write_access"); | ||
429 | err = ext4_journal_get_write_access(handle, gd_bh); | ||
430 | if (err) | ||
431 | goto error_return; | ||
432 | /* | ||
433 | * make sure we don't allow a parallel init on other groups in the | ||
434 | * same buddy cache | ||
435 | */ | ||
436 | down_write(&grp->alloc_sem); | ||
437 | for (i = 0, blocks_freed = 0; i < count; i++) { | ||
438 | BUFFER_TRACE(bitmap_bh, "clear bit"); | ||
439 | if (!ext4_clear_bit_atomic(ext4_group_lock_ptr(sb, block_group), | ||
440 | bit + i, bitmap_bh->b_data)) { | ||
441 | ext4_error(sb, "bit already cleared for block %llu", | ||
442 | (ext4_fsblk_t)(block + i)); | ||
443 | BUFFER_TRACE(bitmap_bh, "bit already cleared"); | ||
444 | } else { | ||
445 | blocks_freed++; | ||
446 | } | ||
447 | } | ||
448 | ext4_lock_group(sb, block_group); | ||
449 | blk_free_count = blocks_freed + ext4_free_blks_count(sb, desc); | ||
450 | ext4_free_blks_set(sb, desc, blk_free_count); | ||
451 | desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc); | ||
452 | ext4_unlock_group(sb, block_group); | ||
453 | percpu_counter_add(&sbi->s_freeblocks_counter, blocks_freed); | ||
454 | |||
455 | if (sbi->s_log_groups_per_flex) { | ||
456 | ext4_group_t flex_group = ext4_flex_group(sbi, block_group); | ||
457 | atomic_add(blocks_freed, | ||
458 | &sbi->s_flex_groups[flex_group].free_blocks); | ||
459 | } | ||
460 | /* | ||
461 | * request to reload the buddy with the | ||
462 | * new bitmap information | ||
463 | */ | ||
464 | set_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &(grp->bb_state)); | ||
465 | grp->bb_free += blocks_freed; | ||
466 | up_write(&grp->alloc_sem); | ||
467 | |||
468 | /* We dirtied the bitmap block */ | ||
469 | BUFFER_TRACE(bitmap_bh, "dirtied bitmap block"); | ||
470 | err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh); | ||
471 | |||
472 | /* And the group descriptor block */ | ||
473 | BUFFER_TRACE(gd_bh, "dirtied group descriptor block"); | ||
474 | ret = ext4_handle_dirty_metadata(handle, NULL, gd_bh); | ||
475 | if (!err) | ||
476 | err = ret; | ||
477 | |||
478 | error_return: | ||
479 | brelse(bitmap_bh); | ||
480 | ext4_std_error(sb, err); | ||
481 | return; | ||
482 | } | ||
483 | |||
484 | /** | ||
485 | * ext4_has_free_blocks() | 365 | * ext4_has_free_blocks() |
486 | * @sbi: in-core super block structure. | 366 | * @sbi: in-core super block structure. |
487 | * @nblocks: number of needed blocks | 367 | * @nblocks: number of needed blocks |
@@ -489,7 +369,8 @@ error_return: | |||
489 | * Check if filesystem has nblocks free & available for allocation. | 369 | * Check if filesystem has nblocks free & available for allocation. |
490 | * On success return 1, return 0 on failure. | 370 | * On success return 1, return 0 on failure. |
491 | */ | 371 | */ |
492 | int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks) | 372 | static int ext4_has_free_blocks(struct ext4_sb_info *sbi, |
373 | s64 nblocks, unsigned int flags) | ||
493 | { | 374 | { |
494 | s64 free_blocks, dirty_blocks, root_blocks; | 375 | s64 free_blocks, dirty_blocks, root_blocks; |
495 | struct percpu_counter *fbc = &sbi->s_freeblocks_counter; | 376 | struct percpu_counter *fbc = &sbi->s_freeblocks_counter; |
@@ -503,11 +384,6 @@ int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks) | |||
503 | EXT4_FREEBLOCKS_WATERMARK) { | 384 | EXT4_FREEBLOCKS_WATERMARK) { |
504 | free_blocks = percpu_counter_sum_positive(fbc); | 385 | free_blocks = percpu_counter_sum_positive(fbc); |
505 | dirty_blocks = percpu_counter_sum_positive(dbc); | 386 | dirty_blocks = percpu_counter_sum_positive(dbc); |
506 | if (dirty_blocks < 0) { | ||
507 | printk(KERN_CRIT "Dirty block accounting " | ||
508 | "went wrong %lld\n", | ||
509 | (long long)dirty_blocks); | ||
510 | } | ||
511 | } | 387 | } |
512 | /* Check whether we have space after | 388 | /* Check whether we have space after |
513 | * accounting for current dirty blocks & root reserved blocks. | 389 | * accounting for current dirty blocks & root reserved blocks. |
@@ -518,7 +394,9 @@ int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks) | |||
518 | /* Hm, nope. Are (enough) root reserved blocks available? */ | 394 | /* Hm, nope. Are (enough) root reserved blocks available? */ |
519 | if (sbi->s_resuid == current_fsuid() || | 395 | if (sbi->s_resuid == current_fsuid() || |
520 | ((sbi->s_resgid != 0) && in_group_p(sbi->s_resgid)) || | 396 | ((sbi->s_resgid != 0) && in_group_p(sbi->s_resgid)) || |
521 | capable(CAP_SYS_RESOURCE)) { | 397 | capable(CAP_SYS_RESOURCE) || |
398 | (flags & EXT4_MB_USE_ROOT_BLOCKS)) { | ||
399 | |||
522 | if (free_blocks >= (nblocks + dirty_blocks)) | 400 | if (free_blocks >= (nblocks + dirty_blocks)) |
523 | return 1; | 401 | return 1; |
524 | } | 402 | } |
@@ -527,9 +405,9 @@ int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks) | |||
527 | } | 405 | } |
528 | 406 | ||
529 | int ext4_claim_free_blocks(struct ext4_sb_info *sbi, | 407 | int ext4_claim_free_blocks(struct ext4_sb_info *sbi, |
530 | s64 nblocks) | 408 | s64 nblocks, unsigned int flags) |
531 | { | 409 | { |
532 | if (ext4_has_free_blocks(sbi, nblocks)) { | 410 | if (ext4_has_free_blocks(sbi, nblocks, flags)) { |
533 | percpu_counter_add(&sbi->s_dirtyblocks_counter, nblocks); | 411 | percpu_counter_add(&sbi->s_dirtyblocks_counter, nblocks); |
534 | return 0; | 412 | return 0; |
535 | } else | 413 | } else |
@@ -543,14 +421,14 @@ int ext4_claim_free_blocks(struct ext4_sb_info *sbi, | |||
543 | * | 421 | * |
544 | * ext4_should_retry_alloc() is called when ENOSPC is returned, and if | 422 | * ext4_should_retry_alloc() is called when ENOSPC is returned, and if |
545 | * it is profitable to retry the operation, this function will wait | 423 | * it is profitable to retry the operation, this function will wait |
546 | * for the current or commiting transaction to complete, and then | 424 | * for the current or committing transaction to complete, and then |
547 | * return TRUE. | 425 | * return TRUE. |
548 | * | 426 | * |
549 | * if the total number of retries exceed three times, return FALSE. | 427 | * if the total number of retries exceed three times, return FALSE. |
550 | */ | 428 | */ |
551 | int ext4_should_retry_alloc(struct super_block *sb, int *retries) | 429 | int ext4_should_retry_alloc(struct super_block *sb, int *retries) |
552 | { | 430 | { |
553 | if (!ext4_has_free_blocks(EXT4_SB(sb), 1) || | 431 | if (!ext4_has_free_blocks(EXT4_SB(sb), 1, 0) || |
554 | (*retries)++ > 3 || | 432 | (*retries)++ > 3 || |
555 | !EXT4_SB(sb)->s_journal) | 433 | !EXT4_SB(sb)->s_journal) |
556 | return 0; | 434 | return 0; |
@@ -573,7 +451,8 @@ int ext4_should_retry_alloc(struct super_block *sb, int *retries) | |||
573 | * error stores in errp pointer | 451 | * error stores in errp pointer |
574 | */ | 452 | */ |
575 | ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode, | 453 | ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode, |
576 | ext4_fsblk_t goal, unsigned long *count, int *errp) | 454 | ext4_fsblk_t goal, unsigned int flags, |
455 | unsigned long *count, int *errp) | ||
577 | { | 456 | { |
578 | struct ext4_allocation_request ar; | 457 | struct ext4_allocation_request ar; |
579 | ext4_fsblk_t ret; | 458 | ext4_fsblk_t ret; |
@@ -583,6 +462,7 @@ ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode, | |||
583 | ar.inode = inode; | 462 | ar.inode = inode; |
584 | ar.goal = goal; | 463 | ar.goal = goal; |
585 | ar.len = count ? *count : 1; | 464 | ar.len = count ? *count : 1; |
465 | ar.flags = flags; | ||
586 | 466 | ||
587 | ret = ext4_mb_new_blocks(handle, &ar, errp); | 467 | ret = ext4_mb_new_blocks(handle, &ar, errp); |
588 | if (count) | 468 | if (count) |
@@ -591,7 +471,8 @@ ext4_fsblk_t ext4_new_meta_blocks(handle_t *handle, struct inode *inode, | |||
591 | * Account for the allocated meta blocks. We will never | 471 | * Account for the allocated meta blocks. We will never |
592 | * fail EDQUOT for metdata, but we do account for it. | 472 | * fail EDQUOT for metdata, but we do account for it. |
593 | */ | 473 | */ |
594 | if (!(*errp) && EXT4_I(inode)->i_delalloc_reserved_flag) { | 474 | if (!(*errp) && |
475 | ext4_test_inode_state(inode, EXT4_STATE_DELALLOC_RESERVED)) { | ||
595 | spin_lock(&EXT4_I(inode)->i_block_reservation_lock); | 476 | spin_lock(&EXT4_I(inode)->i_block_reservation_lock); |
596 | EXT4_I(inode)->i_allocated_meta_blocks += ar.len; | 477 | EXT4_I(inode)->i_allocated_meta_blocks += ar.len; |
597 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); | 478 | spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); |