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

1 // SPDX-License-Identifier: GPL-2.0
29 if (d.v->d_type == DT_SUBVOL in dirent_points_to_inode_nowarn()
30 ? le32_to_cpu(d.v->d_child_subvol) == inode->bi_subvol in dirent_points_to_inode_nowarn()
31 : le64_to_cpu(d.v->d_inum) == inode->bi_inum) in dirent_points_to_inode_nowarn()
33 return -BCH_ERR_ENOENT_dirent_doesnt_match_inode; in dirent_points_to_inode_nowarn()
64 * -BCH_ERR_transaction_restart_nested, this is not how we do things anymore:
76 sectors += k.k->size; in bch2_count_inode_sectors()
92 if (k.k->type == KEY_TYPE_dirent && in bch2_count_subdirs()
93 bkey_s_c_to_dirent(k).v->d_type == DT_DIR) in bch2_count_subdirs()
127 : -BCH_ERR_ENOENT_inode; in lookup_inode()
146 *target = le64_to_cpu(d.v->d_inum); in lookup_dirent_in_snapshot()
147 *type = d.v->d_type; in lookup_dirent_in_snapshot()
154 * We can't rely on master_subvol - it might have been deleted.
164 if (k.k->type != KEY_TYPE_snapshot) in find_snapshot_tree_subvol()
168 if (le32_to_cpu(s.v->tree) != tree_id) in find_snapshot_tree_subvol()
171 if (s.v->subvol) { in find_snapshot_tree_subvol()
172 *subvol = le32_to_cpu(s.v->subvol); in find_snapshot_tree_subvol()
176 ret = -BCH_ERR_ENOENT_no_snapshot_tree_subvol; in find_snapshot_tree_subvol()
187 struct bch_fs *c = trans->c; in lookup_lostfound()
223 subvol->v.inode = cpu_to_le64(reattaching_inum); in lookup_lostfound()
253 return -BCH_ERR_ENOENT_not_directory; in lookup_lostfound()
289 lostfound->bi_dir = root_inode.bi_inum; in lookup_lostfound()
290 lostfound->bi_snapshot = le32_to_cpu(st.root_snapshot); in lookup_lostfound()
305 mode_to_type(lostfound->bi_mode), in lookup_lostfound()
307 lostfound->bi_inum, in lookup_lostfound()
308 &lostfound->bi_dir_offset, in lookup_lostfound()
321 if (inode->bi_inum == BCACHEFS_ROOT_INO && in inode_should_reattach()
322 inode->bi_subvol == BCACHEFS_ROOT_SUBVOL) in inode_should_reattach()
334 * the parent subvolume - versioning is not needed - and keeping them in inode_should_reattach()
336 * don't have a consistent snapshot ID to do check the inode <-> dirent in inode_should_reattach()
340 * a disconnected older version - that's expected. in inode_should_reattach()
346 if (inode->bi_subvol && in inode_should_reattach()
347 (inode->bi_flags & BCH_INODE_has_child_snapshot)) in inode_should_reattach()
350 return !inode->bi_dir && !(inode->bi_flags & BCH_INODE_unlinked); in inode_should_reattach()
364 if (bpos_eq(k.k->p, d_pos)) { in maybe_delete_dirent()
374 bkey_init(&k->k); in maybe_delete_dirent()
375 k->k.type = KEY_TYPE_whiteout; in maybe_delete_dirent()
376 k->k.p = iter.pos; in maybe_delete_dirent()
386 struct bch_fs *c = trans->c; in reattach_inode()
391 u32 dirent_snapshot = inode->bi_snapshot; in reattach_inode()
392 if (inode->bi_subvol) { in reattach_inode()
393 inode->bi_parent_subvol = BCACHEFS_ROOT_SUBVOL; in reattach_inode()
396 ret = subvol_lookup(trans, inode->bi_parent_subvol, in reattach_inode()
401 snprintf(name_buf, sizeof(name_buf), "subvol-%u", inode->bi_subvol); in reattach_inode()
403 snprintf(name_buf, sizeof(name_buf), "%llu", inode->bi_inum); in reattach_inode()
406 ret = lookup_lostfound(trans, dirent_snapshot, &lostfound, inode->bi_inum); in reattach_inode()
410 lostfound.bi_nlink += S_ISDIR(inode->bi_mode); in reattach_inode()
413 if (!inode->bi_subvol) { in reattach_inode()
414 BUG_ON(!bch2_snapshot_is_ancestor(c, inode->bi_snapshot, lostfound.bi_snapshot)); in reattach_inode()
415 lostfound.bi_snapshot = inode->bi_snapshot; in reattach_inode()
425 inode->bi_dir = lostfound.bi_inum; in reattach_inode()
428 inode->bi_parent_subvol, lostfound.bi_inum, in reattach_inode()
433 inode->bi_subvol ?: inode->bi_inum, in reattach_inode()
434 &inode->bi_dir_offset, in reattach_inode()
451 if (!inode->bi_subvol && bch2_snapshot_is_leaf(c, inode->bi_snapshot) <= 0) { in reattach_inode()
459 BTREE_ID_inodes, SPOS(0, inode->bi_inum, inode->bi_snapshot - 1), in reattach_inode()
461 if (k.k->p.offset != inode->bi_inum) in reattach_inode()
465 !bch2_snapshot_is_ancestor(c, k.k->p.snapshot, inode->bi_snapshot) || in reattach_inode()
466 snapshot_list_has_ancestor(c, &whiteouts_done, k.k->p.snapshot)) in reattach_inode()
476 SPOS(lostfound.bi_inum, inode->bi_dir_offset, in reattach_inode()
478 k.k->p.snapshot); in reattach_inode()
482 ret = snapshot_list_add(c, &whiteouts_done, k.k->p.snapshot); in reattach_inode()
486 iter.snapshot = k.k->p.snapshot; in reattach_inode()
487 child_inode.bi_dir = inode->bi_dir; in reattach_inode()
488 child_inode.bi_dir_offset = inode->bi_dir_offset; in reattach_inode()
513 if (!inode->bi_dir) in remove_backpointer()
516 struct bch_fs *c = trans->c; in remove_backpointer()
519 SPOS(inode->bi_dir, inode->bi_dir_offset, inode->bi_snapshot)); in remove_backpointer()
522 bch2_fsck_remove_dirent(trans, d.k->p); in remove_backpointer()
529 struct bch_fs *c = trans->c; in reattach_subvol()
533 (subvol_inum) { s.k->p.offset, le64_to_cpu(s.v->inode) }, in reattach_subvol()
551 struct bch_fs *c = trans->c; in reconstruct_subvol()
555 return -BCH_ERR_fsck_repair_unimplemented; in reconstruct_subvol()
560 * not check_inodes - the root of this subvolume doesn't exist or we in reconstruct_subvol()
590 bkey_subvolume_init(&new_subvol->k_i); in reconstruct_subvol()
591 new_subvol->k.p.offset = subvolid; in reconstruct_subvol()
592 new_subvol->v.snapshot = cpu_to_le32(snapshotid); in reconstruct_subvol()
593 new_subvol->v.inode = cpu_to_le64(inum); in reconstruct_subvol()
594 ret = bch2_btree_insert_trans(trans, BTREE_ID_subvolumes, &new_subvol->k_i, 0); in reconstruct_subvol()
607 u32 snapshot_tree = le32_to_cpu(s->v.tree); in reconstruct_subvol()
609 s->v.subvol = cpu_to_le32(subvolid); in reconstruct_subvol()
610 SET_BCH_SNAPSHOT_SUBVOL(&s->v, true); in reconstruct_subvol()
621 if (!st->v.master_subvol) in reconstruct_subvol()
622 st->v.master_subvol = cpu_to_le32(subvolid); in reconstruct_subvol()
630 struct bch_fs *c = trans->c; in reconstruct_inode()
645 i_size = k.k->p.offset << 9; in reconstruct_inode()
674 darray_exit(&s->ids); in snapshots_seen_exit()
685 __darray_for_each(s->ids, i) { in snapshots_seen_add_inorder()
692 int ret = darray_insert_item(&s->ids, i - s->ids.data, id); in snapshots_seen_add_inorder()
695 s->ids.size); in snapshots_seen_add_inorder()
702 if (!bkey_eq(s->pos, pos)) in snapshots_seen_update()
703 s->ids.nr = 0; in snapshots_seen_update()
704 s->pos = pos; in snapshots_seen_update()
706 return snapshot_list_add_nodup(c, &s->ids, pos.snapshot); in snapshots_seen_update()
710 * key_visible_in_snapshot - returns true if @id is a descendent of @ancestor,
728 EBUG_ON(ancestor != seen->pos.snapshot); in key_visible_in_snapshot()
729 EBUG_ON(ancestor != darray_last(seen->ids)); in key_visible_in_snapshot()
739 * we've seen a key that overwrote @ancestor - i.e. also a descendent of in key_visible_in_snapshot()
747 for (i = seen->ids.nr - 2; in key_visible_in_snapshot()
748 i >= 0 && seen->ids.data[i] >= id; in key_visible_in_snapshot()
749 --i) in key_visible_in_snapshot()
750 if (bch2_snapshot_is_ancestor(c, id, seen->ids.data[i])) in key_visible_in_snapshot()
757 * ref_visible - given a key with snapshot id @src that points to a key with
789 for (_i = (_w)->inodes.data; _i < (_w)->inodes.data + (_w)->inodes.nr && \
790 (_i)->snapshot <= (_snapshot); _i++) \
791 if (key_visible_in_snapshot(_c, _s, _i->snapshot, _snapshot))
812 darray_exit(&w->inodes); in inode_walker_exit()
813 darray_exit(&w->deletes); in inode_walker_exit()
827 darray_push(&w->inodes, ((struct inode_walker_entry) { in add_inode()
829 .snapshot = inode.k->p.snapshot, in add_inode()
836 struct bch_fs *c = trans->c; in get_inodes_all_snapshots()
842 * We no longer have inodes for w->last_pos; clear this to avoid in get_inodes_all_snapshots()
846 w->have_inodes = false; in get_inodes_all_snapshots()
847 w->recalculate_sums = false; in get_inodes_all_snapshots()
848 w->inodes.nr = 0; in get_inodes_all_snapshots()
852 if (k.k->p.offset != inum) in get_inodes_all_snapshots()
863 w->first_this_inode = true; in get_inodes_all_snapshots()
864 w->have_inodes = true; in get_inodes_all_snapshots()
871 bool is_whiteout = k.k->type == KEY_TYPE_whiteout; in lookup_inode_for_snapshot()
874 __darray_for_each(w->inodes, i) in lookup_inode_for_snapshot()
875 if (bch2_snapshot_is_ancestor(c, k.k->p.snapshot, i->snapshot)) in lookup_inode_for_snapshot()
880 BUG_ON(k.k->p.snapshot > i->snapshot); in lookup_inode_for_snapshot()
882 if (k.k->p.snapshot != i->snapshot && !is_whiteout) { in lookup_inode_for_snapshot()
885 new.snapshot = k.k->p.snapshot; in lookup_inode_for_snapshot()
895 w->last_pos.inode, k.k->p.snapshot, i->snapshot, buf.buf); in lookup_inode_for_snapshot()
898 while (i > w->inodes.data && i[-1].snapshot > k.k->p.snapshot) in lookup_inode_for_snapshot()
899 --i; in lookup_inode_for_snapshot()
901 size_t pos = i - w->inodes.data; in lookup_inode_for_snapshot()
902 int ret = darray_insert_item(&w->inodes, pos, new); in lookup_inode_for_snapshot()
906 i = w->inodes.data + pos; in lookup_inode_for_snapshot()
916 if (w->last_pos.inode != k.k->p.inode) { in walk_inode()
917 int ret = get_inodes_all_snapshots(trans, w, k.k->p.inode); in walk_inode()
922 w->last_pos = k.k->p; in walk_inode()
924 return lookup_inode_for_snapshot(trans->c, w, k); in walk_inode()
932 struct bch_fs *c = trans->c; in get_visible_inodes()
937 w->inodes.nr = 0; in get_visible_inodes()
938 w->deletes.nr = 0; in get_visible_inodes()
940 for_each_btree_key_reverse_norestart(trans, iter, BTREE_ID_inodes, SPOS(0, inum, s->pos.snapshot), in get_visible_inodes()
942 if (k.k->p.offset != inum) in get_visible_inodes()
945 if (!ref_visible(c, s, s->pos.snapshot, k.k->p.snapshot)) in get_visible_inodes()
948 if (snapshot_list_has_ancestor(c, &w->deletes, k.k->p.snapshot)) in get_visible_inodes()
953 : snapshot_list_add(c, &w->deletes, k.k->p.snapshot); in get_visible_inodes()
965 * return value: 0 -> delete k1, 1 -> delete k2
973 if (new->k.type != KEY_TYPE_dirent) in bch2_fsck_update_backpointers()
980 if (d->v.d_type == DT_SUBVOL) { in bch2_fsck_update_backpointers()
983 ret = get_visible_inodes(trans, &target, s, le64_to_cpu(d->v.d_inum)); in bch2_fsck_update_backpointers()
988 i->inode.bi_dir_offset = d->k.p.offset; in bch2_fsck_update_backpointers()
989 ret = __bch2_fsck_write_inode(trans, &i->inode); in bch2_fsck_update_backpointers()
1004 if (inode->bi_subvol) { in inode_get_dirent()
1006 int ret = subvol_lookup(trans, inode->bi_parent_subvol, snapshot, &inum); in inode_get_dirent()
1011 return dirent_get_by_pos(trans, iter, SPOS(inode->bi_dir, inode->bi_dir_offset, *snapshot)); in inode_get_dirent()
1018 int ret = bkey_err(k) ?: k.k->type == KEY_TYPE_set; in check_inode_deleted_list()
1027 struct bch_fs *c = trans->c; in check_inode_dirent_inode()
1030 u32 inode_snapshot = inode->bi_snapshot; in check_inode_dirent_inode()
1038 inode->bi_subvol && in check_inode_dirent_inode()
1039 (inode->bi_flags & BCH_INODE_has_child_snapshot)) { in check_inode_dirent_inode()
1048 inode->bi_dir = 0; in check_inode_dirent_inode()
1049 inode->bi_dir_offset = 0; in check_inode_dirent_inode()
1070 inode->bi_dir = 0; in check_inode_dirent_inode()
1071 inode->bi_dir_offset = 0; in check_inode_dirent_inode()
1094 if (k.k->p.offset != inum) in get_snapshot_root_inode()
1115 struct bch_fs *c = trans->c; in check_inode()
1127 ret = snapshots_seen_update(c, s, iter->btree_id, k.k->p); in check_inode()
1138 if (snapshot_root->bi_inum != u.bi_inum) { in check_inode()
1144 if (fsck_err_on(u.bi_hash_seed != snapshot_root->bi_hash_seed || in check_inode()
1148 u.bi_hash_seed = snapshot_root->bi_hash_seed; in check_inode()
1172 ret = bch2_empty_dir_snapshot(trans, k.k->p.offset, 0, k.k->p.snapshot); in check_inode()
1173 if (ret && ret != -BCH_ERR_ENOTEMPTY_dir_not_empty) in check_inode()
1186 ret = bch2_inode_has_child_snapshots(trans, k.k->p); in check_inode()
1207 if (!test_bit(BCH_FS_started, &c->flags)) { in check_inode()
1212 * They might be referred to by a logged operation - in check_inode()
1214 * truncate on an unlinked but open file - so we want to in check_inode()
1218 ret = check_inode_deleted_list(trans, k.k->p); in check_inode()
1225 u.bi_inum, k.k->p.snapshot); in check_inode()
1227 ret = bch2_btree_bit_mod_buffered(trans, BTREE_ID_deleted_inodes, k.k->p, 1); in check_inode()
1231 ret = bch2_inode_or_descendents_is_open(trans, k.k->p); in check_inode()
1239 ret = bch2_inode_rm_snapshot(trans, u.bi_inum, iter->pos.snapshot); in check_inode()
1252 u.bi_inum, k.k->p.snapshot, u.bi_subvol, u.bi_parent_subvol)) { in check_inode()
1264 if (ret && (c->sb.btrees_lost_data & BIT_ULL(BTREE_ID_subvolumes))) { in check_inode()
1265 ret = reconstruct_subvol(trans, k.k->p.snapshot, u.bi_subvol, u.bi_inum); in check_inode()
1272 u.bi_inum, k.k->p.snapshot, u.bi_subvol) || in check_inode()
1275 k.k->p.snapshot), in check_inode()
1278 u.bi_inum, k.k->p.snapshot, u.bi_subvol, in check_inode()
1287 if (fsck_err_on(u.bi_journal_seq > journal_cur_seq(&c->journal), in check_inode()
1290 journal_cur_seq(&c->journal), in check_inode()
1294 u.bi_journal_seq = journal_cur_seq(&c->journal); in check_inode()
1334 struct bch_fs *c = trans->c; in find_oldest_inode_needs_reattach()
1346 SPOS(0, inode->bi_inum, inode->bi_snapshot + 1), in find_oldest_inode_needs_reattach()
1348 if (k.k->p.offset != inode->bi_inum) in find_oldest_inode_needs_reattach()
1351 if (!bch2_snapshot_is_ancestor(c, inode->bi_snapshot, k.k->p.snapshot)) in find_oldest_inode_needs_reattach()
1409 * that points to it has its backpointer field set - so we're just looking for
1410 * non-unlinked inodes without backpointers:
1446 struct bch_fs *c = trans->c; in check_key_has_inode()
1452 if (k.k->type == KEY_TYPE_whiteout) in check_key_has_inode()
1455 if (!i && (c->sb.btrees_lost_data & BIT_ULL(BTREE_ID_inodes))) { in check_key_has_inode()
1456 ret = reconstruct_inode(trans, iter->btree_id, k.k->p.snapshot, k.k->p.inode) ?: in check_key_has_inode()
1461 inode->last_pos.inode--; in check_key_has_inode()
1462 ret = -BCH_ERR_transaction_restart_nested; in check_key_has_inode()
1473 if (fsck_err_on(i && !btree_matches_i_mode(iter->btree_id, i->inode.bi_mode), in check_key_has_inode()
1476 i->inode.bi_mode, in check_key_has_inode()
1493 struct bch_fs *c = trans->c; in check_i_sectors_notnested()
1497 darray_for_each(w->inodes, i) { in check_i_sectors_notnested()
1498 if (i->inode.bi_sectors == i->count) in check_i_sectors_notnested()
1501 count2 = bch2_count_inode_sectors(trans, w->last_pos.inode, i->snapshot); in check_i_sectors_notnested()
1503 if (w->recalculate_sums) in check_i_sectors_notnested()
1504 i->count = count2; in check_i_sectors_notnested()
1506 if (i->count != count2) { in check_i_sectors_notnested()
1508 w->last_pos.inode, i->snapshot, i->count, count2); in check_i_sectors_notnested()
1509 i->count = count2; in check_i_sectors_notnested()
1512 if (fsck_err_on(!(i->inode.bi_flags & BCH_INODE_i_sectors_dirty), in check_i_sectors_notnested()
1515 w->last_pos.inode, i->snapshot, in check_i_sectors_notnested()
1516 i->inode.bi_sectors, i->count)) { in check_i_sectors_notnested()
1517 i->inode.bi_sectors = i->count; in check_i_sectors_notnested()
1518 ret = bch2_fsck_write_inode(trans, &i->inode); in check_i_sectors_notnested()
1530 u32 restart_count = trans->restart_count; in check_i_sectors()
1548 darray_for_each(extent_ends->e, i) in extent_ends_reset()
1549 snapshots_seen_exit(&i->seen); in extent_ends_reset()
1550 extent_ends->e.nr = 0; in extent_ends_reset()
1556 darray_exit(&extent_ends->e); in extent_ends_exit()
1570 .offset = k.k->p.offset, in extent_ends_at()
1571 .snapshot = k.k->p.snapshot, in extent_ends_at()
1575 n.seen.ids.data = kmemdup(seen->ids.data, in extent_ends_at()
1576 sizeof(seen->ids.data[0]) * seen->ids.size, in extent_ends_at()
1579 return -BCH_ERR_ENOMEM_fsck_extent_ends_at; in extent_ends_at()
1581 __darray_for_each(extent_ends->e, i) { in extent_ends_at()
1582 if (i->snapshot == k.k->p.snapshot) { in extent_ends_at()
1583 snapshots_seen_exit(&i->seen); in extent_ends_at()
1588 if (i->snapshot >= k.k->p.snapshot) in extent_ends_at()
1592 return darray_insert_item(&extent_ends->e, i - extent_ends->e.data, n); in extent_ends_at()
1599 bool *fixed, in overlapping_extents_found() argument
1602 struct bch_fs *c = trans->c; in overlapping_extents_found()
1621 if (!bpos_eq(pos1, k1.k->p)) { in overlapping_extents_found()
1629 ret = -BCH_ERR_internal_fsck_err; in overlapping_extents_found()
1643 if (bpos_ge(k2.k->p, pos2.p)) in overlapping_extents_found()
1650 if (bpos_gt(k2.k->p, pos2.p) || in overlapping_extents_found()
1651 pos2.size != k2.k->size) { in overlapping_extents_found()
1654 ret = -BCH_ERR_internal_fsck_err; in overlapping_extents_found()
1671 trans->extra_disk_res += bch2_bkey_sectors_compressed(k2); in overlapping_extents_found()
1684 *fixed = true; in overlapping_extents_found()
1691 extent_end->offset = bkey_start_offset(&pos2); in overlapping_extents_found()
1699 * We overwrote the second extent - restart in overlapping_extents_found()
1702 ret = -BCH_ERR_transaction_restart_nested; in overlapping_extents_found()
1718 bool *fixed) in check_overlapping_extents() argument
1720 struct bch_fs *c = trans->c; in check_overlapping_extents()
1724 if (bpos_eq(extent_ends->last_pos, k.k->p)) in check_overlapping_extents()
1727 if (extent_ends->last_pos.inode != k.k->p.inode) in check_overlapping_extents()
1730 darray_for_each(extent_ends->e, i) { in check_overlapping_extents()
1731 if (i->offset <= bkey_start_offset(k.k)) in check_overlapping_extents()
1735 k.k->p.snapshot, seen, in check_overlapping_extents()
1736 i->snapshot, &i->seen)) in check_overlapping_extents()
1739 ret = overlapping_extents_found(trans, iter->btree_id, in check_overlapping_extents()
1740 SPOS(iter->pos.inode, in check_overlapping_extents()
1741 i->offset, in check_overlapping_extents()
1742 i->snapshot), in check_overlapping_extents()
1743 &i->seen, in check_overlapping_extents()
1744 *k.k, fixed, i); in check_overlapping_extents()
1749 extent_ends->last_pos = k.k->p; in check_overlapping_extents()
1757 struct bch_fs *c = trans->c; in check_extent_overbig()
1761 unsigned encoded_extent_max_sectors = c->opts.encoded_extent_max >> 9; in check_extent_overbig()
1783 struct bch_fs *c = trans->c; in check_extent()
1793 if (inode->last_pos.inode != k.k->p.inode && inode->have_inodes) { in check_extent()
1799 ret = snapshots_seen_update(c, s, iter->btree_id, k.k->p); in check_extent()
1812 if (k.k->type != KEY_TYPE_whiteout) { in check_extent()
1814 &inode->recalculate_sums); in check_extent()
1823 for (struct inode_walker_entry *i = extent_i ?: &darray_last(inode->inodes); in check_extent()
1824 inode->inodes.data && i >= inode->inodes.data; in check_extent()
1825 --i) { in check_extent()
1826 if (i->snapshot > k.k->p.snapshot || in check_extent()
1827 !key_visible_in_snapshot(c, s, i->snapshot, k.k->p.snapshot)) in check_extent()
1830 if (fsck_err_on(k.k->p.offset > round_up(i->inode.bi_size, block_bytes(c)) >> 9 && in check_extent()
1834 i->inode.bi_inum, i->snapshot, i->inode.bi_size, in check_extent()
1839 bch2_btree_iter_set_snapshot(trans, &iter2, i->snapshot); in check_extent()
1847 iter->k.type = KEY_TYPE_whiteout; in check_extent()
1858 for (struct inode_walker_entry *i = extent_i ?: &darray_last(inode->inodes); in check_extent()
1859 inode->inodes.data && i >= inode->inodes.data; in check_extent()
1860 --i) { in check_extent()
1861 if (i->snapshot > k.k->p.snapshot || in check_extent()
1862 !key_visible_in_snapshot(c, s, i->snapshot, k.k->p.snapshot)) in check_extent()
1865 i->count += k.k->size; in check_extent()
1869 if (k.k->type != KEY_TYPE_whiteout) { in check_extent()
1936 struct bch_fs *c = trans->c; in check_subdir_count_notnested()
1940 darray_for_each(w->inodes, i) { in check_subdir_count_notnested()
1941 if (i->inode.bi_nlink == i->count) in check_subdir_count_notnested()
1944 count2 = bch2_count_subdirs(trans, w->last_pos.inode, i->snapshot); in check_subdir_count_notnested()
1948 if (i->count != count2) { in check_subdir_count_notnested()
1950 w->last_pos.inode, i->snapshot, i->count, count2); in check_subdir_count_notnested()
1951 i->count = count2; in check_subdir_count_notnested()
1952 if (i->inode.bi_nlink == i->count) in check_subdir_count_notnested()
1956 if (fsck_err_on(i->inode.bi_nlink != i->count, in check_subdir_count_notnested()
1959 w->last_pos.inode, i->snapshot, i->inode.bi_nlink, i->count)) { in check_subdir_count_notnested()
1960 i->inode.bi_nlink = i->count; in check_subdir_count_notnested()
1961 ret = bch2_fsck_write_inode(trans, &i->inode); in check_subdir_count_notnested()
1973 u32 restart_count = trans->restart_count; in check_subdir_dirents_count()
1986 if (k.k->type != KEY_TYPE_subvolume) in find_snapshot_subvol()
1990 if (bch2_snapshot_is_ancestor(trans->c, le32_to_cpu(s.v->snapshot), snapshot)) { in find_snapshot_subvol()
1992 *subvolid = k.k->p.offset; in find_snapshot_subvol()
1997 ret = -ENOENT; in find_snapshot_subvol()
2007 struct bch_fs *c = trans->c; in check_dirent_to_subvol()
2010 u32 parent_subvol = le32_to_cpu(d.v->d_parent_subvol); in check_dirent_to_subvol()
2011 u32 target_subvol = le32_to_cpu(d.v->d_child_subvol); in check_dirent_to_subvol()
2023 (!ret && !bch2_snapshot_is_ancestor(c, parent_snapshot, d.k->p.snapshot))) { in check_dirent_to_subvol()
2024 int ret2 = find_snapshot_subvol(trans, d.k->p.snapshot, &new_parent_subvol); in check_dirent_to_subvol()
2031 (c->sb.btrees_lost_data & BIT_ULL(BTREE_ID_subvolumes))) { in check_dirent_to_subvol()
2033 * Couldn't find a subvol for dirent's snapshot - but we lost in check_dirent_to_subvol()
2036 ret = reconstruct_subvol(trans, d.k->p.snapshot, parent_subvol, 0); in check_dirent_to_subvol()
2040 parent_snapshot = d.k->p.snapshot; in check_dirent_to_subvol()
2047 fsck_err_on(!ret && !bch2_snapshot_is_ancestor(c, parent_snapshot, d.k->p.snapshot), in check_dirent_to_subvol()
2053 bch_err(c, "could not find a subvol for snapshot %u", d.k->p.snapshot); in check_dirent_to_subvol()
2054 return -BCH_ERR_fsck_repair_unimplemented; in check_dirent_to_subvol()
2062 new_dirent->v.d_parent_subvol = cpu_to_le32(new_parent_subvol); in check_dirent_to_subvol()
2077 return bch2_fsck_remove_dirent(trans, d.k->p); in check_dirent_to_subvol()
2082 if (fsck_err_on(le32_to_cpu(s.v->fs_path_parent) != parent_subvol, in check_dirent_to_subvol()
2093 n->v.fs_path_parent = cpu_to_le32(parent_subvol); in check_dirent_to_subvol()
2096 u64 target_inum = le64_to_cpu(s.v->inode); in check_dirent_to_subvol()
2097 u32 target_snapshot = le32_to_cpu(s.v->snapshot); in check_dirent_to_subvol()
2105 ret = -BCH_ERR_fsck_repair_unimplemented; in check_dirent_to_subvol()
2115 subvol_root.bi_snapshot = le32_to_cpu(s.v->snapshot); in check_dirent_to_subvol()
2139 struct bch_fs *c = trans->c; in check_dirent()
2150 ret = snapshots_seen_update(c, s, iter->btree_id, k.k->p); in check_dirent()
2154 if (k.k->type == KEY_TYPE_whiteout) in check_dirent()
2157 if (dir->last_pos.inode != k.k->p.inode && dir->have_inodes) { in check_dirent()
2175 if (dir->first_this_inode) in check_dirent()
2176 *hash_info = bch2_hash_info_init(c, &i->inode); in check_dirent()
2177 dir->first_this_inode = false; in check_dirent()
2188 if (k.k->type != KEY_TYPE_dirent) in check_dirent()
2194 if (fsck_err_on(d.v->d_casefold != !!hash_info->cf_encoding, in check_dirent()
2201 u32 subvol = d.v->d_type == DT_SUBVOL in check_dirent()
2202 ? d.v->d_parent_subvol in check_dirent()
2204 u64 target = d.v->d_type == DT_SUBVOL in check_dirent()
2205 ? d.v->d_child_subvol in check_dirent()
2206 : d.v->d_inum; in check_dirent()
2213 d.k->p.inode, d.k->p.snapshot, in check_dirent()
2215 d.v->d_type, in check_dirent()
2228 if (d.v->d_type == DT_SUBVOL) { in check_dirent()
2233 ret = get_visible_inodes(trans, target, s, le64_to_cpu(d.v->d_inum)); in check_dirent()
2237 if (fsck_err_on(!target->inodes.nr, in check_dirent()
2243 ret = bch2_fsck_remove_dirent(trans, d.k->p); in check_dirent()
2248 darray_for_each(target->inodes, i) { in check_dirent()
2249 ret = bch2_check_dirent_target(trans, iter, d, &i->inode, true); in check_dirent()
2254 darray_for_each(target->deletes, i) in check_dirent()
2255 if (fsck_err_on(!snapshot_list_has_id(&s->ids, *i), in check_dirent()
2265 SPOS(k.k->p.inode, k.k->p.offset, *i), in check_dirent()
2283 for_each_visible_inode(c, s, dir, d.k->p.snapshot, i) { in check_dirent()
2284 if (d.v->d_type == DT_DIR) in check_dirent()
2285 i->count++; in check_dirent()
2286 i->i_size += bkey_bytes(d.k); in check_dirent()
2328 struct bch_fs *c = trans->c; in check_xattr()
2350 if (inode->first_this_inode) in check_xattr()
2351 *hash_info = bch2_hash_info_init(c, &i->inode); in check_xattr()
2352 inode->first_this_inode = false; in check_xattr()
2384 struct bch_fs *c = trans->c; in check_root_trans()
2405 bkey_subvolume_init(&root_subvol->k_i); in check_root_trans()
2406 root_subvol->k.p.offset = BCACHEFS_ROOT_SUBVOL; in check_root_trans()
2407 root_subvol->v.flags = 0; in check_root_trans()
2408 root_subvol->v.snapshot = cpu_to_le32(snapshot); in check_root_trans()
2409 root_subvol->v.inode = cpu_to_le64(inum); in check_root_trans()
2410 ret = bch2_btree_insert_trans(trans, BTREE_ID_subvolumes, &root_subvol->k_i, 0); in check_root_trans()
2460 struct bch_fs *c = trans->c; in check_subvol_path()
2466 if (k.k->type != KEY_TYPE_subvolume) in check_subvol_path()
2469 while (k.k->p.offset != BCACHEFS_ROOT_SUBVOL) { in check_subvol_path()
2470 ret = darray_push(&subvol_path, k.k->p.offset); in check_subvol_path()
2478 (subvol_inum) { s.k->p.offset, le64_to_cpu(s.v->inode) }, in check_subvol_path()
2483 u32 parent = le32_to_cpu(s.v->fs_path_parent); in check_subvol_path()
2499 if (fsck_err_on(k.k->type != KEY_TYPE_subvolume, in check_subvol_path()
2539 SPOS(0, p->inum, p->snapshot), 0); in bch2_bi_depth_renumber_one()
2543 !bkey_is_inode(k.k) ? -BCH_ERR_ENOENT_inode in bch2_bi_depth_renumber_one()
2560 u32 restart_count = trans->restart_count; in bch2_bi_depth_renumber()
2566 bch_err_fn(trans->c, ret); in bch2_bi_depth_renumber()
2579 if (i->inum == inum && in path_is_dup()
2580 i->snapshot == snapshot) in path_is_dup()
2587 struct bch_fs *c = trans->c; in check_path_loop()
2591 u32 snapshot = inode_k.k->p.snapshot; in check_path_loop()
2639 !bkey_is_inode(inode_k.k) ? -BCH_ERR_ENOENT_inode in check_path_loop()
2654 snapshot = inode_k.k->p.snapshot; in check_path_loop()
2662 pr_err("%llu:%u", i->inum, i->snapshot); in check_path_loop()
2695 * have been fixed by prior passes
2732 if (t->nr == t->size) { in add_nlink()
2733 size_t new_size = max_t(size_t, 128UL, t->size * 2); in add_nlink()
2734 void *d = kvmalloc_array(new_size, sizeof(t->d[0]), GFP_KERNEL); in add_nlink()
2739 return -BCH_ERR_ENOMEM_fsck_add_nlink; in add_nlink()
2742 if (t->d) in add_nlink()
2743 memcpy(d, t->d, t->size * sizeof(t->d[0])); in add_nlink()
2744 kvfree(t->d); in add_nlink()
2746 t->d = d; in add_nlink()
2747 t->size = new_size; in add_nlink()
2751 t->d[t->nr++] = (struct nlink) { in add_nlink()
2764 return cmp_int(l->inum, r->inum); in nlink_cmp()
2768 struct nlink_table *links, in inc_link() argument
2778 link = __inline_bsearch(&key, links->d, links->nr, in inc_link()
2779 sizeof(links->d[0]), nlink_cmp); in inc_link()
2783 while (link > links->d && link[0].inum == link[-1].inum) in inc_link()
2784 --link; in inc_link()
2786 for (; link < links->d + links->nr && link->inum == inum; link++) in inc_link()
2787 if (ref_visible(c, s, snapshot, link->snapshot)) { in inc_link()
2788 link->count++; in inc_link()
2789 if (link->snapshot >= snapshot) in inc_link()
2828 ret = add_nlink(c, t, k.k->p.offset, k.k->p.snapshot); in check_nlinks_find_hardlinks()
2830 *end = k.k->p.offset; in check_nlinks_find_hardlinks()
2842 static int check_nlinks_walk_dirents(struct bch_fs *c, struct nlink_table *links, in check_nlinks_walk_dirents() argument
2854 ret = snapshots_seen_update(c, &s, iter.btree_id, k.k->p); in check_nlinks_walk_dirents()
2858 if (k.k->type == KEY_TYPE_dirent) { in check_nlinks_walk_dirents()
2861 if (d.v->d_type != DT_DIR && in check_nlinks_walk_dirents()
2862 d.v->d_type != DT_SUBVOL) in check_nlinks_walk_dirents()
2863 inc_link(c, &s, links, range_start, range_end, in check_nlinks_walk_dirents()
2864 le64_to_cpu(d.v->d_inum), d.k->p.snapshot); in check_nlinks_walk_dirents()
2877 struct nlink_table *links, in check_nlinks_update_inode() argument
2881 struct nlink *link = &links->d[*idx]; in check_nlinks_update_inode()
2884 if (k.k->p.offset >= range_end) in check_nlinks_update_inode()
2900 while ((cmp_int(link->inum, k.k->p.offset) ?: in check_nlinks_update_inode()
2901 cmp_int(link->snapshot, k.k->p.snapshot)) < 0) { in check_nlinks_update_inode()
2902 BUG_ON(*idx == links->nr); in check_nlinks_update_inode()
2903 link = &links->d[++*idx]; in check_nlinks_update_inode()
2906 if (fsck_err_on(bch2_inode_nlink_get(&u) != link->count, in check_nlinks_update_inode()
2910 bch2_inode_nlink_get(&u), link->count)) { in check_nlinks_update_inode()
2911 bch2_inode_nlink_set(&u, link->count); in check_nlinks_update_inode()
2920 struct nlink_table *links, in check_nlinks_update_hardlinks() argument
2930 check_nlinks_update_inode(trans, &iter, k, links, &idx, range_end))); in check_nlinks_update_hardlinks()
2941 struct nlink_table links = { 0 }; in bch2_check_nlinks() local
2949 ret = check_nlinks_find_hardlinks(c, &links, in bch2_check_nlinks()
2953 ret = check_nlinks_walk_dirents(c, &links, in bch2_check_nlinks()
2959 ret = check_nlinks_update_hardlinks(c, &links, in bch2_check_nlinks()
2965 links.nr = 0; in bch2_check_nlinks()
2968 kvfree(links.d); in bch2_check_nlinks()
2979 if (k.k->type != KEY_TYPE_reflink_p) in fix_reflink_p_key()
2984 if (!p.v->front_pad && !p.v->back_pad) in fix_reflink_p_key()
2992 bkey_reassemble(&u->k_i, k); in fix_reflink_p_key()
2993 u->v.front_pad = 0; in fix_reflink_p_key()
2994 u->v.back_pad = 0; in fix_reflink_p_key()
2996 return bch2_trans_update(trans, iter, &u->k_i, BTREE_TRIGGER_norun); in fix_reflink_p_key()
3001 if (c->sb.version >= bcachefs_metadata_version_reflink_p_fix) in bch2_fix_reflink_p()
3032 struct bch_fs *c = thr->c; in bch2_fsck_offline_thread_fn()
3038 ret = bch2_fs_start(thr->c); in bch2_fsck_offline_thread_fn()
3042 if (test_bit(BCH_FS_errors_fixed, &c->flags)) { in bch2_fsck_offline_thread_fn()
3043 bch2_stdio_redirect_printf(&stdio->stdio, false, "%s: errors fixed\n", c->name); in bch2_fsck_offline_thread_fn()
3046 if (test_bit(BCH_FS_error, &c->flags)) { in bch2_fsck_offline_thread_fn()
3047 bch2_stdio_redirect_printf(&stdio->stdio, false, "%s: still has errors\n", c->name); in bch2_fsck_offline_thread_fn()
3068 return -EFAULT; in bch2_ioctl_fsck_offline()
3071 return -EINVAL; in bch2_ioctl_fsck_offline()
3074 return -EPERM; in bch2_ioctl_fsck_offline()
3078 ret = copy_from_user_errcode(&dev_u64, &user_arg->devs[i], sizeof(u64)); in bch2_ioctl_fsck_offline()
3096 ret = -ENOMEM; in bch2_ioctl_fsck_offline()
3100 thr->opts = bch2_opts_empty(); in bch2_ioctl_fsck_offline()
3105 bch2_parse_mount_opts(NULL, &thr->opts, NULL, optstr, false); in bch2_ioctl_fsck_offline()
3113 opt_set(thr->opts, stdio, (u64)(unsigned long)&thr->thr.stdio); in bch2_ioctl_fsck_offline()
3114 opt_set(thr->opts, read_only, 1); in bch2_ioctl_fsck_offline()
3115 opt_set(thr->opts, ratelimit_errors, 0); in bch2_ioctl_fsck_offline()
3118 opt_set(thr->opts, nostart, true); in bch2_ioctl_fsck_offline()
3120 bch2_thread_with_stdio_init(&thr->thr, &bch2_offline_fsck_ops); in bch2_ioctl_fsck_offline()
3122 thr->c = bch2_fs_open(devs.data, arg.nr_devs, thr->opts); in bch2_ioctl_fsck_offline()
3124 if (!IS_ERR(thr->c) && in bch2_ioctl_fsck_offline()
3125 thr->c->opts.errors == BCH_ON_ERROR_panic) in bch2_ioctl_fsck_offline()
3126 thr->c->opts.errors = BCH_ON_ERROR_ro; in bch2_ioctl_fsck_offline()
3128 ret = __bch2_run_thread_with_stdio(&thr->thr); in bch2_ioctl_fsck_offline()
3136 bch2_fsck_thread_exit(&thr->thr); in bch2_ioctl_fsck_offline()
3144 struct bch_fs *c = thr->c; in bch2_fsck_online_thread_fn()
3146 c->stdio_filter = current; in bch2_fsck_online_thread_fn()
3147 c->stdio = &thr->thr.stdio; in bch2_fsck_online_thread_fn()
3150 * XXX: can we figure out a way to do this without mucking with c->opts? in bch2_fsck_online_thread_fn()
3152 unsigned old_fix_errors = c->opts.fix_errors; in bch2_fsck_online_thread_fn()
3153 if (opt_defined(thr->opts, fix_errors)) in bch2_fsck_online_thread_fn()
3154 c->opts.fix_errors = thr->opts.fix_errors; in bch2_fsck_online_thread_fn()
3156 c->opts.fix_errors = FSCK_FIX_ask; in bch2_fsck_online_thread_fn()
3158 c->opts.fsck = true; in bch2_fsck_online_thread_fn()
3159 set_bit(BCH_FS_fsck_running, &c->flags); in bch2_fsck_online_thread_fn()
3161 c->curr_recovery_pass = BCH_RECOVERY_PASS_check_alloc_info; in bch2_fsck_online_thread_fn()
3164 clear_bit(BCH_FS_fsck_running, &c->flags); in bch2_fsck_online_thread_fn()
3167 c->stdio = NULL; in bch2_fsck_online_thread_fn()
3168 c->stdio_filter = NULL; in bch2_fsck_online_thread_fn()
3169 c->opts.fix_errors = old_fix_errors; in bch2_fsck_online_thread_fn()
3171 up(&c->online_fsck_mutex); in bch2_fsck_online_thread_fn()
3187 return -EINVAL; in bch2_ioctl_fsck_online()
3190 return -EPERM; in bch2_ioctl_fsck_online()
3193 return -EROFS; in bch2_ioctl_fsck_online()
3195 if (down_trylock(&c->online_fsck_mutex)) { in bch2_ioctl_fsck_online()
3197 return -EAGAIN; in bch2_ioctl_fsck_online()
3202 ret = -ENOMEM; in bch2_ioctl_fsck_online()
3206 thr->c = c; in bch2_ioctl_fsck_online()
3207 thr->opts = bch2_opts_empty(); in bch2_ioctl_fsck_online()
3213 bch2_parse_mount_opts(c, &thr->opts, NULL, optstr, false); in bch2_ioctl_fsck_online()
3221 ret = bch2_run_thread_with_stdio(&thr->thr, &bch2_online_fsck_ops); in bch2_ioctl_fsck_online()
3226 bch2_fsck_thread_exit(&thr->thr); in bch2_ioctl_fsck_online()
3227 up(&c->online_fsck_mutex); in bch2_ioctl_fsck_online()