shithub: lwext4

Download patch

ref: 13b86cb3c22b6a08638bd87c4b7f31e070d60dc1
parent: 9c9fdb96e86ad654ae1706813de807762793e7a0
author: ngkaho1234 <ngkaho1234@gmail.com>
date: Sat Nov 28 22:30:26 EST 2015

ext4_journal: fix wrong parsing of revoke blocks list.

--- a/lwext4/ext4_journal.c
+++ b/lwext4/ext4_journal.c
@@ -324,12 +324,9 @@
 	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)
+static void jbd_add_revoke_block_tags(struct recover_info *info,
+				      ext4_fsblk_t block)
 {
-	struct recover_info *info = arg;
 	struct revoke_entry *revoke_entry;
 
 	ext4_dbg(DEBUG_JBD, "Add block %" PRIu64 " to revoke tree\n", block);
@@ -371,19 +368,36 @@
 #define ACTION_RECOVER 2
 
 
-static void jbd_build_revoke_root(struct jbd_fs *jbd_fs,
+static void jbd_build_revoke_tree(struct jbd_fs *jbd_fs,
 				  struct jbd_bhdr *header,
 				  struct recover_info *info)
 {
+	char *blocks_entry;
 	struct jbd_revoke_header *revoke_hdr =
 		(struct jbd_revoke_header *)header;
+	uint32_t i, nr_entries, record_len = 4;
+	if (JBD_HAS_INCOMPAT_FEATURE(&jbd_fs->sb,
+				     JBD_FEATURE_INCOMPAT_64BIT))
+		record_len = 8;
 
-	jbd_iterate_block_table(jbd_fs,
-				revoke_hdr + 1,
-				jbd_get32(&jbd_fs->sb, blocksize) -
-					sizeof(struct jbd_revoke_header),
-				jbd_add_revoke_block_tags,
-				info);
+	nr_entries = (revoke_hdr->count -
+			sizeof(struct jbd_revoke_header)) /
+			record_len;
+
+	blocks_entry = (char *)(revoke_hdr + 1);
+
+	for (i = 0;i < nr_entries;i++) {
+		if (record_len == 8) {
+			uint64_t *blocks =
+				(uint64_t *)blocks_entry;
+			jbd_add_revoke_block_tags(info, *blocks);
+		} else {
+			uint32_t *blocks =
+				(uint32_t *)blocks_entry;
+			jbd_add_revoke_block_tags(info, *blocks);
+		}
+		blocks_entry += record_len;
+	}
 }
 
 static void jbd_debug_descriptor_block(struct jbd_fs *jbd_fs,
@@ -464,7 +478,8 @@
 					    this_block, this_trans_id);
 			if (action == ACTION_REVOKE) {
 				info->this_trans_id = this_trans_id;
-				jbd_build_revoke_root(jbd_fs, header, info);
+				jbd_build_revoke_tree(jbd_fs,
+						header, info);
 			}
 			break;
 		default: