diff options
Diffstat (limited to 'fs/jbd/revoke.c')
-rw-r--r-- | fs/jbd/revoke.c | 44 |
1 files changed, 30 insertions, 14 deletions
diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c index c7bd649bbbdc..da6cd9bdaabc 100644 --- a/fs/jbd/revoke.c +++ b/fs/jbd/revoke.c | |||
@@ -55,6 +55,25 @@ | |||
55 | * need do nothing. | 55 | * need do nothing. |
56 | * RevokeValid set, Revoked set: | 56 | * RevokeValid set, Revoked set: |
57 | * buffer has been revoked. | 57 | * buffer has been revoked. |
58 | * | ||
59 | * Locking rules: | ||
60 | * We keep two hash tables of revoke records. One hashtable belongs to the | ||
61 | * running transaction (is pointed to by journal->j_revoke), the other one | ||
62 | * belongs to the committing transaction. Accesses to the second hash table | ||
63 | * happen only from the kjournald and no other thread touches this table. Also | ||
64 | * journal_switch_revoke_table() which switches which hashtable belongs to the | ||
65 | * running and which to the committing transaction is called only from | ||
66 | * kjournald. Therefore we need no locks when accessing the hashtable belonging | ||
67 | * to the committing transaction. | ||
68 | * | ||
69 | * All users operating on the hash table belonging to the running transaction | ||
70 | * have a handle to the transaction. Therefore they are safe from kjournald | ||
71 | * switching hash tables under them. For operations on the lists of entries in | ||
72 | * the hash table j_revoke_lock is used. | ||
73 | * | ||
74 | * Finally, also replay code uses the hash tables but at this moment noone else | ||
75 | * can touch them (filesystem isn't mounted yet) and hence no locking is | ||
76 | * needed. | ||
58 | */ | 77 | */ |
59 | 78 | ||
60 | #ifndef __KERNEL__ | 79 | #ifndef __KERNEL__ |
@@ -67,6 +86,7 @@ | |||
67 | #include <linux/slab.h> | 86 | #include <linux/slab.h> |
68 | #include <linux/list.h> | 87 | #include <linux/list.h> |
69 | #include <linux/init.h> | 88 | #include <linux/init.h> |
89 | #include <linux/bio.h> | ||
70 | #endif | 90 | #endif |
71 | #include <linux/log2.h> | 91 | #include <linux/log2.h> |
72 | 92 | ||
@@ -99,8 +119,8 @@ struct jbd_revoke_table_s | |||
99 | #ifdef __KERNEL__ | 119 | #ifdef __KERNEL__ |
100 | static void write_one_revoke_record(journal_t *, transaction_t *, | 120 | static void write_one_revoke_record(journal_t *, transaction_t *, |
101 | struct journal_head **, int *, | 121 | struct journal_head **, int *, |
102 | struct jbd_revoke_record_s *); | 122 | struct jbd_revoke_record_s *, int); |
103 | static void flush_descriptor(journal_t *, struct journal_head *, int); | 123 | static void flush_descriptor(journal_t *, struct journal_head *, int, int); |
104 | #endif | 124 | #endif |
105 | 125 | ||
106 | /* Utility functions to maintain the revoke table */ | 126 | /* Utility functions to maintain the revoke table */ |
@@ -402,8 +422,6 @@ int journal_revoke(handle_t *handle, unsigned long blocknr, | |||
402 | * the second time we would still have a pending revoke to cancel. So, | 422 | * the second time we would still have a pending revoke to cancel. So, |
403 | * do not trust the Revoked bit on buffers unless RevokeValid is also | 423 | * do not trust the Revoked bit on buffers unless RevokeValid is also |
404 | * set. | 424 | * set. |
405 | * | ||
406 | * The caller must have the journal locked. | ||
407 | */ | 425 | */ |
408 | int journal_cancel_revoke(handle_t *handle, struct journal_head *jh) | 426 | int journal_cancel_revoke(handle_t *handle, struct journal_head *jh) |
409 | { | 427 | { |
@@ -481,12 +499,9 @@ void journal_switch_revoke_table(journal_t *journal) | |||
481 | /* | 499 | /* |
482 | * Write revoke records to the journal for all entries in the current | 500 | * Write revoke records to the journal for all entries in the current |
483 | * revoke hash, deleting the entries as we go. | 501 | * revoke hash, deleting the entries as we go. |
484 | * | ||
485 | * Called with the journal lock held. | ||
486 | */ | 502 | */ |
487 | |||
488 | void journal_write_revoke_records(journal_t *journal, | 503 | void journal_write_revoke_records(journal_t *journal, |
489 | transaction_t *transaction) | 504 | transaction_t *transaction, int write_op) |
490 | { | 505 | { |
491 | struct journal_head *descriptor; | 506 | struct journal_head *descriptor; |
492 | struct jbd_revoke_record_s *record; | 507 | struct jbd_revoke_record_s *record; |
@@ -510,14 +525,14 @@ void journal_write_revoke_records(journal_t *journal, | |||
510 | hash_list->next; | 525 | hash_list->next; |
511 | write_one_revoke_record(journal, transaction, | 526 | write_one_revoke_record(journal, transaction, |
512 | &descriptor, &offset, | 527 | &descriptor, &offset, |
513 | record); | 528 | record, write_op); |
514 | count++; | 529 | count++; |
515 | list_del(&record->hash); | 530 | list_del(&record->hash); |
516 | kmem_cache_free(revoke_record_cache, record); | 531 | kmem_cache_free(revoke_record_cache, record); |
517 | } | 532 | } |
518 | } | 533 | } |
519 | if (descriptor) | 534 | if (descriptor) |
520 | flush_descriptor(journal, descriptor, offset); | 535 | flush_descriptor(journal, descriptor, offset, write_op); |
521 | jbd_debug(1, "Wrote %d revoke records\n", count); | 536 | jbd_debug(1, "Wrote %d revoke records\n", count); |
522 | } | 537 | } |
523 | 538 | ||
@@ -530,7 +545,8 @@ static void write_one_revoke_record(journal_t *journal, | |||
530 | transaction_t *transaction, | 545 | transaction_t *transaction, |
531 | struct journal_head **descriptorp, | 546 | struct journal_head **descriptorp, |
532 | int *offsetp, | 547 | int *offsetp, |
533 | struct jbd_revoke_record_s *record) | 548 | struct jbd_revoke_record_s *record, |
549 | int write_op) | ||
534 | { | 550 | { |
535 | struct journal_head *descriptor; | 551 | struct journal_head *descriptor; |
536 | int offset; | 552 | int offset; |
@@ -549,7 +565,7 @@ static void write_one_revoke_record(journal_t *journal, | |||
549 | /* Make sure we have a descriptor with space left for the record */ | 565 | /* Make sure we have a descriptor with space left for the record */ |
550 | if (descriptor) { | 566 | if (descriptor) { |
551 | if (offset == journal->j_blocksize) { | 567 | if (offset == journal->j_blocksize) { |
552 | flush_descriptor(journal, descriptor, offset); | 568 | flush_descriptor(journal, descriptor, offset, write_op); |
553 | descriptor = NULL; | 569 | descriptor = NULL; |
554 | } | 570 | } |
555 | } | 571 | } |
@@ -586,7 +602,7 @@ static void write_one_revoke_record(journal_t *journal, | |||
586 | 602 | ||
587 | static void flush_descriptor(journal_t *journal, | 603 | static void flush_descriptor(journal_t *journal, |
588 | struct journal_head *descriptor, | 604 | struct journal_head *descriptor, |
589 | int offset) | 605 | int offset, int write_op) |
590 | { | 606 | { |
591 | journal_revoke_header_t *header; | 607 | journal_revoke_header_t *header; |
592 | struct buffer_head *bh = jh2bh(descriptor); | 608 | struct buffer_head *bh = jh2bh(descriptor); |
@@ -601,7 +617,7 @@ static void flush_descriptor(journal_t *journal, | |||
601 | set_buffer_jwrite(bh); | 617 | set_buffer_jwrite(bh); |
602 | BUFFER_TRACE(bh, "write"); | 618 | BUFFER_TRACE(bh, "write"); |
603 | set_buffer_dirty(bh); | 619 | set_buffer_dirty(bh); |
604 | ll_rw_block(SWRITE, 1, &bh); | 620 | ll_rw_block((write_op == WRITE) ? SWRITE : SWRITE_SYNC_PLUG, 1, &bh); |
605 | } | 621 | } |
606 | #endif | 622 | #endif |
607 | 623 | ||