Messages in this thread Patch in this message |  | | From | Zhihao Cheng <> | | Subject | [PATCH RFC 09/17] ubifs: repair: Re-write data | | Date | Thu, 28 Dec 2023 09:41:04 +0800 |
| |
This is the 9/13 step of repairing. Re-write data. Read data from LEB and write back data, make sure that all LEB is ended with empty data(0xFF). It will prevent failed gc scanning in next mounting.
Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com> --- fs/ubifs/repair.c | 117 ++++++++++++++++++++++++++++++++++++---------- fs/ubifs/repair.h | 11 +++++ 2 files changed, 104 insertions(+), 24 deletions(-)
diff --git a/fs/ubifs/repair.c b/fs/ubifs/repair.c index 7d97de6219fa..59b79481974a 100644 --- a/fs/ubifs/repair.c +++ b/fs/ubifs/repair.c @@ -32,6 +32,8 @@ struct scanned_info { static int init_repair_info(struct ubifs_info *c) { + int err; + c->repair = kzalloc(sizeof(struct ubifs_repair_info), GFP_KERNEL); if (!c->repair) return -ENOMEM; @@ -39,15 +41,28 @@ static int init_repair_info(struct ubifs_info *c) c->repair->scanned_files = RB_ROOT; c->repair->used_lebs = bitmap_zalloc(c->main_lebs, GFP_KERNEL); if (!c->repair->used_lebs) { - kfree(c->repair); - return -ENOMEM; + err = -ENOMEM; + goto free_repair; + } + c->repair->lpts = kzalloc(sizeof(struct lprops) * c->main_lebs, + GFP_KERNEL); + if (!c->repair->lpts) { + err = -ENOMEM; + goto free_used_lebs; } return 0; + +free_used_lebs: + bitmap_free(c->repair->used_lebs); +free_repair: + kfree(c->repair); + return err; } static void destroy_repair_info(struct ubifs_info *c) { + kfree(c->repair->lpts); bitmap_free(c->repair->used_lebs); kfree(c->repair); } @@ -1026,9 +1041,13 @@ 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; + int lnum = del_ino_node->header.lnum - c->main_first; + int pos = del_ino_node->header.offs + + ALIGN(del_ino_node->header.len, 8); - set_bit(lnum - c->main_first, c->repair->used_lebs); + set_bit(lnum, c->repair->used_lebs); + c->repair->lpts[lnum].end = + max(c->repair->lpts[lnum].end, pos); rb_erase(&valid_ino_node->rb, &si->valid_inos); kfree(valid_ino_node); } @@ -1045,9 +1064,13 @@ 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; + int lnum = del_dent_node->header.lnum - c->main_first; + int pos = del_dent_node->header.offs + + ALIGN(del_dent_node->header.len, 8); - set_bit(lnum - c->main_first, c->repair->used_lebs); + set_bit(lnum, c->repair->used_lebs); + c->repair->lpts[lnum].end = + max(c->repair->lpts[lnum].end, pos); rb_erase(&valid_dent_node->rb, &si->valid_dents); kfree(valid_dent_node); } @@ -1746,21 +1769,37 @@ static char *get_file_name(struct ubifs_info *c, struct scanned_file *file) return name; } +static void parse_node_location(struct ubifs_info *c, struct scanned_node *sn) +{ + int lnum, pos; + + lnum = sn->lnum - c->main_first; + pos = sn->offs + ALIGN(sn->len, 8); + + set_bit(lnum, c->repair->used_lebs); + c->repair->lpts[lnum].end = max(c->repair->lpts[lnum].end, pos); +} + /** - * record_used_lebs - record used LEBs. + * traverse_files_and_nodes - traverse all nodes from valid files. * @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. + * This function traverses all nodes from valid files and does following + * things: + * 1. Record all used LEBs which may hold useful nodes, then left unused + * LEBs could be taken for storing new index tree. + * 2. Re-write data to prevent failed gc scanning in the subsequent mounting + * process caused by corrupted data. */ -static void record_used_lebs(struct ubifs_info *c) +static int traverse_files_and_nodes(struct ubifs_info *c) { - int lnum; + int i, err = 0; struct rb_node *node, *n; struct scanned_file *file; struct scanned_dent_node *dent_node; struct scanned_data_node *data_node; + ubifs_msg(c, "Step 8: Record used LEBs"); for (node = rb_first(&c->repair->scanned_files); node; node = rb_next(node)) { cond_resched(); @@ -1772,30 +1811,58 @@ static void record_used_lebs(struct ubifs_info *c) ubifs_get_type_name(ubifs_get_dent_type(file->ino.mode)), c->vi.ubi_num, c->vi.vol_id); - lnum = file->ino.header.lnum; - set_bit(lnum - c->main_first, c->repair->used_lebs); + parse_node_location(c, &file->ino.header); - if (file->trun.header.exist) { - lnum = file->trun.header.lnum; - set_bit(lnum - c->main_first, c->repair->used_lebs); - } + if (file->trun.header.exist) + parse_node_location(c, &file->trun.header); for (n = rb_first(&file->data_nodes); n; n = rb_next(n)) { cond_resched(); data_node = rb_entry(n, struct scanned_data_node, rb); - lnum = data_node->header.lnum; - set_bit(lnum - c->main_first, c->repair->used_lebs); + parse_node_location(c, &data_node->header); } for (n = rb_first(&file->dent_nodes); n; n = rb_next(n)) { cond_resched(); dent_node = rb_entry(n, struct scanned_dent_node, rb); - lnum = dent_node->header.lnum; - set_bit(lnum - c->main_first, c->repair->used_lebs); + parse_node_location(c, &dent_node->header); } } + + /* Re-write data. */ + ubifs_msg(c, "Step 9: Re-write data"); + for (i = 0; i < c->main_lebs; ++i) { + int lnum, len, end; + + if (fatal_signal_pending(current)) + return -EINTR; + cond_resched(); + + if (!test_bit(i, c->repair->used_lebs)) + continue; + + lnum = i + c->main_first; + dbg_repair("re-write LEB %d, in ubi%d_%d", + lnum, c->vi.ubi_num, c->vi.vol_id); + + end = c->repair->lpts[i].end; + len = ALIGN(end, c->min_io_size); + + err = ubifs_leb_read(c, lnum, c->sbuf, 0, len, 0); + if (err && err != -EBADMSG) + return err; + + if (len > end) + ubifs_pad(c, c->sbuf + end, len - end); + + err = ubifs_leb_change(c, lnum, c->sbuf, len); + if (err) + return err; + } + + return err; } static int do_repair(struct ubifs_info *c) @@ -1835,9 +1902,11 @@ static int do_repair(struct ubifs_info *c) if (err) goto out; - /* Step 8: Record used LEBs. */ - ubifs_msg(c, "Step 8: Record used LEBs"); - record_used_lebs(c); + /* + * Step 8: Record used LEBs. + * Step 9: Re-write data to clean corrupted data. + */ + err = traverse_files_and_nodes(c); out: destroy_scanned_info(c, &si); diff --git a/fs/ubifs/repair.h b/fs/ubifs/repair.h index fecf437ff0f7..2ab885fefee0 100644 --- a/fs/ubifs/repair.h +++ b/fs/ubifs/repair.h @@ -151,13 +151,24 @@ struct scanned_file { struct rb_root data_nodes; }; + +/** + * lprops - logical eraseblock properties. + * @end: the end postition of LEB calculated by the last node + */ +struct lprops { + int end; +}; + /** * ubifs_repair_info - per-FS repairing information. * @usen_lebs: a bitmap used for recording used lebs + * @lpts: lprops table * @scanned_files: tree of all scanned files */ struct ubifs_repair_info { unsigned long *used_lebs; + struct lprops *lpts; struct rb_root scanned_files; }; -- 2.31.1
|  |