86 #include <linux/time.h>
89 #include <linux/errno.h>
90 #include <linux/slab.h>
91 #include <linux/list.h>
97 static struct kmem_cache *jbd2_revoke_record_cache;
98 static struct kmem_cache *jbd2_revoke_table_cache;
124 static void write_one_revoke_record(journal_t *,
transaction_t *,
127 static void flush_descriptor(journal_t *,
struct journal_head *,
int,
int);
133 static inline int hash(journal_t *journal,
unsigned long long block)
137 int hash = (
int)block ^ (
int)((block >> 31) >> 1);
139 return ((hash << (hash_shift - 6)) ^
141 (hash << (hash_shift - 12))) & (table->
hash_size - 1);
144 static int insert_revoke_hash(journal_t *journal,
unsigned long long blocknr,
157 hash_list = &journal->j_revoke->hash_table[
hash(journal, blocknr)];
158 spin_lock(&journal->j_revoke_lock);
159 list_add(&record->
hash, hash_list);
160 spin_unlock(&journal->j_revoke_lock);
166 jbd_debug(1,
"ENOMEM in %s, retrying\n", __func__);
174 unsigned long long blocknr)
179 hash_list = &journal->j_revoke->hash_table[
hash(journal, blocknr)];
181 spin_lock(&journal->j_revoke_lock);
183 while (&(record->
hash) != hash_list) {
184 if (record->
blocknr == blocknr) {
185 spin_unlock(&journal->j_revoke_lock);
190 spin_unlock(&journal->j_revoke_lock);
196 if (jbd2_revoke_record_cache) {
198 jbd2_revoke_record_cache =
NULL;
200 if (jbd2_revoke_table_cache) {
202 jbd2_revoke_table_cache =
NULL;
208 J_ASSERT(!jbd2_revoke_record_cache);
209 J_ASSERT(!jbd2_revoke_table_cache);
213 if (!jbd2_revoke_record_cache)
214 goto record_cache_failure;
218 if (!jbd2_revoke_table_cache)
219 goto table_cache_failure;
223 record_cache_failure:
237 while((tmp >>= 1
UL) != 0
UL)
264 J_ASSERT(list_empty(hash_list));
274 J_ASSERT(journal->j_revoke_table[0] ==
NULL);
277 journal->j_revoke_table[0] = jbd2_journal_init_revoke_table(hash_size);
278 if (!journal->j_revoke_table[0])
281 journal->j_revoke_table[1] = jbd2_journal_init_revoke_table(hash_size);
282 if (!journal->j_revoke_table[1])
285 journal->j_revoke = journal->j_revoke_table[1];
292 jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]);
300 journal->j_revoke =
NULL;
301 if (journal->j_revoke_table[0])
302 jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]);
303 if (journal->j_revoke_table[1])
304 jbd2_journal_destroy_revoke_table(journal->j_revoke_table[1]);
334 int jbd2_journal_revoke(handle_t *
handle,
unsigned long long blocknr,
335 struct buffer_head *bh_in)
337 struct buffer_head *bh =
NULL;
344 BUFFER_TRACE(bh_in,
"enter");
346 journal = handle->h_transaction->t_journal;
348 J_ASSERT (!
"Cannot set revoke feature!");
352 bdev = journal->j_fs_dev;
358 BUFFER_TRACE(bh,
"found on hash");
360 #ifdef JBD2_EXPENSIVE_CHECKING
362 struct buffer_head *bh2;
369 if (bh2 != bh && buffer_revokevalid(bh2))
376 J_ASSERT_BH(bh2, buffer_revoked(bh2));
386 if (!J_EXPECT_BH(bh, !buffer_revoked(bh),
387 "inconsistent data on disk")) {
392 set_buffer_revoked(bh);
393 set_buffer_revokevalid(bh);
395 BUFFER_TRACE(bh_in,
"call jbd2_journal_forget");
398 BUFFER_TRACE(bh,
"call brelse");
403 jbd_debug(2,
"insert revoke for block %llu, bh_in=%p\n",blocknr, bh_in);
404 err = insert_revoke_hash(journal, blocknr,
405 handle->h_transaction->t_tid);
406 BUFFER_TRACE(bh_in,
"exit");
425 int jbd2_journal_cancel_revoke(handle_t *handle,
struct journal_head *jh)
428 journal_t *journal = handle->h_transaction->t_journal;
431 struct buffer_head *bh = jh2bh(jh);
433 jbd_debug(4,
"journal_head %p, cancelling revoke\n", jh);
439 if (test_set_buffer_revokevalid(bh)) {
440 need_cancel = test_clear_buffer_revoked(bh);
443 clear_buffer_revoked(bh);
447 record = find_revoke_record(journal, bh->b_blocknr);
449 jbd_debug(4,
"cancelled existing revoke on "
450 "blocknr %llu\n", (
unsigned long long)bh->b_blocknr);
451 spin_lock(&journal->j_revoke_lock);
453 spin_unlock(&journal->j_revoke_lock);
459 #ifdef JBD2_EXPENSIVE_CHECKING
461 record = find_revoke_record(journal, bh->b_blocknr);
462 J_ASSERT_JH(jh, record ==
NULL);
470 struct buffer_head *bh2;
474 clear_buffer_revoked(bh2);
486 void jbd2_clear_buffer_revoked_flags(journal_t *journal)
491 for (i = 0; i < revoke->
hash_size; i++) {
498 struct buffer_head *bh;
502 journal->j_blocksize);
504 clear_buffer_revoked(bh);
515 void jbd2_journal_switch_revoke_table(journal_t *journal)
519 if (journal->j_revoke == journal->j_revoke_table[0])
520 journal->j_revoke = journal->j_revoke_table[1];
522 journal->j_revoke = journal->j_revoke_table[0];
524 for (i = 0; i < journal->j_revoke->hash_size; i++)
525 INIT_LIST_HEAD(&journal->j_revoke->hash_table[i]);
532 void jbd2_journal_write_revoke_records(journal_t *journal,
547 revoke = journal->j_revoke == journal->j_revoke_table[0] ?
548 journal->j_revoke_table[1] : journal->j_revoke_table[0];
550 for (i = 0; i < revoke->
hash_size; i++) {
553 while (!list_empty(hash_list)) {
556 write_one_revoke_record(journal, transaction,
557 &descriptor, &offset,
565 flush_descriptor(journal, descriptor, offset, write_op);
566 jbd_debug(1,
"Wrote %d revoke records\n", count);
574 static void write_one_revoke_record(journal_t *journal,
590 if (is_journal_aborted(journal))
593 descriptor = *descriptorp;
602 if (offset >= journal->j_blocksize - csum_size) {
603 flush_descriptor(journal, descriptor, offset, write_op);
618 JBUFFER_TRACE(descriptor,
"file as BJ_LogCtl");
639 static void jbd2_revoke_csum_set(journal_t *
j,
649 (jh2bh(descriptor)->b_data + j->j_blocksize -
652 csum = jbd2_chksum(j, j->j_csum_seed, jh2bh(descriptor)->b_data,
664 static void flush_descriptor(journal_t *journal,
666 int offset,
int write_op)
669 struct buffer_head *bh = jh2bh(descriptor);
671 if (is_journal_aborted(journal)) {
678 jbd2_revoke_csum_set(journal, descriptor);
680 set_buffer_jwrite(bh);
681 BUFFER_TRACE(bh,
"write");
682 set_buffer_dirty(bh);
710 unsigned long long blocknr,
715 record = find_revoke_record(journal, blocknr);
719 if (tid_gt(sequence, record->
sequence))
723 return insert_revoke_hash(journal, blocknr, sequence);
734 unsigned long long blocknr,
739 record = find_revoke_record(journal, blocknr);
742 if (tid_gt(sequence, record->
sequence))
759 revoke = journal->j_revoke;
761 for (i = 0; i < revoke->
hash_size; i++) {
763 while (!list_empty(hash_list)) {