Lines Matching +full:fixed +full:- +full:links
1 // SPDX-License-Identifier: GPL-2.0
11 #include "fs-common.h"
25 * -BCH_ERR_transaction_restart_nested, this is not how we do things anymore:
37 sectors += k.k->size; in bch2_count_inode_sectors()
53 if (k.k->type == KEY_TYPE_dirent && in bch2_count_subdirs()
54 bkey_s_c_to_dirent(k).v->d_type == DT_DIR) in bch2_count_subdirs()
90 if (!k.k || !bkey_eq(k.k->p, POS(0, inode_nr))) { in lookup_first_inode()
91 ret = -BCH_ERR_ENOENT_inode; in lookup_first_inode()
97 bch_err_msg(trans->c, ret, "fetching inode %llu", inode_nr); in lookup_first_inode()
118 : -BCH_ERR_ENOENT_inode; in lookup_inode()
139 *target = le64_to_cpu(d.v->d_inum); in lookup_dirent_in_snapshot()
140 *type = d.v->d_type; in lookup_dirent_in_snapshot()
156 inode_p->inode.k.p.snapshot = snapshot; in __write_inode()
159 &inode_p->inode.k_i, in __write_inode()
169 bch_err_fn(trans->c, ret); in fsck_write_inode()
175 struct bch_fs *c = trans->c; in __remove_dirent()
202 struct bch_fs *c = trans->c; in lookup_lostfound()
244 return -BCH_ERR_ENOENT_not_directory; in lookup_lostfound()
269 lostfound->bi_dir = root_inode.bi_inum; in lookup_lostfound()
284 mode_to_type(lostfound->bi_mode), in lookup_lostfound()
286 lostfound->bi_inum, in lookup_lostfound()
287 &lostfound->bi_dir_offset, in lookup_lostfound()
312 if (S_ISDIR(inode->bi_mode)) { in reattach_inode()
320 dir_hash = bch2_hash_info_init(trans->c, &lostfound); in reattach_inode()
322 snprintf(name_buf, sizeof(name_buf), "%llu", inode->bi_inum); in reattach_inode()
329 &name, inode->bi_inum, &dir_offset, in reattach_inode()
334 inode->bi_dir = lostfound.bi_inum; in reattach_inode()
335 inode->bi_dir_offset = dir_offset; in reattach_inode()
348 POS(inode->bi_dir, inode->bi_dir_offset), 0, in remove_backpointer()
351 __remove_dirent(trans, d.k->p); in remove_backpointer()
368 darray_exit(&s->ids); in snapshots_seen_exit()
384 __darray_for_each(s->ids, i) { in snapshots_seen_add_inorder()
385 if (i->id == id) in snapshots_seen_add_inorder()
387 if (i->id > id) in snapshots_seen_add_inorder()
391 ret = darray_insert_item(&s->ids, i - s->ids.data, n); in snapshots_seen_add_inorder()
394 s->ids.size); in snapshots_seen_add_inorder()
407 if (!bkey_eq(s->pos, pos)) in snapshots_seen_update()
408 s->ids.nr = 0; in snapshots_seen_update()
410 s->pos = pos; in snapshots_seen_update()
411 s->pos.snapshot = n.equiv; in snapshots_seen_update()
413 darray_for_each(s->ids, i) { in snapshots_seen_update()
414 if (i->id == n.id) in snapshots_seen_update()
421 if (i->equiv == n.equiv) { in snapshots_seen_update()
426 i->id, n.id, n.equiv); in snapshots_seen_update()
427 set_bit(BCH_FS_need_delete_dead_snapshots, &c->flags); in snapshots_seen_update()
432 ret = darray_push(&s->ids, n); in snapshots_seen_update()
435 s->ids.size); in snapshots_seen_update()
440 * key_visible_in_snapshot - returns true if @id is a descendent of @ancestor,
460 EBUG_ON(ancestor != seen->pos.snapshot); in key_visible_in_snapshot()
461 EBUG_ON(ancestor != seen->ids.data[seen->ids.nr - 1].equiv); in key_visible_in_snapshot()
471 * we've seen a key that overwrote @ancestor - i.e. also a descendent of in key_visible_in_snapshot()
479 for (i = seen->ids.nr - 2; in key_visible_in_snapshot()
480 i >= 0 && seen->ids.data[i].equiv >= id; in key_visible_in_snapshot()
481 --i) in key_visible_in_snapshot()
482 if (bch2_snapshot_is_ancestor(c, id, seen->ids.data[i].equiv)) in key_visible_in_snapshot()
489 * ref_visible - given a key with snapshot id @src that points to a key with
524 for (_i = (_w)->inodes.data; _i < (_w)->inodes.data + (_w)->inodes.nr && \
525 (_i)->snapshot <= (_snapshot); _i++) \
526 if (key_visible_in_snapshot(_c, _s, _i->snapshot, _snapshot))
545 darray_exit(&w->inodes); in inode_walker_exit()
560 return darray_push(&w->inodes, ((struct inode_walker_entry) { in add_inode()
562 .snapshot = bch2_snapshot_equiv(c, inode.k->p.snapshot), in add_inode()
569 struct bch_fs *c = trans->c; in get_inodes_all_snapshots()
574 w->recalculate_sums = false; in get_inodes_all_snapshots()
575 w->inodes.nr = 0; in get_inodes_all_snapshots()
579 if (k.k->p.offset != inum) in get_inodes_all_snapshots()
590 w->first_this_inode = true; in get_inodes_all_snapshots()
602 __darray_for_each(w->inodes, i) in lookup_inode_for_snapshot()
603 if (bch2_snapshot_is_ancestor(c, snapshot, i->snapshot)) in lookup_inode_for_snapshot()
608 BUG_ON(snapshot > i->snapshot); in lookup_inode_for_snapshot()
610 if (snapshot != i->snapshot && !is_whiteout) { in lookup_inode_for_snapshot()
619 w->last_pos.inode, snapshot, i->snapshot); in lookup_inode_for_snapshot()
621 while (i > w->inodes.data && i[-1].snapshot > snapshot) in lookup_inode_for_snapshot()
622 --i; in lookup_inode_for_snapshot()
624 pos = i - w->inodes.data; in lookup_inode_for_snapshot()
625 ret = darray_insert_item(&w->inodes, pos, new); in lookup_inode_for_snapshot()
629 i = w->inodes.data + pos; in lookup_inode_for_snapshot()
639 if (w->last_pos.inode != pos.inode) { in walk_inode()
643 } else if (bkey_cmp(w->last_pos, pos)) { in walk_inode()
644 darray_for_each(w->inodes, i) in walk_inode()
645 i->seen_this_pos = false; in walk_inode()
648 w->last_pos = pos; in walk_inode()
650 return lookup_inode_for_snapshot(trans->c, w, pos.snapshot, is_whiteout); in walk_inode()
658 struct bch_fs *c = trans->c; in __get_visible_inodes()
663 w->inodes.nr = 0; in __get_visible_inodes()
667 u32 equiv = bch2_snapshot_equiv(c, k.k->p.snapshot); in __get_visible_inodes()
669 if (k.k->p.offset != inum) in __get_visible_inodes()
672 if (!ref_visible(c, s, s->pos.snapshot, equiv)) in __get_visible_inodes()
678 if (equiv >= s->pos.snapshot) in __get_visible_inodes()
690 struct bch_fs *c = trans->c; in check_key_has_snapshot()
694 if (mustfix_fsck_err_on(!bch2_snapshot_equiv(c, k.k->p.snapshot), c, in check_key_has_snapshot()
721 bkey_init(&delete->k); in hash_redo_key()
722 delete->k.p = k_iter->pos; in hash_redo_key()
726 (subvol_inum) { 0, k.k->p.inode }, in hash_redo_key()
727 k.k->p.snapshot, tmp, in hash_redo_key()
738 struct bch_fs *c = trans->c; in hash_check_key()
745 if (hash_k.k->type != desc.key_type) in hash_check_key()
750 if (likely(hash == hash_k.k->p.offset)) in hash_check_key()
753 if (hash_k.k->p.offset < hash) in hash_check_key()
757 SPOS(hash_k.k->p.inode, hash, hash_k.k->p.snapshot), in hash_check_key()
759 if (bkey_eq(k.k->p, hash_k.k->p)) in hash_check_key()
762 if (fsck_err_on(k.k->type == desc.key_type && in hash_check_key()
785 bch2_btree_id_str(desc.btree_id), hash_k.k->p.inode, hash_k.k->p.offset, hash, in hash_check_key()
792 ret = -BCH_ERR_transaction_restart_nested; in hash_check_key()
807 return k.k->type == KEY_TYPE_set; in check_inode_deleted_list()
817 struct bch_fs *c = trans->c; in check_inode()
828 ret = snapshots_seen_update(c, s, iter->btree_id, k.k->p); in check_inode()
843 if (prev->bi_inum != u.bi_inum) in check_inode()
846 if (fsck_err_on(prev->bi_hash_seed != u.bi_hash_seed || in check_inode()
851 return -BCH_ERR_fsck_repair_unimplemented; in check_inode()
855 bch2_key_has_snapshot_overwrites(trans, BTREE_ID_inodes, k.k->p)) { in check_inode()
858 ret = bch2_propagate_key_to_snapshot_leaves(trans, iter->btree_id, k, &new_min_pos); in check_inode()
864 ret = __write_inode(trans, &u, iter->pos.snapshot); in check_inode()
875 ret = check_inode_deleted_list(trans, k.k->p); in check_inode()
881 u.bi_inum, k.k->p.snapshot); in check_inode()
886 (!c->sb.clean || in check_inode()
890 ret = bch2_inode_rm_snapshot(trans, u.bi_inum, iter->pos.snapshot); in check_inode()
896 (!c->sb.clean || in check_inode()
903 * XXX: need to truncate partial blocks too here - or ideally in check_inode()
908 iter->pos.snapshot), in check_inode()
926 (!c->sb.clean || in check_inode()
935 sectors = bch2_count_inode_sectors(trans, u.bi_inum, iter->pos.snapshot); in check_inode()
954 ret = __write_inode(trans, &u, iter->pos.snapshot); in check_inode()
967 bool full = c->opts.fsck; in bch2_check_inodes()
995 return inode->bi_dir == d.k->p.inode && in inode_points_to_dirent()
996 inode->bi_dir_offset == d.k->p.offset; in inode_points_to_dirent()
1002 return d.v->d_type == DT_SUBVOL in dirent_points_to_inode()
1003 ? le32_to_cpu(d.v->d_child_subvol) == inode->bi_subvol in dirent_points_to_inode()
1004 : le64_to_cpu(d.v->d_inum) == inode->bi_inum; in dirent_points_to_inode()
1009 struct bch_fs *c = trans->c; in check_i_sectors()
1010 u32 restart_count = trans->restart_count; in check_i_sectors()
1014 darray_for_each(w->inodes, i) { in check_i_sectors()
1015 if (i->inode.bi_sectors == i->count) in check_i_sectors()
1018 count2 = bch2_count_inode_sectors(trans, w->last_pos.inode, i->snapshot); in check_i_sectors()
1020 if (w->recalculate_sums) in check_i_sectors()
1021 i->count = count2; in check_i_sectors()
1023 if (i->count != count2) { in check_i_sectors()
1025 w->last_pos.inode, i->snapshot, i->count, count2); in check_i_sectors()
1026 return -BCH_ERR_internal_fsck_err; in check_i_sectors()
1029 if (fsck_err_on(!(i->inode.bi_flags & BCH_INODE_i_sectors_dirty), in check_i_sectors()
1032 w->last_pos.inode, i->snapshot, in check_i_sectors()
1033 i->inode.bi_sectors, i->count)) { in check_i_sectors()
1034 i->inode.bi_sectors = i->count; in check_i_sectors()
1035 ret = fsck_write_inode(trans, &i->inode, i->snapshot); in check_i_sectors()
1058 darray_for_each(extent_ends->e, i) in extent_ends_reset()
1059 snapshots_seen_exit(&i->seen); in extent_ends_reset()
1060 extent_ends->e.nr = 0; in extent_ends_reset()
1066 darray_exit(&extent_ends->e); in extent_ends_exit()
1080 .offset = k.k->p.offset, in extent_ends_at()
1081 .snapshot = k.k->p.snapshot, in extent_ends_at()
1085 n.seen.ids.data = kmemdup(seen->ids.data, in extent_ends_at()
1086 sizeof(seen->ids.data[0]) * seen->ids.size, in extent_ends_at()
1089 return -BCH_ERR_ENOMEM_fsck_extent_ends_at; in extent_ends_at()
1091 __darray_for_each(extent_ends->e, i) { in extent_ends_at()
1092 if (i->snapshot == k.k->p.snapshot) { in extent_ends_at()
1093 snapshots_seen_exit(&i->seen); in extent_ends_at()
1098 if (i->snapshot >= k.k->p.snapshot) in extent_ends_at()
1102 return darray_insert_item(&extent_ends->e, i - extent_ends->e.data, n); in extent_ends_at()
1109 bool *fixed, in overlapping_extents_found() argument
1112 struct bch_fs *c = trans->c; in overlapping_extents_found()
1131 if (!bpos_eq(pos1, k1.k->p)) { in overlapping_extents_found()
1139 ret = -BCH_ERR_internal_fsck_err; in overlapping_extents_found()
1153 if (bpos_ge(k2.k->p, pos2.p)) in overlapping_extents_found()
1160 if (bpos_gt(k2.k->p, pos2.p) || in overlapping_extents_found()
1161 pos2.size != k2.k->size) { in overlapping_extents_found()
1164 ret = -BCH_ERR_internal_fsck_err; in overlapping_extents_found()
1181 trans->extra_disk_res += bch2_bkey_sectors_compressed(k2); in overlapping_extents_found()
1192 *fixed = true; in overlapping_extents_found()
1199 extent_end->offset = bkey_start_offset(&pos2); in overlapping_extents_found()
1207 * We overwrote the second extent - restart in overlapping_extents_found()
1210 ret = -BCH_ERR_transaction_restart_nested; in overlapping_extents_found()
1227 bool *fixed) in check_overlapping_extents() argument
1229 struct bch_fs *c = trans->c; in check_overlapping_extents()
1233 if (bpos_eq(extent_ends->last_pos, k.k->p)) in check_overlapping_extents()
1236 if (extent_ends->last_pos.inode != k.k->p.inode) in check_overlapping_extents()
1239 darray_for_each(extent_ends->e, i) { in check_overlapping_extents()
1240 if (i->offset <= bkey_start_offset(k.k)) in check_overlapping_extents()
1244 k.k->p.snapshot, seen, in check_overlapping_extents()
1245 i->snapshot, &i->seen)) in check_overlapping_extents()
1248 ret = overlapping_extents_found(trans, iter->btree_id, in check_overlapping_extents()
1249 SPOS(iter->pos.inode, in check_overlapping_extents()
1250 i->offset, in check_overlapping_extents()
1251 i->snapshot), in check_overlapping_extents()
1252 &i->seen, in check_overlapping_extents()
1253 *k.k, fixed, i); in check_overlapping_extents()
1262 extent_ends->last_pos = k.k->p; in check_overlapping_extents()
1270 struct bch_fs *c = trans->c; in check_extent_overbig()
1274 unsigned encoded_extent_max_sectors = c->opts.encoded_extent_max >> 9; in check_extent_overbig()
1295 struct bch_fs *c = trans->c; in check_extent()
1298 struct bpos equiv = k.k->p; in check_extent()
1301 equiv.snapshot = bch2_snapshot_equiv(c, k.k->p.snapshot); in check_extent()
1309 if (inode->last_pos.inode != k.k->p.inode) { in check_extent()
1315 i = walk_inode(trans, inode, equiv, k.k->type == KEY_TYPE_whiteout); in check_extent()
1320 ret = snapshots_seen_update(c, s, iter->btree_id, k.k->p); in check_extent()
1324 if (k.k->type != KEY_TYPE_whiteout) { in check_extent()
1332 !S_ISREG(i->inode.bi_mode) && in check_extent()
1333 !S_ISLNK(i->inode.bi_mode), in check_extent()
1336 i->inode.bi_mode, in check_extent()
1343 &inode->recalculate_sums); in check_extent()
1354 i = inode->inodes.data + inode->inodes.nr - 1; in check_extent()
1357 inode->inodes.data && i >= inode->inodes.data; in check_extent()
1358 --i) { in check_extent()
1359 if (i->snapshot > equiv.snapshot || in check_extent()
1360 !key_visible_in_snapshot(c, s, i->snapshot, equiv.snapshot)) in check_extent()
1363 if (k.k->type != KEY_TYPE_whiteout) { in check_extent()
1364 if (fsck_err_on(!(i->inode.bi_flags & BCH_INODE_i_size_dirty) && in check_extent()
1365 k.k->p.offset > round_up(i->inode.bi_size, block_bytes(c)) >> 9 && in check_extent()
1369 i->inode.bi_inum, i->snapshot, i->inode.bi_size, in check_extent()
1374 bch2_btree_iter_set_snapshot(&iter2, i->snapshot); in check_extent()
1382 iter->k.type = KEY_TYPE_whiteout; in check_extent()
1386 i->count += k.k->size; in check_extent()
1389 i->seen_this_pos = true; in check_extent()
1458 struct bch_fs *c = trans->c; in check_subdir_count()
1459 u32 restart_count = trans->restart_count; in check_subdir_count()
1463 darray_for_each(w->inodes, i) { in check_subdir_count()
1464 if (i->inode.bi_nlink == i->count) in check_subdir_count()
1467 count2 = bch2_count_subdirs(trans, w->last_pos.inode, i->snapshot); in check_subdir_count()
1471 if (i->count != count2) { in check_subdir_count()
1473 i->count, count2); in check_subdir_count()
1474 i->count = count2; in check_subdir_count()
1475 if (i->inode.bi_nlink == i->count) in check_subdir_count()
1479 if (fsck_err_on(i->inode.bi_nlink != i->count, in check_subdir_count()
1482 w->last_pos.inode, i->snapshot, i->inode.bi_nlink, i->count)) { in check_subdir_count()
1483 i->inode.bi_nlink = i->count; in check_subdir_count()
1484 ret = fsck_write_inode(trans, &i->inode, i->snapshot); in check_subdir_count()
1500 struct bch_fs *c = trans->c; in check_dirent_target()
1506 if (!target->bi_dir && in check_dirent_target()
1507 !target->bi_dir_offset) { in check_dirent_target()
1508 target->bi_dir = d.k->p.inode; in check_dirent_target()
1509 target->bi_dir_offset = d.k->p.offset; in check_dirent_target()
1518 SPOS(target->bi_dir, target->bi_dir_offset, target_snapshot)); in check_dirent_target()
1531 if (fsck_err_on(S_ISDIR(target->bi_mode) && backpointer_exists, in check_dirent_target()
1533 "directory %llu:%u with multiple links\n%s", in check_dirent_target()
1534 target->bi_inum, target_snapshot, buf.buf)) { in check_dirent_target()
1535 ret = __remove_dirent(trans, d.k->p); in check_dirent_target()
1544 if (fsck_err_on(backpointer_exists && !target->bi_nlink, in check_dirent_target()
1546 "inode %llu:%u type %s has multiple links but i_nlink 0\n%s", in check_dirent_target()
1547 target->bi_inum, target_snapshot, bch2_d_types[d.v->d_type], buf.buf)) { in check_dirent_target()
1548 target->bi_nlink++; in check_dirent_target()
1549 target->bi_flags &= ~BCH_INODE_unlinked; in check_dirent_target()
1561 target->bi_inum, target_snapshot, in check_dirent_target()
1562 target->bi_dir, in check_dirent_target()
1563 target->bi_dir_offset, in check_dirent_target()
1564 d.k->p.inode, in check_dirent_target()
1565 d.k->p.offset)) { in check_dirent_target()
1566 target->bi_dir = d.k->p.inode; in check_dirent_target()
1567 target->bi_dir_offset = d.k->p.offset; in check_dirent_target()
1575 if (fsck_err_on(d.v->d_type != inode_d_type(target), in check_dirent_target()
1578 bch2_d_type_str(d.v->d_type), in check_dirent_target()
1587 bkey_reassemble(&n->k_i, d.s_c); in check_dirent_target()
1588 n->v.d_type = inode_d_type(target); in check_dirent_target()
1590 ret = bch2_trans_update(trans, iter, &n->k_i, 0); in check_dirent_target()
1597 if (fsck_err_on(d.v->d_type == DT_SUBVOL && in check_dirent_target()
1598 target->bi_parent_subvol != le32_to_cpu(d.v->d_parent_subvol), in check_dirent_target()
1601 le32_to_cpu(d.v->d_parent_subvol), in check_dirent_target()
1602 target->bi_parent_subvol)) { in check_dirent_target()
1608 bkey_reassemble(&n->k_i, d.s_c); in check_dirent_target()
1609 n->v.d_parent_subvol = cpu_to_le32(target->bi_parent_subvol); in check_dirent_target()
1611 ret = bch2_trans_update(trans, iter, &n->k_i, 0); in check_dirent_target()
1633 struct bch_fs *c = trans->c; in check_dirent()
1646 equiv = k.k->p; in check_dirent()
1647 equiv.snapshot = bch2_snapshot_equiv(c, k.k->p.snapshot); in check_dirent()
1649 ret = snapshots_seen_update(c, s, iter->btree_id, k.k->p); in check_dirent()
1653 if (k.k->type == KEY_TYPE_whiteout) in check_dirent()
1656 if (dir->last_pos.inode != k.k->p.inode) { in check_dirent()
1662 BUG_ON(!btree_iter_path(trans, iter)->should_be_locked); in check_dirent()
1664 i = walk_inode(trans, dir, equiv, k.k->type == KEY_TYPE_whiteout); in check_dirent()
1669 if (dir->first_this_inode && dir->inodes.nr) in check_dirent()
1670 *hash_info = bch2_hash_info_init(c, &dir->inodes.data[0].inode); in check_dirent()
1671 dir->first_this_inode = false; in check_dirent()
1685 if (fsck_err_on(!S_ISDIR(i->inode.bi_mode), in check_dirent()
1688 bch2_d_type_str(inode_d_type(&i->inode)), in check_dirent()
1704 if (k.k->type != KEY_TYPE_dirent) in check_dirent()
1709 if (d.v->d_type == DT_SUBVOL) { in check_dirent()
1711 u32 target_subvol = le32_to_cpu(d.v->d_child_subvol); in check_dirent()
1722 le32_to_cpu(d.v->d_child_subvol))) { in check_dirent()
1723 ret = __remove_dirent(trans, d.k->p); in check_dirent()
1737 ret = -EINVAL; in check_dirent()
1757 ret = __get_visible_inodes(trans, target, s, le64_to_cpu(d.v->d_inum)); in check_dirent()
1761 if (fsck_err_on(!target->inodes.nr, in check_dirent()
1768 ret = __remove_dirent(trans, d.k->p); in check_dirent()
1773 darray_for_each(target->inodes, i) { in check_dirent()
1775 &i->inode, i->snapshot); in check_dirent()
1781 if (d.v->d_type == DT_DIR) in check_dirent()
1783 i->count++; in check_dirent()
1827 struct bch_fs *c = trans->c; in check_xattr()
1835 i = walk_inode(trans, inode, k.k->p, k.k->type == KEY_TYPE_whiteout); in check_xattr()
1840 if (inode->first_this_inode && inode->inodes.nr) in check_xattr()
1841 *hash_info = bch2_hash_info_init(c, &inode->inodes.data[0].inode); in check_xattr()
1842 inode->first_this_inode = false; in check_xattr()
1846 k.k->p.inode)) in check_xattr()
1881 struct bch_fs *c = trans->c; in check_root_trans()
1949 if (i->inum == inum && in path_is_dup()
1950 i->snapshot == snapshot) in path_is_dup()
1965 p->size); in path_down()
1979 struct bch_fs *c = trans->c; in check_path()
1983 p->nr = 0; in check_path()
1985 while (!(inode->bi_inum == BCACHEFS_ROOT_INO && in check_path()
1986 inode->bi_subvol == BCACHEFS_ROOT_SUBVOL)) { in check_path()
1991 if (inode->bi_subvol) { in check_path()
1994 ret = subvol_lookup(trans, inode->bi_parent_subvol, in check_path()
2001 SPOS(inode->bi_dir, inode->bi_dir_offset, in check_path()
2009 ret = -BCH_ERR_ENOENT_dirent_doesnt_match_inode; in check_path()
2015 inode->bi_inum, snapshot, in check_path()
2017 inode->bi_nlink, in check_path()
2018 inode->bi_dir, in check_path()
2019 inode->bi_dir_offset)) in check_path()
2026 if (!S_ISDIR(inode->bi_mode)) in check_path()
2029 ret = path_down(c, p, inode->bi_inum, snapshot); in check_path()
2037 ret = lookup_inode(trans, inode->bi_dir, inode, &snapshot); in check_path()
2045 if (path_is_dup(p, inode->bi_inum, snapshot)) { in check_path()
2050 pr_err("%llu:%u", i->inum, i->snapshot); in check_path()
2051 pr_err("%llu:%u", inode->bi_inum, snapshot); in check_path()
2064 bch_err_msg(c, ret, "reattaching inode %llu", inode->bi_inum); in check_path()
2120 if (t->nr == t->size) { in add_nlink()
2121 size_t new_size = max_t(size_t, 128UL, t->size * 2); in add_nlink()
2122 void *d = kvmalloc_array(new_size, sizeof(t->d[0]), GFP_KERNEL); in add_nlink()
2127 return -BCH_ERR_ENOMEM_fsck_add_nlink; in add_nlink()
2130 if (t->d) in add_nlink()
2131 memcpy(d, t->d, t->size * sizeof(t->d[0])); in add_nlink()
2132 kvfree(t->d); in add_nlink()
2134 t->d = d; in add_nlink()
2135 t->size = new_size; in add_nlink()
2139 t->d[t->nr++] = (struct nlink) { in add_nlink()
2152 return cmp_int(l->inum, r->inum); in nlink_cmp()
2156 struct nlink_table *links, in inc_link() argument
2166 link = __inline_bsearch(&key, links->d, links->nr, in inc_link()
2167 sizeof(links->d[0]), nlink_cmp); in inc_link()
2171 while (link > links->d && link[0].inum == link[-1].inum) in inc_link()
2172 --link; in inc_link()
2174 for (; link < links->d + links->nr && link->inum == inum; link++) in inc_link()
2175 if (ref_visible(c, s, snapshot, link->snapshot)) { in inc_link()
2176 link->count++; in inc_link()
2177 if (link->snapshot >= snapshot) in inc_link()
2210 ret = add_nlink(c, t, k.k->p.offset, k.k->p.snapshot); in check_nlinks_find_hardlinks()
2212 *end = k.k->p.offset; in check_nlinks_find_hardlinks()
2224 static int check_nlinks_walk_dirents(struct bch_fs *c, struct nlink_table *links, in check_nlinks_walk_dirents() argument
2236 ret = snapshots_seen_update(c, &s, iter.btree_id, k.k->p); in check_nlinks_walk_dirents()
2240 if (k.k->type == KEY_TYPE_dirent) { in check_nlinks_walk_dirents()
2243 if (d.v->d_type != DT_DIR && in check_nlinks_walk_dirents()
2244 d.v->d_type != DT_SUBVOL) in check_nlinks_walk_dirents()
2245 inc_link(c, &s, links, range_start, range_end, in check_nlinks_walk_dirents()
2246 le64_to_cpu(d.v->d_inum), in check_nlinks_walk_dirents()
2247 bch2_snapshot_equiv(c, d.k->p.snapshot)); in check_nlinks_walk_dirents()
2260 struct nlink_table *links, in check_nlinks_update_inode() argument
2263 struct bch_fs *c = trans->c; in check_nlinks_update_inode()
2265 struct nlink *link = &links->d[*idx]; in check_nlinks_update_inode()
2268 if (k.k->p.offset >= range_end) in check_nlinks_update_inode()
2282 while ((cmp_int(link->inum, k.k->p.offset) ?: in check_nlinks_update_inode()
2283 cmp_int(link->snapshot, k.k->p.snapshot)) < 0) { in check_nlinks_update_inode()
2284 BUG_ON(*idx == links->nr); in check_nlinks_update_inode()
2285 link = &links->d[++*idx]; in check_nlinks_update_inode()
2288 if (fsck_err_on(bch2_inode_nlink_get(&u) != link->count, in check_nlinks_update_inode()
2292 bch2_inode_nlink_get(&u), link->count)) { in check_nlinks_update_inode()
2293 bch2_inode_nlink_set(&u, link->count); in check_nlinks_update_inode()
2294 ret = __write_inode(trans, &u, k.k->p.snapshot); in check_nlinks_update_inode()
2302 struct nlink_table *links, in check_nlinks_update_hardlinks() argument
2312 check_nlinks_update_inode(trans, &iter, k, links, &idx, range_end))); in check_nlinks_update_hardlinks()
2323 struct nlink_table links = { 0 }; in bch2_check_nlinks() local
2331 ret = check_nlinks_find_hardlinks(c, &links, in bch2_check_nlinks()
2335 ret = check_nlinks_walk_dirents(c, &links, in bch2_check_nlinks()
2341 ret = check_nlinks_update_hardlinks(c, &links, in bch2_check_nlinks()
2347 links.nr = 0; in bch2_check_nlinks()
2350 kvfree(links.d); in bch2_check_nlinks()
2361 if (k.k->type != KEY_TYPE_reflink_p) in fix_reflink_p_key()
2366 if (!p.v->front_pad && !p.v->back_pad) in fix_reflink_p_key()
2374 bkey_reassemble(&u->k_i, k); in fix_reflink_p_key()
2375 u->v.front_pad = 0; in fix_reflink_p_key()
2376 u->v.back_pad = 0; in fix_reflink_p_key()
2378 return bch2_trans_update(trans, iter, &u->k_i, BTREE_TRIGGER_NORUN); in fix_reflink_p_key()
2383 if (c->sb.version >= bcachefs_metadata_version_reflink_p_fix) in bch2_fix_reflink_p()