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 --- |