fsck.c (86634fa4e6aeff2e190616c304156899beb4d76b) fsck.c (c13d526d9dc1aa0c4962b017c881c28c1e23ca26)
1// SPDX-License-Identifier: GPL-2.0
2
3#include "bcachefs.h"
4#include "bkey_buf.h"
5#include "btree_cache.h"
6#include "btree_update.h"
7#include "buckets.h"
8#include "darray.h"

--- 441 unchanged lines hidden (view full) ---

450
451 if (!st->v.master_subvol)
452 st->v.master_subvol = cpu_to_le32(subvolid);
453
454 bch2_trans_iter_exit(trans, &iter);
455 return 0;
456}
457
1// SPDX-License-Identifier: GPL-2.0
2
3#include "bcachefs.h"
4#include "bkey_buf.h"
5#include "btree_cache.h"
6#include "btree_update.h"
7#include "buckets.h"
8#include "darray.h"

--- 441 unchanged lines hidden (view full) ---

450
451 if (!st->v.master_subvol)
452 st->v.master_subvol = cpu_to_le32(subvolid);
453
454 bch2_trans_iter_exit(trans, &iter);
455 return 0;
456}
457
458static int reconstruct_inode(struct btree_trans *trans, u32 snapshot, u64 inum, u64 size, unsigned mode)
458static int reconstruct_inode(struct btree_trans *trans, enum btree_id btree, u32 snapshot, u64 inum)
459{
460 struct bch_fs *c = trans->c;
459{
460 struct bch_fs *c = trans->c;
461 struct bch_inode_unpacked new_inode;
461 unsigned i_mode = S_IFREG;
462 u64 i_size = 0;
462
463
464 switch (btree) {
465 case BTREE_ID_extents: {
466 struct btree_iter iter = {};
467
468 bch2_trans_iter_init(trans, &iter, BTREE_ID_extents, SPOS(inum, U64_MAX, snapshot), 0);
469 struct bkey_s_c k = bch2_btree_iter_peek_prev(&iter);
470 bch2_trans_iter_exit(trans, &iter);
471 int ret = bkey_err(k);
472 if (ret)
473 return ret;
474
475 i_size = k.k->p.offset << 9;
476 break;
477 }
478 case BTREE_ID_dirents:
479 i_mode = S_IFDIR;
480 break;
481 case BTREE_ID_xattrs:
482 break;
483 default:
484 BUG();
485 }
486
487 struct bch_inode_unpacked new_inode;
463 bch2_inode_init_early(c, &new_inode);
488 bch2_inode_init_early(c, &new_inode);
464 bch2_inode_init_late(&new_inode, bch2_current_time(c), 0, 0, mode|0755, 0, NULL);
465 new_inode.bi_size = size;
489 bch2_inode_init_late(&new_inode, bch2_current_time(c), 0, 0, i_mode|0600, 0, NULL);
490 new_inode.bi_size = i_size;
466 new_inode.bi_inum = inum;
467
468 return __bch2_fsck_write_inode(trans, &new_inode, snapshot);
469}
470
491 new_inode.bi_inum = inum;
492
493 return __bch2_fsck_write_inode(trans, &new_inode, snapshot);
494}
495
471static int reconstruct_reg_inode(struct btree_trans *trans, u32 snapshot, u64 inum)
472{
473 struct btree_iter iter = {};
474
475 bch2_trans_iter_init(trans, &iter, BTREE_ID_extents, SPOS(inum, U64_MAX, snapshot), 0);
476 struct bkey_s_c k = bch2_btree_iter_peek_prev(&iter);
477 bch2_trans_iter_exit(trans, &iter);
478 int ret = bkey_err(k);
479 if (ret)
480 return ret;
481
482 return reconstruct_inode(trans, snapshot, inum, k.k->p.offset << 9, S_IFREG);
483}
484
485struct snapshots_seen {
486 struct bpos pos;
487 snapshot_id_list ids;
488};
489
490static inline void snapshots_seen_exit(struct snapshots_seen *s)
491{
492 darray_exit(&s->ids);

--- 672 unchanged lines hidden (view full) ---

1165 NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
1166 check_inode(trans, &iter, k, &prev, &s, full)));
1167
1168 snapshots_seen_exit(&s);
1169 bch_err_fn(c, ret);
1170 return ret;
1171}
1172
496struct snapshots_seen {
497 struct bpos pos;
498 snapshot_id_list ids;
499};
500
501static inline void snapshots_seen_exit(struct snapshots_seen *s)
502{
503 darray_exit(&s->ids);

--- 672 unchanged lines hidden (view full) ---

1176 NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
1177 check_inode(trans, &iter, k, &prev, &s, full)));
1178
1179 snapshots_seen_exit(&s);
1180 bch_err_fn(c, ret);
1181 return ret;
1182}
1183
1184static inline bool btree_matches_i_mode(enum btree_id btree, unsigned mode)
1185{
1186 switch (btree) {
1187 case BTREE_ID_extents:
1188 return S_ISREG(mode) || S_ISLNK(mode);
1189 case BTREE_ID_dirents:
1190 return S_ISDIR(mode);
1191 case BTREE_ID_xattrs:
1192 return true;
1193 default:
1194 BUG();
1195 }
1196}
1197
1198static int check_key_has_inode(struct btree_trans *trans,
1199 struct btree_iter *iter,
1200 struct inode_walker *inode,
1201 struct inode_walker_entry *i,
1202 struct bkey_s_c k)
1203{
1204 struct bch_fs *c = trans->c;
1205 struct printbuf buf = PRINTBUF;
1206 int ret = PTR_ERR_OR_ZERO(i);
1207 if (ret)
1208 return ret;
1209
1210 if (k.k->type == KEY_TYPE_whiteout)
1211 goto out;
1212
1213 if (!i && (c->sb.btrees_lost_data & BIT_ULL(BTREE_ID_inodes))) {
1214 ret = reconstruct_inode(trans, iter->btree_id, k.k->p.snapshot, k.k->p.inode) ?:
1215 bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
1216 if (ret)
1217 goto err;
1218
1219 inode->last_pos.inode--;
1220 ret = -BCH_ERR_transaction_restart_nested;
1221 goto err;
1222 }
1223
1224 if (fsck_err_on(!i, c, key_in_missing_inode,
1225 "key in missing inode:\n %s",
1226 (printbuf_reset(&buf),
1227 bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
1228 goto delete;
1229
1230 if (fsck_err_on(i && !btree_matches_i_mode(iter->btree_id, i->inode.bi_mode),
1231 c, key_in_wrong_inode_type,
1232 "key for wrong inode mode %o:\n %s",
1233 i->inode.bi_mode,
1234 (printbuf_reset(&buf),
1235 bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
1236 goto delete;
1237out:
1238err:
1239fsck_err:
1240 printbuf_exit(&buf);
1241 bch_err_fn(c, ret);
1242 return ret;
1243delete:
1244 ret = bch2_btree_delete_at(trans, iter, BTREE_UPDATE_internal_snapshot_node);
1245 goto out;
1246}
1247
1173static int check_i_sectors_notnested(struct btree_trans *trans, struct inode_walker *w)
1174{
1175 struct bch_fs *c = trans->c;
1176 int ret = 0;
1177 s64 count2;
1178
1179 darray_for_each(w->inodes, i) {
1180 if (i->inode.bi_sectors == i->count)

--- 290 unchanged lines hidden (view full) ---

1471 }
1472
1473 if (inode->last_pos.inode != k.k->p.inode) {
1474 ret = check_i_sectors(trans, inode);
1475 if (ret)
1476 goto err;
1477 }
1478
1248static int check_i_sectors_notnested(struct btree_trans *trans, struct inode_walker *w)
1249{
1250 struct bch_fs *c = trans->c;
1251 int ret = 0;
1252 s64 count2;
1253
1254 darray_for_each(w->inodes, i) {
1255 if (i->inode.bi_sectors == i->count)

--- 290 unchanged lines hidden (view full) ---

1546 }
1547
1548 if (inode->last_pos.inode != k.k->p.inode) {
1549 ret = check_i_sectors(trans, inode);
1550 if (ret)
1551 goto err;
1552 }
1553
1554 ret = snapshots_seen_update(c, s, iter->btree_id, k.k->p);
1555 if (ret)
1556 goto err;
1557
1479 i = walk_inode(trans, inode, k);
1480 ret = PTR_ERR_OR_ZERO(i);
1481 if (ret)
1482 goto err;
1483
1558 i = walk_inode(trans, inode, k);
1559 ret = PTR_ERR_OR_ZERO(i);
1560 if (ret)
1561 goto err;
1562
1484 ret = snapshots_seen_update(c, s, iter->btree_id, k.k->p);
1563 ret = check_key_has_inode(trans, iter, inode, i, k);
1485 if (ret)
1486 goto err;
1487
1488 if (k.k->type != KEY_TYPE_whiteout) {
1564 if (ret)
1565 goto err;
1566
1567 if (k.k->type != KEY_TYPE_whiteout) {
1489 if (!i && (c->sb.btrees_lost_data & BIT_ULL(BTREE_ID_inodes))) {
1490 ret = reconstruct_reg_inode(trans, k.k->p.snapshot, k.k->p.inode) ?:
1491 bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
1492 if (ret)
1493 goto err;
1494
1495 inode->last_pos.inode--;
1496 ret = -BCH_ERR_transaction_restart_nested;
1497 goto err;
1498 }
1499
1500 if (fsck_err_on(!i, c, extent_in_missing_inode,
1501 "extent in missing inode:\n %s",
1502 (printbuf_reset(&buf),
1503 bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
1504 goto delete;
1505
1506 if (fsck_err_on(i &&
1507 !S_ISREG(i->inode.bi_mode) &&
1508 !S_ISLNK(i->inode.bi_mode),
1509 c, extent_in_non_reg_inode,
1510 "extent in non regular inode mode %o:\n %s",
1511 i->inode.bi_mode,
1512 (printbuf_reset(&buf),
1513 bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
1514 goto delete;
1515
1516 ret = check_overlapping_extents(trans, s, extent_ends, k, iter,
1517 &inode->recalculate_sums);
1518 if (ret)
1519 goto err;
1520 }
1521
1522 /*
1523 * Check inodes in reverse order, from oldest snapshots to newest,
1524 * starting from the inode that matches this extent's snapshot. If we
1525 * didn't have one, iterate over all inodes:
1526 */
1527 if (!i)
1568 ret = check_overlapping_extents(trans, s, extent_ends, k, iter,
1569 &inode->recalculate_sums);
1570 if (ret)
1571 goto err;
1572 }
1573
1574 /*
1575 * Check inodes in reverse order, from oldest snapshots to newest,
1576 * starting from the inode that matches this extent's snapshot. If we
1577 * didn't have one, iterate over all inodes:
1578 */
1579 if (!i)
1528 i = inode->inodes.data + inode->inodes.nr - 1;
1580 i = &darray_last(inode->inodes);
1529
1530 for (;
1531 inode->inodes.data && i >= inode->inodes.data;
1532 --i) {
1533 if (i->snapshot > k.k->p.snapshot ||
1534 !key_visible_in_snapshot(c, s, i->snapshot, k.k->p.snapshot))
1535 continue;
1536

--- 32 unchanged lines hidden (view full) ---

1569 goto err;
1570 }
1571out:
1572err:
1573fsck_err:
1574 printbuf_exit(&buf);
1575 bch_err_fn(c, ret);
1576 return ret;
1581
1582 for (;
1583 inode->inodes.data && i >= inode->inodes.data;
1584 --i) {
1585 if (i->snapshot > k.k->p.snapshot ||
1586 !key_visible_in_snapshot(c, s, i->snapshot, k.k->p.snapshot))
1587 continue;
1588

--- 32 unchanged lines hidden (view full) ---

1621 goto err;
1622 }
1623out:
1624err:
1625fsck_err:
1626 printbuf_exit(&buf);
1627 bch_err_fn(c, ret);
1628 return ret;
1577delete:
1578 ret = bch2_btree_delete_at(trans, iter, BTREE_UPDATE_internal_snapshot_node);
1579 goto out;
1580}
1581
1582/*
1583 * Walk extents: verify that extents have a corresponding S_ISREG inode, and
1584 * that i_size an i_sectors are consistent
1585 */
1586int bch2_check_extents(struct bch_fs *c)
1587{

--- 416 unchanged lines hidden (view full) ---

2004 goto out;
2005
2006 if (dir->last_pos.inode != k.k->p.inode) {
2007 ret = check_subdir_count(trans, dir);
2008 if (ret)
2009 goto err;
2010 }
2011
1629}
1630
1631/*
1632 * Walk extents: verify that extents have a corresponding S_ISREG inode, and
1633 * that i_size an i_sectors are consistent
1634 */
1635int bch2_check_extents(struct bch_fs *c)
1636{

--- 416 unchanged lines hidden (view full) ---

2053 goto out;
2054
2055 if (dir->last_pos.inode != k.k->p.inode) {
2056 ret = check_subdir_count(trans, dir);
2057 if (ret)
2058 goto err;
2059 }
2060
2012 BUG_ON(!btree_iter_path(trans, iter)->should_be_locked);
2013
2014 i = walk_inode(trans, dir, k);
2015 ret = PTR_ERR_OR_ZERO(i);
2016 if (ret < 0)
2017 goto err;
2018
2061 i = walk_inode(trans, dir, k);
2062 ret = PTR_ERR_OR_ZERO(i);
2063 if (ret < 0)
2064 goto err;
2065
2019 if (dir->first_this_inode && dir->inodes.nr)
2020 *hash_info = bch2_hash_info_init(c, &dir->inodes.data[0].inode);
2021 dir->first_this_inode = false;
2022
2023 if (!i && (c->sb.btrees_lost_data & BIT_ULL(BTREE_ID_inodes))) {
2024 ret = reconstruct_inode(trans, k.k->p.snapshot, k.k->p.inode, 0, S_IFDIR) ?:
2025 bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
2026 if (ret)
2027 goto err;
2028
2029 dir->last_pos.inode--;
2030 ret = -BCH_ERR_transaction_restart_nested;
2066 ret = check_key_has_inode(trans, iter, dir, i, k);
2067 if (ret)
2031 goto err;
2068 goto err;
2032 }
2033
2069
2034 if (fsck_err_on(!i, c, dirent_in_missing_dir_inode,
2035 "dirent in nonexisting directory:\n%s",
2036 (printbuf_reset(&buf),
2037 bch2_bkey_val_to_text(&buf, c, k), buf.buf))) {
2038 ret = bch2_btree_delete_at(trans, iter,
2039 BTREE_UPDATE_internal_snapshot_node);
2040 goto out;
2041 }
2042
2043 if (!i)
2044 goto out;
2045
2070 if (!i)
2071 goto out;
2072
2046 if (fsck_err_on(!S_ISDIR(i->inode.bi_mode),
2047 c, dirent_in_non_dir_inode,
2048 "dirent in non directory inode type %s:\n%s",
2049 bch2_d_type_str(inode_d_type(&i->inode)),
2050 (printbuf_reset(&buf),
2051 bch2_bkey_val_to_text(&buf, c, k), buf.buf))) {
2052 ret = bch2_btree_delete_at(trans, iter, 0);
2053 goto out;
2054 }
2073 if (dir->first_this_inode)
2074 *hash_info = bch2_hash_info_init(c, &i->inode);
2075 dir->first_this_inode = false;
2055
2056 ret = hash_check_key(trans, bch2_dirent_hash_desc, hash_info, iter, k);
2057 if (ret < 0)
2058 goto err;
2059 if (ret) {
2060 /* dirent has been deleted */
2061 ret = 0;
2062 goto out;

--- 88 unchanged lines hidden (view full) ---

2151 if (ret)
2152 return 0;
2153
2154 i = walk_inode(trans, inode, k);
2155 ret = PTR_ERR_OR_ZERO(i);
2156 if (ret)
2157 return ret;
2158
2076
2077 ret = hash_check_key(trans, bch2_dirent_hash_desc, hash_info, iter, k);
2078 if (ret < 0)
2079 goto err;
2080 if (ret) {
2081 /* dirent has been deleted */
2082 ret = 0;
2083 goto out;

--- 88 unchanged lines hidden (view full) ---

2172 if (ret)
2173 return 0;
2174
2175 i = walk_inode(trans, inode, k);
2176 ret = PTR_ERR_OR_ZERO(i);
2177 if (ret)
2178 return ret;
2179
2159 if (inode->first_this_inode && inode->inodes.nr)
2160 *hash_info = bch2_hash_info_init(c, &inode->inodes.data[0].inode);
2161 inode->first_this_inode = false;
2180 ret = check_key_has_inode(trans, iter, inode, i, k);
2181 if (ret)
2182 return ret;
2162
2183
2163 if (fsck_err_on(!i, c, xattr_in_missing_inode,
2164 "xattr for missing inode %llu",
2165 k.k->p.inode))
2166 return bch2_btree_delete_at(trans, iter, 0);
2167
2168 if (!i)
2169 return 0;
2170
2184 if (!i)
2185 return 0;
2186
2187 if (inode->first_this_inode)
2188 *hash_info = bch2_hash_info_init(c, &i->inode);
2189 inode->first_this_inode = false;
2190
2171 ret = hash_check_key(trans, bch2_xattr_hash_desc, hash_info, iter, k);
2191 ret = hash_check_key(trans, bch2_xattr_hash_desc, hash_info, iter, k);
2172fsck_err:
2173 bch_err_fn(c, ret);
2174 return ret;
2175}
2176
2177/*
2178 * Walk xattrs: verify that they all have a corresponding inode
2179 */
2180int bch2_check_xattrs(struct bch_fs *c)

--- 619 unchanged lines hidden ---
2192 bch_err_fn(c, ret);
2193 return ret;
2194}
2195
2196/*
2197 * Walk xattrs: verify that they all have a corresponding inode
2198 */
2199int bch2_check_xattrs(struct bch_fs *c)

--- 619 unchanged lines hidden ---