X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=e2fsck%2Frevoke.c;h=fa608788b93d7c55977b8c64201374ffb6a1a42c;hb=daf3a6ac05e54c608bb03c121b9ef93f1318f7b4;hp=c43e40e982096d1c46473815045f2a13a01346c2;hpb=efc6f628e15de95bcd13e4f0ee223cb42115d520;p=tools%2Fe2fsprogs.git diff --git a/e2fsck/revoke.c b/e2fsck/revoke.c index c43e40e..fa60878 100644 --- a/e2fsck/revoke.c +++ b/e2fsck/revoke.c @@ -1,14 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * linux/fs/revoke.c + * linux/fs/jbd2/revoke.c * * Written by Stephen C. Tweedie , 2000 * * Copyright 2000 Red Hat corp --- All Rights Reserved * - * This file is part of the Linux kernel and is made available under - * the terms of the GNU General Public License, version 2, or at your - * option, any later version, incorporated herein by reference. - * * Journal revoke routines for the generic filesystem journaling code; * part of the ext2fs journaling system. * @@ -47,6 +44,10 @@ * overwriting the new data. We don't even need to clear the revoke * bit here. * + * We cache revoke status of a buffer in the current transaction in b_states + * bits. As the name says, revokevalid flag indicates that the cached revoke + * status of a buffer is valid and we can rely on the cached status. + * * Revoke information on buffers is a tri-state value: * * RevokeValid clear: no cached revoke status, need to look it up @@ -55,39 +56,59 @@ * need do nothing. * RevokeValid set, Revoked set: * buffer has been revoked. + * + * Locking rules: + * We keep two hash tables of revoke records. One hashtable belongs to the + * running transaction (is pointed to by journal->j_revoke), the other one + * belongs to the committing transaction. Accesses to the second hash table + * happen only from the kjournald and no other thread touches this table. Also + * journal_switch_revoke_table() which switches which hashtable belongs to the + * running and which to the committing transaction is called only from + * kjournald. Therefore we need no locks when accessing the hashtable belonging + * to the committing transaction. + * + * All users operating on the hash table belonging to the running transaction + * have a handle to the transaction. Therefore they are safe from kjournald + * switching hash tables under them. For operations on the lists of entries in + * the hash table j_revoke_lock is used. + * + * Finally, also replay code uses the hash tables but at this moment no one else + * can touch them (filesystem isn't mounted yet) and hence no locking is + * needed. */ #ifndef __KERNEL__ #include "jfs_user.h" #else -#include +#include #include -#include +#include #include #include -#include #include -#include #include +#include +#include +#include #endif -static lkmem_cache_t *revoke_record_cache; -static lkmem_cache_t *revoke_table_cache; +static struct kmem_cache *jbd2_revoke_record_cache; +static struct kmem_cache *jbd2_revoke_table_cache; /* Each revoke record represents one single revoked block. During journal replay, this involves recording the transaction ID of the last transaction to revoke this block. */ -struct jbd_revoke_record_s +struct jbd2_revoke_record_s { struct list_head hash; tid_t sequence; /* Used for recovery only */ - unsigned long blocknr; + unsigned long long blocknr; }; /* The revoke table is just a simple hash table of revoke records. */ -struct jbd_revoke_table_s +struct jbd2_revoke_table_s { /* It is conceivable that we might want a larger hash table * for recovery. Must be a power of two. */ @@ -98,167 +119,188 @@ struct jbd_revoke_table_s #ifdef __KERNEL__ -static void write_one_revoke_record(journal_t *, transaction_t *, - struct journal_head **, int *, - struct jbd_revoke_record_s *); -static void flush_descriptor(journal_t *, struct journal_head *, int); +static void write_one_revoke_record(transaction_t *, + struct list_head *, + struct buffer_head **, int *, + struct jbd2_revoke_record_s *); +static void flush_descriptor(journal_t *, struct buffer_head *, int); #endif /* Utility functions to maintain the revoke table */ -/* Borrowed from buffer.c: this is a tried and tested block hash function */ -static inline int hash(journal_t *journal, unsigned long block) +static inline int hash(journal_t *journal, unsigned long long block) { - struct jbd_revoke_table_s *table = journal->j_revoke; - int hash_shift = table->hash_shift; - - return ((block << (hash_shift - 6)) ^ - (block >> 13) ^ - (block << (hash_shift - 12))) & (table->hash_size - 1); + return hash_64(block, journal->j_revoke->hash_shift); } -static int insert_revoke_hash(journal_t *journal, unsigned long blocknr, +static int insert_revoke_hash(journal_t *journal, unsigned long long blocknr, tid_t seq) { struct list_head *hash_list; - struct jbd_revoke_record_s *record; + struct jbd2_revoke_record_s *record; + gfp_t gfp_mask = GFP_NOFS; -#ifdef __KERNEL__ -repeat: -#endif - record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS); + if (journal_oom_retry) + gfp_mask |= __GFP_NOFAIL; + record = kmem_cache_alloc(jbd2_revoke_record_cache, gfp_mask); if (!record) - goto oom; + return -ENOMEM; record->sequence = seq; record->blocknr = blocknr; hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)]; + spin_lock(&journal->j_revoke_lock); list_add(&record->hash, hash_list); + spin_unlock(&journal->j_revoke_lock); return 0; - -oom: -#ifdef __KERNEL__ - if (!journal_oom_retry) - return -ENOMEM; - jbd_debug(1, "ENOMEM in " __FUNCTION__ ", retrying.\n"); - current->policy |= SCHED_YIELD; - schedule(); - goto repeat; -#else - return -ENOMEM; -#endif } /* Find a revoke record in the journal's hash table. */ -static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal, - unsigned long blocknr) +static struct jbd2_revoke_record_s *find_revoke_record(journal_t *journal, + unsigned long long blocknr) { struct list_head *hash_list; - struct jbd_revoke_record_s *record; + struct jbd2_revoke_record_s *record; hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)]; - record = (struct jbd_revoke_record_s *) hash_list->next; + spin_lock(&journal->j_revoke_lock); + record = (struct jbd2_revoke_record_s *) hash_list->next; while (&(record->hash) != hash_list) { - if (record->blocknr == blocknr) + if (record->blocknr == blocknr) { + spin_unlock(&journal->j_revoke_lock); return record; - record = (struct jbd_revoke_record_s *) record->hash.next; + } + record = (struct jbd2_revoke_record_s *) record->hash.next; } + spin_unlock(&journal->j_revoke_lock); return NULL; } -int __init journal_init_revoke_caches(void) +void jbd2_journal_destroy_revoke_record_cache(void) { - revoke_record_cache = kmem_cache_create("revoke_record", - sizeof(struct jbd_revoke_record_s), - 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - if (revoke_record_cache == 0) - return -ENOMEM; - - revoke_table_cache = kmem_cache_create("revoke_table", - sizeof(struct jbd_revoke_table_s), - 0, 0, NULL, NULL); - if (revoke_table_cache == 0) { - kmem_cache_destroy(revoke_record_cache); - revoke_record_cache = NULL; - return -ENOMEM; - } - return 0; + kmem_cache_destroy(jbd2_revoke_record_cache); + jbd2_revoke_record_cache = NULL; } -void journal_destroy_revoke_caches(void) +void jbd2_journal_destroy_revoke_table_cache(void) { - kmem_cache_destroy(revoke_record_cache); - revoke_record_cache = 0; - kmem_cache_destroy(revoke_table_cache); - revoke_table_cache = 0; + kmem_cache_destroy(jbd2_revoke_table_cache); + jbd2_revoke_table_cache = NULL; } -/* Initialise the revoke table for a given journal to a given size. */ - -int journal_init_revoke(journal_t *journal, int hash_size) +int __init jbd2_journal_init_revoke_record_cache(void) { - int shift, tmp; + J_ASSERT(!jbd2_revoke_record_cache); + jbd2_revoke_record_cache = KMEM_CACHE(jbd2_revoke_record_s, + SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY); - J_ASSERT (journal->j_revoke == NULL); + if (!jbd2_revoke_record_cache) { + pr_emerg("JBD2: failed to create revoke_record cache\n"); + return -ENOMEM; + } + return 0; +} - journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL); - if (!journal->j_revoke) +int __init jbd2_journal_init_revoke_table_cache(void) +{ + J_ASSERT(!jbd2_revoke_table_cache); + jbd2_revoke_table_cache = KMEM_CACHE(jbd2_revoke_table_s, + SLAB_TEMPORARY); + if (!jbd2_revoke_table_cache) { + pr_emerg("JBD2: failed to create revoke_table cache\n"); return -ENOMEM; + } + return 0; +} - /* Check that the hash_size is a power of two */ - J_ASSERT ((hash_size & (hash_size-1)) == 0); +static struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size) +{ + int shift = 0; + int tmp = hash_size; + struct jbd2_revoke_table_s *table; - journal->j_revoke->hash_size = hash_size; + table = kmem_cache_alloc(jbd2_revoke_table_cache, GFP_KERNEL); + if (!table) + goto out; - shift = 0; - tmp = hash_size; while((tmp >>= 1UL) != 0UL) shift++; - journal->j_revoke->hash_shift = shift; - journal->j_revoke->hash_table = - kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL); - if (!journal->j_revoke->hash_table) { - kmem_cache_free(revoke_table_cache, journal->j_revoke); - journal->j_revoke = NULL; - return -ENOMEM; + table->hash_size = hash_size; + table->hash_shift = shift; + table->hash_table = + kmalloc_array(hash_size, sizeof(struct list_head), GFP_KERNEL); + if (!table->hash_table) { + kmem_cache_free(jbd2_revoke_table_cache, table); + table = NULL; + goto out; } for (tmp = 0; tmp < hash_size; tmp++) - INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]); + INIT_LIST_HEAD(&table->hash_table[tmp]); - return 0; +out: + return table; } -/* Destoy a journal's revoke table. The table must already be empty! */ - -void journal_destroy_revoke(journal_t *journal) +static void jbd2_journal_destroy_revoke_table(struct jbd2_revoke_table_s *table) { - struct jbd_revoke_table_s *table; - struct list_head *hash_list; int i; + struct list_head *hash_list; - table = journal->j_revoke; - if (!table) - return; - - for (i=0; ihash_size; i++) { + for (i = 0; i < table->hash_size; i++) { hash_list = &table->hash_table[i]; - J_ASSERT (list_empty(hash_list)); + J_ASSERT(list_empty(hash_list)); } kfree(table->hash_table); - kmem_cache_free(revoke_table_cache, table); + kmem_cache_free(jbd2_revoke_table_cache, table); +} + +/* Initialise the revoke table for a given journal to a given size. */ +int jbd2_journal_init_revoke(journal_t *journal, int hash_size) +{ + J_ASSERT(journal->j_revoke_table[0] == NULL); + J_ASSERT(is_power_of_2(hash_size)); + + journal->j_revoke_table[0] = jbd2_journal_init_revoke_table(hash_size); + if (!journal->j_revoke_table[0]) + goto fail0; + + journal->j_revoke_table[1] = jbd2_journal_init_revoke_table(hash_size); + if (!journal->j_revoke_table[1]) + goto fail1; + + journal->j_revoke = journal->j_revoke_table[1]; + + spin_lock_init(&journal->j_revoke_lock); + + return 0; + +fail1: + jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]); + journal->j_revoke_table[0] = NULL; +fail0: + return -ENOMEM; +} + +/* Destroy a journal's revoke table. The table must already be empty! */ +void jbd2_journal_destroy_revoke(journal_t *journal) +{ journal->j_revoke = NULL; + if (journal->j_revoke_table[0]) + jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]); + if (journal->j_revoke_table[1]) + jbd2_journal_destroy_revoke_table(journal->j_revoke_table[1]); } #ifdef __KERNEL__ /* - * journal_revoke: revoke a given buffer_head from the journal. This + * jbd2_journal_revoke: revoke a given buffer_head from the journal. This * prevents the block from being replayed during recovery if we take a * crash after this current transaction commits. Any subsequent * metadata writes of the buffer in this transaction cancel the @@ -270,96 +312,104 @@ void journal_destroy_revoke(journal_t *journal) * revoke before clearing the block bitmap when we are deleting * metadata. * - * Revoke performs a journal_forget on any buffer_head passed in as a + * Revoke performs a jbd2_journal_forget on any buffer_head passed in as a * parameter, but does _not_ forget the buffer_head if the bh was only * found implicitly. * * bh_in may not be a journalled buffer - it may have come off * the hash tables without an attached journal_head. * - * If bh_in is non-zero, journal_revoke() will decrement its b_count + * If bh_in is non-zero, jbd2_journal_revoke() will decrement its b_count * by one. */ -int journal_revoke(handle_t *handle, unsigned long blocknr, +int jbd2_journal_revoke(handle_t *handle, unsigned long long blocknr, struct buffer_head *bh_in) { struct buffer_head *bh = NULL; journal_t *journal; - kdev_t dev; + struct block_device *bdev; int err; + might_sleep(); if (bh_in) BUFFER_TRACE(bh_in, "enter"); journal = handle->h_transaction->t_journal; - if (!journal_set_features(journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)){ + if (!jbd2_journal_set_features(journal, 0, 0, JBD2_FEATURE_INCOMPAT_REVOKE)){ J_ASSERT (!"Cannot set revoke feature!"); return -EINVAL; } - dev = journal->j_fs_dev; + bdev = journal->j_fs_dev; bh = bh_in; if (!bh) { - bh = get_hash_table(dev, blocknr, journal->j_blocksize); + bh = __find_get_block(bdev, blocknr, journal->j_blocksize); if (bh) BUFFER_TRACE(bh, "found on hash"); } -#ifdef JBD_EXPENSIVE_CHECKING +#ifdef JBD2_EXPENSIVE_CHECKING else { struct buffer_head *bh2; /* If there is a different buffer_head lying around in * memory anywhere... */ - bh2 = get_hash_table(dev, blocknr, journal->j_blocksize); + bh2 = __find_get_block(bdev, blocknr, journal->j_blocksize); if (bh2) { /* ... and it has RevokeValid status... */ - if ((bh2 != bh) && - test_bit(BH_RevokeValid, &bh2->b_state)) + if (bh2 != bh && buffer_revokevalid(bh2)) /* ...then it better be revoked too, * since it's illegal to create a revoke * record against a buffer_head which is * not marked revoked --- that would * risk missing a subsequent revoke * cancel. */ - J_ASSERT_BH(bh2, test_bit(BH_Revoked, & - bh2->b_state)); - __brelse(bh2); + J_ASSERT_BH(bh2, buffer_revoked(bh2)); + put_bh(bh2); } } #endif + if (WARN_ON_ONCE(handle->h_revoke_credits <= 0)) { + if (!bh_in) + brelse(bh); + return -EIO; + } /* We really ought not ever to revoke twice in a row without first having the revoke cancelled: it's illegal to free a block twice without allocating it in between! */ if (bh) { - J_ASSERT_BH(bh, !test_bit(BH_Revoked, &bh->b_state)); - set_bit(BH_Revoked, &bh->b_state); - set_bit(BH_RevokeValid, &bh->b_state); + if (!J_EXPECT_BH(bh, !buffer_revoked(bh), + "inconsistent data on disk")) { + if (!bh_in) + brelse(bh); + return -EIO; + } + set_buffer_revoked(bh); + set_buffer_revokevalid(bh); if (bh_in) { - BUFFER_TRACE(bh_in, "call journal_forget"); - journal_forget(handle, bh_in); + BUFFER_TRACE(bh_in, "call jbd2_journal_forget"); + jbd2_journal_forget(handle, bh_in); } else { BUFFER_TRACE(bh, "call brelse"); __brelse(bh); } } + handle->h_revoke_credits--; - lock_journal(journal); - jbd_debug(2, "insert revoke for block %lu, bh_in=%p\n", blocknr, bh_in); + jbd_debug(2, "insert revoke for block %llu, bh_in=%p\n",blocknr, bh_in); err = insert_revoke_hash(journal, blocknr, handle->h_transaction->t_tid); - unlock_journal(journal); BUFFER_TRACE(bh_in, "exit"); return err; } /* * Cancel an outstanding revoke. For use only internally by the - * journaling code (called from journal_get_write_access). + * journaling code (called from jbd2_journal_get_write_access). * - * We trust the BH_Revoked bit on the buffer if the buffer is already + * We trust buffer_revoked() on the buffer if the buffer is already * being journaled: if there is no revoke pending on the buffer, then we * don't do anything here. * @@ -369,12 +419,10 @@ int journal_revoke(handle_t *handle, unsigned long blocknr, * the second time we would still have a pending revoke to cancel. So, * do not trust the Revoked bit on buffers unless RevokeValid is also * set. - * - * The caller must have the journal locked. */ -int journal_cancel_revoke(handle_t *handle, struct journal_head *jh) +int jbd2_journal_cancel_revoke(handle_t *handle, struct journal_head *jh) { - struct jbd_revoke_record_s *record; + struct jbd2_revoke_record_s *record; journal_t *journal = handle->h_transaction->t_journal; int need_cancel; int did_revoke = 0; /* akpm: debug */ @@ -386,25 +434,27 @@ int journal_cancel_revoke(handle_t *handle, struct journal_head *jh) * only perform the full cancel if the revoke bit is set. If * not, we can't trust the revoke bit, and we need to do the * full search for a revoke record. */ - if (test_and_set_bit(BH_RevokeValid, &bh->b_state)) - need_cancel = (test_and_clear_bit(BH_Revoked, &bh->b_state)); - else { + if (test_set_buffer_revokevalid(bh)) { + need_cancel = test_clear_buffer_revoked(bh); + } else { need_cancel = 1; - clear_bit(BH_Revoked, &bh->b_state); + clear_buffer_revoked(bh); } if (need_cancel) { record = find_revoke_record(journal, bh->b_blocknr); if (record) { jbd_debug(4, "cancelled existing revoke on " - "blocknr %lu\n", bh->b_blocknr); + "blocknr %llu\n", (unsigned long long)bh->b_blocknr); + spin_lock(&journal->j_revoke_lock); list_del(&record->hash); - kmem_cache_free(revoke_record_cache, record); + spin_unlock(&journal->j_revoke_lock); + kmem_cache_free(jbd2_revoke_record_cache, record); did_revoke = 1; } } -#ifdef JBD_EXPENSIVE_CHECKING +#ifdef JBD2_EXPENSIVE_CHECKING /* There better not be one left behind by now! */ record = find_revoke_record(journal, bh->b_blocknr); J_ASSERT_JH(jh, record == NULL); @@ -414,52 +464,98 @@ int journal_cancel_revoke(handle_t *handle, struct journal_head *jh) * buffer_head? If so, we'd better make sure we clear the * revoked status on any hashed alias too, otherwise the revoke * state machine will get very upset later on. */ - if (need_cancel && !bh->b_pprev) { + if (need_cancel) { struct buffer_head *bh2; - bh2 = get_hash_table(bh->b_dev, bh->b_blocknr, bh->b_size); + bh2 = __find_get_block(bh->b_bdev, bh->b_blocknr, bh->b_size); if (bh2) { - clear_bit(BH_Revoked, &bh2->b_state); + if (bh2 != bh) + clear_buffer_revoked(bh2); __brelse(bh2); } } - return did_revoke; } +/* + * journal_clear_revoked_flag clears revoked flag of buffers in + * revoke table to reflect there is no revoked buffers in the next + * transaction which is going to be started. + */ +void jbd2_clear_buffer_revoked_flags(journal_t *journal) +{ + struct jbd2_revoke_table_s *revoke = journal->j_revoke; + int i = 0; + + for (i = 0; i < revoke->hash_size; i++) { + struct list_head *hash_list; + struct list_head *list_entry; + hash_list = &revoke->hash_table[i]; + + list_for_each(list_entry, hash_list) { + struct jbd2_revoke_record_s *record; + struct buffer_head *bh; + record = (struct jbd2_revoke_record_s *)list_entry; + bh = __find_get_block(journal->j_fs_dev, + record->blocknr, + journal->j_blocksize); + if (bh) { + clear_buffer_revoked(bh); + __brelse(bh); + } + } + } +} + +/* journal_switch_revoke table select j_revoke for next transaction + * we do not want to suspend any processing until all revokes are + * written -bzzz + */ +void jbd2_journal_switch_revoke_table(journal_t *journal) +{ + int i; + + if (journal->j_revoke == journal->j_revoke_table[0]) + journal->j_revoke = journal->j_revoke_table[1]; + else + journal->j_revoke = journal->j_revoke_table[0]; + + for (i = 0; i < journal->j_revoke->hash_size; i++) + INIT_LIST_HEAD(&journal->j_revoke->hash_table[i]); +} /* * Write revoke records to the journal for all entries in the current * revoke hash, deleting the entries as we go. - * - * Called with the journal lock held. */ - -void journal_write_revoke_records(journal_t *journal, - transaction_t *transaction) +void jbd2_journal_write_revoke_records(transaction_t *transaction, + struct list_head *log_bufs) { - struct journal_head *descriptor; - struct jbd_revoke_record_s *record; - struct jbd_revoke_table_s *revoke; + journal_t *journal = transaction->t_journal; + struct buffer_head *descriptor; + struct jbd2_revoke_record_s *record; + struct jbd2_revoke_table_s *revoke; struct list_head *hash_list; int i, offset, count; descriptor = NULL; offset = 0; count = 0; - revoke = journal->j_revoke; + + /* select revoke table for committing transaction */ + revoke = journal->j_revoke == journal->j_revoke_table[0] ? + journal->j_revoke_table[1] : journal->j_revoke_table[0]; for (i = 0; i < revoke->hash_size; i++) { hash_list = &revoke->hash_table[i]; while (!list_empty(hash_list)) { - record = (struct jbd_revoke_record_s *) + record = (struct jbd2_revoke_record_s *) hash_list->next; - write_one_revoke_record(journal, transaction, - &descriptor, &offset, - record); + write_one_revoke_record(transaction, log_bufs, + &descriptor, &offset, record); count++; list_del(&record->hash); - kmem_cache_free(revoke_record_cache, record); + kmem_cache_free(jbd2_revoke_record_cache, record); } } if (descriptor) @@ -472,19 +568,20 @@ void journal_write_revoke_records(journal_t *journal, * block if the old one is full or if we have not already created one. */ -static void write_one_revoke_record(journal_t *journal, - transaction_t *transaction, - struct journal_head **descriptorp, +static void write_one_revoke_record(transaction_t *transaction, + struct list_head *log_bufs, + struct buffer_head **descriptorp, int *offsetp, - struct jbd_revoke_record_s *record) + struct jbd2_revoke_record_s *record) { - struct journal_head *descriptor; - int offset; - journal_header_t *header; + journal_t *journal = transaction->t_journal; + int csum_size = 0; + struct buffer_head *descriptor; + int sz, offset; /* If we are already aborting, this all becomes a noop. We still need to go round the loop in - journal_write_revoke_records in order to free all of the + jbd2_journal_write_revoke_records in order to free all of the revoke records: only the IO to the journal is omitted. */ if (is_journal_aborted(journal)) return; @@ -492,34 +589,45 @@ static void write_one_revoke_record(journal_t *journal, descriptor = *descriptorp; offset = *offsetp; + /* Do we need to leave space at the end for a checksum? */ + if (jbd2_journal_has_csum_v2or3(journal)) + csum_size = sizeof(struct jbd2_journal_block_tail); + + if (jbd2_has_feature_64bit(journal)) + sz = 8; + else + sz = 4; + /* Make sure we have a descriptor with space left for the record */ if (descriptor) { - if (offset == journal->j_blocksize) { + if (offset + sz > journal->j_blocksize - csum_size) { flush_descriptor(journal, descriptor, offset); descriptor = NULL; } } if (!descriptor) { - descriptor = journal_get_descriptor_buffer(journal); + descriptor = jbd2_journal_get_descriptor_buffer(transaction, + JBD2_REVOKE_BLOCK); if (!descriptor) return; - header = (journal_header_t *) &jh2bh(descriptor)->b_data[0]; - header->h_magic = htonl(JFS_MAGIC_NUMBER); - header->h_blocktype = htonl(JFS_REVOKE_BLOCK); - header->h_sequence = htonl(transaction->t_tid); /* Record it so that we can wait for IO completion later */ - JBUFFER_TRACE(descriptor, "file as BJ_LogCtl"); - journal_file_buffer(descriptor, transaction, BJ_LogCtl); + BUFFER_TRACE(descriptor, "file in log_bufs"); + jbd2_file_log_bh(log_bufs, descriptor); - offset = sizeof(journal_revoke_header_t); + offset = sizeof(jbd2_journal_revoke_header_t); *descriptorp = descriptor; } - * ((unsigned int *)(&jh2bh(descriptor)->b_data[offset])) = - htonl(record->blocknr); - offset += 4; + if (jbd2_has_feature_64bit(journal)) + * ((__be64 *)(&descriptor->b_data[offset])) = + cpu_to_be64(record->blocknr); + else + * ((__be32 *)(&descriptor->b_data[offset])) = + cpu_to_be32(record->blocknr); + offset += sz; + *offsetp = offset; } @@ -531,27 +639,23 @@ static void write_one_revoke_record(journal_t *journal, */ static void flush_descriptor(journal_t *journal, - struct journal_head *descriptor, + struct buffer_head *descriptor, int offset) { - journal_revoke_header_t *header; + jbd2_journal_revoke_header_t *header; - if (is_journal_aborted(journal)) { - JBUFFER_TRACE(descriptor, "brelse"); - __brelse(jh2bh(descriptor)); + if (is_journal_aborted(journal)) return; - } - header = (journal_revoke_header_t *) jh2bh(descriptor)->b_data; - header->r_count = htonl(offset); - set_bit(BH_JWrite, &jh2bh(descriptor)->b_state); - { - struct buffer_head *bh = jh2bh(descriptor); - BUFFER_TRACE(bh, "write"); - ll_rw_block (WRITE, 1, &bh); - } -} + header = (jbd2_journal_revoke_header_t *)descriptor->b_data; + header->r_count = cpu_to_be32(offset); + jbd2_descriptor_block_csum_set(journal, descriptor); + set_buffer_jwrite(descriptor); + BUFFER_TRACE(descriptor, "write"); + set_buffer_dirty(descriptor); + write_dirty_buffer(descriptor, REQ_SYNC); +} #endif /* @@ -576,15 +680,15 @@ static void flush_descriptor(journal_t *journal, * single block. */ -int journal_set_revoke(journal_t *journal, - unsigned long blocknr, +int jbd2_journal_set_revoke(journal_t *journal, + unsigned long long blocknr, tid_t sequence) { - struct jbd_revoke_record_s *record; + struct jbd2_revoke_record_s *record; record = find_revoke_record(journal, blocknr); if (record) { - /* If we have multiple occurences, only record the + /* If we have multiple occurrences, only record the * latest sequence number in the hashed record */ if (tid_gt(sequence, record->sequence)) record->sequence = sequence; @@ -600,11 +704,11 @@ int journal_set_revoke(journal_t *journal, * ones, but later transactions still need replayed. */ -int journal_test_revoke(journal_t *journal, - unsigned long blocknr, +int jbd2_journal_test_revoke(journal_t *journal, + unsigned long long blocknr, tid_t sequence) { - struct jbd_revoke_record_s *record; + struct jbd2_revoke_record_s *record; record = find_revoke_record(journal, blocknr); if (!record) @@ -619,22 +723,21 @@ int journal_test_revoke(journal_t *journal, * that it can be reused by the running filesystem. */ -void journal_clear_revoke(journal_t *journal) +void jbd2_journal_clear_revoke(journal_t *journal) { int i; struct list_head *hash_list; - struct jbd_revoke_record_s *record; - struct jbd_revoke_table_s *revoke; + struct jbd2_revoke_record_s *record; + struct jbd2_revoke_table_s *revoke; revoke = journal->j_revoke; for (i = 0; i < revoke->hash_size; i++) { hash_list = &revoke->hash_table[i]; while (!list_empty(hash_list)) { - record = (struct jbd_revoke_record_s*) hash_list->next; + record = (struct jbd2_revoke_record_s*) hash_list->next; list_del(&record->hash); - kmem_cache_free(revoke_record_cache, record); + kmem_cache_free(jbd2_revoke_record_cache, record); } } } -