| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * This file is part of UBIFS. |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * 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 |
|---|
| 18 | 6 | * |
|---|
| 19 | 7 | * Authors: Adrian Hunter |
|---|
| 20 | 8 | * Artem Bityutskiy (Битюцкий Артём) |
|---|
| .. | .. |
|---|
| 212 | 200 | save_flags = mst->flags; |
|---|
| 213 | 201 | mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY); |
|---|
| 214 | 202 | |
|---|
| 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; |
|---|
| 216 | 207 | err = ubifs_leb_change(c, lnum, mst, sz); |
|---|
| 217 | 208 | if (err) |
|---|
| 218 | 209 | goto out; |
|---|
| .. | .. |
|---|
| 264 | 255 | offs2 = (void *)mst2 - buf2; |
|---|
| 265 | 256 | if (offs1 == offs2) { |
|---|
| 266 | 257 | /* 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)) |
|---|
| 270 | 259 | goto out_err; |
|---|
| 271 | 260 | mst = mst1; |
|---|
| 272 | 261 | } else if (offs2 + sz == offs1) { |
|---|
| .. | .. |
|---|
| 862 | 851 | goto out_err; |
|---|
| 863 | 852 | } |
|---|
| 864 | 853 | 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); |
|---|
| 866 | 855 | goto out_err; |
|---|
| 867 | 856 | } |
|---|
| 868 | 857 | if (le64_to_cpu(cs_node->cmt_no) != c->cmt_no) { |
|---|
| .. | .. |
|---|
| 1495 | 1484 | } |
|---|
| 1496 | 1485 | |
|---|
| 1497 | 1486 | /** |
|---|
| 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 | +/** |
|---|
| 1498 | 1552 | * ubifs_recover_size - recover inode size. |
|---|
| 1499 | 1553 | * @c: UBIFS file-system description object |
|---|
| 1554 | + * @in_place: If true, do a in-place size fixup |
|---|
| 1500 | 1555 | * |
|---|
| 1501 | 1556 | * This function attempts to fix inode size discrepancies identified by the |
|---|
| 1502 | 1557 | * 'ubifs_recover_size_accum()' function. |
|---|
| 1503 | 1558 | * |
|---|
| 1504 | 1559 | * This functions returns %0 on success and a negative error code on failure. |
|---|
| 1505 | 1560 | */ |
|---|
| 1506 | | -int ubifs_recover_size(struct ubifs_info *c) |
|---|
| 1561 | +int ubifs_recover_size(struct ubifs_info *c, bool in_place) |
|---|
| 1507 | 1562 | { |
|---|
| 1508 | 1563 | struct rb_node *this = rb_first(&c->size_tree); |
|---|
| 1509 | 1564 | |
|---|
| .. | .. |
|---|
| 1512 | 1567 | int err; |
|---|
| 1513 | 1568 | |
|---|
| 1514 | 1569 | e = rb_entry(this, struct size_entry, rb); |
|---|
| 1570 | + |
|---|
| 1571 | + this = rb_next(this); |
|---|
| 1572 | + |
|---|
| 1515 | 1573 | if (!e->exists) { |
|---|
| 1516 | 1574 | union ubifs_key key; |
|---|
| 1517 | 1575 | |
|---|
| .. | .. |
|---|
| 1535 | 1593 | } |
|---|
| 1536 | 1594 | |
|---|
| 1537 | 1595 | 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)); |
|---|
| 1542 | 1597 | |
|---|
| 1543 | | - ubifs_assert(c, !e->inode); |
|---|
| 1598 | + /* |
|---|
| 1599 | + * We found data that is outside the found inode size, |
|---|
| 1600 | + * fixup the inode size |
|---|
| 1601 | + */ |
|---|
| 1544 | 1602 | |
|---|
| 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) { |
|---|
| 1564 | 1604 | err = fix_size_in_place(c, e); |
|---|
| 1565 | 1605 | if (err) |
|---|
| 1566 | 1606 | return err; |
|---|
| 1567 | 1607 | iput(e->inode); |
|---|
| 1608 | + } else { |
|---|
| 1609 | + err = inode_fix_size(c, e); |
|---|
| 1610 | + if (err) |
|---|
| 1611 | + return err; |
|---|
| 1612 | + continue; |
|---|
| 1568 | 1613 | } |
|---|
| 1569 | 1614 | } |
|---|
| 1570 | 1615 | |
|---|
| 1571 | | - this = rb_next(this); |
|---|
| 1572 | 1616 | rb_erase(&e->rb, &c->size_tree); |
|---|
| 1573 | 1617 | kfree(e); |
|---|
| 1574 | 1618 | } |
|---|