Messages in this thread Patch in this message |  | | From | Zhihao Cheng <> | | Subject | [PATCH RFC 01/17] ubifs: repair: Load filesystem info from volume | | Date | Thu, 28 Dec 2023 09:40:56 +0800 |
| |
This is the 1/13 step of repairing. Open UBI volume and read UBIFS super block, which is similar to UBIFS mounting process. If read superblock failed, repair is failure.
Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com> --- fs/ubifs/Makefile | 2 +- fs/ubifs/repair.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++ fs/ubifs/super.c | 10 ++--- fs/ubifs/ubifs.h | 5 +++ 4 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 fs/ubifs/repair.c
diff --git a/fs/ubifs/Makefile b/fs/ubifs/Makefile index 314c80b24a76..88a11f85e150 100644 --- a/fs/ubifs/Makefile +++ b/fs/ubifs/Makefile @@ -5,7 +5,7 @@ ubifs-y += shrinker.o journal.o file.o dir.o super.o sb.o io.o ubifs-y += tnc.o master.o scan.o replay.o log.o commit.o gc.o orphan.o ubifs-y += budget.o find.o tnc_commit.o compress.o lpt.o lprops.o ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o debug.o -ubifs-y += misc.o sysfs.o +ubifs-y += misc.o sysfs.o repair.o ubifs-$(CONFIG_FS_ENCRYPTION) += crypto.o ubifs-$(CONFIG_UBIFS_FS_XATTR) += xattr.o ubifs-$(CONFIG_UBIFS_FS_AUTHENTICATION) += auth.o diff --git a/fs/ubifs/repair.c b/fs/ubifs/repair.c new file mode 100644 index 000000000000..b722187de74f --- /dev/null +++ b/fs/ubifs/repair.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This file is part of UBIFS. + * + * Copyright (C) 2023-2024, Huawei Technologies Co, Ltd. + * + * Authors: Zhihao Cheng <chengzhihao1@huawei.com> + */ + +/* + * This file implements ubifs repair. + */ + +#include <linux/module.h> +#include "ubifs.h" + +int ubifs_repair(const char *dev_name) +{ + int err = 0; + struct ubifs_info *c; + struct ubi_volume_desc *ubi; + struct super_block *fake_sb; + + ubi = open_ubi(dev_name, UBI_READWRITE); + if (IS_ERR(ubi)) { + err = PTR_ERR(ubi); + pr_err("cannot open dev %s, err %d\n", dev_name, err); + return err; + } + + fake_sb = kzalloc(sizeof(struct super_block), GFP_KERNEL); + if (!fake_sb) { + err = -ENOMEM; + goto close_volume; + } + + c = alloc_ubifs_info(ubi); + if (!c) { + err = -ENOMEM; + goto free_sb; + } + + c->ubi = ubi; + c->vfs_sb = fake_sb; + c->max_inode_sz = key_max_inode_size(c); + if (c->max_inode_sz > MAX_LFS_FILESIZE) + c->max_inode_sz = MAX_LFS_FILESIZE; + + err = init_constants_early(c); + if (err) + goto free_ubifs; + + err = ubifs_debugging_init(c); + if (err) + goto free_ubifs; + + if (c->ro_media) { + err = -EROFS; + goto free_debug; + } + + err = check_volume_empty(c); + if (err) + goto free_debug; + + if (c->empty) { + ubifs_err(c, "empty filesystem"); + err = -ENODEV; + goto free_debug; + } + + c->sbuf = vmalloc(c->leb_size); + if (!c->sbuf) { + err = -ENOMEM; + goto free_debug; + } + + /* Step 1: Load filesystem info from volume. */ + ubifs_msg(c, "Step 1: Load filesystem"); + err = ubifs_read_superblock(c); + if (err) + goto free_sup; + + /* TODO: Support repairing authenticated image. */ + if (le32_to_cpu(c->sup_node->flags) & UBIFS_FLG_AUTHENTICATION) { + ubifs_err(c, "not support authentication"); + err = -EOPNOTSUPP; + goto free_sup; + } + + err = init_constants_sb(c); + if (err) + goto free_sup; + + ubifs_msg(c, "Repair success!"); + +free_sup: + kfree(c->sup_node); + vfree(c->sbuf); +free_debug: + ubifs_debugging_exit(c); +free_ubifs: + kfree(c); +free_sb: + kfree(fake_sb); +close_volume: + ubi_close_volume(ubi); + return err; +} diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index eabb0f44ea3e..ad726523d491 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -506,7 +506,7 @@ static int ubifs_sync_fs(struct super_block *sb, int wait) * requirements. Returns zero in case of success and a negative error code in * case of failure. */ -static int init_constants_early(struct ubifs_info *c) +int init_constants_early(struct ubifs_info *c) { if (c->vi.corrupted) { ubifs_warn(c, "UBI volume is corrupted - read-only mode"); @@ -670,7 +670,7 @@ static int bud_wbuf_callback(struct ubifs_info *c, int lnum, int free, int pad) * makes sure they are all right. Returns zero in case of success and a * negative error code in case of failure. */ -static int init_constants_sb(struct ubifs_info *c) +int init_constants_sb(struct ubifs_info *c) { int tmp, err; long long tmp64; @@ -934,7 +934,7 @@ static void free_buds(struct ubifs_info *c) * Returns zero in case of success and a negative error code in case of * failure. */ -static int check_volume_empty(struct ubifs_info *c) +int check_volume_empty(struct ubifs_info *c) { int lnum, err; @@ -2086,7 +2086,7 @@ const struct super_operations ubifs_super_operations = { * returns UBI volume description object in case of success and a negative * error code in case of failure. */ -static struct ubi_volume_desc *open_ubi(const char *name, int mode) +struct ubi_volume_desc *open_ubi(const char *name, int mode) { struct ubi_volume_desc *ubi; int dev, vol; @@ -2132,7 +2132,7 @@ static struct ubi_volume_desc *open_ubi(const char *name, int mode) return ERR_PTR(-EINVAL); } -static struct ubifs_info *alloc_ubifs_info(struct ubi_volume_desc *ubi) +struct ubifs_info *alloc_ubifs_info(struct ubi_volume_desc *ubi) { struct ubifs_info *c; diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 3916dc4f30ca..a7ee8010ad66 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -2072,6 +2072,11 @@ static inline int ubifs_init_security(struct inode *dentry, /* super.c */ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum); +int init_constants_early(struct ubifs_info *c); +int init_constants_sb(struct ubifs_info *c); +int check_volume_empty(struct ubifs_info *c); +struct ubi_volume_desc *open_ubi(const char *name, int mode); +struct ubifs_info *alloc_ubifs_info(struct ubi_volume_desc *ubi); /* recovery.c */ int ubifs_recover_master_node(struct ubifs_info *c); -- 2.31.1
|  |