diff options
author | Younger Liu <younger.liu@huawei.com> | 2013-09-11 17:19:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-11 18:56:28 -0400 |
commit | 2b1e55c389105b722cccadfa47f5615f57d8887f (patch) | |
tree | d5f6a8458a64e8a92f5df71822c75b25f6f0e065 /fs/ocfs2/journal.c | |
parent | 5e42781caf6f5f1c77e842d6dcbbf5c51b8b2c29 (diff) |
ocfs2: lighten up allocate transaction
The issue scenario is as following:
When fallocating a very large disk space for a small file,
__ocfs2_extend_allocation attempts to get a very large transaction. For
some journal sizes, there may be not enough room for this transaction,
and the fallocate will fail.
The patch below extends & restarts the transaction as necessary while
allocating space, and should work with even the smallest journal. This
patch refers ext4 resize.
Test:
# mkfs.ocfs2 -b 4K -C 32K -T datafiles /dev/sdc
...(jounral size is 32M)
# mount.ocfs2 /dev/sdc /mnt/ocfs2/
# touch /mnt/ocfs2/1.log
# fallocate -o 0 -l 400G /mnt/ocfs2/1.log
fallocate: /mnt/ocfs2/1.log: fallocate failed: Cannot allocate memory
# tail -f /var/log/messages
[ 7372.278591] JBD: fallocate wants too many credits (2051 > 2048)
[ 7372.278597] (fallocate,6438,0):__ocfs2_extend_allocation:709 ERROR: status = -12
[ 7372.278603] (fallocate,6438,0):ocfs2_allocate_unwritten_extents:1504 ERROR: status = -12
[ 7372.278607] (fallocate,6438,0):__ocfs2_change_file_space:1955 ERROR: status = -12
^C
With this patch, the test works well.
Signed-off-by: Younger Liu <younger.liu@huawei.com>
Cc: Jie Liu <jeff.liu@oracle.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Mark Fasheh <mfasheh@suse.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ocfs2/journal.c')
-rw-r--r-- | fs/ocfs2/journal.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 242170d83971..a126cb37ca4d 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c | |||
@@ -455,6 +455,41 @@ bail: | |||
455 | return status; | 455 | return status; |
456 | } | 456 | } |
457 | 457 | ||
458 | /* | ||
459 | * If we have fewer than thresh credits, extend by OCFS2_MAX_TRANS_DATA. | ||
460 | * If that fails, restart the transaction & regain write access for the | ||
461 | * buffer head which is used for metadata modifications. | ||
462 | * Taken from Ext4: extend_or_restart_transaction() | ||
463 | */ | ||
464 | int ocfs2_allocate_extend_trans(handle_t *handle, int thresh) | ||
465 | { | ||
466 | int status, old_nblks; | ||
467 | |||
468 | BUG_ON(!handle); | ||
469 | |||
470 | old_nblks = handle->h_buffer_credits; | ||
471 | trace_ocfs2_allocate_extend_trans(old_nblks, thresh); | ||
472 | |||
473 | if (old_nblks < thresh) | ||
474 | return 0; | ||
475 | |||
476 | status = jbd2_journal_extend(handle, OCFS2_MAX_TRANS_DATA); | ||
477 | if (status < 0) { | ||
478 | mlog_errno(status); | ||
479 | goto bail; | ||
480 | } | ||
481 | |||
482 | if (status > 0) { | ||
483 | status = jbd2_journal_restart(handle, OCFS2_MAX_TRANS_DATA); | ||
484 | if (status < 0) | ||
485 | mlog_errno(status); | ||
486 | } | ||
487 | |||
488 | bail: | ||
489 | return status; | ||
490 | } | ||
491 | |||
492 | |||
458 | struct ocfs2_triggers { | 493 | struct ocfs2_triggers { |
459 | struct jbd2_buffer_trigger_type ot_triggers; | 494 | struct jbd2_buffer_trigger_type ot_triggers; |
460 | int ot_offset; | 495 | int ot_offset; |