diff mbox series

[RFC,16/17] ubifs: Enable ubifs_repair in '/sys/kernel/debug/ubifs/repair_fs'

Message ID 20231228014112.2836317-17-chengzhihao1@huawei.com
State Changes Requested
Headers show
Series ubifs: Add filesystem repair support | expand

Commit Message

Zhihao Cheng Dec. 28, 2023, 1:41 a.m. UTC
Add new interface '/sys/kernel/debug/ubifs/repair_fs' to enable
ubifs repair.

Invoke UBIFS repair by:
 echo UBIFS_DEV > /sys/kernel/debug/ubifs/repair_fs, UBIFS_DEV could be:
 1. ubiX_Y: X means UBI device number and Y means UBI volume number.
    For example: echo "ubi0_0" > /sys/kernel/debug/ubifs/repair_fs
 2. /dev/ubiX_Y: X means UBI device number and Y means UBI volume number.
    For example: echo "/dev/ubi0_0" > /sys/kernel/debug/ubifs/repair_fs
 3. ubiX:NAME: X means UBI device number and NAME means UBI volume name.
    For example: echo "ubi0:userdata" > /sys/kernel/debug/ubifs/repair_fs

Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
---
 fs/ubifs/debug.c  | 33 +++++++++++++++++++++++++++++++++
 fs/ubifs/repair.h |  2 ++
 2 files changed, 35 insertions(+)
diff mbox series

Patch

diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 1fe180c22b96..e8d6e948c32c 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -22,6 +22,7 @@ 
 #include <linux/random.h>
 #include <linux/ctype.h>
 #include "ubifs.h"
+#include "repair.h"
 
 static DEFINE_SPINLOCK(dbg_lock);
 
@@ -2868,6 +2869,7 @@  static struct dentry *dfs_chk_orph;
 static struct dentry *dfs_chk_lprops;
 static struct dentry *dfs_chk_fs;
 static struct dentry *dfs_tst_rcvry;
+static struct dentry *dfs_repair_fs;
 
 static ssize_t dfs_global_file_read(struct file *file, char __user *u,
 				    size_t count, loff_t *ppos)
@@ -2899,6 +2901,33 @@  static ssize_t dfs_global_file_write(struct file *file, const char __user *u,
 	struct dentry *dent = file->f_path.dentry;
 	int val;
 
+	if (dent == dfs_repair_fs) {
+		int ret, i;
+		size_t buf_size;
+		char *dev_name;
+
+		dev_name = vmalloc(PAGE_SIZE);
+		if (!dev_name)
+			return -ENOMEM;
+
+		buf_size = min_t(size_t, count, PAGE_SIZE - 1);
+		if (copy_from_user(dev_name, u, buf_size)) {
+			vfree(dev_name);
+			return -EFAULT;
+		}
+
+		/* Filter '\n' */
+		for (i = 0; i < buf_size; ++i)
+			if (dev_name[i] == '\n' || dev_name[i] == '\0')
+				break;
+		dev_name[i] = '\0';
+
+		ret = ubifs_repair(dev_name);
+		vfree(dev_name);
+
+		return ret < 0 ? ret : count;
+	}
+
 	val = interpret_user_input(u, count);
 	if (val < 0)
 		return val;
@@ -2965,6 +2994,10 @@  void dbg_debugfs_init(void)
 	fname = "tst_recovery";
 	dfs_tst_rcvry = debugfs_create_file(fname, S_IRUSR | S_IWUSR,
 					    dfs_rootdir, NULL, &dfs_global_fops);
+
+	fname = "repair_fs";
+	dfs_repair_fs = debugfs_create_file(fname, S_IWUSR, dfs_rootdir,
+					    NULL, &dfs_global_fops);
 }
 
 /**
diff --git a/fs/ubifs/repair.h b/fs/ubifs/repair.h
index f8d18f07e324..3dcf94787cbe 100644
--- a/fs/ubifs/repair.h
+++ b/fs/ubifs/repair.h
@@ -171,4 +171,6 @@  struct ubifs_repair_info {
 	bool need_update_lpt;
 };
 
+int ubifs_repair(const char *dev_name);
+
 #endif /* !__UBIFS_REPAIR_H__ */