aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhihao Cheng <chengzhihao1@huawei.com>2024-11-11 17:01:14 +0800
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2024-11-11 10:32:46 +0100
commitfe2784abac3a0b26ec2ae899156f5c840231d1b6 (patch)
treefed2f22e9f5310103c5a319eef3b99e142ba9f42
parent7ff702596bd5590a93ae55d217753fe4b671c6f4 (diff)
fsck.ubifs: rebuild_fs: Record used LEBs
This is the 7/12 step of rebuilding. Record used LEBs which may hold useful nodes, then left unused LEBs could be taken for storing new index tree. Notice, LEB that contains effective nodes on deleted trees in step 1 is regarded as used. Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com> Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--ubifs-utils/fsck.ubifs/fsck.ubifs.h2
-rw-r--r--ubifs-utils/fsck.ubifs/rebuild_fs.c116
2 files changed, 115 insertions, 3 deletions
diff --git a/ubifs-utils/fsck.ubifs/fsck.ubifs.h b/ubifs-utils/fsck.ubifs/fsck.ubifs.h
index bb5d1c4..a3b755b 100644
--- a/ubifs-utils/fsck.ubifs/fsck.ubifs.h
+++ b/ubifs-utils/fsck.ubifs/fsck.ubifs.h
@@ -180,9 +180,11 @@ struct scanned_file {
/**
* ubifs_rebuild_info - UBIFS rebuilding information.
+ * @used_lebs: a bitmap used for recording used lebs
* @scanned_files: tree of all scanned files
*/
struct ubifs_rebuild_info {
+ unsigned long *used_lebs;
struct rb_root scanned_files;
};
diff --git a/ubifs-utils/fsck.ubifs/rebuild_fs.c b/ubifs-utils/fsck.ubifs/rebuild_fs.c
index ecf6b0c..3be0844 100644
--- a/ubifs-utils/fsck.ubifs/rebuild_fs.c
+++ b/ubifs-utils/fsck.ubifs/rebuild_fs.c
@@ -48,19 +48,29 @@ static int init_rebuild_info(struct ubifs_info *c)
if (!FSCK(c)->rebuild) {
err = -ENOMEM;
log_err(c, errno, "can not allocate rebuild info");
- goto out;
+ goto free_sbuf;
}
FSCK(c)->rebuild->scanned_files = RB_ROOT;
+ FSCK(c)->rebuild->used_lebs = kcalloc(BITS_TO_LONGS(c->main_lebs),
+ sizeof(unsigned long), GFP_KERNEL);
+ if (!FSCK(c)->rebuild->used_lebs) {
+ err = -ENOMEM;
+ log_err(c, errno, "can not allocate bitmap of used lebs");
+ goto free_rebuild;
+ }
return 0;
-out:
+free_rebuild:
+ kfree(FSCK(c)->rebuild);
+free_sbuf:
vfree(c->sbuf);
return err;
}
static void destroy_rebuild_info(struct ubifs_info *c)
{
+ kfree(FSCK(c)->rebuild->used_lebs);
kfree(FSCK(c)->rebuild);
vfree(c->sbuf);
}
@@ -451,6 +461,9 @@ static void remove_del_nodes(struct ubifs_info *c, struct scanned_info *si)
valid_ino_node = lookup_valid_ino_node(c, si, del_ino_node);
if (valid_ino_node) {
+ int lnum = del_ino_node->header.lnum;
+
+ set_bit(lnum - c->main_first, FSCK(c)->rebuild->used_lebs);
rb_erase(&valid_ino_node->rb, &si->valid_inos);
kfree(valid_ino_node);
}
@@ -466,6 +479,9 @@ static void remove_del_nodes(struct ubifs_info *c, struct scanned_info *si)
valid_dent_node = lookup_valid_dent_node(c, si, del_dent_node);
if (valid_dent_node) {
+ int lnum = del_dent_node->header.lnum;
+
+ set_bit(lnum - c->main_first, FSCK(c)->rebuild->used_lebs);
rb_erase(&valid_dent_node->rb, &si->valid_dents);
kfree(valid_dent_node);
}
@@ -627,6 +643,94 @@ static void extract_dentry_tree(struct ubifs_info *c)
}
}
+static const char *get_file_name(struct ubifs_info *c, struct scanned_file *file)
+{
+ static char name[UBIFS_MAX_NLEN + 1];
+ struct rb_node *node;
+ struct scanned_dent_node *dent_node;
+
+ node = rb_first(&file->dent_nodes);
+ if (!node) {
+ ubifs_assert(c, file->inum == UBIFS_ROOT_INO);
+ return "/";
+ }
+
+ if (c->encrypted && !file->ino.is_xattr)
+ /* Encrypted file name. */
+ return "<encrypted>";
+
+ /* Get name from any one dentry. */
+ dent_node = rb_entry(node, struct scanned_dent_node, rb);
+ memcpy(name, dent_node->name, dent_node->nlen);
+ /* @dent->name could be non '\0' terminated. */
+ name[dent_node->nlen] = '\0';
+ return name;
+}
+
+static void record_file_used_lebs(struct ubifs_info *c,
+ struct scanned_file *file)
+{
+ int lnum;
+ struct rb_node *node;
+ struct scanned_file *xattr_file;
+ struct scanned_dent_node *dent_node;
+ struct scanned_data_node *data_node;
+
+ dbg_fsck("recovered file(inum:%lu name:%s type:%s), in %s",
+ file->inum, get_file_name(c, file),
+ file->ino.is_xattr ? "xattr" :
+ ubifs_get_type_name(ubifs_get_dent_type(file->ino.mode)),
+ c->dev_name);
+
+ lnum = file->ino.header.lnum;
+ set_bit(lnum - c->main_first, FSCK(c)->rebuild->used_lebs);
+
+ if (file->trun.header.exist) {
+ lnum = file->trun.header.lnum;
+ set_bit(lnum - c->main_first, FSCK(c)->rebuild->used_lebs);
+ }
+
+ for (node = rb_first(&file->data_nodes); node; node = rb_next(node)) {
+ data_node = rb_entry(node, struct scanned_data_node, rb);
+
+ lnum = data_node->header.lnum;
+ set_bit(lnum - c->main_first, FSCK(c)->rebuild->used_lebs);
+ }
+
+ for (node = rb_first(&file->dent_nodes); node; node = rb_next(node)) {
+ dent_node = rb_entry(node, struct scanned_dent_node, rb);
+
+ lnum = dent_node->header.lnum;
+ set_bit(lnum - c->main_first, FSCK(c)->rebuild->used_lebs);
+ }
+
+ for (node = rb_first(&file->xattr_files); node; node = rb_next(node)) {
+ xattr_file = rb_entry(node, struct scanned_file, rb);
+
+ record_file_used_lebs(c, xattr_file);
+ }
+}
+
+/**
+ * record_used_lebs - record used LEBs.
+ * @c: UBIFS file-system description object
+ *
+ * This function records all used LEBs which may hold useful nodes, then left
+ * unused LEBs could be taken for storing new index tree.
+ */
+static void record_used_lebs(struct ubifs_info *c)
+{
+ struct rb_node *node;
+ struct scanned_file *file;
+ struct rb_root *tree = &FSCK(c)->rebuild->scanned_files;
+
+ for (node = rb_first(tree); node; node = rb_next(node)) {
+ file = rb_entry(node, struct scanned_file, rb);
+
+ record_file_used_lebs(c, file);
+ }
+}
+
/**
* ubifs_rebuild_filesystem - Rebuild filesystem.
* @c: UBIFS file-system description object
@@ -680,8 +784,14 @@ int ubifs_rebuild_filesystem(struct ubifs_info *c)
/* Step 6: Check & correct files' information. */
log_out(c, "Check & correct file information");
err = check_and_correct_files(c);
- if (err)
+ if (err) {
exit_code |= FSCK_ERROR;
+ goto out;
+ }
+
+ /* Step 7: Record used LEBs. */
+ log_out(c, "Record used LEBs");
+ record_used_lebs(c);
out:
destroy_scanned_info(c, &si);