diff mbox series

[mtd-utils,v2,RESEND,051/102] fsck.ubifs: Load filesystem information from UBI volume

Message ID 20241111090124.2070455-12-chengzhihao1@huawei.com
State Accepted
Delegated to: David Oberhollenzer
Headers show
Series Add fsck.ubifs support | expand

Commit Message

Zhihao Cheng Nov. 11, 2024, 9:01 a.m. UTC
Load filesystem information from UBI volume (Similar to UBIFS mounting
process), initialize kinds of buffers and read superblock. This is the
base step for both fsck and rebuild_fs. Subsequent pacthes will complete
this step by adding more steps(eg. read master, replay journal, etc.)
which are only used in fsck.

Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
---
 ubifs-utils/Makemodule.am           |   3 +-
 ubifs-utils/fsck.ubifs/fsck.ubifs.c |   7 ++
 ubifs-utils/fsck.ubifs/fsck.ubifs.h |   7 ++
 ubifs-utils/fsck.ubifs/load_fs.c    | 127 ++++++++++++++++++++++++++++++++++++
 ubifs-utils/fsck.ubifs/problem.c    |   4 +-
 5 files changed, 146 insertions(+), 2 deletions(-)
 create mode 100644 ubifs-utils/fsck.ubifs/load_fs.c
diff mbox series

Patch

diff --git a/ubifs-utils/Makemodule.am b/ubifs-utils/Makemodule.am
index 590f17b6..baba1853 100644
--- a/ubifs-utils/Makemodule.am
+++ b/ubifs-utils/Makemodule.am
@@ -81,7 +81,8 @@  fsck_ubifs_SOURCES = \
 	$(libubifs_SOURCES) \
 	ubifs-utils/fsck.ubifs/fsck.ubifs.h \
 	ubifs-utils/fsck.ubifs/fsck.ubifs.c \
-	ubifs-utils/fsck.ubifs/problem.c
+	ubifs-utils/fsck.ubifs/problem.c \
+	ubifs-utils/fsck.ubifs/load_fs.c
 
 fsck_ubifs_LDADD = libmtd.a libubi.a $(ZLIB_LIBS) $(LZO_LIBS) $(ZSTD_LIBS) $(UUID_LIBS) $(LIBSELINUX_LIBS) $(OPENSSL_LIBS) \
 		   $(DUMP_STACK_LD) -lm -lpthread
diff --git a/ubifs-utils/fsck.ubifs/fsck.ubifs.c b/ubifs-utils/fsck.ubifs/fsck.ubifs.c
index a3672411..ef94fcfb 100644
--- a/ubifs-utils/fsck.ubifs/fsck.ubifs.c
+++ b/ubifs-utils/fsck.ubifs/fsck.ubifs.c
@@ -423,8 +423,15 @@  int main(int argc, char *argv[])
 		goto out_destroy_fsck;
 	}
 
+	/* Init: Read superblock */
+	err = ubifs_load_filesystem(c);
+	if (err)
+		goto out_close;
+
 	err = do_fsck();
 
+	ubifs_destroy_filesystem(c);
+out_close:
 	ubifs_close_volume(c);
 out_destroy_fsck:
 	destroy_fsck_info(c);
diff --git a/ubifs-utils/fsck.ubifs/fsck.ubifs.h b/ubifs-utils/fsck.ubifs/fsck.ubifs.h
index 762745f9..c21082e0 100644
--- a/ubifs-utils/fsck.ubifs/fsck.ubifs.h
+++ b/ubifs-utils/fsck.ubifs/fsck.ubifs.h
@@ -36,6 +36,9 @@ 
 enum { NORMAL_MODE = 0, SAFE_MODE, DANGER_MODE0,
        DANGER_MODE1, REBUILD_MODE, CHECK_MODE };
 
+/* Types of inconsistent problems */
+enum { SB_CORRUPTED = 0 };
+
 /**
  * struct ubifs_fsck_info - UBIFS fsck information.
  * @mode: working mode
@@ -95,4 +98,8 @@  extern int exit_code;
 /* problem.c */
 bool fix_problem(const struct ubifs_info *c, int problem_type);
 
+/* load_fs.c */
+int ubifs_load_filesystem(struct ubifs_info *c);
+void ubifs_destroy_filesystem(struct ubifs_info *c);
+
 #endif
diff --git a/ubifs-utils/fsck.ubifs/load_fs.c b/ubifs-utils/fsck.ubifs/load_fs.c
new file mode 100644
index 00000000..4a06b4c2
--- /dev/null
+++ b/ubifs-utils/fsck.ubifs/load_fs.c
@@ -0,0 +1,127 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024, Huawei Technologies Co, Ltd.
+ *
+ * Authors: Zhihao Cheng <chengzhihao1@huawei.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "bitops.h"
+#include "kmem.h"
+#include "ubifs.h"
+#include "defs.h"
+#include "debug.h"
+#include "key.h"
+#include "misc.h"
+#include "fsck.ubifs.h"
+
+int ubifs_load_filesystem(struct ubifs_info *c)
+{
+	int err;
+	size_t sz;
+
+	err = init_constants_early(c);
+	if (err) {
+		exit_code |= FSCK_ERROR;
+		return err;
+	}
+
+	err = check_volume_empty(c);
+	if (err <= 0) {
+		exit_code |= FSCK_ERROR;
+		log_err(c, 0, "%s UBI volume!", err < 0 ? "bad" : "empty");
+		return -EINVAL;
+	}
+
+	if (c->ro_media && !c->ro_mount) {
+		exit_code |= FSCK_ERROR;
+		log_err(c, 0, "cannot read-write on read-only media");
+		return -EROFS;
+	}
+
+	err = -ENOMEM;
+	c->bottom_up_buf = kmalloc_array(BOTTOM_UP_HEIGHT, sizeof(int),
+					 GFP_KERNEL);
+	if (!c->bottom_up_buf) {
+		exit_code |= FSCK_ERROR;
+		log_err(c, errno, "cannot allocate bottom_up_buf");
+		goto out_free;
+	}
+
+	c->sbuf = vmalloc(c->leb_size);
+	if (!c->sbuf) {
+		exit_code |= FSCK_ERROR;
+		log_err(c, errno, "cannot allocate sbuf");
+		goto out_free;
+	}
+
+	if (!c->ro_mount) {
+		c->ileb_buf = vmalloc(c->leb_size);
+		if (!c->ileb_buf) {
+			exit_code |= FSCK_ERROR;
+			log_err(c, errno, "cannot allocate ileb_buf");
+			goto out_free;
+		}
+	}
+
+	c->mounting = 1;
+
+	log_out(c, "Read superblock");
+	err = ubifs_read_superblock(c);
+	if (err) {
+		if (test_and_clear_failure_reason_callback(c, FR_DATA_CORRUPTED))
+			fix_problem(c, SB_CORRUPTED);
+		exit_code |= FSCK_ERROR;
+		goto out_mounting;
+	}
+
+	err = init_constants_sb(c);
+	if (err) {
+		exit_code |= FSCK_ERROR;
+		goto out_mounting;
+	}
+
+	sz = ALIGN(c->max_idx_node_sz, c->min_io_size) * 2;
+	c->cbuf = kmalloc(sz, GFP_NOFS);
+	if (!c->cbuf) {
+		err = -ENOMEM;
+		exit_code |= FSCK_ERROR;
+		log_err(c, errno, "cannot allocate cbuf");
+		goto out_mounting;
+	}
+
+	err = alloc_wbufs(c);
+	if (err) {
+		exit_code |= FSCK_ERROR;
+		log_err(c, 0, "cannot allocate wbuf");
+		goto out_mounting;
+	}
+
+	c->mounting = 0;
+
+	return 0;
+
+out_mounting:
+	c->mounting = 0;
+out_free:
+	kfree(c->cbuf);
+	kfree(c->ileb_buf);
+	kfree(c->sbuf);
+	kfree(c->bottom_up_buf);
+	kfree(c->sup_node);
+
+	return err;
+}
+
+void ubifs_destroy_filesystem(struct ubifs_info *c)
+{
+	free_wbufs(c);
+
+	kfree(c->cbuf);
+	kfree(c->ileb_buf);
+	kfree(c->sbuf);
+	kfree(c->bottom_up_buf);
+	kfree(c->sup_node);
+}
diff --git a/ubifs-utils/fsck.ubifs/problem.c b/ubifs-utils/fsck.ubifs/problem.c
index 9a8c2e06..acb9e45e 100644
--- a/ubifs-utils/fsck.ubifs/problem.c
+++ b/ubifs-utils/fsck.ubifs/problem.c
@@ -34,7 +34,9 @@  struct fsck_problem {
 	const char *desc;
 };
 
-static const struct fsck_problem problem_table[] = {};
+static const struct fsck_problem problem_table[] = {
+	{0, "Corrupted superblock"},	// SB_CORRUPTED
+};
 
 static void print_problem(const struct ubifs_info *c,
 			  const struct fsck_problem *problem)