Viewing: jbd2-revoke-rhashtable-rhel7.patch

Index: linux-3.10.0-1160.80.1.el7/fs/jbd2/recovery.c
===================================================================
--- linux-3.10.0-1160.80.1.el7.orig/fs/jbd2/recovery.c
+++ linux-3.10.0-1160.80.1.el7/fs/jbd2/recovery.c
@@ -22,6 +22,7 @@
 #include <linux/errno.h>
 #include <linux/crc32.h>
 #include <linux/blkdev.h>
+#include <linux/rhashtable.h>
 #endif
 
 /*
@@ -255,6 +256,10 @@ int jbd2_journal_recover(journal_t *jour
 	memset(&info, 0, sizeof(info));
 	sb = journal->j_superblock;
 
+	err = jbd2_journal_init_recovery_revoke(journal);
+	if (err)
+		return err;
+
 	/*
 	 * The journal superblock's s_start field (the current log head)
 	 * is always zero if, and only if, the journal was cleanly
Index: linux-3.10.0-1160.80.1.el7/fs/jbd2/revoke.c
===================================================================
--- linux-3.10.0-1160.80.1.el7.orig/fs/jbd2/revoke.c
+++ linux-3.10.0-1160.80.1.el7/fs/jbd2/revoke.c
@@ -93,6 +93,7 @@
 #include <linux/bio.h>
 #include <linux/log2.h>
 #include <linux/hash.h>
+#include <linux/rhashtable.h>
 #endif
 
 static struct kmem_cache *jbd2_revoke_record_cache;
@@ -104,7 +105,10 @@ static struct kmem_cache *jbd2_revoke_ta
 
 struct jbd2_revoke_record_s
 {
-	struct list_head  hash;
+ 	union {
+ 		struct list_head  hash;
+ 		struct rhash_head linkage;
+	};
 	tid_t		  sequence;	/* Used for recovery only */
 	unsigned long long	  blocknr;
 };
@@ -701,13 +705,21 @@ static void flush_descriptor(journal_t *
  * single block.
  */
 
+static const struct rhashtable_params revoke_rhashtable_params = {
+	.key_len     = sizeof(unsigned long long),
+	.key_offset  = offsetof(struct jbd2_revoke_record_s, blocknr),
+	.head_offset = offsetof(struct jbd2_revoke_record_s, linkage),
+};
+
 int jbd2_journal_set_revoke(journal_t *journal,
 		       unsigned long long blocknr,
 		       tid_t sequence)
 {
-	struct jbd2_revoke_record_s *record;
+	struct jbd2_revoke_record_s *record, *old;
+	gfp_t gfp_mask = GFP_NOFS;
 
-	record = find_revoke_record(journal, blocknr);
+	record = rhashtable_lookup(&journal->j_revoke_rhtable, &blocknr,
+				revoke_rhashtable_params);
 	if (record) {
 		/* If we have multiple occurrences, only record the
 		 * latest sequence number in the hashed record */
@@ -715,7 +727,24 @@ int jbd2_journal_set_revoke(journal_t *j
 			record->sequence = sequence;
 		return 0;
 	}
-	return insert_revoke_hash(journal, blocknr, sequence);
+
+	if (journal_oom_retry)
+		gfp_mask |= __GFP_NOFAIL;
+	record = kmem_cache_alloc(jbd2_revoke_record_cache, gfp_mask);
+	if (!record)
+		return -ENOMEM;
+
+	record->sequence = sequence;
+	record->blocknr = blocknr;
+	old = rhashtable_lookup_get_insert_fast(&journal->j_revoke_rhtable,
+				 &record->linkage, revoke_rhashtable_params);
+	if (IS_ERR(old)) {
+		kmem_cache_free(jbd2_revoke_record_cache, record);
+		return PTR_ERR(old);
+	}
+	BUG_ON(old != NULL);
+
+	return 0;
 }
 
 /*
@@ -731,7 +760,8 @@ int jbd2_journal_test_revoke(journal_t *
 {
 	struct jbd2_revoke_record_s *record;
 
-	record = find_revoke_record(journal, blocknr);
+	record = rhashtable_lookup(&journal->j_revoke_rhtable, &blocknr,
+				revoke_rhashtable_params);
 	if (!record)
 		return 0;
 	if (tid_gt(sequence, record->sequence))
@@ -739,6 +769,17 @@ int jbd2_journal_test_revoke(journal_t *
 	return 1;
 }
 
+int jbd2_journal_init_recovery_revoke(journal_t *journal)
+{
+	return rhashtable_init(&journal->j_revoke_rhtable,
+				&revoke_rhashtable_params);
+}
+ 
+static void jbd2_revoke_record_free(void *ptr, void *arg)
+{
+	kmem_cache_free(jbd2_revoke_record_cache, ptr);
+}
+ 
 /*
  * Finally, once recovery is over, we need to clear the revoke table so
  * that it can be reused by the running filesystem.
@@ -746,19 +787,6 @@ int jbd2_journal_test_revoke(journal_t *
 
 void jbd2_journal_clear_revoke(journal_t *journal)
 {
-	int i;
-	struct list_head *hash_list;
-	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 jbd2_revoke_record_s*) hash_list->next;
-			list_del(&record->hash);
-			kmem_cache_free(jbd2_revoke_record_cache, record);
-		}
-	}
+	rhashtable_free_and_destroy(&journal->j_revoke_rhtable,
+					jbd2_revoke_record_free, NULL);
 }
Index: linux-3.10.0-1160.80.1.el7/include/linux/jbd2.h
===================================================================
--- linux-3.10.0-1160.80.1.el7.orig/include/linux/jbd2.h
+++ linux-3.10.0-1160.80.1.el7/include/linux/jbd2.h
@@ -31,6 +31,7 @@
 #include <linux/timer.h>
 #include <linux/slab.h>
 #include <crypto/hash.h>
+#include <linux/rhashtable.h>
 #endif
 
 #define journal_oom_retry 1
@@ -944,6 +945,11 @@ struct journal_s
 	struct jbd2_revoke_table_s *j_revoke_table[2];
 
 	/*
+	 * rhashtable for revoke records during recovery
+	 */
+	struct rhashtable	j_revoke_rhtable;
+
+	/*
 	 * array of bhs for jbd2_journal_commit_transaction
 	 */
 	struct buffer_head	**j_wbuf;
@@ -1231,6 +1237,7 @@ extern void	   jbd2_journal_write_revoke
 /* Recovery revoke support */
 extern int	jbd2_journal_set_revoke(journal_t *, unsigned long long, tid_t);
 extern int	jbd2_journal_test_revoke(journal_t *, unsigned long long, tid_t);
+extern int	jbd2_journal_init_recovery_revoke(journal_t *);
 extern void	jbd2_journal_clear_revoke(journal_t *);
 extern void	jbd2_journal_switch_revoke_table(journal_t *journal);
 extern void	jbd2_clear_buffer_revoked_flags(journal_t *journal);