From patchwork Thu Dec 28 01:41:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhihao Cheng X-Patchwork-Id: 1880655 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=RAqpPvxI; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=patchwork.ozlabs.org) Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:3::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4T0rky02xrz23dZ for ; Thu, 28 Dec 2023 12:38:50 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=ihCCikQ9+jGj1erUx6qiONx2nDQEU3pHpMXFKrYbZrU=; b=RAqpPvxInQ/1w4 6ppolnU/OajMBwlBI0gVDK6oEFoUBhgP3I4JL2Gw1hsXME4SwAjDonXrA/0rDOZx+JqDF59Lqk1pR qnrwf+F3U5IyNI81ZqWfIXFpR5WYb0VJkQ71AM+SIjRaW0ONYJ9y4l/X09wJ5/KBv3TyJhTdbOfiO WPSpt0+dYb+xu9haQP7u7pX5jeM0lzXsOWmV6W7dyTcN14Jce9M8fzNzkxq7FdzwMgubWAXfTjUY4 G8VbLC8f8NcVDjIZrq1etsu98pTtIXBQ55nLujEe8nvx5ntUE2pKsg/w3MHJtiY9yh62cVZJFRwA8 tmH0PTonhcOY1SeQ1I6A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1rIfLx-00FpgL-0R; Thu, 28 Dec 2023 01:38:29 +0000 Received: from szxga04-in.huawei.com ([45.249.212.190]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1rIfLn-00FpX0-0M for linux-mtd@lists.infradead.org; Thu, 28 Dec 2023 01:38:23 +0000 Received: from mail.maildlp.com (unknown [172.19.163.17]) by szxga04-in.huawei.com (SkyGuard) with ESMTP id 4T0rjn326qz1wq13; Thu, 28 Dec 2023 09:37:49 +0800 (CST) Received: from kwepemm000013.china.huawei.com (unknown [7.193.23.81]) by mail.maildlp.com (Postfix) with ESMTPS id 3DD651A0173; Thu, 28 Dec 2023 09:38:12 +0800 (CST) Received: from huawei.com (10.175.127.227) by kwepemm000013.china.huawei.com (7.193.23.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.35; Thu, 28 Dec 2023 09:38:11 +0800 From: Zhihao Cheng To: , , , , CC: , Subject: [PATCH RFC 09/17] ubifs: repair: Re-write data Date: Thu, 28 Dec 2023 09:41:04 +0800 Message-ID: <20231228014112.2836317-10-chengzhihao1@huawei.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20231228014112.2836317-1-chengzhihao1@huawei.com> References: <20231228014112.2836317-1-chengzhihao1@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.175.127.227] X-ClientProxiedBy: dggems706-chm.china.huawei.com (10.3.19.183) To kwepemm000013.china.huawei.com (7.193.23.81) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20231227_173819_503886_5600D812 X-CRM114-Status: GOOD ( 15.72 ) X-Spam-Score: -2.3 (--) X-Spam-Report: Spam detection software, running on the system "bombadil.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: 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 --- fs/ubifs/repair.c | 117 ++++++++++++++++++++++++++++++++++++ fs/ubifs/repair.h | 11 +++++ 2 files changed, 104 insertions(+), 24 del [...] Content analysis details: (-2.3 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [45.249.212.190 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 RCVD_IN_MSPIKE_H4 RBL: Very Good reputation (+4) [45.249.212.190 listed in wl.mailspike.net] 0.0 RCVD_IN_MSPIKE_WL Mailspike good senders X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org 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 --- 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; };