shithub: lwext4

Download patch

ref: 82529f8ee832bf67da9a4cf52b4b89fdbaf0c077
parent: 29d9896af914e4a058de154920ce55eb6371de93
author: ngkaho1234 <[email protected]>
date: Thu Nov 26 06:01:13 EST 2015

ext4_journal.c: journal replay skeletal code.

--- a/lwext4/ext4.c
+++ b/lwext4/ext4.c
@@ -46,6 +46,7 @@
 #include "ext4_super.h"
 #include "ext4_dir_idx.h"
 #include "ext4_xattr.h"
+#include "ext4_journal.h"
 
 
 #include <stdlib.h>
@@ -408,6 +409,17 @@
 			free(bc);
 		}
 		return r;
+	}
+
+	/* TODO: journal mount checking. */
+	if (ext4_sb_feature_com(&mp->fs.sb, EXT4_FCOM_HAS_JOURNAL)) {
+		struct jbd_fs jbd_fs = {0};
+		r = jbd_get_fs(&mp->fs, &jbd_fs);
+		if (r != EOK)
+			return r;
+
+		r = jbd_recover(&jbd_fs);
+		jbd_put_fs(&jbd_fs);
 	}
 
 	return r;
--- a/lwext4/ext4_debug.h
+++ b/lwext4/ext4_debug.h
@@ -77,6 +77,7 @@
 #define DEBUG_XATTR (1 << 13)
 #define DEBUG_MKFS (1 << 14)
 #define DEBUG_EXT4 (1 << 15)
+#define DEBUG_JBD (1 << 16)
 
 #define DEBUG_ALL (0xFFFFFFFF)
 
@@ -113,6 +114,8 @@
 		return "ext4_xattr: ";
 	case DEBUG_MKFS:
 		return "ext4_mkfs: ";
+	case DEBUG_JBD:
+		return "ext4_jbd: ";
 	case DEBUG_EXT4:
 		return "ext4: ";
 	}
--- a/lwext4/ext4_journal.c
+++ b/lwext4/ext4_journal.c
@@ -48,6 +48,19 @@
 				    EXT4_SUPERBLOCK_SIZE);
 }
 
+static bool jbd_verify_sb(struct jbd_sb *sb)
+{
+	struct jbd_bhdr *bhdr = &sb->header;
+	if (bhdr->magic != to_be32(JBD_MAGIC_NUMBER))
+		return false;
+
+	if (bhdr->blocktype != to_be32(JBD_SUPERBLOCK) &&
+	    bhdr->blocktype != to_be32(JBD_SUPERBLOCK_V2))
+		return false;
+
+	return true;
+}
+
 int jbd_get_fs(struct ext4_fs *fs,
 	       struct jbd_fs *jbd_fs)
 {
@@ -69,6 +82,7 @@
 		memset(jbd_fs, 0, sizeof(struct jbd_fs));
 		ext4_fs_put_inode_ref(&jbd_fs->inode_ref);
 	}
+
 	return rc;
 }
 
@@ -132,10 +146,113 @@
 			      block);
 }
 
-int jbd_recovery(struct jbd_fs *jbd_fs)
+/* Make sure we wrap around the log correctly! */
+#define wrap(sb, var)						\
+do {									\
+	if (var >= to_be32((sb)->maxlen))					\
+		var -= (to_be32((sb)->maxlen) - to_be32((sb)->first));	\
+} while (0)
+
+#define ACTION_SCAN 0
+#define ACTION_REVOKE 1
+#define ACTION_RECOVER 2
+
+struct recover_info {
+	uint32_t start_trans_id;
+	uint32_t last_trans_id;
+};
+
+int jbd_iterate_log(struct jbd_fs *jbd_fs,
+		    struct recover_info *info,
+		    int action)
 {
+	int r = EOK;
+	bool log_end = false;
 	struct jbd_sb *sb = &jbd_fs->sb;
+	uint32_t start_trans_id, this_trans_id;
+	uint32_t start_block, this_block;
+
+	start_trans_id = this_trans_id = to_be32(sb->sequence);
+	start_block = this_block = to_be32(sb->start);
+
+	ext4_dbg(DEBUG_JBD, "Start of journal at trans id: %" PRIu32 "\n",
+			    start_trans_id);
+
+	while (!log_end) {
+		struct ext4_block block;
+		struct jbd_bhdr *header;
+		if (action != ACTION_SCAN)
+			if (this_trans_id > info->last_trans_id) {
+				log_end = true;
+				continue;
+			}
+
+		r = jbd_block_get(jbd_fs, &block, this_block);
+		if (r != EOK)
+			break;
+
+		header = (struct jbd_bhdr *)block.data;
+		if (header->magic != to_be32(JBD_MAGIC_NUMBER)) {
+			log_end = true;
+			continue;
+		}
+
+		if (header->sequence != to_be32(this_trans_id)) {
+			if (this_trans_id <= info->last_trans_id)
+				r = EIO;
+
+			log_end = true;
+			continue;
+		}
+
+		switch (header->blocktype) {
+		case JBD_DESCRIPTOR_BLOCK:
+			ext4_dbg(DEBUG_JBD, "Descriptor block: %u, "
+					    "trans_id: %u\n",
+					    this_block, this_trans_id);
+			break;
+		case JBD_COMMIT_BLOCK:
+			ext4_dbg(DEBUG_JBD, "Commit block: %u, "
+					    "trans_id: %u\n",
+					    this_block, this_trans_id);
+			this_trans_id++;
+			break;
+		case JBD_REVOKE_BLOCK:
+			ext4_dbg(DEBUG_JBD, "Revoke block: %u, "
+					    "trans_id: %u\n",
+					    this_block, this_trans_id);
+			break;
+		default:
+			log_end = true;
+			break;
+		}
+		jbd_block_set(jbd_fs, &block);
+		this_block++;
+		wrap(sb, this_block);
+		if (this_block == start_block)
+			log_end = true;
+
+	}
+	ext4_dbg(DEBUG_JBD, "End of journal.\n");
+	if (r == EOK && action == ACTION_SCAN) {
+		info->start_trans_id = start_trans_id;
+		if (this_trans_id > start_trans_id)
+			info->last_trans_id = this_trans_id - 1;
+		else
+			info->last_trans_id = this_trans_id;
+	}
+
+	return r;
+}
+
+int jbd_recover(struct jbd_fs *jbd_fs)
+{
+	int r;
+	struct recover_info info;
+	struct jbd_sb *sb = &jbd_fs->sb;
 	if (!sb->start)
 		return EOK;
 
+	r = jbd_iterate_log(jbd_fs, &info, ACTION_SCAN);
+	return r;
 }
--- a/lwext4/ext4_journal.h
+++ b/lwext4/ext4_journal.h
@@ -56,6 +56,7 @@
 int jbd_inode_bmap(struct jbd_fs *jbd_fs,
 		   ext4_lblk_t iblock,
 		   ext4_fsblk_t *fblock);
+int jbd_recover(struct jbd_fs *jbd_fs);
 
 #ifdef __cplusplus
 }