Messages in this thread Patch in this message |  | | From | Zhihao Cheng <> | | Subject | [PATCH RFC 13/17] ubifs: repair: Build LPT | | Date | Thu, 28 Dec 2023 09:41:08 +0800 |
| |
This is the 11/13 step of repairing. All LEBs' properties can be calculated in previous steps according to all nodes' position, then construct LPT just like mkfs does, and write TNC on flash.
Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com> --- fs/ubifs/repair.c | 113 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 93 insertions(+), 20 deletions(-)
diff --git a/fs/ubifs/repair.c b/fs/ubifs/repair.c index 724f58510599..8d40cff26f7a 100644 --- a/fs/ubifs/repair.c +++ b/fs/ubifs/repair.c @@ -1059,6 +1059,21 @@ lookup_valid_dent_node(struct ubifs_info *c, struct scanned_info *si, return NULL; } +static void update_lpt(struct ubifs_info *c, struct scanned_node *sn, + bool deleted) +{ + int lnum = sn->lnum - c->main_first; + int 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); + + if (deleted) + return; + + c->repair->lpts[lnum].used += ALIGN(sn->len, 8); +} + /** * remove_del_nodes - remove deleted nodes from valid node tree. * @c: UBIFS file-system description object @@ -1083,13 +1098,7 @@ 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 - c->main_first; - int pos = del_ino_node->header.offs + - ALIGN(del_ino_node->header.len, 8); - - set_bit(lnum, c->repair->used_lebs); - c->repair->lpts[lnum].end = - max(c->repair->lpts[lnum].end, pos); + update_lpt(c, &del_ino_node->header, true); rb_erase(&valid_ino_node->rb, &si->valid_inos); kfree(valid_ino_node); } @@ -1106,13 +1115,7 @@ 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 - c->main_first; - int pos = del_dent_node->header.offs + - ALIGN(del_dent_node->header.len, 8); - - set_bit(lnum, c->repair->used_lebs); - c->repair->lpts[lnum].end = - max(c->repair->lpts[lnum].end, pos); + update_lpt(c, &del_dent_node->header, true); rb_erase(&valid_dent_node->rb, &si->valid_dents); kfree(valid_dent_node); } @@ -1861,6 +1864,14 @@ static int flush_write_buf(struct ubifs_info *c) if (err) return err; + if (c->repair->need_update_lpt) { + int lnum = c->repair->head_lnum - c->main_first; + + c->repair->lpts[lnum].free = c->leb_size - len; + c->repair->lpts[lnum].dirty = pad; + c->repair->lpts[lnum].flags = LPROPS_INDEX; + } + c->repair->head_lnum = -1; return 0; @@ -2001,14 +2012,9 @@ static int parse_node_info(struct ubifs_info *c, struct scanned_node *sn, union ubifs_key *key, char *name, int name_len, struct list_head *idx_list, int *idx_cnt) { - int lnum, pos; struct idx_entry *e; - 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); + update_lpt(c, sn, idx_cnt == NULL); if (idx_cnt == NULL) /* Skip truncation node. */ @@ -2085,6 +2091,7 @@ static int build_tnc(struct ubifs_info *c, struct list_head *lower_idxs, return -ENOMEM; list_sort(c, lower_idxs, cmp_idx); + c->repair->need_update_lpt = true; ubifs_assert(c, lower_cnt != 0); @@ -2156,6 +2163,7 @@ static int build_tnc(struct ubifs_info *c, struct list_head *lower_idxs, /* Flush the last index LEB */ err = flush_write_buf(c); + c->repair->need_update_lpt = false; out: list_for_each_entry_safe(e, tmp_e, lower_idxs, list) { @@ -2300,6 +2308,65 @@ static int traverse_files_and_nodes(struct ubifs_info *c) return err; } +/** + * build_lpt - construct LPT and write it into flash. + * @c: UBIFS file-system description object + * + * This function builds LPT according to @c->repair->lpts and writes LPT + * into flash. + */ +int build_lpt(struct ubifs_info *c) +{ + int i, len, free, dirty, err; + u8 hash_lpt[UBIFS_HASH_ARR_SZ]; + + /* Set gc lnum. */ + err = get_free_leb(c); + if (err) + return err; + c->gc_lnum = c->repair->head_lnum; + /* GC LEB is empty. */ + c->lst.empty_lebs = 1; + + /* Update LPT. */ + for (i = 0; i < c->main_lebs; i++) { + cond_resched(); + + if (!test_bit(i, c->repair->used_lebs)) { + free = c->leb_size; + dirty = 0; + c->lst.empty_lebs++; + } else if (c->repair->lpts[i].flags & LPROPS_INDEX) { + free = c->repair->lpts[i].free; + dirty = c->repair->lpts[i].dirty; + c->lst.idx_lebs += 1; + } else { + len = ALIGN(c->repair->lpts[i].end, c->min_io_size); + free = c->leb_size - len; + dirty = len - c->repair->lpts[i].used; + } + + c->repair->lpts[i].free = free; + c->repair->lpts[i].dirty = dirty; + c->lst.total_free += free; + c->lst.total_dirty += dirty; + + if (!(c->repair->lpts[i].flags & LPROPS_INDEX)) { + int spc; + + spc = free + dirty; + if (spc < c->dead_wm) + c->lst.total_dead += spc; + else + c->lst.total_dark += ubifs_calc_dark(c, spc); + c->lst.total_used += c->leb_size - spc; + } + } + + /* Write LPT. */ + return ubifs_create_lpt(c, c->repair->lpts, c->main_lebs, hash_lpt); +} + static int do_repair(struct ubifs_info *c) { int err = 0; @@ -2343,6 +2410,12 @@ static int do_repair(struct ubifs_info *c) * Step 10: Build TNC. */ err = traverse_files_and_nodes(c); + if (err) + goto out; + + /* Step 11. Build LPT. */ + ubifs_msg(c, "Step 11: Build LPT"); + err = build_lpt(c); out: destroy_scanned_info(c, &si); -- 2.31.1
|  |