diff options
author | Chris Mason <mason@suse.com> | 2006-02-01 06:06:49 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-02-01 11:53:26 -0500 |
commit | e0e851cf30f1a9bd2e2a7624e9810378d6a2b072 (patch) | |
tree | a8cf33d9b22594fb5c1094bd8b15f2f315b53f2d /fs/reiserfs/journal.c | |
parent | fc5cd582e9c934ddaf6f310179488932cd154794 (diff) |
[PATCH] reiserfs: reiserfs hang and performance fix for data=journal mode
In data=journal mode, reiserfs writepage needs to make sure not to trigger
transactions while being run under PF_MEMALLOC. This patch makes sure to
redirty the page instead of forcing a transaction start in this case.
Also, calling filemap_fdata* in order to trigger io on the block device can
cause lock inversions on the page lock. Instead, do simple batching from
flush_commit_list.
Signed-off-by: Chris Mason <mason@suse.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/reiserfs/journal.c')
-rw-r--r-- | fs/reiserfs/journal.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index bc8fe963b3cc..1b2402a9a8e1 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c | |||
@@ -988,6 +988,7 @@ static int flush_commit_list(struct super_block *s, | |||
988 | struct reiserfs_journal *journal = SB_JOURNAL(s); | 988 | struct reiserfs_journal *journal = SB_JOURNAL(s); |
989 | int barrier = 0; | 989 | int barrier = 0; |
990 | int retval = 0; | 990 | int retval = 0; |
991 | int write_len; | ||
991 | 992 | ||
992 | reiserfs_check_lock_depth(s, "flush_commit_list"); | 993 | reiserfs_check_lock_depth(s, "flush_commit_list"); |
993 | 994 | ||
@@ -1037,16 +1038,24 @@ static int flush_commit_list(struct super_block *s, | |||
1037 | BUG_ON(!list_empty(&jl->j_bh_list)); | 1038 | BUG_ON(!list_empty(&jl->j_bh_list)); |
1038 | /* | 1039 | /* |
1039 | * for the description block and all the log blocks, submit any buffers | 1040 | * for the description block and all the log blocks, submit any buffers |
1040 | * that haven't already reached the disk | 1041 | * that haven't already reached the disk. Try to write at least 256 |
1042 | * log blocks. later on, we will only wait on blocks that correspond | ||
1043 | * to this transaction, but while we're unplugging we might as well | ||
1044 | * get a chunk of data on there. | ||
1041 | */ | 1045 | */ |
1042 | atomic_inc(&journal->j_async_throttle); | 1046 | atomic_inc(&journal->j_async_throttle); |
1043 | for (i = 0; i < (jl->j_len + 1); i++) { | 1047 | write_len = jl->j_len + 1; |
1048 | if (write_len < 256) | ||
1049 | write_len = 256; | ||
1050 | for (i = 0 ; i < write_len ; i++) { | ||
1044 | bn = SB_ONDISK_JOURNAL_1st_BLOCK(s) + (jl->j_start + i) % | 1051 | bn = SB_ONDISK_JOURNAL_1st_BLOCK(s) + (jl->j_start + i) % |
1045 | SB_ONDISK_JOURNAL_SIZE(s); | 1052 | SB_ONDISK_JOURNAL_SIZE(s); |
1046 | tbh = journal_find_get_block(s, bn); | 1053 | tbh = journal_find_get_block(s, bn); |
1047 | if (buffer_dirty(tbh)) /* redundant, ll_rw_block() checks */ | 1054 | if (tbh) { |
1048 | ll_rw_block(SWRITE, 1, &tbh); | 1055 | if (buffer_dirty(tbh)) |
1049 | put_bh(tbh); | 1056 | ll_rw_block(WRITE, 1, &tbh) ; |
1057 | put_bh(tbh) ; | ||
1058 | } | ||
1050 | } | 1059 | } |
1051 | atomic_dec(&journal->j_async_throttle); | 1060 | atomic_dec(&journal->j_async_throttle); |
1052 | 1061 | ||