Lines Matching +full:fixed +full:- +full:links

1 // SPDX-License-Identifier: GPL-2.0
12 #include "fs-common.h"
27 return inode->bi_dir == d.k->p.inode && in inode_points_to_dirent()
28 inode->bi_dir_offset == d.k->p.offset; in inode_points_to_dirent()
34 if (d.v->d_type == DT_SUBVOL in dirent_points_to_inode_nowarn()
35 ? le32_to_cpu(d.v->d_child_subvol) == inode->bi_subvol in dirent_points_to_inode_nowarn()
36 : le64_to_cpu(d.v->d_inum) == inode->bi_inum) in dirent_points_to_inode_nowarn()
38 return -BCH_ERR_ENOENT_dirent_doesnt_match_inode; in dirent_points_to_inode_nowarn()
69 * -BCH_ERR_transaction_restart_nested, this is not how we do things anymore:
81 sectors += k.k->size; in bch2_count_inode_sectors()
97 if (k.k->type == KEY_TYPE_dirent && in bch2_count_subdirs()
98 bkey_s_c_to_dirent(k).v->d_type == DT_DIR) in bch2_count_subdirs()
126 if (k.k->p.offset != inode_nr) in lookup_first_inode()
133 ret = -BCH_ERR_ENOENT_inode; in lookup_first_inode()
135 bch_err_msg(trans->c, ret, "fetching inode %llu", inode_nr); in lookup_first_inode()
155 : -BCH_ERR_ENOENT_inode; in lookup_inode()
174 *target = le64_to_cpu(d.v->d_inum); in lookup_dirent_in_snapshot()
175 *type = d.v->d_type; in lookup_dirent_in_snapshot()
182 struct bch_fs *c = trans->c; in __remove_dirent()
211 struct bch_fs *c = trans->c; in lookup_lostfound()
242 subvol->v.inode = cpu_to_le64(reattaching_inum); in lookup_lostfound()
269 return -BCH_ERR_ENOENT_not_directory; in lookup_lostfound()
300 lostfound->bi_dir = root_inode.bi_inum; in lookup_lostfound()
301 lostfound->bi_snapshot = le32_to_cpu(st.root_snapshot); in lookup_lostfound()
316 mode_to_type(lostfound->bi_mode), in lookup_lostfound()
318 lostfound->bi_inum, in lookup_lostfound()
319 &lostfound->bi_dir_offset, in lookup_lostfound()
331 if (inode->bi_inum == BCACHEFS_ROOT_INO && in inode_should_reattach()
332 inode->bi_subvol == BCACHEFS_ROOT_SUBVOL) in inode_should_reattach()
335 return !inode->bi_dir && !(inode->bi_flags & BCH_INODE_unlinked); in inode_should_reattach()
349 if (bpos_eq(k.k->p, d_pos)) { in maybe_delete_dirent()
359 bkey_init(&k->k); in maybe_delete_dirent()
360 k->k.type = KEY_TYPE_whiteout; in maybe_delete_dirent()
361 k->k.p = iter.pos; in maybe_delete_dirent()
371 struct bch_fs *c = trans->c; in reattach_inode()
376 u32 dirent_snapshot = inode->bi_snapshot; in reattach_inode()
377 if (inode->bi_subvol) { in reattach_inode()
378 inode->bi_parent_subvol = BCACHEFS_ROOT_SUBVOL; in reattach_inode()
381 ret = subvol_lookup(trans, inode->bi_parent_subvol, in reattach_inode()
386 snprintf(name_buf, sizeof(name_buf), "subvol-%u", inode->bi_subvol); in reattach_inode()
388 snprintf(name_buf, sizeof(name_buf), "%llu", inode->bi_inum); in reattach_inode()
391 ret = lookup_lostfound(trans, dirent_snapshot, &lostfound, inode->bi_inum); in reattach_inode()
395 lostfound.bi_nlink += S_ISDIR(inode->bi_mode); in reattach_inode()
398 if (!inode->bi_subvol) { in reattach_inode()
399 BUG_ON(!bch2_snapshot_is_ancestor(c, inode->bi_snapshot, lostfound.bi_snapshot)); in reattach_inode()
400 lostfound.bi_snapshot = inode->bi_snapshot; in reattach_inode()
410 inode->bi_dir = lostfound.bi_inum; in reattach_inode()
413 inode->bi_parent_subvol, lostfound.bi_inum, in reattach_inode()
418 inode->bi_subvol ?: inode->bi_inum, in reattach_inode()
419 &inode->bi_dir_offset, in reattach_inode()
435 if (!inode->bi_subvol && bch2_snapshot_is_leaf(c, inode->bi_snapshot) <= 0) { in reattach_inode()
443 BTREE_ID_inodes, SPOS(0, inode->bi_inum, inode->bi_snapshot - 1), in reattach_inode()
445 if (k.k->p.offset != inode->bi_inum) in reattach_inode()
449 !bch2_snapshot_is_ancestor(c, k.k->p.snapshot, inode->bi_snapshot) || in reattach_inode()
450 snapshot_list_has_ancestor(c, &whiteouts_done, k.k->p.snapshot)) in reattach_inode()
458 SPOS(lostfound.bi_inum, inode->bi_dir_offset, in reattach_inode()
460 k.k->p.snapshot); in reattach_inode()
464 ret = snapshot_list_add(c, &whiteouts_done, k.k->p.snapshot); in reattach_inode()
468 iter.snapshot = k.k->p.snapshot; in reattach_inode()
469 child_inode.bi_dir = inode->bi_dir; in reattach_inode()
470 child_inode.bi_dir_offset = inode->bi_dir_offset; in reattach_inode()
488 if (!inode->bi_dir) in remove_backpointer()
491 struct bch_fs *c = trans->c; in remove_backpointer()
495 SPOS(inode->bi_dir, inode->bi_dir_offset, inode->bi_snapshot), 0, in remove_backpointer()
499 __remove_dirent(trans, d.k->p); in remove_backpointer()
506 struct bch_fs *c = trans->c; in reattach_subvol()
510 (subvol_inum) { s.k->p.offset, le64_to_cpu(s.v->inode) }, in reattach_subvol()
528 struct bch_fs *c = trans->c; in reconstruct_subvol()
532 return -BCH_ERR_fsck_repair_unimplemented; in reconstruct_subvol()
537 * not check_inodes - the root of this subvolume doesn't exist or we in reconstruct_subvol()
567 bkey_subvolume_init(&new_subvol->k_i); in reconstruct_subvol()
568 new_subvol->k.p.offset = subvolid; in reconstruct_subvol()
569 new_subvol->v.snapshot = cpu_to_le32(snapshotid); in reconstruct_subvol()
570 new_subvol->v.inode = cpu_to_le64(inum); in reconstruct_subvol()
571 ret = bch2_btree_insert_trans(trans, BTREE_ID_subvolumes, &new_subvol->k_i, 0); in reconstruct_subvol()
584 u32 snapshot_tree = le32_to_cpu(s->v.tree); in reconstruct_subvol()
586 s->v.subvol = cpu_to_le32(subvolid); in reconstruct_subvol()
587 SET_BCH_SNAPSHOT_SUBVOL(&s->v, true); in reconstruct_subvol()
598 if (!st->v.master_subvol) in reconstruct_subvol()
599 st->v.master_subvol = cpu_to_le32(subvolid); in reconstruct_subvol()
607 struct bch_fs *c = trans->c; in reconstruct_inode()
622 i_size = k.k->p.offset << 9; in reconstruct_inode()
651 darray_exit(&s->ids); in snapshots_seen_exit()
662 __darray_for_each(s->ids, i) { in snapshots_seen_add_inorder()
669 int ret = darray_insert_item(&s->ids, i - s->ids.data, id); in snapshots_seen_add_inorder()
672 s->ids.size); in snapshots_seen_add_inorder()
679 if (!bkey_eq(s->pos, pos)) in snapshots_seen_update()
680 s->ids.nr = 0; in snapshots_seen_update()
681 s->pos = pos; in snapshots_seen_update()
683 return snapshot_list_add_nodup(c, &s->ids, pos.snapshot); in snapshots_seen_update()
687 * key_visible_in_snapshot - returns true if @id is a descendent of @ancestor,
705 EBUG_ON(ancestor != seen->pos.snapshot); in key_visible_in_snapshot()
706 EBUG_ON(ancestor != darray_last(seen->ids)); in key_visible_in_snapshot()
716 * we've seen a key that overwrote @ancestor - i.e. also a descendent of in key_visible_in_snapshot()
724 for (i = seen->ids.nr - 2; in key_visible_in_snapshot()
725 i >= 0 && seen->ids.data[i] >= id; in key_visible_in_snapshot()
726 --i) in key_visible_in_snapshot()
727 if (bch2_snapshot_is_ancestor(c, id, seen->ids.data[i])) in key_visible_in_snapshot()
734 * ref_visible - given a key with snapshot id @src that points to a key with
766 for (_i = (_w)->inodes.data; _i < (_w)->inodes.data + (_w)->inodes.nr && \
767 (_i)->snapshot <= (_snapshot); _i++) \
768 if (key_visible_in_snapshot(_c, _s, _i->snapshot, _snapshot))
787 darray_exit(&w->inodes); in inode_walker_exit()
802 return darray_push(&w->inodes, ((struct inode_walker_entry) { in add_inode()
804 .snapshot = inode.k->p.snapshot, in add_inode()
811 struct bch_fs *c = trans->c; in get_inodes_all_snapshots()
817 * We no longer have inodes for w->last_pos; clear this to avoid in get_inodes_all_snapshots()
821 w->have_inodes = false; in get_inodes_all_snapshots()
822 w->recalculate_sums = false; in get_inodes_all_snapshots()
823 w->inodes.nr = 0; in get_inodes_all_snapshots()
827 if (k.k->p.offset != inum) in get_inodes_all_snapshots()
838 w->first_this_inode = true; in get_inodes_all_snapshots()
839 w->have_inodes = true; in get_inodes_all_snapshots()
846 bool is_whiteout = k.k->type == KEY_TYPE_whiteout; in lookup_inode_for_snapshot()
849 __darray_for_each(w->inodes, i) in lookup_inode_for_snapshot()
850 if (bch2_snapshot_is_ancestor(c, k.k->p.snapshot, i->snapshot)) in lookup_inode_for_snapshot()
855 BUG_ON(k.k->p.snapshot > i->snapshot); in lookup_inode_for_snapshot()
857 if (k.k->p.snapshot != i->snapshot && !is_whiteout) { in lookup_inode_for_snapshot()
860 new.snapshot = k.k->p.snapshot; in lookup_inode_for_snapshot()
869 w->last_pos.inode, k.k->p.snapshot, i->snapshot, buf.buf); in lookup_inode_for_snapshot()
872 while (i > w->inodes.data && i[-1].snapshot > k.k->p.snapshot) in lookup_inode_for_snapshot()
873 --i; in lookup_inode_for_snapshot()
875 size_t pos = i - w->inodes.data; in lookup_inode_for_snapshot()
876 int ret = darray_insert_item(&w->inodes, pos, new); in lookup_inode_for_snapshot()
880 i = w->inodes.data + pos; in lookup_inode_for_snapshot()
890 if (w->last_pos.inode != k.k->p.inode) { in walk_inode()
891 int ret = get_inodes_all_snapshots(trans, w, k.k->p.inode); in walk_inode()
896 w->last_pos = k.k->p; in walk_inode()
898 return lookup_inode_for_snapshot(trans->c, w, k); in walk_inode()
906 struct bch_fs *c = trans->c; in get_visible_inodes()
911 w->inodes.nr = 0; in get_visible_inodes()
915 if (k.k->p.offset != inum) in get_visible_inodes()
918 if (!ref_visible(c, s, s->pos.snapshot, k.k->p.snapshot)) in get_visible_inodes()
924 if (k.k->p.snapshot >= s->pos.snapshot) in get_visible_inodes()
934 if (d.v->d_type == DT_SUBVOL) { in dirent_has_target()
937 int ret = subvol_lookup(trans, le32_to_cpu(d.v->d_child_subvol), &snap, &inum); in dirent_has_target()
944 SPOS(0, le64_to_cpu(d.v->d_inum), d.k->p.snapshot), 0); in dirent_has_target()
958 * return value: 0 -> delete k1, 1 -> delete k2
996 if (new->k.type != KEY_TYPE_dirent) in fsck_update_backpointers()
1003 if (d->v.d_type == DT_SUBVOL) { in fsck_update_backpointers()
1006 ret = get_visible_inodes(trans, &target, s, le64_to_cpu(d->v.d_inum)); in fsck_update_backpointers()
1011 i->inode.bi_dir_offset = d->k.p.offset; in fsck_update_backpointers()
1012 ret = __bch2_fsck_write_inode(trans, &i->inode); in fsck_update_backpointers()
1034 bkey_dirent_init(&new->k_i); in fsck_rename_dirent()
1036 new->k.p = old.k->p; in fsck_rename_dirent()
1039 unsigned len = sprintf(new->v.d_name, "%.*s.fsck_renamed-%u", in fsck_rename_dirent()
1044 return -EINVAL; in fsck_rename_dirent()
1046 new->k.u64s = u64s; in fsck_rename_dirent()
1049 (subvol_inum) { 0, old.k->p.inode }, in fsck_rename_dirent()
1050 old.k->p.snapshot, &new->k_i, in fsck_rename_dirent()
1059 return fsck_update_backpointers(trans, s, desc, hash_info, &new->k_i); in fsck_rename_dirent()
1068 struct bch_fs *c = trans->c; in hash_check_key()
1075 if (hash_k.k->type != desc.key_type) in hash_check_key()
1080 if (likely(hash == hash_k.k->p.offset)) in hash_check_key()
1083 if (hash_k.k->p.offset < hash) in hash_check_key()
1087 SPOS(hash_k.k->p.inode, hash, hash_k.k->p.snapshot), in hash_check_key()
1089 if (bkey_eq(k.k->p, hash_k.k->p)) in hash_check_key()
1092 if (k.k->type == desc.key_type && in hash_check_key()
1108 bch2_btree_id_str(desc.btree_id), hash_k.k->p.inode, hash_k.k->p.offset, hash, in hash_check_key()
1116 (subvol_inum) { 0, hash_k.k->p.inode }, in hash_check_key()
1117 hash_k.k->p.snapshot, new, in hash_check_key()
1131 -BCH_ERR_transaction_restart_nested; in hash_check_key()
1165 -BCH_ERR_transaction_restart_nested; in hash_check_key()
1181 if (inode->bi_subvol) { in inode_get_dirent()
1183 int ret = subvol_lookup(trans, inode->bi_parent_subvol, snapshot, &inum); in inode_get_dirent()
1188 return dirent_get_by_pos(trans, iter, SPOS(inode->bi_dir, inode->bi_dir_offset, *snapshot)); in inode_get_dirent()
1195 int ret = bkey_err(k) ?: k.k->type == KEY_TYPE_set; in check_inode_deleted_list()
1204 struct bch_fs *c = trans->c; in check_inode_dirent_inode()
1207 u32 inode_snapshot = inode->bi_snapshot; in check_inode_dirent_inode()
1230 inode->bi_dir = 0; in check_inode_dirent_inode()
1231 inode->bi_dir_offset = 0; in check_inode_dirent_inode()
1254 if (k.k->p.offset != inum) in get_snapshot_root_inode()
1275 struct bch_fs *c = trans->c; in check_inode()
1287 ret = snapshots_seen_update(c, s, iter->btree_id, k.k->p); in check_inode()
1296 if (snapshot_root->bi_inum != u.bi_inum) { in check_inode()
1302 if (fsck_err_on(u.bi_hash_seed != snapshot_root->bi_hash_seed || in check_inode()
1306 u.bi_hash_seed = snapshot_root->bi_hash_seed; in check_inode()
1330 ret = bch2_empty_dir_snapshot(trans, k.k->p.offset, 0, k.k->p.snapshot); in check_inode()
1331 if (ret && ret != -BCH_ERR_ENOTEMPTY_dir_not_empty) in check_inode()
1344 ret = bch2_inode_has_child_snapshots(trans, k.k->p); in check_inode()
1365 if (!test_bit(BCH_FS_started, &c->flags)) { in check_inode()
1370 * They might be referred to by a logged operation - in check_inode()
1372 * truncate on an unlinked but open file - so we want to in check_inode()
1376 ret = check_inode_deleted_list(trans, k.k->p); in check_inode()
1383 u.bi_inum, k.k->p.snapshot); in check_inode()
1385 ret = bch2_btree_bit_mod_buffered(trans, BTREE_ID_deleted_inodes, k.k->p, 1); in check_inode()
1389 ret = bch2_inode_or_descendents_is_open(trans, k.k->p); in check_inode()
1397 ret = bch2_inode_rm_snapshot(trans, u.bi_inum, iter->pos.snapshot); in check_inode()
1410 u.bi_inum, k.k->p.snapshot, u.bi_subvol, u.bi_parent_subvol)) { in check_inode()
1422 if (ret && (c->sb.btrees_lost_data & BIT_ULL(BTREE_ID_subvolumes))) { in check_inode()
1423 ret = reconstruct_subvol(trans, k.k->p.snapshot, u.bi_subvol, u.bi_inum); in check_inode()
1430 u.bi_inum, k.k->p.snapshot, u.bi_subvol) || in check_inode()
1433 k.k->p.snapshot), in check_inode()
1436 u.bi_inum, k.k->p.snapshot, u.bi_subvol, in check_inode()
1481 struct bch_fs *c = trans->c; in find_oldest_inode_needs_reattach()
1493 SPOS(0, inode->bi_inum, inode->bi_snapshot + 1), in find_oldest_inode_needs_reattach()
1495 if (k.k->p.offset != inode->bi_inum) in find_oldest_inode_needs_reattach()
1498 if (!bch2_snapshot_is_ancestor(c, inode->bi_snapshot, k.k->p.snapshot)) in find_oldest_inode_needs_reattach()
1552 * that points to it has its backpointer field set - so we're just looking for
1553 * non-unlinked inodes without backpointers:
1589 struct bch_fs *c = trans->c; in check_key_has_inode()
1595 if (k.k->type == KEY_TYPE_whiteout) in check_key_has_inode()
1598 if (!i && (c->sb.btrees_lost_data & BIT_ULL(BTREE_ID_inodes))) { in check_key_has_inode()
1599 ret = reconstruct_inode(trans, iter->btree_id, k.k->p.snapshot, k.k->p.inode) ?: in check_key_has_inode()
1604 inode->last_pos.inode--; in check_key_has_inode()
1605 ret = -BCH_ERR_transaction_restart_nested; in check_key_has_inode()
1616 if (fsck_err_on(i && !btree_matches_i_mode(iter->btree_id, i->inode.bi_mode), in check_key_has_inode()
1619 i->inode.bi_mode, in check_key_has_inode()
1636 struct bch_fs *c = trans->c; in check_i_sectors_notnested()
1640 darray_for_each(w->inodes, i) { in check_i_sectors_notnested()
1641 if (i->inode.bi_sectors == i->count) in check_i_sectors_notnested()
1644 count2 = bch2_count_inode_sectors(trans, w->last_pos.inode, i->snapshot); in check_i_sectors_notnested()
1646 if (w->recalculate_sums) in check_i_sectors_notnested()
1647 i->count = count2; in check_i_sectors_notnested()
1649 if (i->count != count2) { in check_i_sectors_notnested()
1651 w->last_pos.inode, i->snapshot, i->count, count2); in check_i_sectors_notnested()
1652 return -BCH_ERR_internal_fsck_err; in check_i_sectors_notnested()
1655 if (fsck_err_on(!(i->inode.bi_flags & BCH_INODE_i_sectors_dirty), in check_i_sectors_notnested()
1658 w->last_pos.inode, i->snapshot, in check_i_sectors_notnested()
1659 i->inode.bi_sectors, i->count)) { in check_i_sectors_notnested()
1660 i->inode.bi_sectors = i->count; in check_i_sectors_notnested()
1661 ret = bch2_fsck_write_inode(trans, &i->inode); in check_i_sectors_notnested()
1673 u32 restart_count = trans->restart_count; in check_i_sectors()
1691 darray_for_each(extent_ends->e, i) in extent_ends_reset()
1692 snapshots_seen_exit(&i->seen); in extent_ends_reset()
1693 extent_ends->e.nr = 0; in extent_ends_reset()
1699 darray_exit(&extent_ends->e); in extent_ends_exit()
1713 .offset = k.k->p.offset, in extent_ends_at()
1714 .snapshot = k.k->p.snapshot, in extent_ends_at()
1718 n.seen.ids.data = kmemdup(seen->ids.data, in extent_ends_at()
1719 sizeof(seen->ids.data[0]) * seen->ids.size, in extent_ends_at()
1722 return -BCH_ERR_ENOMEM_fsck_extent_ends_at; in extent_ends_at()
1724 __darray_for_each(extent_ends->e, i) { in extent_ends_at()
1725 if (i->snapshot == k.k->p.snapshot) { in extent_ends_at()
1726 snapshots_seen_exit(&i->seen); in extent_ends_at()
1731 if (i->snapshot >= k.k->p.snapshot) in extent_ends_at()
1735 return darray_insert_item(&extent_ends->e, i - extent_ends->e.data, n); in extent_ends_at()
1742 bool *fixed, in overlapping_extents_found() argument
1745 struct bch_fs *c = trans->c; in overlapping_extents_found()
1764 if (!bpos_eq(pos1, k1.k->p)) { in overlapping_extents_found()
1772 ret = -BCH_ERR_internal_fsck_err; in overlapping_extents_found()
1786 if (bpos_ge(k2.k->p, pos2.p)) in overlapping_extents_found()
1793 if (bpos_gt(k2.k->p, pos2.p) || in overlapping_extents_found()
1794 pos2.size != k2.k->size) { in overlapping_extents_found()
1797 ret = -BCH_ERR_internal_fsck_err; in overlapping_extents_found()
1814 trans->extra_disk_res += bch2_bkey_sectors_compressed(k2); in overlapping_extents_found()
1825 *fixed = true; in overlapping_extents_found()
1832 extent_end->offset = bkey_start_offset(&pos2); in overlapping_extents_found()
1840 * We overwrote the second extent - restart in overlapping_extents_found()
1843 ret = -BCH_ERR_transaction_restart_nested; in overlapping_extents_found()
1859 bool *fixed) in check_overlapping_extents() argument
1861 struct bch_fs *c = trans->c; in check_overlapping_extents()
1865 if (bpos_eq(extent_ends->last_pos, k.k->p)) in check_overlapping_extents()
1868 if (extent_ends->last_pos.inode != k.k->p.inode) in check_overlapping_extents()
1871 darray_for_each(extent_ends->e, i) { in check_overlapping_extents()
1872 if (i->offset <= bkey_start_offset(k.k)) in check_overlapping_extents()
1876 k.k->p.snapshot, seen, in check_overlapping_extents()
1877 i->snapshot, &i->seen)) in check_overlapping_extents()
1880 ret = overlapping_extents_found(trans, iter->btree_id, in check_overlapping_extents()
1881 SPOS(iter->pos.inode, in check_overlapping_extents()
1882 i->offset, in check_overlapping_extents()
1883 i->snapshot), in check_overlapping_extents()
1884 &i->seen, in check_overlapping_extents()
1885 *k.k, fixed, i); in check_overlapping_extents()
1890 extent_ends->last_pos = k.k->p; in check_overlapping_extents()
1898 struct bch_fs *c = trans->c; in check_extent_overbig()
1902 unsigned encoded_extent_max_sectors = c->opts.encoded_extent_max >> 9; in check_extent_overbig()
1924 struct bch_fs *c = trans->c; in check_extent()
1934 if (inode->last_pos.inode != k.k->p.inode && inode->have_inodes) { in check_extent()
1940 ret = snapshots_seen_update(c, s, iter->btree_id, k.k->p); in check_extent()
1953 if (k.k->type != KEY_TYPE_whiteout) { in check_extent()
1955 &inode->recalculate_sums); in check_extent()
1964 for (struct inode_walker_entry *i = extent_i ?: &darray_last(inode->inodes); in check_extent()
1965 inode->inodes.data && i >= inode->inodes.data; in check_extent()
1966 --i) { in check_extent()
1967 if (i->snapshot > k.k->p.snapshot || in check_extent()
1968 !key_visible_in_snapshot(c, s, i->snapshot, k.k->p.snapshot)) in check_extent()
1971 if (fsck_err_on(k.k->p.offset > round_up(i->inode.bi_size, block_bytes(c)) >> 9 && in check_extent()
1975 i->inode.bi_inum, i->snapshot, i->inode.bi_size, in check_extent()
1980 bch2_btree_iter_set_snapshot(&iter2, i->snapshot); in check_extent()
1988 iter->k.type = KEY_TYPE_whiteout; in check_extent()
1999 for (struct inode_walker_entry *i = extent_i ?: &darray_last(inode->inodes); in check_extent()
2000 inode->inodes.data && i >= inode->inodes.data; in check_extent()
2001 --i) { in check_extent()
2002 if (i->snapshot > k.k->p.snapshot || in check_extent()
2003 !key_visible_in_snapshot(c, s, i->snapshot, k.k->p.snapshot)) in check_extent()
2006 i->count += k.k->size; in check_extent()
2010 if (k.k->type != KEY_TYPE_whiteout) { in check_extent()
2077 struct bch_fs *c = trans->c; in check_subdir_count_notnested()
2081 darray_for_each(w->inodes, i) { in check_subdir_count_notnested()
2082 if (i->inode.bi_nlink == i->count) in check_subdir_count_notnested()
2085 count2 = bch2_count_subdirs(trans, w->last_pos.inode, i->snapshot); in check_subdir_count_notnested()
2089 if (i->count != count2) { in check_subdir_count_notnested()
2091 w->last_pos.inode, i->snapshot, i->count, count2); in check_subdir_count_notnested()
2092 i->count = count2; in check_subdir_count_notnested()
2093 if (i->inode.bi_nlink == i->count) in check_subdir_count_notnested()
2097 if (fsck_err_on(i->inode.bi_nlink != i->count, in check_subdir_count_notnested()
2100 w->last_pos.inode, i->snapshot, i->inode.bi_nlink, i->count)) { in check_subdir_count_notnested()
2101 i->inode.bi_nlink = i->count; in check_subdir_count_notnested()
2102 ret = bch2_fsck_write_inode(trans, &i->inode); in check_subdir_count_notnested()
2114 u32 restart_count = trans->restart_count; in check_subdir_count()
2125 struct bch_fs *c = trans->c; in check_dirent_inode_dirent()
2133 if (!target->bi_dir && in check_dirent_inode_dirent()
2134 !target->bi_dir_offset) { in check_dirent_inode_dirent()
2135 fsck_err_on(S_ISDIR(target->bi_mode), in check_dirent_inode_dirent()
2144 fsck_err_on(target->bi_flags & BCH_INODE_unlinked, in check_dirent_inode_dirent()
2153 target->bi_flags &= ~BCH_INODE_unlinked; in check_dirent_inode_dirent()
2154 target->bi_dir = d.k->p.inode; in check_dirent_inode_dirent()
2155 target->bi_dir_offset = d.k->p.offset; in check_dirent_inode_dirent()
2169 SPOS(target->bi_dir, target->bi_dir_offset, target->bi_snapshot)); in check_dirent_inode_dirent()
2182 target->bi_inum, target->bi_snapshot, in check_dirent_inode_dirent()
2183 target->bi_dir, in check_dirent_inode_dirent()
2184 target->bi_dir_offset, in check_dirent_inode_dirent()
2185 d.k->p.inode, in check_dirent_inode_dirent()
2186 d.k->p.offset)) { in check_dirent_inode_dirent()
2187 target->bi_dir = d.k->p.inode; in check_dirent_inode_dirent()
2188 target->bi_dir_offset = d.k->p.offset; in check_dirent_inode_dirent()
2199 (S_ISDIR(target->bi_mode) || in check_dirent_inode_dirent()
2200 target->bi_subvol), in check_dirent_inode_dirent()
2202 "%s %llu:%u with multiple links\n%s", in check_dirent_inode_dirent()
2203 S_ISDIR(target->bi_mode) ? "directory" : "subvolume", in check_dirent_inode_dirent()
2204 target->bi_inum, target->bi_snapshot, buf.buf)) { in check_dirent_inode_dirent()
2205 ret = __remove_dirent(trans, d.k->p); in check_dirent_inode_dirent()
2214 if (fsck_err_on(backpointer_exists && !target->bi_nlink, in check_dirent_inode_dirent()
2216 "inode %llu:%u type %s has multiple links but i_nlink 0\n%s", in check_dirent_inode_dirent()
2217 target->bi_inum, target->bi_snapshot, bch2_d_types[d.v->d_type], buf.buf)) { in check_dirent_inode_dirent()
2218 target->bi_nlink++; in check_dirent_inode_dirent()
2219 target->bi_flags &= ~BCH_INODE_unlinked; in check_dirent_inode_dirent()
2239 struct bch_fs *c = trans->c; in check_dirent_target()
2248 if (fsck_err_on(d.v->d_type != inode_d_type(target), in check_dirent_target()
2251 bch2_d_type_str(d.v->d_type), in check_dirent_target()
2260 bkey_reassemble(&n->k_i, d.s_c); in check_dirent_target()
2261 n->v.d_type = inode_d_type(target); in check_dirent_target()
2262 if (n->v.d_type == DT_SUBVOL) { in check_dirent_target()
2263 n->v.d_parent_subvol = cpu_to_le32(target->bi_parent_subvol); in check_dirent_target()
2264 n->v.d_child_subvol = cpu_to_le32(target->bi_subvol); in check_dirent_target()
2266 n->v.d_inum = cpu_to_le64(target->bi_inum); in check_dirent_target()
2269 ret = bch2_trans_update(trans, iter, &n->k_i, 0); in check_dirent_target()
2290 if (k.k->type != KEY_TYPE_subvolume) in find_snapshot_subvol()
2294 if (bch2_snapshot_is_ancestor(trans->c, le32_to_cpu(s.v->snapshot), snapshot)) { in find_snapshot_subvol()
2296 *subvolid = k.k->p.offset; in find_snapshot_subvol()
2301 ret = -ENOENT; in find_snapshot_subvol()
2311 struct bch_fs *c = trans->c; in check_dirent_to_subvol()
2314 u32 parent_subvol = le32_to_cpu(d.v->d_parent_subvol); in check_dirent_to_subvol()
2315 u32 target_subvol = le32_to_cpu(d.v->d_child_subvol); in check_dirent_to_subvol()
2327 (!ret && !bch2_snapshot_is_ancestor(c, parent_snapshot, d.k->p.snapshot))) { in check_dirent_to_subvol()
2328 int ret2 = find_snapshot_subvol(trans, d.k->p.snapshot, &new_parent_subvol); in check_dirent_to_subvol()
2335 (c->sb.btrees_lost_data & BIT_ULL(BTREE_ID_subvolumes))) { in check_dirent_to_subvol()
2337 * Couldn't find a subvol for dirent's snapshot - but we lost in check_dirent_to_subvol()
2340 ret = reconstruct_subvol(trans, d.k->p.snapshot, parent_subvol, 0); in check_dirent_to_subvol()
2344 parent_snapshot = d.k->p.snapshot; in check_dirent_to_subvol()
2351 fsck_err_on(!ret && !bch2_snapshot_is_ancestor(c, parent_snapshot, d.k->p.snapshot), in check_dirent_to_subvol()
2357 bch_err(c, "could not find a subvol for snapshot %u", d.k->p.snapshot); in check_dirent_to_subvol()
2358 return -BCH_ERR_fsck_repair_unimplemented; in check_dirent_to_subvol()
2366 new_dirent->v.d_parent_subvol = cpu_to_le32(new_parent_subvol); in check_dirent_to_subvol()
2381 return __remove_dirent(trans, d.k->p); in check_dirent_to_subvol()
2386 if (fsck_err_on(le32_to_cpu(s.v->fs_path_parent) != parent_subvol, in check_dirent_to_subvol()
2397 n->v.fs_path_parent = cpu_to_le32(parent_subvol); in check_dirent_to_subvol()
2400 u64 target_inum = le64_to_cpu(s.v->inode); in check_dirent_to_subvol()
2401 u32 target_snapshot = le32_to_cpu(s.v->snapshot); in check_dirent_to_subvol()
2409 ret = -BCH_ERR_fsck_repair_unimplemented; in check_dirent_to_subvol()
2419 subvol_root.bi_snapshot = le32_to_cpu(s.v->snapshot); in check_dirent_to_subvol()
2443 struct bch_fs *c = trans->c; in check_dirent()
2454 ret = snapshots_seen_update(c, s, iter->btree_id, k.k->p); in check_dirent()
2458 if (k.k->type == KEY_TYPE_whiteout) in check_dirent()
2461 if (dir->last_pos.inode != k.k->p.inode && dir->have_inodes) { in check_dirent()
2479 if (dir->first_this_inode) in check_dirent()
2480 *hash_info = bch2_hash_info_init(c, &i->inode); in check_dirent()
2481 dir->first_this_inode = false; in check_dirent()
2492 if (k.k->type != KEY_TYPE_dirent) in check_dirent()
2497 if (d.v->d_type == DT_SUBVOL) { in check_dirent()
2502 ret = get_visible_inodes(trans, target, s, le64_to_cpu(d.v->d_inum)); in check_dirent()
2506 if (fsck_err_on(!target->inodes.nr, in check_dirent()
2512 ret = __remove_dirent(trans, d.k->p); in check_dirent()
2517 darray_for_each(target->inodes, i) { in check_dirent()
2518 ret = check_dirent_target(trans, iter, d, &i->inode); in check_dirent()
2528 if (d.v->d_type == DT_DIR) in check_dirent()
2529 for_each_visible_inode(c, s, dir, d.k->p.snapshot, i) in check_dirent()
2530 i->count++; in check_dirent()
2571 struct bch_fs *c = trans->c; in check_xattr()
2593 if (inode->first_this_inode) in check_xattr()
2594 *hash_info = bch2_hash_info_init(c, &i->inode); in check_xattr()
2595 inode->first_this_inode = false; in check_xattr()
2627 struct bch_fs *c = trans->c; in check_root_trans()
2648 bkey_subvolume_init(&root_subvol->k_i); in check_root_trans()
2649 root_subvol->k.p.offset = BCACHEFS_ROOT_SUBVOL; in check_root_trans()
2650 root_subvol->v.flags = 0; in check_root_trans()
2651 root_subvol->v.snapshot = cpu_to_le32(snapshot); in check_root_trans()
2652 root_subvol->v.inode = cpu_to_le64(inum); in check_root_trans()
2653 ret = bch2_btree_insert_trans(trans, BTREE_ID_subvolumes, &root_subvol->k_i, 0); in check_root_trans()
2703 struct bch_fs *c = trans->c; in check_subvol_path()
2709 if (k.k->type != KEY_TYPE_subvolume) in check_subvol_path()
2712 while (k.k->p.offset != BCACHEFS_ROOT_SUBVOL) { in check_subvol_path()
2713 ret = darray_push(&subvol_path, k.k->p.offset); in check_subvol_path()
2721 (subvol_inum) { s.k->p.offset, le64_to_cpu(s.v->inode) }, in check_subvol_path()
2726 u32 parent = le32_to_cpu(s.v->fs_path_parent); in check_subvol_path()
2742 if (fsck_err_on(k.k->type != KEY_TYPE_subvolume, in check_subvol_path()
2780 if (i->inum == inum && in path_is_dup()
2781 i->snapshot == snapshot) in path_is_dup()
2788 struct bch_fs *c = trans->c; in check_path()
2792 u32 snapshot = inode_k.k->p.snapshot; in check_path()
2795 p->nr = 0; in check_path()
2838 !bkey_is_inode(inode_k.k) ? -BCH_ERR_ENOENT_inode in check_path()
2846 snapshot = inode_k.k->p.snapshot; in check_path()
2853 pr_err("%llu:%u", i->inum, i->snapshot); in check_path()
2878 * have been fixed by prior passes
2919 if (t->nr == t->size) { in add_nlink()
2920 size_t new_size = max_t(size_t, 128UL, t->size * 2); in add_nlink()
2921 void *d = kvmalloc_array(new_size, sizeof(t->d[0]), GFP_KERNEL); in add_nlink()
2926 return -BCH_ERR_ENOMEM_fsck_add_nlink; in add_nlink()
2929 if (t->d) in add_nlink()
2930 memcpy(d, t->d, t->size * sizeof(t->d[0])); in add_nlink()
2931 kvfree(t->d); in add_nlink()
2933 t->d = d; in add_nlink()
2934 t->size = new_size; in add_nlink()
2938 t->d[t->nr++] = (struct nlink) { in add_nlink()
2951 return cmp_int(l->inum, r->inum); in nlink_cmp()
2955 struct nlink_table *links, in inc_link() argument
2965 link = __inline_bsearch(&key, links->d, links->nr, in inc_link()
2966 sizeof(links->d[0]), nlink_cmp); in inc_link()
2970 while (link > links->d && link[0].inum == link[-1].inum) in inc_link()
2971 --link; in inc_link()
2973 for (; link < links->d + links->nr && link->inum == inum; link++) in inc_link()
2974 if (ref_visible(c, s, snapshot, link->snapshot)) { in inc_link()
2975 link->count++; in inc_link()
2976 if (link->snapshot >= snapshot) in inc_link()
3013 ret = add_nlink(c, t, k.k->p.offset, k.k->p.snapshot); in check_nlinks_find_hardlinks()
3015 *end = k.k->p.offset; in check_nlinks_find_hardlinks()
3027 static int check_nlinks_walk_dirents(struct bch_fs *c, struct nlink_table *links, in check_nlinks_walk_dirents() argument
3039 ret = snapshots_seen_update(c, &s, iter.btree_id, k.k->p); in check_nlinks_walk_dirents()
3043 if (k.k->type == KEY_TYPE_dirent) { in check_nlinks_walk_dirents()
3046 if (d.v->d_type != DT_DIR && in check_nlinks_walk_dirents()
3047 d.v->d_type != DT_SUBVOL) in check_nlinks_walk_dirents()
3048 inc_link(c, &s, links, range_start, range_end, in check_nlinks_walk_dirents()
3049 le64_to_cpu(d.v->d_inum), d.k->p.snapshot); in check_nlinks_walk_dirents()
3062 struct nlink_table *links, in check_nlinks_update_inode() argument
3066 struct nlink *link = &links->d[*idx]; in check_nlinks_update_inode()
3069 if (k.k->p.offset >= range_end) in check_nlinks_update_inode()
3083 while ((cmp_int(link->inum, k.k->p.offset) ?: in check_nlinks_update_inode()
3084 cmp_int(link->snapshot, k.k->p.snapshot)) < 0) { in check_nlinks_update_inode()
3085 BUG_ON(*idx == links->nr); in check_nlinks_update_inode()
3086 link = &links->d[++*idx]; in check_nlinks_update_inode()
3089 if (fsck_err_on(bch2_inode_nlink_get(&u) != link->count, in check_nlinks_update_inode()
3093 bch2_inode_nlink_get(&u), link->count)) { in check_nlinks_update_inode()
3094 bch2_inode_nlink_set(&u, link->count); in check_nlinks_update_inode()
3103 struct nlink_table *links, in check_nlinks_update_hardlinks() argument
3113 check_nlinks_update_inode(trans, &iter, k, links, &idx, range_end))); in check_nlinks_update_hardlinks()
3124 struct nlink_table links = { 0 }; in bch2_check_nlinks() local
3132 ret = check_nlinks_find_hardlinks(c, &links, in bch2_check_nlinks()
3136 ret = check_nlinks_walk_dirents(c, &links, in bch2_check_nlinks()
3142 ret = check_nlinks_update_hardlinks(c, &links, in bch2_check_nlinks()
3148 links.nr = 0; in bch2_check_nlinks()
3151 kvfree(links.d); in bch2_check_nlinks()
3162 if (k.k->type != KEY_TYPE_reflink_p) in fix_reflink_p_key()
3167 if (!p.v->front_pad && !p.v->back_pad) in fix_reflink_p_key()
3175 bkey_reassemble(&u->k_i, k); in fix_reflink_p_key()
3176 u->v.front_pad = 0; in fix_reflink_p_key()
3177 u->v.back_pad = 0; in fix_reflink_p_key()
3179 return bch2_trans_update(trans, iter, &u->k_i, BTREE_TRIGGER_norun); in fix_reflink_p_key()
3184 if (c->sb.version >= bcachefs_metadata_version_reflink_p_fix) in bch2_fix_reflink_p()