diff options
Diffstat (limited to 'fs/jbd2')
| -rw-r--r-- | fs/jbd2/commit.c | 9 | ||||
| -rw-r--r-- | fs/jbd2/journal.c | 19 | ||||
| -rw-r--r-- | fs/jbd2/transaction.c | 47 |
3 files changed, 75 insertions, 0 deletions
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index ebc667bc54a8..c8a1bace685a 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
| @@ -509,6 +509,10 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
| 509 | if (is_journal_aborted(journal)) { | 509 | if (is_journal_aborted(journal)) { |
| 510 | clear_buffer_jbddirty(jh2bh(jh)); | 510 | clear_buffer_jbddirty(jh2bh(jh)); |
| 511 | JBUFFER_TRACE(jh, "journal is aborting: refile"); | 511 | JBUFFER_TRACE(jh, "journal is aborting: refile"); |
| 512 | jbd2_buffer_abort_trigger(jh, | ||
| 513 | jh->b_frozen_data ? | ||
| 514 | jh->b_frozen_triggers : | ||
| 515 | jh->b_triggers); | ||
| 512 | jbd2_journal_refile_buffer(journal, jh); | 516 | jbd2_journal_refile_buffer(journal, jh); |
| 513 | /* If that was the last one, we need to clean up | 517 | /* If that was the last one, we need to clean up |
| 514 | * any descriptor buffers which may have been | 518 | * any descriptor buffers which may have been |
| @@ -844,6 +848,9 @@ restart_loop: | |||
| 844 | * data. | 848 | * data. |
| 845 | * | 849 | * |
| 846 | * Otherwise, we can just throw away the frozen data now. | 850 | * Otherwise, we can just throw away the frozen data now. |
| 851 | * | ||
| 852 | * We also know that the frozen data has already fired | ||
| 853 | * its triggers if they exist, so we can clear that too. | ||
| 847 | */ | 854 | */ |
| 848 | if (jh->b_committed_data) { | 855 | if (jh->b_committed_data) { |
| 849 | jbd2_free(jh->b_committed_data, bh->b_size); | 856 | jbd2_free(jh->b_committed_data, bh->b_size); |
| @@ -851,10 +858,12 @@ restart_loop: | |||
| 851 | if (jh->b_frozen_data) { | 858 | if (jh->b_frozen_data) { |
| 852 | jh->b_committed_data = jh->b_frozen_data; | 859 | jh->b_committed_data = jh->b_frozen_data; |
| 853 | jh->b_frozen_data = NULL; | 860 | jh->b_frozen_data = NULL; |
| 861 | jh->b_frozen_triggers = NULL; | ||
| 854 | } | 862 | } |
| 855 | } else if (jh->b_frozen_data) { | 863 | } else if (jh->b_frozen_data) { |
| 856 | jbd2_free(jh->b_frozen_data, bh->b_size); | 864 | jbd2_free(jh->b_frozen_data, bh->b_size); |
| 857 | jh->b_frozen_data = NULL; | 865 | jh->b_frozen_data = NULL; |
| 866 | jh->b_frozen_triggers = NULL; | ||
| 858 | } | 867 | } |
| 859 | 868 | ||
| 860 | spin_lock(&journal->j_list_lock); | 869 | spin_lock(&journal->j_list_lock); |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index e70d657a19f8..f6bff9d6f8df 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
| @@ -50,6 +50,7 @@ EXPORT_SYMBOL(jbd2_journal_unlock_updates); | |||
| 50 | EXPORT_SYMBOL(jbd2_journal_get_write_access); | 50 | EXPORT_SYMBOL(jbd2_journal_get_write_access); |
| 51 | EXPORT_SYMBOL(jbd2_journal_get_create_access); | 51 | EXPORT_SYMBOL(jbd2_journal_get_create_access); |
| 52 | EXPORT_SYMBOL(jbd2_journal_get_undo_access); | 52 | EXPORT_SYMBOL(jbd2_journal_get_undo_access); |
| 53 | EXPORT_SYMBOL(jbd2_journal_set_triggers); | ||
| 53 | EXPORT_SYMBOL(jbd2_journal_dirty_metadata); | 54 | EXPORT_SYMBOL(jbd2_journal_dirty_metadata); |
| 54 | EXPORT_SYMBOL(jbd2_journal_release_buffer); | 55 | EXPORT_SYMBOL(jbd2_journal_release_buffer); |
| 55 | EXPORT_SYMBOL(jbd2_journal_forget); | 56 | EXPORT_SYMBOL(jbd2_journal_forget); |
| @@ -290,6 +291,7 @@ int jbd2_journal_write_metadata_buffer(transaction_t *transaction, | |||
| 290 | struct page *new_page; | 291 | struct page *new_page; |
| 291 | unsigned int new_offset; | 292 | unsigned int new_offset; |
| 292 | struct buffer_head *bh_in = jh2bh(jh_in); | 293 | struct buffer_head *bh_in = jh2bh(jh_in); |
| 294 | struct jbd2_buffer_trigger_type *triggers; | ||
| 293 | 295 | ||
| 294 | /* | 296 | /* |
| 295 | * The buffer really shouldn't be locked: only the current committing | 297 | * The buffer really shouldn't be locked: only the current committing |
| @@ -314,13 +316,23 @@ repeat: | |||
| 314 | done_copy_out = 1; | 316 | done_copy_out = 1; |
| 315 | new_page = virt_to_page(jh_in->b_frozen_data); | 317 | new_page = virt_to_page(jh_in->b_frozen_data); |
| 316 | new_offset = offset_in_page(jh_in->b_frozen_data); | 318 | new_offset = offset_in_page(jh_in->b_frozen_data); |
| 319 | triggers = jh_in->b_frozen_triggers; | ||
| 317 | } else { | 320 | } else { |
| 318 | new_page = jh2bh(jh_in)->b_page; | 321 | new_page = jh2bh(jh_in)->b_page; |
| 319 | new_offset = offset_in_page(jh2bh(jh_in)->b_data); | 322 | new_offset = offset_in_page(jh2bh(jh_in)->b_data); |
| 323 | triggers = jh_in->b_triggers; | ||
| 320 | } | 324 | } |
| 321 | 325 | ||
| 322 | mapped_data = kmap_atomic(new_page, KM_USER0); | 326 | mapped_data = kmap_atomic(new_page, KM_USER0); |
| 323 | /* | 327 | /* |
| 328 | * Fire any commit trigger. Do this before checking for escaping, | ||
| 329 | * as the trigger may modify the magic offset. If a copy-out | ||
| 330 | * happens afterwards, it will have the correct data in the buffer. | ||
| 331 | */ | ||
| 332 | jbd2_buffer_commit_trigger(jh_in, mapped_data + new_offset, | ||
| 333 | triggers); | ||
| 334 | |||
| 335 | /* | ||
| 324 | * Check for escaping | 336 | * Check for escaping |
| 325 | */ | 337 | */ |
| 326 | if (*((__be32 *)(mapped_data + new_offset)) == | 338 | if (*((__be32 *)(mapped_data + new_offset)) == |
| @@ -352,6 +364,13 @@ repeat: | |||
| 352 | new_page = virt_to_page(tmp); | 364 | new_page = virt_to_page(tmp); |
| 353 | new_offset = offset_in_page(tmp); | 365 | new_offset = offset_in_page(tmp); |
| 354 | done_copy_out = 1; | 366 | done_copy_out = 1; |
| 367 | |||
| 368 | /* | ||
| 369 | * This isn't strictly necessary, as we're using frozen | ||
| 370 | * data for the escaping, but it keeps consistency with | ||
| 371 | * b_frozen_data usage. | ||
| 372 | */ | ||
| 373 | jh_in->b_frozen_triggers = jh_in->b_triggers; | ||
| 355 | } | 374 | } |
| 356 | 375 | ||
| 357 | /* | 376 | /* |
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 39b7805a599a..4f925a4f3d05 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
| @@ -741,6 +741,12 @@ done: | |||
| 741 | source = kmap_atomic(page, KM_USER0); | 741 | source = kmap_atomic(page, KM_USER0); |
| 742 | memcpy(jh->b_frozen_data, source+offset, jh2bh(jh)->b_size); | 742 | memcpy(jh->b_frozen_data, source+offset, jh2bh(jh)->b_size); |
| 743 | kunmap_atomic(source, KM_USER0); | 743 | kunmap_atomic(source, KM_USER0); |
| 744 | |||
| 745 | /* | ||
| 746 | * Now that the frozen data is saved off, we need to store | ||
| 747 | * any matching triggers. | ||
| 748 | */ | ||
| 749 | jh->b_frozen_triggers = jh->b_triggers; | ||
| 744 | } | 750 | } |
| 745 | jbd_unlock_bh_state(bh); | 751 | jbd_unlock_bh_state(bh); |
| 746 | 752 | ||
| @@ -944,6 +950,47 @@ out: | |||
| 944 | } | 950 | } |
| 945 | 951 | ||
| 946 | /** | 952 | /** |
| 953 | * void jbd2_journal_set_triggers() - Add triggers for commit writeout | ||
| 954 | * @bh: buffer to trigger on | ||
| 955 | * @type: struct jbd2_buffer_trigger_type containing the trigger(s). | ||
| 956 | * | ||
| 957 | * Set any triggers on this journal_head. This is always safe, because | ||
| 958 | * triggers for a committing buffer will be saved off, and triggers for | ||
| 959 | * a running transaction will match the buffer in that transaction. | ||
| 960 | * | ||
| 961 | * Call with NULL to clear the triggers. | ||
| 962 | */ | ||
| 963 | void jbd2_journal_set_triggers(struct buffer_head *bh, | ||
| 964 | struct jbd2_buffer_trigger_type *type) | ||
| 965 | { | ||
| 966 | struct journal_head *jh = bh2jh(bh); | ||
| 967 | |||
| 968 | jh->b_triggers = type; | ||
| 969 | } | ||
| 970 | |||
| 971 | void jbd2_buffer_commit_trigger(struct journal_head *jh, void *mapped_data, | ||
| 972 | struct jbd2_buffer_trigger_type *triggers) | ||
| 973 | { | ||
| 974 | struct buffer_head *bh = jh2bh(jh); | ||
| 975 | |||
| 976 | if (!triggers || !triggers->t_commit) | ||
| 977 | return; | ||
| 978 | |||
| 979 | triggers->t_commit(triggers, bh, mapped_data, bh->b_size); | ||
| 980 | } | ||
| 981 | |||
| 982 | void jbd2_buffer_abort_trigger(struct journal_head *jh, | ||
| 983 | struct jbd2_buffer_trigger_type *triggers) | ||
| 984 | { | ||
| 985 | if (!triggers || !triggers->t_abort) | ||
| 986 | return; | ||
| 987 | |||
| 988 | triggers->t_abort(triggers, jh2bh(jh)); | ||
| 989 | } | ||
| 990 | |||
| 991 | |||
| 992 | |||
| 993 | /** | ||
| 947 | * int jbd2_journal_dirty_metadata() - mark a buffer as containing dirty metadata | 994 | * int jbd2_journal_dirty_metadata() - mark a buffer as containing dirty metadata |
| 948 | * @handle: transaction to add buffer to. | 995 | * @handle: transaction to add buffer to. |
| 949 | * @bh: buffer to mark | 996 | * @bh: buffer to mark |
