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
}