aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jbd2/journal.c
diff options
context:
space:
mode:
authorJoel Becker <joel.becker@oracle.com>2008-09-11 18:35:47 -0400
committerMark Fasheh <mfasheh@suse.com>2009-01-05 11:40:30 -0500
commite06c8227fd94ec181849ba206bf032be31c4295c (patch)
tree67261cd94aa86dc6112d7de74304c2a1af5b64fb /fs/jbd2/journal.c
parent754938c142ae0c28360426c43f965ddc5164b21e (diff)
jbd2: Add buffer triggers
Filesystems often to do compute intensive operation on some metadata. If this operation is repeated many times, it can be very expensive. It would be much nicer if the operation could be performed once before a buffer goes to disk. This adds triggers to jbd2 buffer heads. Just before writing a metadata buffer to the journal, jbd2 will optionally call a commit trigger associated with the buffer. If the journal is aborted, an abort trigger will be called on any dirty buffers as they are dropped from pending transactions. ocfs2 will use this feature. Initially I tried to come up with a more generic trigger that could be used for non-buffer-related events like transaction completion. It doesn't tie nicely, because the information a buffer trigger needs (specific to a journal_head) isn't the same as what a transaction trigger needs (specific to a tranaction_t or perhaps journal_t). So I implemented a buffer set, with the understanding that journal/transaction wide triggers should be implemented separately. There is only one trigger set allowed per buffer. I can't think of any reason to attach more than one set. Contrast this with a journal or transaction in which multiple places may want to watch the entire transaction separately. The trigger sets are considered static allocation from the jbd2 perspective. ocfs2 will just have one trigger set per block type, setting the same set on every bh of the same type. Signed-off-by: Joel Becker <joel.becker@oracle.com> Cc: "Theodore Ts'o" <tytso@mit.edu> Cc: <linux-ext4@vger.kernel.org> Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/jbd2/journal.c')
-rw-r--r--fs/jbd2/journal.c19
1 files changed, 19 insertions, 0 deletions
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 /*