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 | |
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')
-rw-r--r-- | fs/ocfs2/file.c | 6 | ||||
-rw-r--r-- | fs/ocfs2/journal.c | 35 | ||||
-rw-r--r-- | fs/ocfs2/journal.h | 11 | ||||
-rw-r--r-- | fs/ocfs2/ocfs2_trace.h | 2 |
4 files changed, 49 insertions, 5 deletions
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 3261d71319ee..409c549ae02a 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -671,11 +671,7 @@ restarted_transaction: | |||
671 | } else { | 671 | } else { |
672 | BUG_ON(why != RESTART_TRANS); | 672 | BUG_ON(why != RESTART_TRANS); |
673 | 673 | ||
674 | /* TODO: This can be more intelligent. */ | 674 | status = ocfs2_allocate_extend_trans(handle, 1); |
675 | credits = ocfs2_calc_extend_credits(osb->sb, | ||
676 | &fe->id2.i_list, | ||
677 | clusters_to_add); | ||
678 | status = ocfs2_extend_trans(handle, credits); | ||
679 | if (status < 0) { | 675 | if (status < 0) { |
680 | /* handle still has to be committed at | 676 | /* handle still has to be committed at |
681 | * this point. */ | 677 | * this point. */ |
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; |
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 0a992737dcaf..0b479bab3671 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h | |||
@@ -258,6 +258,17 @@ handle_t *ocfs2_start_trans(struct ocfs2_super *osb, | |||
258 | int ocfs2_commit_trans(struct ocfs2_super *osb, | 258 | int ocfs2_commit_trans(struct ocfs2_super *osb, |
259 | handle_t *handle); | 259 | handle_t *handle); |
260 | int ocfs2_extend_trans(handle_t *handle, int nblocks); | 260 | int ocfs2_extend_trans(handle_t *handle, int nblocks); |
261 | int ocfs2_allocate_extend_trans(handle_t *handle, | ||
262 | int thresh); | ||
263 | |||
264 | /* | ||
265 | * Define an arbitrary limit for the amount of data we will anticipate | ||
266 | * writing to any given transaction. For unbounded transactions such as | ||
267 | * fallocate(2) we can write more than this, but we always | ||
268 | * start off at the maximum transaction size and grow the transaction | ||
269 | * optimistically as we go. | ||
270 | */ | ||
271 | #define OCFS2_MAX_TRANS_DATA 64U | ||
261 | 272 | ||
262 | /* | 273 | /* |
263 | * Create access is for when we get a newly created buffer and we're | 274 | * Create access is for when we get a newly created buffer and we're |
diff --git a/fs/ocfs2/ocfs2_trace.h b/fs/ocfs2/ocfs2_trace.h index 3b481f490633..1b60c62aa9d6 100644 --- a/fs/ocfs2/ocfs2_trace.h +++ b/fs/ocfs2/ocfs2_trace.h | |||
@@ -2579,6 +2579,8 @@ DEFINE_OCFS2_INT_INT_EVENT(ocfs2_extend_trans); | |||
2579 | 2579 | ||
2580 | DEFINE_OCFS2_INT_EVENT(ocfs2_extend_trans_restart); | 2580 | DEFINE_OCFS2_INT_EVENT(ocfs2_extend_trans_restart); |
2581 | 2581 | ||
2582 | DEFINE_OCFS2_INT_INT_EVENT(ocfs2_allocate_extend_trans); | ||
2583 | |||
2582 | DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(ocfs2_journal_access); | 2584 | DEFINE_OCFS2_ULL_ULL_UINT_UINT_EVENT(ocfs2_journal_access); |
2583 | 2585 | ||
2584 | DEFINE_OCFS2_ULL_EVENT(ocfs2_journal_dirty); | 2586 | DEFINE_OCFS2_ULL_EVENT(ocfs2_journal_dirty); |