diff options
Diffstat (limited to 'fs/jbd/commit.c')
-rw-r--r-- | fs/jbd/commit.c | 45 |
1 files changed, 34 insertions, 11 deletions
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 52c15c776029..86b39b167c23 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c | |||
@@ -86,7 +86,12 @@ nope: | |||
86 | static void release_data_buffer(struct buffer_head *bh) | 86 | static void release_data_buffer(struct buffer_head *bh) |
87 | { | 87 | { |
88 | if (buffer_freed(bh)) { | 88 | if (buffer_freed(bh)) { |
89 | WARN_ON_ONCE(buffer_dirty(bh)); | ||
89 | clear_buffer_freed(bh); | 90 | clear_buffer_freed(bh); |
91 | clear_buffer_mapped(bh); | ||
92 | clear_buffer_new(bh); | ||
93 | clear_buffer_req(bh); | ||
94 | bh->b_bdev = NULL; | ||
90 | release_buffer_page(bh); | 95 | release_buffer_page(bh); |
91 | } else | 96 | } else |
92 | put_bh(bh); | 97 | put_bh(bh); |
@@ -866,17 +871,35 @@ restart_loop: | |||
866 | * there's no point in keeping a checkpoint record for | 871 | * there's no point in keeping a checkpoint record for |
867 | * it. */ | 872 | * it. */ |
868 | 873 | ||
869 | /* A buffer which has been freed while still being | 874 | /* |
870 | * journaled by a previous transaction may end up still | 875 | * A buffer which has been freed while still being journaled by |
871 | * being dirty here, but we want to avoid writing back | 876 | * a previous transaction. |
872 | * that buffer in the future after the "add to orphan" | 877 | */ |
873 | * operation been committed, That's not only a performance | 878 | if (buffer_freed(bh)) { |
874 | * gain, it also stops aliasing problems if the buffer is | 879 | /* |
875 | * left behind for writeback and gets reallocated for another | 880 | * If the running transaction is the one containing |
876 | * use in a different page. */ | 881 | * "add to orphan" operation (b_next_transaction != |
877 | if (buffer_freed(bh) && !jh->b_next_transaction) { | 882 | * NULL), we have to wait for that transaction to |
878 | clear_buffer_freed(bh); | 883 | * commit before we can really get rid of the buffer. |
879 | clear_buffer_jbddirty(bh); | 884 | * So just clear b_modified to not confuse transaction |
885 | * credit accounting and refile the buffer to | ||
886 | * BJ_Forget of the running transaction. If the just | ||
887 | * committed transaction contains "add to orphan" | ||
888 | * operation, we can completely invalidate the buffer | ||
889 | * now. We are rather throughout in that since the | ||
890 | * buffer may be still accessible when blocksize < | ||
891 | * pagesize and it is attached to the last partial | ||
892 | * page. | ||
893 | */ | ||
894 | jh->b_modified = 0; | ||
895 | if (!jh->b_next_transaction) { | ||
896 | clear_buffer_freed(bh); | ||
897 | clear_buffer_jbddirty(bh); | ||
898 | clear_buffer_mapped(bh); | ||
899 | clear_buffer_new(bh); | ||
900 | clear_buffer_req(bh); | ||
901 | bh->b_bdev = NULL; | ||
902 | } | ||
880 | } | 903 | } |
881 | 904 | ||
882 | if (buffer_jbddirty(bh)) { | 905 | if (buffer_jbddirty(bh)) { |