Skip to content

Commit 758ea4f

Browse files
author
Kent Overstreet
committed
bcachefs: Move bch2_check_dirent_target() to namei.c
We're gradually running more and more fsck.c checks at runtime, whereever applicable; when we do so they get moved out of fsck.c. Next patch will call bch2_check_dirent_target() from bch2_lookup(). Signed-off-by: Kent Overstreet <[email protected]>
1 parent 4fcd4de commit 758ea4f

File tree

5 files changed

+236
-224
lines changed

5 files changed

+236
-224
lines changed

fs/bcachefs/dirent.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,3 +729,54 @@ int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx)
729729

730730
return ret < 0 ? ret : 0;
731731
}
732+
733+
/* fsck */
734+
735+
static int lookup_first_inode(struct btree_trans *trans, u64 inode_nr,
736+
struct bch_inode_unpacked *inode)
737+
{
738+
struct btree_iter iter;
739+
struct bkey_s_c k;
740+
int ret;
741+
742+
for_each_btree_key_norestart(trans, iter, BTREE_ID_inodes, POS(0, inode_nr),
743+
BTREE_ITER_all_snapshots, k, ret) {
744+
if (k.k->p.offset != inode_nr)
745+
break;
746+
if (!bkey_is_inode(k.k))
747+
continue;
748+
ret = bch2_inode_unpack(k, inode);
749+
goto found;
750+
}
751+
ret = -BCH_ERR_ENOENT_inode;
752+
found:
753+
bch_err_msg(trans->c, ret, "fetching inode %llu", inode_nr);
754+
bch2_trans_iter_exit(trans, &iter);
755+
return ret;
756+
}
757+
758+
int bch2_fsck_remove_dirent(struct btree_trans *trans, struct bpos pos)
759+
{
760+
struct bch_fs *c = trans->c;
761+
struct btree_iter iter;
762+
struct bch_inode_unpacked dir_inode;
763+
struct bch_hash_info dir_hash_info;
764+
int ret;
765+
766+
ret = lookup_first_inode(trans, pos.inode, &dir_inode);
767+
if (ret)
768+
goto err;
769+
770+
dir_hash_info = bch2_hash_info_init(c, &dir_inode);
771+
772+
bch2_trans_iter_init(trans, &iter, BTREE_ID_dirents, pos, BTREE_ITER_intent);
773+
774+
ret = bch2_btree_iter_traverse(&iter) ?:
775+
bch2_hash_delete_at(trans, bch2_dirent_hash_desc,
776+
&dir_hash_info, &iter,
777+
BTREE_UPDATE_internal_snapshot_node);
778+
bch2_trans_iter_exit(trans, &iter);
779+
err:
780+
bch_err_fn(c, ret);
781+
return ret;
782+
}

fs/bcachefs/dirent.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,6 @@ int bch2_empty_dir_snapshot(struct btree_trans *, u64, u32, u32);
8282
int bch2_empty_dir_trans(struct btree_trans *, subvol_inum);
8383
int bch2_readdir(struct bch_fs *, subvol_inum, struct dir_context *);
8484

85+
int bch2_fsck_remove_dirent(struct btree_trans *, struct bpos);
86+
8587
#endif /* _BCACHEFS_DIRENT_H */

fs/bcachefs/fsck.c

Lines changed: 5 additions & 224 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,6 @@
2323
#include <linux/bsearch.h>
2424
#include <linux/dcache.h> /* struct qstr */
2525

26-
static bool inode_points_to_dirent(struct bch_inode_unpacked *inode,
27-
struct bkey_s_c_dirent d)
28-
{
29-
return inode->bi_dir == d.k->p.inode &&
30-
inode->bi_dir_offset == d.k->p.offset;
31-
}
32-
3326
static int dirent_points_to_inode_nowarn(struct bkey_s_c_dirent d,
3427
struct bch_inode_unpacked *inode)
3528
{
@@ -116,29 +109,6 @@ static int subvol_lookup(struct btree_trans *trans, u32 subvol,
116109
return ret;
117110
}
118111

119-
static int lookup_first_inode(struct btree_trans *trans, u64 inode_nr,
120-
struct bch_inode_unpacked *inode)
121-
{
122-
struct btree_iter iter;
123-
struct bkey_s_c k;
124-
int ret;
125-
126-
for_each_btree_key_norestart(trans, iter, BTREE_ID_inodes, POS(0, inode_nr),
127-
BTREE_ITER_all_snapshots, k, ret) {
128-
if (k.k->p.offset != inode_nr)
129-
break;
130-
if (!bkey_is_inode(k.k))
131-
continue;
132-
ret = bch2_inode_unpack(k, inode);
133-
goto found;
134-
}
135-
ret = -BCH_ERR_ENOENT_inode;
136-
found:
137-
bch_err_msg(trans->c, ret, "fetching inode %llu", inode_nr);
138-
bch2_trans_iter_exit(trans, &iter);
139-
return ret;
140-
}
141-
142112
static int lookup_inode(struct btree_trans *trans, u64 inode_nr, u32 snapshot,
143113
struct bch_inode_unpacked *inode)
144114
{
@@ -179,32 +149,6 @@ static int lookup_dirent_in_snapshot(struct btree_trans *trans,
179149
return 0;
180150
}
181151

182-
static int __remove_dirent(struct btree_trans *trans, struct bpos pos)
183-
{
184-
struct bch_fs *c = trans->c;
185-
struct btree_iter iter;
186-
struct bch_inode_unpacked dir_inode;
187-
struct bch_hash_info dir_hash_info;
188-
int ret;
189-
190-
ret = lookup_first_inode(trans, pos.inode, &dir_inode);
191-
if (ret)
192-
goto err;
193-
194-
dir_hash_info = bch2_hash_info_init(c, &dir_inode);
195-
196-
bch2_trans_iter_init(trans, &iter, BTREE_ID_dirents, pos, BTREE_ITER_intent);
197-
198-
ret = bch2_btree_iter_traverse(&iter) ?:
199-
bch2_hash_delete_at(trans, bch2_dirent_hash_desc,
200-
&dir_hash_info, &iter,
201-
BTREE_UPDATE_internal_snapshot_node);
202-
bch2_trans_iter_exit(trans, &iter);
203-
err:
204-
bch_err_fn(c, ret);
205-
return ret;
206-
}
207-
208152
/*
209153
* Find any subvolume associated with a tree of snapshots
210154
* We can't rely on master_subvol - it might have been deleted.
@@ -548,7 +492,7 @@ static int remove_backpointer(struct btree_trans *trans,
548492
SPOS(inode->bi_dir, inode->bi_dir_offset, inode->bi_snapshot));
549493
int ret = bkey_err(d) ?:
550494
dirent_points_to_inode(c, d, inode) ?:
551-
__remove_dirent(trans, d.k->p);
495+
bch2_fsck_remove_dirent(trans, d.k->p);
552496
bch2_trans_iter_exit(trans, &iter);
553497
return ret;
554498
}
@@ -1985,169 +1929,6 @@ static int check_subdir_dirents_count(struct btree_trans *trans, struct inode_wa
19851929
trans_was_restarted(trans, restart_count);
19861930
}
19871931

1988-
noinline_for_stack
1989-
static int check_dirent_inode_dirent(struct btree_trans *trans,
1990-
struct btree_iter *iter,
1991-
struct bkey_s_c_dirent d,
1992-
struct bch_inode_unpacked *target)
1993-
{
1994-
struct bch_fs *c = trans->c;
1995-
struct printbuf buf = PRINTBUF;
1996-
struct btree_iter bp_iter = { NULL };
1997-
int ret = 0;
1998-
1999-
if (inode_points_to_dirent(target, d))
2000-
return 0;
2001-
2002-
if (!target->bi_dir &&
2003-
!target->bi_dir_offset) {
2004-
fsck_err_on(S_ISDIR(target->bi_mode),
2005-
trans, inode_dir_missing_backpointer,
2006-
"directory with missing backpointer\n%s",
2007-
(printbuf_reset(&buf),
2008-
bch2_bkey_val_to_text(&buf, c, d.s_c),
2009-
prt_printf(&buf, "\n"),
2010-
bch2_inode_unpacked_to_text(&buf, target),
2011-
buf.buf));
2012-
2013-
fsck_err_on(target->bi_flags & BCH_INODE_unlinked,
2014-
trans, inode_unlinked_but_has_dirent,
2015-
"inode unlinked but has dirent\n%s",
2016-
(printbuf_reset(&buf),
2017-
bch2_bkey_val_to_text(&buf, c, d.s_c),
2018-
prt_printf(&buf, "\n"),
2019-
bch2_inode_unpacked_to_text(&buf, target),
2020-
buf.buf));
2021-
2022-
target->bi_flags &= ~BCH_INODE_unlinked;
2023-
target->bi_dir = d.k->p.inode;
2024-
target->bi_dir_offset = d.k->p.offset;
2025-
return __bch2_fsck_write_inode(trans, target);
2026-
}
2027-
2028-
if (bch2_inode_should_have_single_bp(target) &&
2029-
!fsck_err(trans, inode_wrong_backpointer,
2030-
"dirent points to inode that does not point back:\n %s",
2031-
(bch2_bkey_val_to_text(&buf, c, d.s_c),
2032-
prt_printf(&buf, "\n "),
2033-
bch2_inode_unpacked_to_text(&buf, target),
2034-
buf.buf)))
2035-
goto err;
2036-
2037-
struct bkey_s_c_dirent bp_dirent = dirent_get_by_pos(trans, &bp_iter,
2038-
SPOS(target->bi_dir, target->bi_dir_offset, target->bi_snapshot));
2039-
ret = bkey_err(bp_dirent);
2040-
if (ret && !bch2_err_matches(ret, ENOENT))
2041-
goto err;
2042-
2043-
bool backpointer_exists = !ret;
2044-
ret = 0;
2045-
2046-
if (fsck_err_on(!backpointer_exists,
2047-
trans, inode_wrong_backpointer,
2048-
"inode %llu:%u has wrong backpointer:\n"
2049-
"got %llu:%llu\n"
2050-
"should be %llu:%llu",
2051-
target->bi_inum, target->bi_snapshot,
2052-
target->bi_dir,
2053-
target->bi_dir_offset,
2054-
d.k->p.inode,
2055-
d.k->p.offset)) {
2056-
target->bi_dir = d.k->p.inode;
2057-
target->bi_dir_offset = d.k->p.offset;
2058-
ret = __bch2_fsck_write_inode(trans, target);
2059-
goto out;
2060-
}
2061-
2062-
bch2_bkey_val_to_text(&buf, c, d.s_c);
2063-
prt_newline(&buf);
2064-
if (backpointer_exists)
2065-
bch2_bkey_val_to_text(&buf, c, bp_dirent.s_c);
2066-
2067-
if (fsck_err_on(backpointer_exists &&
2068-
(S_ISDIR(target->bi_mode) ||
2069-
target->bi_subvol),
2070-
trans, inode_dir_multiple_links,
2071-
"%s %llu:%u with multiple links\n%s",
2072-
S_ISDIR(target->bi_mode) ? "directory" : "subvolume",
2073-
target->bi_inum, target->bi_snapshot, buf.buf)) {
2074-
ret = __remove_dirent(trans, d.k->p);
2075-
goto out;
2076-
}
2077-
2078-
/*
2079-
* hardlinked file with nlink 0:
2080-
* We're just adjusting nlink here so check_nlinks() will pick
2081-
* it up, it ignores inodes with nlink 0
2082-
*/
2083-
if (fsck_err_on(backpointer_exists && !target->bi_nlink,
2084-
trans, inode_multiple_links_but_nlink_0,
2085-
"inode %llu:%u type %s has multiple links but i_nlink 0\n%s",
2086-
target->bi_inum, target->bi_snapshot, bch2_d_types[d.v->d_type], buf.buf)) {
2087-
target->bi_nlink++;
2088-
target->bi_flags &= ~BCH_INODE_unlinked;
2089-
ret = __bch2_fsck_write_inode(trans, target);
2090-
if (ret)
2091-
goto err;
2092-
}
2093-
out:
2094-
err:
2095-
fsck_err:
2096-
bch2_trans_iter_exit(trans, &bp_iter);
2097-
printbuf_exit(&buf);
2098-
bch_err_fn(c, ret);
2099-
return ret;
2100-
}
2101-
2102-
noinline_for_stack
2103-
static int check_dirent_target(struct btree_trans *trans,
2104-
struct btree_iter *iter,
2105-
struct bkey_s_c_dirent d,
2106-
struct bch_inode_unpacked *target)
2107-
{
2108-
struct bch_fs *c = trans->c;
2109-
struct bkey_i_dirent *n;
2110-
struct printbuf buf = PRINTBUF;
2111-
int ret = 0;
2112-
2113-
ret = check_dirent_inode_dirent(trans, iter, d, target);
2114-
if (ret)
2115-
goto err;
2116-
2117-
if (fsck_err_on(d.v->d_type != inode_d_type(target),
2118-
trans, dirent_d_type_wrong,
2119-
"incorrect d_type: got %s, should be %s:\n%s",
2120-
bch2_d_type_str(d.v->d_type),
2121-
bch2_d_type_str(inode_d_type(target)),
2122-
(printbuf_reset(&buf),
2123-
bch2_bkey_val_to_text(&buf, c, d.s_c), buf.buf))) {
2124-
n = bch2_trans_kmalloc(trans, bkey_bytes(d.k));
2125-
ret = PTR_ERR_OR_ZERO(n);
2126-
if (ret)
2127-
goto err;
2128-
2129-
bkey_reassemble(&n->k_i, d.s_c);
2130-
n->v.d_type = inode_d_type(target);
2131-
if (n->v.d_type == DT_SUBVOL) {
2132-
n->v.d_parent_subvol = cpu_to_le32(target->bi_parent_subvol);
2133-
n->v.d_child_subvol = cpu_to_le32(target->bi_subvol);
2134-
} else {
2135-
n->v.d_inum = cpu_to_le64(target->bi_inum);
2136-
}
2137-
2138-
ret = bch2_trans_update(trans, iter, &n->k_i, 0);
2139-
if (ret)
2140-
goto err;
2141-
2142-
d = dirent_i_to_s_c(n);
2143-
}
2144-
err:
2145-
fsck_err:
2146-
printbuf_exit(&buf);
2147-
bch_err_fn(c, ret);
2148-
return ret;
2149-
}
2150-
21511932
/* find a subvolume that's a descendent of @snapshot: */
21521933
static int find_snapshot_subvol(struct btree_trans *trans, u32 snapshot, u32 *subvolid)
21531934
{
@@ -2247,7 +2028,7 @@ static int check_dirent_to_subvol(struct btree_trans *trans, struct btree_iter *
22472028
if (fsck_err(trans, dirent_to_missing_subvol,
22482029
"dirent points to missing subvolume\n%s",
22492030
(bch2_bkey_val_to_text(&buf, c, d.s_c), buf.buf)))
2250-
return __remove_dirent(trans, d.k->p);
2031+
return bch2_fsck_remove_dirent(trans, d.k->p);
22512032
ret = 0;
22522033
goto out;
22532034
}
@@ -2291,7 +2072,7 @@ static int check_dirent_to_subvol(struct btree_trans *trans, struct btree_iter *
22912072
goto err;
22922073
}
22932074

2294-
ret = check_dirent_target(trans, iter, d, &subvol_root);
2075+
ret = bch2_check_dirent_target(trans, iter, d, &subvol_root);
22952076
if (ret)
22962077
goto err;
22972078
out:
@@ -2378,13 +2159,13 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
23782159
(printbuf_reset(&buf),
23792160
bch2_bkey_val_to_text(&buf, c, k),
23802161
buf.buf))) {
2381-
ret = __remove_dirent(trans, d.k->p);
2162+
ret = bch2_fsck_remove_dirent(trans, d.k->p);
23822163
if (ret)
23832164
goto err;
23842165
}
23852166

23862167
darray_for_each(target->inodes, i) {
2387-
ret = check_dirent_target(trans, iter, d, &i->inode);
2168+
ret = bch2_check_dirent_target(trans, iter, d, &i->inode);
23882169
if (ret)
23892170
goto err;
23902171
}

0 commit comments

Comments
 (0)