shithub: lwext4

Download patch

ref: 9c9fdb96e86ad654ae1706813de807762793e7a0
parent: 43da1b2f9a9b6922369cc47e265cac3c93112325
author: ngkaho1234 <ngkaho1234@gmail.com>
date: Sat Nov 28 13:13:18 EST 2015

ext4_journal: add building revoke tree.

--- a/lwext4/ext4_journal.c
+++ b/lwext4/ext4_journal.c
@@ -16,6 +16,35 @@
 #include <string.h>
 #include <malloc.h>
 
+struct revoke_entry {
+	ext4_fsblk_t block;
+	uint32_t trans_id;
+	RB_ENTRY(revoke_entry) revoke_node;
+};
+
+struct recover_info {
+	uint32_t start_trans_id;
+	uint32_t last_trans_id;
+	uint32_t this_trans_id;
+	RB_HEAD(jbd_revoke, revoke_entry) revoke_root;
+};
+
+static int
+jbd_revoke_entry_cmp(struct revoke_entry *a, struct revoke_entry *b)
+{
+	if (a->block > b->block)
+		return 1;
+	else if (a->block < b->block)
+		return -1;
+	return 0;
+}
+
+RB_GENERATE_INTERNAL(jbd_revoke, revoke_entry, revoke_node,
+		     jbd_revoke_entry_cmp, static inline)
+
+#define jbd_alloc_revoke_entry() calloc(1, sizeof(struct revoke_entry))
+#define jbd_free_revoke_entry(addr) free(addr)
+
 int jbd_inode_bmap(struct jbd_fs *jbd_fs,
 		   ext4_lblk_t iblock,
 		   ext4_fsblk_t *fblock);
@@ -285,12 +314,51 @@
 	return;
 }
 
-struct revoke_entry {
-	ext4_fsblk_t block;
-	uint32_t trans_id;
-	RB_ENTRY(revoke_entry) revoke_node;
-};
+static struct revoke_entry *
+jbd_revoke_entry_lookup(struct recover_info *info, ext4_fsblk_t block)
+{
+	struct revoke_entry tmp = {
+		.block = block
+	};
 
+	return RB_FIND(jbd_revoke, &info->revoke_root, &tmp);
+}
+
+static void jbd_add_revoke_block_tags(struct jbd_fs *jbd_fs __unused,
+				      ext4_fsblk_t block,
+				      uint8_t *uuid __unused,
+				      void *arg)
+{
+	struct recover_info *info = arg;
+	struct revoke_entry *revoke_entry;
+
+	ext4_dbg(DEBUG_JBD, "Add block %" PRIu64 " to revoke tree\n", block);
+	revoke_entry = jbd_revoke_entry_lookup(info, block);
+	if (revoke_entry) {
+		revoke_entry->trans_id = info->this_trans_id;
+		return;
+	}
+
+	revoke_entry = jbd_alloc_revoke_entry();
+	ext4_assert(revoke_entry);
+	revoke_entry->block = block;
+	revoke_entry->trans_id = info->this_trans_id;
+	RB_INSERT(jbd_revoke, &info->revoke_root, revoke_entry);
+
+	return;
+}
+
+static void jbd_destroy_revoke_tree(struct recover_info *info)
+{
+	while (!RB_EMPTY(&info->revoke_root)) {
+		struct revoke_entry *revoke_entry =
+			RB_MIN(jbd_revoke, &info->revoke_root);
+		ext4_assert(revoke_entry);
+		RB_REMOVE(jbd_revoke, &info->revoke_root, revoke_entry);
+		jbd_free_revoke_entry(revoke_entry);
+	}
+}
+
 /* Make sure we wrap around the log correctly! */
 #define wrap(sb, var)						\
 do {									\
@@ -302,11 +370,6 @@
 #define ACTION_REVOKE 1
 #define ACTION_RECOVER 2
 
-struct recover_info {
-	uint32_t start_trans_id;
-	uint32_t last_trans_id;
-	RB_HEAD(jbd_revoke, revoke_entry) revoke_root;
-};
 
 static void jbd_build_revoke_root(struct jbd_fs *jbd_fs,
 				  struct jbd_bhdr *header,
@@ -319,10 +382,8 @@
 				revoke_hdr + 1,
 				jbd_get32(&jbd_fs->sb, blocksize) -
 					sizeof(struct jbd_revoke_header),
-				jbd_display_block_tags,
-				NULL);
-
-	(void)info;
+				jbd_add_revoke_block_tags,
+				info);
 }
 
 static void jbd_debug_descriptor_block(struct jbd_fs *jbd_fs,
@@ -387,7 +448,9 @@
 			ext4_dbg(DEBUG_JBD, "Descriptor block: %u, "
 					    "trans_id: %u\n",
 					    this_block, this_trans_id);
-			jbd_debug_descriptor_block(jbd_fs, header, &this_block);
+			if (action == ACTION_SCAN)
+				jbd_debug_descriptor_block(jbd_fs,
+						header, &this_block);
 			break;
 		case JBD_COMMIT_BLOCK:
 			ext4_dbg(DEBUG_JBD, "Commit block: %u, "
@@ -399,7 +462,10 @@
 			ext4_dbg(DEBUG_JBD, "Revoke block: %u, "
 					    "trans_id: %u\n",
 					    this_block, this_trans_id);
-			jbd_build_revoke_root(jbd_fs, header, info);
+			if (action == ACTION_REVOKE) {
+				info->this_trans_id = this_trans_id;
+				jbd_build_revoke_root(jbd_fs, header, info);
+			}
 			break;
 		default:
 			log_end = true;
@@ -432,6 +498,13 @@
 	if (!sb->start)
 		return EOK;
 
+	RB_INIT(&info.revoke_root);
+
 	r = jbd_iterate_log(jbd_fs, &info, ACTION_SCAN);
+	if (r != EOK)
+		return r;
+
+	r = jbd_iterate_log(jbd_fs, &info, ACTION_REVOKE);
+	jbd_destroy_revoke_tree(&info);
 	return r;
 }