aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/jbd2/commit.c9
-rw-r--r--fs/jbd2/journal.c19
-rw-r--r--fs/jbd2/transaction.c47
-rw-r--r--include/linux/jbd2.h31
-rw-r--r--include/linux/journal-head.h8
5 files changed, 114 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);
50EXPORT_SYMBOL(jbd2_journal_get_write_access); 50EXPORT_SYMBOL(jbd2_journal_get_write_access);
51EXPORT_SYMBOL(jbd2_journal_get_create_access); 51EXPORT_SYMBOL(jbd2_journal_get_create_access);
52EXPORT_SYMBOL(jbd2_journal_get_undo_access); 52EXPORT_SYMBOL(jbd2_journal_get_undo_access);
53EXPORT_SYMBOL(jbd2_journal_set_triggers);
53EXPORT_SYMBOL(jbd2_journal_dirty_metadata); 54EXPORT_SYMBOL(jbd2_journal_dirty_metadata);
54EXPORT_SYMBOL(jbd2_journal_release_buffer); 55EXPORT_SYMBOL(jbd2_journal_release_buffer);
55EXPORT_SYMBOL(jbd2_journal_forget); 56EXPORT_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 */
963void 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
971void 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
982void 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
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index f36645745489..34456476e761 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -1008,6 +1008,35 @@ int __jbd2_journal_clean_checkpoint_list(journal_t *journal);
1008int __jbd2_journal_remove_checkpoint(struct journal_head *); 1008int __jbd2_journal_remove_checkpoint(struct journal_head *);
1009void __jbd2_journal_insert_checkpoint(struct journal_head *, transaction_t *); 1009void __jbd2_journal_insert_checkpoint(struct journal_head *, transaction_t *);
1010 1010
1011
1012/*
1013 * Triggers
1014 */
1015
1016struct jbd2_buffer_trigger_type {
1017 /*
1018 * Fired just before a buffer is written to the journal.
1019 * mapped_data is a mapped buffer that is the frozen data for
1020 * commit.
1021 */
1022 void (*t_commit)(struct jbd2_buffer_trigger_type *type,
1023 struct buffer_head *bh, void *mapped_data,
1024 size_t size);
1025
1026 /*
1027 * Fired during journal abort for dirty buffers that will not be
1028 * committed.
1029 */
1030 void (*t_abort)(struct jbd2_buffer_trigger_type *type,
1031 struct buffer_head *bh);
1032};
1033
1034extern void jbd2_buffer_commit_trigger(struct journal_head *jh,
1035 void *mapped_data,
1036 struct jbd2_buffer_trigger_type *triggers);
1037extern void jbd2_buffer_abort_trigger(struct journal_head *jh,
1038 struct jbd2_buffer_trigger_type *triggers);
1039
1011/* Buffer IO */ 1040/* Buffer IO */
1012extern int 1041extern int
1013jbd2_journal_write_metadata_buffer(transaction_t *transaction, 1042jbd2_journal_write_metadata_buffer(transaction_t *transaction,
@@ -1046,6 +1075,8 @@ extern int jbd2_journal_extend (handle_t *, int nblocks);
1046extern int jbd2_journal_get_write_access(handle_t *, struct buffer_head *); 1075extern int jbd2_journal_get_write_access(handle_t *, struct buffer_head *);
1047extern int jbd2_journal_get_create_access (handle_t *, struct buffer_head *); 1076extern int jbd2_journal_get_create_access (handle_t *, struct buffer_head *);
1048extern int jbd2_journal_get_undo_access(handle_t *, struct buffer_head *); 1077extern int jbd2_journal_get_undo_access(handle_t *, struct buffer_head *);
1078void jbd2_journal_set_triggers(struct buffer_head *,
1079 struct jbd2_buffer_trigger_type *type);
1049extern int jbd2_journal_dirty_metadata (handle_t *, struct buffer_head *); 1080extern int jbd2_journal_dirty_metadata (handle_t *, struct buffer_head *);
1050extern void jbd2_journal_release_buffer (handle_t *, struct buffer_head *); 1081extern void jbd2_journal_release_buffer (handle_t *, struct buffer_head *);
1051extern int jbd2_journal_forget (handle_t *, struct buffer_head *); 1082extern int jbd2_journal_forget (handle_t *, struct buffer_head *);
diff --git a/include/linux/journal-head.h b/include/linux/journal-head.h
index bb70ebb6a2d5..525aac3c97df 100644
--- a/include/linux/journal-head.h
+++ b/include/linux/journal-head.h
@@ -12,6 +12,8 @@
12 12
13typedef unsigned int tid_t; /* Unique transaction ID */ 13typedef unsigned int tid_t; /* Unique transaction ID */
14typedef struct transaction_s transaction_t; /* Compound transaction type */ 14typedef struct transaction_s transaction_t; /* Compound transaction type */
15
16
15struct buffer_head; 17struct buffer_head;
16 18
17struct journal_head { 19struct journal_head {
@@ -87,6 +89,12 @@ struct journal_head {
87 * [j_list_lock] 89 * [j_list_lock]
88 */ 90 */
89 struct journal_head *b_cpnext, *b_cpprev; 91 struct journal_head *b_cpnext, *b_cpprev;
92
93 /* Trigger type */
94 struct jbd2_buffer_trigger_type *b_triggers;
95
96 /* Trigger type for the committing transaction's frozen data */
97 struct jbd2_buffer_trigger_type *b_frozen_triggers;
90}; 98};
91 99
92#endif /* JOURNAL_HEAD_H_INCLUDED */ 100#endif /* JOURNAL_HEAD_H_INCLUDED */