diff mbox series

[RFC,mtd-utils,095/110] fsck.ubifs: Check and create the lost+found

Message ID 20240607042615.2069840-96-chengzhihao1@huawei.com
State New
Delegated to: David Oberhollenzer
Headers show
Series Add fsck.ubifs support | expand

Commit Message

Zhihao Cheng June 7, 2024, 4:26 a.m. UTC
From: Huang Xiaojia <huangxiaojia2@huawei.com>

This is the 16/18 step of fsck. Check whether the lost+found is existed,
create a new one if it is not found. This step makes sure that disconnected
file can be recovered under the lost+found.

Signed-off-by: Huang Xiaojia <huangxiaojia2@huawei.com>
Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
---
 ubifs-utils/Makemodule.am                    |  3 +-
 ubifs-utils/fsck.ubifs/fsck.ubifs.c          | 15 ++++-
 ubifs-utils/fsck.ubifs/fsck.ubifs.h          |  5 ++
 ubifs-utils/fsck.ubifs/handle_disconnected.c | 89 ++++++++++++++++++++++++++++
 4 files changed, 110 insertions(+), 2 deletions(-)
 create mode 100644 ubifs-utils/fsck.ubifs/handle_disconnected.c
diff mbox series

Patch

diff --git a/ubifs-utils/Makemodule.am b/ubifs-utils/Makemodule.am
index f63ca7a2..77a9be1a 100644
--- a/ubifs-utils/Makemodule.am
+++ b/ubifs-utils/Makemodule.am
@@ -85,7 +85,8 @@  fsck_ubifs_SOURCES = \
 	ubifs-utils/fsck.ubifs/extract_files.c \
 	ubifs-utils/fsck.ubifs/rebuild_fs.c \
 	ubifs-utils/fsck.ubifs/check_files.c \
-	ubifs-utils/fsck.ubifs/check_space.c
+	ubifs-utils/fsck.ubifs/check_space.c \
+	ubifs-utils/fsck.ubifs/handle_disconnected.c
 
 fsck_ubifs_LDADD = libmtd.a libubi.a $(ZLIB_LIBS) $(LZO_LIBS) $(ZSTD_LIBS) $(UUID_LIBS) $(LIBSELINUX_LIBS) $(OPENSSL_LIBS) -lm -lpthread
 fsck_ubifs_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_CFLAGS) $(LZO_CFLAGS) $(ZSTD_CFLAGS) $(UUID_CFLAGS) $(LIBSELINUX_CFLAGS) \
diff --git a/ubifs-utils/fsck.ubifs/fsck.ubifs.c b/ubifs-utils/fsck.ubifs/fsck.ubifs.c
index 584965fc..0910676c 100644
--- a/ubifs-utils/fsck.ubifs/fsck.ubifs.c
+++ b/ubifs-utils/fsck.ubifs/fsck.ubifs.c
@@ -526,8 +526,20 @@  static int do_fsck(void)
 
 	log_out(c, "Check and create root dir");
 	err = check_and_create_root(c);
-	if (err)
+	if (err) {
+		exit_code |= FSCK_ERROR;
+		goto free_disconnected_files_2;
+	}
+
+	if (list_empty(&FSCK(c)->disconnected_files))
+		return err;
+
+	log_out(c, "Check and create lost+found");
+	err = check_and_create_lost_found(c);
+	if (err) {
 		exit_code |= FSCK_ERROR;
+		goto free_disconnected_files_2;
+	}
 
 free_disconnected_files_2:
 	destroy_file_list(c, &FSCK(c)->disconnected_files);
@@ -583,6 +595,7 @@  int main(int argc, char *argv[])
 	 * Step 13: Commit problem fixing modifications
 	 * Step 14: Check and correct the index size
 	 * Step 15: Check and create root dir
+	 * Step 16: Check and create lost+found
 	 */
 	err = do_fsck();
 	if (err && FSCK(c)->try_rebuild) {
diff --git a/ubifs-utils/fsck.ubifs/fsck.ubifs.h b/ubifs-utils/fsck.ubifs/fsck.ubifs.h
index 5c305ba0..dc24e83c 100644
--- a/ubifs-utils/fsck.ubifs/fsck.ubifs.h
+++ b/ubifs-utils/fsck.ubifs/fsck.ubifs.h
@@ -277,6 +277,7 @@  struct ubifs_rebuild_info {
  * @lpts: lprops table
  * @try_rebuild: %true means that try to rebuild fs when fsck failed
  * @rebuild: rebuilding-related information
+ * @lost_and_found: inode number of the lost+found directory, %0 means invalid
  */
 struct ubifs_fsck_info {
 	int mode;
@@ -288,6 +289,7 @@  struct ubifs_fsck_info {
 	struct ubifs_lprops *lpts;
 	bool try_rebuild;
 	struct ubifs_rebuild_info *rebuild;
+	ino_t lost_and_found;
 };
 
 #define FSCK(c) ((struct ubifs_fsck_info*)c->private)
@@ -384,4 +386,7 @@  int build_lpt(struct ubifs_info *c, calculate_lp_callback calculate_lp_cb,
 int check_and_correct_space(struct ubifs_info *c);
 int check_and_correct_index_size(struct ubifs_info *c);
 
+/* handle_disconnected.c */
+int check_and_create_lost_found(struct ubifs_info *c);
+
 #endif
diff --git a/ubifs-utils/fsck.ubifs/handle_disconnected.c b/ubifs-utils/fsck.ubifs/handle_disconnected.c
new file mode 100644
index 00000000..b9a380f9
--- /dev/null
+++ b/ubifs-utils/fsck.ubifs/handle_disconnected.c
@@ -0,0 +1,89 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024, Huawei Technologies Co, Ltd.
+ *
+ * Authors: Huang Xiaojia <huangxiaojia2@huawei.com>
+ *          Zhihao Cheng <chengzhihao1@huawei.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include "linux_err.h"
+#include "kmem.h"
+#include "ubifs.h"
+#include "defs.h"
+#include "debug.h"
+#include "key.h"
+#include "fsck.ubifs.h"
+
+#define LOST_FOUND_DIR_NAME "lost+found"
+
+/**
+ * check_and_create_lost_found - Check and create the lost+found directory.
+ * @c: UBIFS file-system description object
+ *
+ * This function checks whether the lost+found directory exists and creates a
+ * new one if no valid lost+found existing. If there is a valid lost+found
+ * directory, inode number is stored in @FSCK(c)->lost_and_found. Returns zero
+ * in case of success, a negative error code in case of failure.
+ */
+int check_and_create_lost_found(struct ubifs_info *c)
+{
+	struct ubifs_inode *root_ui, *lost_found_ui;
+	struct fscrypt_name nm;
+	int err = 0;
+
+	root_ui = ubifs_lookup_by_inum(c, UBIFS_ROOT_INO);
+	if (IS_ERR(root_ui)) {
+		err = PTR_ERR(root_ui);
+		/* Previous step ensures that the root dir is valid. */
+		ubifs_assert(c, err != -ENOENT);
+		return err;
+	}
+
+	if (root_ui->flags & UBIFS_CRYPT_FL) {
+		ubifs_msg(c, "The root dir is encrypted, skip checking lost+found");
+		goto free_root;
+	}
+
+	fname_name(&nm) = LOST_FOUND_DIR_NAME;
+	fname_len(&nm) = strlen(LOST_FOUND_DIR_NAME);
+	lost_found_ui = ubifs_lookup(c, root_ui, &nm);
+	if (IS_ERR(lost_found_ui)) {
+		err = PTR_ERR(lost_found_ui);
+		if (err != -ENOENT)
+			goto free_root;
+
+		/* Not found. Create a new lost+found. */
+		err = ubifs_mkdir(c, root_ui, &nm, S_IRUGO | S_IWUSR | S_IXUSR);
+		if (err < 0) {
+			if (err == -ENOSPC) {
+				ubifs_msg(c, "No free space to create lost+found");
+				err = 0;
+			}
+			goto free_root;
+		}
+		lost_found_ui = ubifs_lookup(c, root_ui, &nm);
+		if (IS_ERR(lost_found_ui)) {
+			err = PTR_ERR(lost_found_ui);
+			ubifs_assert(c, err != -ENOENT);
+			goto free_root;
+		}
+		FSCK(c)->lost_and_found = lost_found_ui->vfs_inode.inum;
+		ubifs_msg(c, "Create the lost+found");
+	} else if (!(lost_found_ui->flags & UBIFS_CRYPT_FL) &&
+		   S_ISDIR(lost_found_ui->vfs_inode.mode)) {
+		FSCK(c)->lost_and_found = lost_found_ui->vfs_inode.inum;
+	} else {
+		ubifs_msg(c, "The type of lost+found is %s%s",
+			  ubifs_get_type_name(ubifs_get_dent_type(lost_found_ui->vfs_inode.mode)),
+			  lost_found_ui->flags & UBIFS_CRYPT_FL ? ", encrypted" : "");
+	}
+
+	kfree(lost_found_ui);
+free_root:
+	kfree(root_ui);
+	return err;
+}