diff options
author | Joel Becker <joel.becker@oracle.com> | 2008-09-11 18:53:07 -0400 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-01-05 11:40:31 -0500 |
commit | 50655ae9e91d272d48997bada59efe166aa5e343 (patch) | |
tree | ca821943897781fe4852c6ac447ccb4760ec8c65 | |
parent | d6b32bbb3eae3fb787f1c33bf9f767ca1ddeb208 (diff) |
ocfs2: Add journal_access functions with jbd2 triggers.
We create wrappers for ocfs2_journal_access() that are specific to the
type of metadata block. This allows us to associate jbd2 commit
triggers with the block. The triggers will compute metadata ecc in a
future commit.
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
-rw-r--r-- | fs/ocfs2/journal.c | 159 | ||||
-rw-r--r-- | fs/ocfs2/journal.h | 31 |
2 files changed, 181 insertions, 9 deletions
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 302f1144a708..2daa5848faf2 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include "ocfs2.h" | 35 | #include "ocfs2.h" |
36 | 36 | ||
37 | #include "alloc.h" | 37 | #include "alloc.h" |
38 | #include "blockcheck.h" | ||
38 | #include "dir.h" | 39 | #include "dir.h" |
39 | #include "dlmglue.h" | 40 | #include "dlmglue.h" |
40 | #include "extent_map.h" | 41 | #include "extent_map.h" |
@@ -369,10 +370,110 @@ bail: | |||
369 | return status; | 370 | return status; |
370 | } | 371 | } |
371 | 372 | ||
372 | int ocfs2_journal_access(handle_t *handle, | 373 | struct ocfs2_triggers { |
373 | struct inode *inode, | 374 | struct jbd2_buffer_trigger_type ot_triggers; |
374 | struct buffer_head *bh, | 375 | int ot_offset; |
375 | int type) | 376 | }; |
377 | |||
378 | static inline struct ocfs2_triggers *to_ocfs2_trigger(struct jbd2_buffer_trigger_type *triggers) | ||
379 | { | ||
380 | return container_of(triggers, struct ocfs2_triggers, ot_triggers); | ||
381 | } | ||
382 | |||
383 | static void ocfs2_commit_trigger(struct jbd2_buffer_trigger_type *triggers, | ||
384 | struct buffer_head *bh, | ||
385 | void *data, size_t size) | ||
386 | { | ||
387 | struct ocfs2_triggers *ot = to_ocfs2_trigger(triggers); | ||
388 | |||
389 | /* | ||
390 | * We aren't guaranteed to have the superblock here, so we | ||
391 | * must unconditionally compute the ecc data. | ||
392 | * __ocfs2_journal_access() will only set the triggers if | ||
393 | * metaecc is enabled. | ||
394 | */ | ||
395 | ocfs2_block_check_compute(data, size, data + ot->ot_offset); | ||
396 | } | ||
397 | |||
398 | /* | ||
399 | * Quota blocks have their own trigger because the struct ocfs2_block_check | ||
400 | * offset depends on the blocksize. | ||
401 | */ | ||
402 | static void ocfs2_dq_commit_trigger(struct jbd2_buffer_trigger_type *triggers, | ||
403 | struct buffer_head *bh, | ||
404 | void *data, size_t size) | ||
405 | { | ||
406 | struct ocfs2_disk_dqtrailer *dqt = | ||
407 | ocfs2_block_dqtrailer(size, data); | ||
408 | |||
409 | /* | ||
410 | * We aren't guaranteed to have the superblock here, so we | ||
411 | * must unconditionally compute the ecc data. | ||
412 | * __ocfs2_journal_access() will only set the triggers if | ||
413 | * metaecc is enabled. | ||
414 | */ | ||
415 | ocfs2_block_check_compute(data, size, &dqt->dq_check); | ||
416 | } | ||
417 | |||
418 | static void ocfs2_abort_trigger(struct jbd2_buffer_trigger_type *triggers, | ||
419 | struct buffer_head *bh) | ||
420 | { | ||
421 | mlog(ML_ERROR, | ||
422 | "ocfs2_abort_trigger called by JBD2. bh = 0x%lx, " | ||
423 | "bh->b_blocknr = %llu\n", | ||
424 | (unsigned long)bh, | ||
425 | (unsigned long long)bh->b_blocknr); | ||
426 | |||
427 | /* We aren't guaranteed to have the superblock here - but if we | ||
428 | * don't, it'll just crash. */ | ||
429 | ocfs2_error(bh->b_assoc_map->host->i_sb, | ||
430 | "JBD2 has aborted our journal, ocfs2 cannot continue\n"); | ||
431 | } | ||
432 | |||
433 | static struct ocfs2_triggers di_triggers = { | ||
434 | .ot_triggers = { | ||
435 | .t_commit = ocfs2_commit_trigger, | ||
436 | .t_abort = ocfs2_abort_trigger, | ||
437 | }, | ||
438 | .ot_offset = offsetof(struct ocfs2_dinode, i_check), | ||
439 | }; | ||
440 | |||
441 | static struct ocfs2_triggers eb_triggers = { | ||
442 | .ot_triggers = { | ||
443 | .t_commit = ocfs2_commit_trigger, | ||
444 | .t_abort = ocfs2_abort_trigger, | ||
445 | }, | ||
446 | .ot_offset = offsetof(struct ocfs2_extent_block, h_check), | ||
447 | }; | ||
448 | |||
449 | static struct ocfs2_triggers gd_triggers = { | ||
450 | .ot_triggers = { | ||
451 | .t_commit = ocfs2_commit_trigger, | ||
452 | .t_abort = ocfs2_abort_trigger, | ||
453 | }, | ||
454 | .ot_offset = offsetof(struct ocfs2_group_desc, bg_check), | ||
455 | }; | ||
456 | |||
457 | static struct ocfs2_triggers xb_triggers = { | ||
458 | .ot_triggers = { | ||
459 | .t_commit = ocfs2_commit_trigger, | ||
460 | .t_abort = ocfs2_abort_trigger, | ||
461 | }, | ||
462 | .ot_offset = offsetof(struct ocfs2_xattr_block, xb_check), | ||
463 | }; | ||
464 | |||
465 | static struct ocfs2_triggers dq_triggers = { | ||
466 | .ot_triggers = { | ||
467 | .t_commit = ocfs2_dq_commit_trigger, | ||
468 | .t_abort = ocfs2_abort_trigger, | ||
469 | }, | ||
470 | }; | ||
471 | |||
472 | static int __ocfs2_journal_access(handle_t *handle, | ||
473 | struct inode *inode, | ||
474 | struct buffer_head *bh, | ||
475 | struct ocfs2_triggers *triggers, | ||
476 | int type) | ||
376 | { | 477 | { |
377 | int status; | 478 | int status; |
378 | 479 | ||
@@ -418,6 +519,8 @@ int ocfs2_journal_access(handle_t *handle, | |||
418 | status = -EINVAL; | 519 | status = -EINVAL; |
419 | mlog(ML_ERROR, "Uknown access type!\n"); | 520 | mlog(ML_ERROR, "Uknown access type!\n"); |
420 | } | 521 | } |
522 | if (!status && ocfs2_meta_ecc(OCFS2_SB(inode->i_sb)) && triggers) | ||
523 | jbd2_journal_set_triggers(bh, &triggers->ot_triggers); | ||
421 | mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); | 524 | mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); |
422 | 525 | ||
423 | if (status < 0) | 526 | if (status < 0) |
@@ -428,6 +531,54 @@ int ocfs2_journal_access(handle_t *handle, | |||
428 | return status; | 531 | return status; |
429 | } | 532 | } |
430 | 533 | ||
534 | int ocfs2_journal_access_di(handle_t *handle, struct inode *inode, | ||
535 | struct buffer_head *bh, int type) | ||
536 | { | ||
537 | return __ocfs2_journal_access(handle, inode, bh, &di_triggers, | ||
538 | type); | ||
539 | } | ||
540 | |||
541 | int ocfs2_journal_access_eb(handle_t *handle, struct inode *inode, | ||
542 | struct buffer_head *bh, int type) | ||
543 | { | ||
544 | return __ocfs2_journal_access(handle, inode, bh, &eb_triggers, | ||
545 | type); | ||
546 | } | ||
547 | |||
548 | int ocfs2_journal_access_gd(handle_t *handle, struct inode *inode, | ||
549 | struct buffer_head *bh, int type) | ||
550 | { | ||
551 | return __ocfs2_journal_access(handle, inode, bh, &gd_triggers, | ||
552 | type); | ||
553 | } | ||
554 | |||
555 | int ocfs2_journal_access_db(handle_t *handle, struct inode *inode, | ||
556 | struct buffer_head *bh, int type) | ||
557 | { | ||
558 | /* Right now, nothing for dirblocks */ | ||
559 | return __ocfs2_journal_access(handle, inode, bh, NULL, type); | ||
560 | } | ||
561 | |||
562 | int ocfs2_journal_access_xb(handle_t *handle, struct inode *inode, | ||
563 | struct buffer_head *bh, int type) | ||
564 | { | ||
565 | return __ocfs2_journal_access(handle, inode, bh, &xb_triggers, | ||
566 | type); | ||
567 | } | ||
568 | |||
569 | int ocfs2_journal_access_dq(handle_t *handle, struct inode *inode, | ||
570 | struct buffer_head *bh, int type) | ||
571 | { | ||
572 | return __ocfs2_journal_access(handle, inode, bh, &dq_triggers, | ||
573 | type); | ||
574 | } | ||
575 | |||
576 | int ocfs2_journal_access(handle_t *handle, struct inode *inode, | ||
577 | struct buffer_head *bh, int type) | ||
578 | { | ||
579 | return __ocfs2_journal_access(handle, inode, bh, NULL, type); | ||
580 | } | ||
581 | |||
431 | int ocfs2_journal_dirty(handle_t *handle, | 582 | int ocfs2_journal_dirty(handle_t *handle, |
432 | struct buffer_head *bh) | 583 | struct buffer_head *bh) |
433 | { | 584 | { |
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h index 37013bf9ce28..bca370dab021 100644 --- a/fs/ocfs2/journal.h +++ b/fs/ocfs2/journal.h | |||
@@ -212,9 +212,12 @@ static inline void ocfs2_checkpoint_inode(struct inode *inode) | |||
212 | * ocfs2_extend_trans - Extend a handle by nblocks credits. This may | 212 | * ocfs2_extend_trans - Extend a handle by nblocks credits. This may |
213 | * commit the handle to disk in the process, but will | 213 | * commit the handle to disk in the process, but will |
214 | * not release any locks taken during the transaction. | 214 | * not release any locks taken during the transaction. |
215 | * ocfs2_journal_access - Notify the handle that we want to journal this | 215 | * ocfs2_journal_access* - Notify the handle that we want to journal this |
216 | * buffer. Will have to call ocfs2_journal_dirty once | 216 | * buffer. Will have to call ocfs2_journal_dirty once |
217 | * we've actually dirtied it. Type is one of . or . | 217 | * we've actually dirtied it. Type is one of . or . |
218 | * Always call the specific flavor of | ||
219 | * ocfs2_journal_access_*() unless you intend to | ||
220 | * manage the checksum by hand. | ||
218 | * ocfs2_journal_dirty - Mark a journalled buffer as having dirty data. | 221 | * ocfs2_journal_dirty - Mark a journalled buffer as having dirty data. |
219 | * ocfs2_jbd2_file_inode - Mark an inode so that its data goes out before | 222 | * ocfs2_jbd2_file_inode - Mark an inode so that its data goes out before |
220 | * the current handle commits. | 223 | * the current handle commits. |
@@ -244,10 +247,28 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks); | |||
244 | #define OCFS2_JOURNAL_ACCESS_WRITE 1 | 247 | #define OCFS2_JOURNAL_ACCESS_WRITE 1 |
245 | #define OCFS2_JOURNAL_ACCESS_UNDO 2 | 248 | #define OCFS2_JOURNAL_ACCESS_UNDO 2 |
246 | 249 | ||
247 | int ocfs2_journal_access(handle_t *handle, | 250 | /* ocfs2_inode */ |
248 | struct inode *inode, | 251 | int ocfs2_journal_access_di(handle_t *handle, struct inode *inode, |
249 | struct buffer_head *bh, | 252 | struct buffer_head *bh, int type); |
250 | int type); | 253 | /* ocfs2_extent_block */ |
254 | int ocfs2_journal_access_eb(handle_t *handle, struct inode *inode, | ||
255 | struct buffer_head *bh, int type); | ||
256 | /* ocfs2_group_desc */ | ||
257 | int ocfs2_journal_access_gd(handle_t *handle, struct inode *inode, | ||
258 | struct buffer_head *bh, int type); | ||
259 | /* ocfs2_xattr_block */ | ||
260 | int ocfs2_journal_access_xb(handle_t *handle, struct inode *inode, | ||
261 | struct buffer_head *bh, int type); | ||
262 | /* quota blocks */ | ||
263 | int ocfs2_journal_access_dq(handle_t *handle, struct inode *inode, | ||
264 | struct buffer_head *bh, int type); | ||
265 | /* dirblock */ | ||
266 | int ocfs2_journal_access_db(handle_t *handle, struct inode *inode, | ||
267 | struct buffer_head *bh, int type); | ||
268 | /* Anything that has no ecc */ | ||
269 | int ocfs2_journal_access(handle_t *handle, struct inode *inode, | ||
270 | struct buffer_head *bh, int type); | ||
271 | |||
251 | /* | 272 | /* |
252 | * A word about the journal_access/journal_dirty "dance". It is | 273 | * A word about the journal_access/journal_dirty "dance". It is |
253 | * entirely legal to journal_access a buffer more than once (as long | 274 | * entirely legal to journal_access a buffer more than once (as long |