hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/ubifs/recovery.c
....@@ -1,20 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * This file is part of UBIFS.
34 *
45 * Copyright (C) 2006-2008 Nokia Corporation
5
- *
6
- * This program is free software; you can redistribute it and/or modify it
7
- * under the terms of the GNU General Public License version 2 as published by
8
- * the Free Software Foundation.
9
- *
10
- * This program is distributed in the hope that it will be useful, but WITHOUT
11
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13
- * more details.
14
- *
15
- * You should have received a copy of the GNU General Public License along with
16
- * this program; if not, write to the Free Software Foundation, Inc., 51
17
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
186 *
197 * Authors: Adrian Hunter
208 * Artem Bityutskiy (Битюцкий Артём)
....@@ -212,7 +200,10 @@
212200 save_flags = mst->flags;
213201 mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY);
214202
215
- ubifs_prepare_node(c, mst, UBIFS_MST_NODE_SZ, 1);
203
+ err = ubifs_prepare_node_hmac(c, mst, UBIFS_MST_NODE_SZ,
204
+ offsetof(struct ubifs_mst_node, hmac), 1);
205
+ if (err)
206
+ goto out;
216207 err = ubifs_leb_change(c, lnum, mst, sz);
217208 if (err)
218209 goto out;
....@@ -264,9 +255,7 @@
264255 offs2 = (void *)mst2 - buf2;
265256 if (offs1 == offs2) {
266257 /* Same offset, so must be the same */
267
- if (memcmp((void *)mst1 + UBIFS_CH_SZ,
268
- (void *)mst2 + UBIFS_CH_SZ,
269
- UBIFS_MST_NODE_SZ - UBIFS_CH_SZ))
258
+ if (ubifs_compare_master_node(c, mst1, mst2))
270259 goto out_err;
271260 mst = mst1;
272261 } else if (offs2 + sz == offs1) {
....@@ -862,7 +851,7 @@
862851 goto out_err;
863852 }
864853 if (cs_node->ch.node_type != UBIFS_CS_NODE) {
865
- ubifs_err(c, "Node a CS node, type is %d", cs_node->ch.node_type);
854
+ ubifs_err(c, "Not a CS node, type is %d", cs_node->ch.node_type);
866855 goto out_err;
867856 }
868857 if (le64_to_cpu(cs_node->cmt_no) != c->cmt_no) {
....@@ -1495,15 +1484,81 @@
14951484 }
14961485
14971486 /**
1487
+ * inode_fix_size - fix inode size
1488
+ * @c: UBIFS file-system description object
1489
+ * @e: inode size information for recovery
1490
+ */
1491
+static int inode_fix_size(struct ubifs_info *c, struct size_entry *e)
1492
+{
1493
+ struct inode *inode;
1494
+ struct ubifs_inode *ui;
1495
+ int err;
1496
+
1497
+ if (c->ro_mount)
1498
+ ubifs_assert(c, !e->inode);
1499
+
1500
+ if (e->inode) {
1501
+ /* Remounting rw, pick up inode we stored earlier */
1502
+ inode = e->inode;
1503
+ } else {
1504
+ inode = ubifs_iget(c->vfs_sb, e->inum);
1505
+ if (IS_ERR(inode))
1506
+ return PTR_ERR(inode);
1507
+
1508
+ if (inode->i_size >= e->d_size) {
1509
+ /*
1510
+ * The original inode in the index already has a size
1511
+ * big enough, nothing to do
1512
+ */
1513
+ iput(inode);
1514
+ return 0;
1515
+ }
1516
+
1517
+ dbg_rcvry("ino %lu size %lld -> %lld",
1518
+ (unsigned long)e->inum,
1519
+ inode->i_size, e->d_size);
1520
+
1521
+ ui = ubifs_inode(inode);
1522
+
1523
+ inode->i_size = e->d_size;
1524
+ ui->ui_size = e->d_size;
1525
+ ui->synced_i_size = e->d_size;
1526
+
1527
+ e->inode = inode;
1528
+ }
1529
+
1530
+ /*
1531
+ * In readonly mode just keep the inode pinned in memory until we go
1532
+ * readwrite. In readwrite mode write the inode to the journal with the
1533
+ * fixed size.
1534
+ */
1535
+ if (c->ro_mount)
1536
+ return 0;
1537
+
1538
+ err = ubifs_jnl_write_inode(c, inode);
1539
+
1540
+ iput(inode);
1541
+
1542
+ if (err)
1543
+ return err;
1544
+
1545
+ rb_erase(&e->rb, &c->size_tree);
1546
+ kfree(e);
1547
+
1548
+ return 0;
1549
+}
1550
+
1551
+/**
14981552 * ubifs_recover_size - recover inode size.
14991553 * @c: UBIFS file-system description object
1554
+ * @in_place: If true, do a in-place size fixup
15001555 *
15011556 * This function attempts to fix inode size discrepancies identified by the
15021557 * 'ubifs_recover_size_accum()' function.
15031558 *
15041559 * This functions returns %0 on success and a negative error code on failure.
15051560 */
1506
-int ubifs_recover_size(struct ubifs_info *c)
1561
+int ubifs_recover_size(struct ubifs_info *c, bool in_place)
15071562 {
15081563 struct rb_node *this = rb_first(&c->size_tree);
15091564
....@@ -1512,6 +1567,9 @@
15121567 int err;
15131568
15141569 e = rb_entry(this, struct size_entry, rb);
1570
+
1571
+ this = rb_next(this);
1572
+
15151573 if (!e->exists) {
15161574 union ubifs_key key;
15171575
....@@ -1535,40 +1593,26 @@
15351593 }
15361594
15371595 if (e->exists && e->i_size < e->d_size) {
1538
- if (c->ro_mount) {
1539
- /* Fix the inode size and pin it in memory */
1540
- struct inode *inode;
1541
- struct ubifs_inode *ui;
1596
+ ubifs_assert(c, !(c->ro_mount && in_place));
15421597
1543
- ubifs_assert(c, !e->inode);
1598
+ /*
1599
+ * We found data that is outside the found inode size,
1600
+ * fixup the inode size
1601
+ */
15441602
1545
- inode = ubifs_iget(c->vfs_sb, e->inum);
1546
- if (IS_ERR(inode))
1547
- return PTR_ERR(inode);
1548
-
1549
- ui = ubifs_inode(inode);
1550
- if (inode->i_size < e->d_size) {
1551
- dbg_rcvry("ino %lu size %lld -> %lld",
1552
- (unsigned long)e->inum,
1553
- inode->i_size, e->d_size);
1554
- inode->i_size = e->d_size;
1555
- ui->ui_size = e->d_size;
1556
- ui->synced_i_size = e->d_size;
1557
- e->inode = inode;
1558
- this = rb_next(this);
1559
- continue;
1560
- }
1561
- iput(inode);
1562
- } else {
1563
- /* Fix the size in place */
1603
+ if (in_place) {
15641604 err = fix_size_in_place(c, e);
15651605 if (err)
15661606 return err;
15671607 iput(e->inode);
1608
+ } else {
1609
+ err = inode_fix_size(c, e);
1610
+ if (err)
1611
+ return err;
1612
+ continue;
15681613 }
15691614 }
15701615
1571
- this = rb_next(this);
15721616 rb_erase(&e->rb, &c->size_tree);
15731617 kfree(e);
15741618 }