535 lines
15 KiB
Diff
535 lines
15 KiB
Diff
From 0ecfac8b60c8ad86a9d60aa6e5ec3acaeeb96064 Mon Sep 17 00:00:00 2001
|
|
From: Kent Overstreet <kent.overstreet@linux.dev>
|
|
Date: Wed, 4 Dec 2024 23:36:33 -0500
|
|
Subject: [PATCH 174/233] bcachefs: factor out str_hash.c
|
|
Content-Type: text/plain; charset="utf-8"
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
|
|
Signed-off-by: Alexander Miroshnichenko <alex@millerson.name>
|
|
---
|
|
fs/bcachefs/Makefile | 1 +
|
|
fs/bcachefs/fsck.c | 214 ++---------------------------------------
|
|
fs/bcachefs/fsck.h | 8 ++
|
|
fs/bcachefs/str_hash.c | 209 ++++++++++++++++++++++++++++++++++++++++
|
|
fs/bcachefs/str_hash.h | 7 ++
|
|
5 files changed, 232 insertions(+), 207 deletions(-)
|
|
create mode 100644 fs/bcachefs/str_hash.c
|
|
|
|
diff --git a/fs/bcachefs/Makefile b/fs/bcachefs/Makefile
|
|
index 56d20e219f59..d2689388d5e8 100644
|
|
--- a/fs/bcachefs/Makefile
|
|
+++ b/fs/bcachefs/Makefile
|
|
@@ -82,6 +82,7 @@ bcachefs-y := \
|
|
siphash.o \
|
|
six.o \
|
|
snapshot.o \
|
|
+ str_hash.o \
|
|
subvolume.o \
|
|
super.o \
|
|
super-io.o \
|
|
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c
|
|
index 1e00b2694db7..22a33b9ba30d 100644
|
|
--- a/fs/bcachefs/fsck.c
|
|
+++ b/fs/bcachefs/fsck.c
|
|
@@ -941,69 +941,16 @@ static int get_visible_inodes(struct btree_trans *trans,
|
|
return ret;
|
|
}
|
|
|
|
-static int dirent_has_target(struct btree_trans *trans, struct bkey_s_c_dirent d)
|
|
-{
|
|
- if (d.v->d_type == DT_SUBVOL) {
|
|
- u32 snap;
|
|
- u64 inum;
|
|
- int ret = subvol_lookup(trans, le32_to_cpu(d.v->d_child_subvol), &snap, &inum);
|
|
- if (ret && !bch2_err_matches(ret, ENOENT))
|
|
- return ret;
|
|
- return !ret;
|
|
- } else {
|
|
- struct btree_iter iter;
|
|
- struct bkey_s_c k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_inodes,
|
|
- SPOS(0, le64_to_cpu(d.v->d_inum), d.k->p.snapshot), 0);
|
|
- int ret = bkey_err(k);
|
|
- if (ret)
|
|
- return ret;
|
|
-
|
|
- ret = bkey_is_inode(k.k);
|
|
- bch2_trans_iter_exit(trans, &iter);
|
|
- return ret;
|
|
- }
|
|
-}
|
|
-
|
|
/*
|
|
* Prefer to delete the first one, since that will be the one at the wrong
|
|
* offset:
|
|
* return value: 0 -> delete k1, 1 -> delete k2
|
|
*/
|
|
-static int hash_pick_winner(struct btree_trans *trans,
|
|
- const struct bch_hash_desc desc,
|
|
- struct bch_hash_info *hash_info,
|
|
- struct bkey_s_c k1,
|
|
- struct bkey_s_c k2)
|
|
-{
|
|
- if (bkey_val_bytes(k1.k) == bkey_val_bytes(k2.k) &&
|
|
- !memcmp(k1.v, k2.v, bkey_val_bytes(k1.k)))
|
|
- return 0;
|
|
-
|
|
- switch (desc.btree_id) {
|
|
- case BTREE_ID_dirents: {
|
|
- int ret = dirent_has_target(trans, bkey_s_c_to_dirent(k1));
|
|
- if (ret < 0)
|
|
- return ret;
|
|
- if (!ret)
|
|
- return 0;
|
|
-
|
|
- ret = dirent_has_target(trans, bkey_s_c_to_dirent(k2));
|
|
- if (ret < 0)
|
|
- return ret;
|
|
- if (!ret)
|
|
- return 1;
|
|
- return 2;
|
|
- }
|
|
- default:
|
|
- return 0;
|
|
- }
|
|
-}
|
|
-
|
|
-static int fsck_update_backpointers(struct btree_trans *trans,
|
|
- struct snapshots_seen *s,
|
|
- const struct bch_hash_desc desc,
|
|
- struct bch_hash_info *hash_info,
|
|
- struct bkey_i *new)
|
|
+int bch2_fsck_update_backpointers(struct btree_trans *trans,
|
|
+ struct snapshots_seen *s,
|
|
+ const struct bch_hash_desc desc,
|
|
+ struct bch_hash_info *hash_info,
|
|
+ struct bkey_i *new)
|
|
{
|
|
if (new->k.type != KEY_TYPE_dirent)
|
|
return 0;
|
|
@@ -1031,153 +978,6 @@ static int fsck_update_backpointers(struct btree_trans *trans,
|
|
return ret;
|
|
}
|
|
|
|
-static int fsck_rename_dirent(struct btree_trans *trans,
|
|
- struct snapshots_seen *s,
|
|
- const struct bch_hash_desc desc,
|
|
- struct bch_hash_info *hash_info,
|
|
- struct bkey_s_c_dirent old)
|
|
-{
|
|
- struct qstr old_name = bch2_dirent_get_name(old);
|
|
- struct bkey_i_dirent *new = bch2_trans_kmalloc(trans, bkey_bytes(old.k) + 32);
|
|
- int ret = PTR_ERR_OR_ZERO(new);
|
|
- if (ret)
|
|
- return ret;
|
|
-
|
|
- bkey_dirent_init(&new->k_i);
|
|
- dirent_copy_target(new, old);
|
|
- new->k.p = old.k->p;
|
|
-
|
|
- for (unsigned i = 0; i < 1000; i++) {
|
|
- unsigned len = sprintf(new->v.d_name, "%.*s.fsck_renamed-%u",
|
|
- old_name.len, old_name.name, i);
|
|
- unsigned u64s = BKEY_U64s + dirent_val_u64s(len);
|
|
-
|
|
- if (u64s > U8_MAX)
|
|
- return -EINVAL;
|
|
-
|
|
- new->k.u64s = u64s;
|
|
-
|
|
- ret = bch2_hash_set_in_snapshot(trans, bch2_dirent_hash_desc, hash_info,
|
|
- (subvol_inum) { 0, old.k->p.inode },
|
|
- old.k->p.snapshot, &new->k_i,
|
|
- BTREE_UPDATE_internal_snapshot_node);
|
|
- if (!bch2_err_matches(ret, EEXIST))
|
|
- break;
|
|
- }
|
|
-
|
|
- if (ret)
|
|
- return ret;
|
|
-
|
|
- return fsck_update_backpointers(trans, s, desc, hash_info, &new->k_i);
|
|
-}
|
|
-
|
|
-static int hash_check_key(struct btree_trans *trans,
|
|
- struct snapshots_seen *s,
|
|
- const struct bch_hash_desc desc,
|
|
- struct bch_hash_info *hash_info,
|
|
- struct btree_iter *k_iter, struct bkey_s_c hash_k)
|
|
-{
|
|
- struct bch_fs *c = trans->c;
|
|
- struct btree_iter iter = { NULL };
|
|
- struct printbuf buf = PRINTBUF;
|
|
- struct bkey_s_c k;
|
|
- u64 hash;
|
|
- int ret = 0;
|
|
-
|
|
- if (hash_k.k->type != desc.key_type)
|
|
- return 0;
|
|
-
|
|
- hash = desc.hash_bkey(hash_info, hash_k);
|
|
-
|
|
- if (likely(hash == hash_k.k->p.offset))
|
|
- return 0;
|
|
-
|
|
- if (hash_k.k->p.offset < hash)
|
|
- goto bad_hash;
|
|
-
|
|
- for_each_btree_key_norestart(trans, iter, desc.btree_id,
|
|
- SPOS(hash_k.k->p.inode, hash, hash_k.k->p.snapshot),
|
|
- BTREE_ITER_slots, k, ret) {
|
|
- if (bkey_eq(k.k->p, hash_k.k->p))
|
|
- break;
|
|
-
|
|
- if (k.k->type == desc.key_type &&
|
|
- !desc.cmp_bkey(k, hash_k))
|
|
- goto duplicate_entries;
|
|
-
|
|
- if (bkey_deleted(k.k)) {
|
|
- bch2_trans_iter_exit(trans, &iter);
|
|
- goto bad_hash;
|
|
- }
|
|
- }
|
|
-out:
|
|
- bch2_trans_iter_exit(trans, &iter);
|
|
- printbuf_exit(&buf);
|
|
- return ret;
|
|
-bad_hash:
|
|
- if (fsck_err(trans, hash_table_key_wrong_offset,
|
|
- "hash table key at wrong offset: btree %s inode %llu offset %llu, hashed to %llu\n %s",
|
|
- bch2_btree_id_str(desc.btree_id), hash_k.k->p.inode, hash_k.k->p.offset, hash,
|
|
- (printbuf_reset(&buf),
|
|
- bch2_bkey_val_to_text(&buf, c, hash_k), buf.buf))) {
|
|
- struct bkey_i *new = bch2_bkey_make_mut_noupdate(trans, hash_k);
|
|
- if (IS_ERR(new))
|
|
- return PTR_ERR(new);
|
|
-
|
|
- k = bch2_hash_set_or_get_in_snapshot(trans, &iter, desc, hash_info,
|
|
- (subvol_inum) { 0, hash_k.k->p.inode },
|
|
- hash_k.k->p.snapshot, new,
|
|
- STR_HASH_must_create|
|
|
- BTREE_ITER_with_updates|
|
|
- BTREE_UPDATE_internal_snapshot_node);
|
|
- ret = bkey_err(k);
|
|
- if (ret)
|
|
- goto out;
|
|
- if (k.k)
|
|
- goto duplicate_entries;
|
|
-
|
|
- ret = bch2_hash_delete_at(trans, desc, hash_info, k_iter,
|
|
- BTREE_UPDATE_internal_snapshot_node) ?:
|
|
- fsck_update_backpointers(trans, s, desc, hash_info, new) ?:
|
|
- bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc) ?:
|
|
- -BCH_ERR_transaction_restart_nested;
|
|
- goto out;
|
|
- }
|
|
-fsck_err:
|
|
- goto out;
|
|
-duplicate_entries:
|
|
- ret = hash_pick_winner(trans, desc, hash_info, hash_k, k);
|
|
- if (ret < 0)
|
|
- goto out;
|
|
-
|
|
- if (!fsck_err(trans, hash_table_key_duplicate,
|
|
- "duplicate hash table keys%s:\n%s",
|
|
- ret != 2 ? "" : ", both point to valid inodes",
|
|
- (printbuf_reset(&buf),
|
|
- bch2_bkey_val_to_text(&buf, c, hash_k),
|
|
- prt_newline(&buf),
|
|
- bch2_bkey_val_to_text(&buf, c, k),
|
|
- buf.buf)))
|
|
- goto out;
|
|
-
|
|
- switch (ret) {
|
|
- case 0:
|
|
- ret = bch2_hash_delete_at(trans, desc, hash_info, k_iter, 0);
|
|
- break;
|
|
- case 1:
|
|
- ret = bch2_hash_delete_at(trans, desc, hash_info, &iter, 0);
|
|
- break;
|
|
- case 2:
|
|
- ret = fsck_rename_dirent(trans, s, desc, hash_info, bkey_s_c_to_dirent(hash_k)) ?:
|
|
- bch2_hash_delete_at(trans, desc, hash_info, k_iter, 0);
|
|
- goto out;
|
|
- }
|
|
-
|
|
- ret = bch2_trans_commit(trans, NULL, NULL, 0) ?:
|
|
- -BCH_ERR_transaction_restart_nested;
|
|
- goto out;
|
|
-}
|
|
-
|
|
static struct bkey_s_c_dirent inode_get_dirent(struct btree_trans *trans,
|
|
struct btree_iter *iter,
|
|
struct bch_inode_unpacked *inode,
|
|
@@ -2496,7 +2296,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
|
|
*hash_info = bch2_hash_info_init(c, &i->inode);
|
|
dir->first_this_inode = false;
|
|
|
|
- ret = hash_check_key(trans, s, bch2_dirent_hash_desc, hash_info, iter, k);
|
|
+ ret = bch2_str_hash_check_key(trans, s, bch2_dirent_hash_desc, hash_info, iter, k);
|
|
if (ret < 0)
|
|
goto err;
|
|
if (ret) {
|
|
@@ -2610,7 +2410,7 @@ static int check_xattr(struct btree_trans *trans, struct btree_iter *iter,
|
|
*hash_info = bch2_hash_info_init(c, &i->inode);
|
|
inode->first_this_inode = false;
|
|
|
|
- ret = hash_check_key(trans, NULL, bch2_xattr_hash_desc, hash_info, iter, k);
|
|
+ ret = bch2_str_hash_check_key(trans, NULL, bch2_xattr_hash_desc, hash_info, iter, k);
|
|
bch_err_fn(c, ret);
|
|
return ret;
|
|
}
|
|
diff --git a/fs/bcachefs/fsck.h b/fs/bcachefs/fsck.h
|
|
index 4481b40a881d..574948278cd4 100644
|
|
--- a/fs/bcachefs/fsck.h
|
|
+++ b/fs/bcachefs/fsck.h
|
|
@@ -2,6 +2,14 @@
|
|
#ifndef _BCACHEFS_FSCK_H
|
|
#define _BCACHEFS_FSCK_H
|
|
|
|
+#include "str_hash.h"
|
|
+
|
|
+int bch2_fsck_update_backpointers(struct btree_trans *,
|
|
+ struct snapshots_seen *,
|
|
+ const struct bch_hash_desc,
|
|
+ struct bch_hash_info *,
|
|
+ struct bkey_i *);
|
|
+
|
|
int bch2_check_inodes(struct bch_fs *);
|
|
int bch2_check_extents(struct bch_fs *);
|
|
int bch2_check_indirect_extents(struct bch_fs *);
|
|
diff --git a/fs/bcachefs/str_hash.c b/fs/bcachefs/str_hash.c
|
|
new file mode 100644
|
|
index 000000000000..c3276a7e7324
|
|
--- /dev/null
|
|
+++ b/fs/bcachefs/str_hash.c
|
|
@@ -0,0 +1,209 @@
|
|
+// SPDX-License-Identifier: GPL-2.0
|
|
+
|
|
+#include "bcachefs.h"
|
|
+#include "btree_cache.h"
|
|
+#include "btree_update.h"
|
|
+#include "dirent.h"
|
|
+#include "fsck.h"
|
|
+#include "str_hash.h"
|
|
+#include "subvolume.h"
|
|
+
|
|
+static int bch2_dirent_has_target(struct btree_trans *trans, struct bkey_s_c_dirent d)
|
|
+{
|
|
+ if (d.v->d_type == DT_SUBVOL) {
|
|
+ struct bch_subvolume subvol;
|
|
+ int ret = bch2_subvolume_get(trans, le32_to_cpu(d.v->d_child_subvol),
|
|
+ false, &subvol);
|
|
+ if (ret && !bch2_err_matches(ret, ENOENT))
|
|
+ return ret;
|
|
+ return !ret;
|
|
+ } else {
|
|
+ struct btree_iter iter;
|
|
+ struct bkey_s_c k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_inodes,
|
|
+ SPOS(0, le64_to_cpu(d.v->d_inum), d.k->p.snapshot), 0);
|
|
+ int ret = bkey_err(k);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = bkey_is_inode(k.k);
|
|
+ bch2_trans_iter_exit(trans, &iter);
|
|
+ return ret;
|
|
+ }
|
|
+}
|
|
+
|
|
+static int fsck_rename_dirent(struct btree_trans *trans,
|
|
+ struct snapshots_seen *s,
|
|
+ const struct bch_hash_desc desc,
|
|
+ struct bch_hash_info *hash_info,
|
|
+ struct bkey_s_c_dirent old)
|
|
+{
|
|
+ struct qstr old_name = bch2_dirent_get_name(old);
|
|
+ struct bkey_i_dirent *new = bch2_trans_kmalloc(trans, bkey_bytes(old.k) + 32);
|
|
+ int ret = PTR_ERR_OR_ZERO(new);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ bkey_dirent_init(&new->k_i);
|
|
+ dirent_copy_target(new, old);
|
|
+ new->k.p = old.k->p;
|
|
+
|
|
+ for (unsigned i = 0; i < 1000; i++) {
|
|
+ unsigned len = sprintf(new->v.d_name, "%.*s.fsck_renamed-%u",
|
|
+ old_name.len, old_name.name, i);
|
|
+ unsigned u64s = BKEY_U64s + dirent_val_u64s(len);
|
|
+
|
|
+ if (u64s > U8_MAX)
|
|
+ return -EINVAL;
|
|
+
|
|
+ new->k.u64s = u64s;
|
|
+
|
|
+ ret = bch2_hash_set_in_snapshot(trans, bch2_dirent_hash_desc, hash_info,
|
|
+ (subvol_inum) { 0, old.k->p.inode },
|
|
+ old.k->p.snapshot, &new->k_i,
|
|
+ BTREE_UPDATE_internal_snapshot_node);
|
|
+ if (!bch2_err_matches(ret, EEXIST))
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ return bch2_fsck_update_backpointers(trans, s, desc, hash_info, &new->k_i);
|
|
+}
|
|
+
|
|
+static int hash_pick_winner(struct btree_trans *trans,
|
|
+ const struct bch_hash_desc desc,
|
|
+ struct bch_hash_info *hash_info,
|
|
+ struct bkey_s_c k1,
|
|
+ struct bkey_s_c k2)
|
|
+{
|
|
+ if (bkey_val_bytes(k1.k) == bkey_val_bytes(k2.k) &&
|
|
+ !memcmp(k1.v, k2.v, bkey_val_bytes(k1.k)))
|
|
+ return 0;
|
|
+
|
|
+ switch (desc.btree_id) {
|
|
+ case BTREE_ID_dirents: {
|
|
+ int ret = bch2_dirent_has_target(trans, bkey_s_c_to_dirent(k1));
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ if (!ret)
|
|
+ return 0;
|
|
+
|
|
+ ret = bch2_dirent_has_target(trans, bkey_s_c_to_dirent(k2));
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ if (!ret)
|
|
+ return 1;
|
|
+ return 2;
|
|
+ }
|
|
+ default:
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+int bch2_str_hash_check_key(struct btree_trans *trans,
|
|
+ struct snapshots_seen *s,
|
|
+ const struct bch_hash_desc desc,
|
|
+ struct bch_hash_info *hash_info,
|
|
+ struct btree_iter *k_iter, struct bkey_s_c hash_k)
|
|
+{
|
|
+ struct bch_fs *c = trans->c;
|
|
+ struct btree_iter iter = { NULL };
|
|
+ struct printbuf buf = PRINTBUF;
|
|
+ struct bkey_s_c k;
|
|
+ u64 hash;
|
|
+ int ret = 0;
|
|
+
|
|
+ if (hash_k.k->type != desc.key_type)
|
|
+ return 0;
|
|
+
|
|
+ hash = desc.hash_bkey(hash_info, hash_k);
|
|
+
|
|
+ if (likely(hash == hash_k.k->p.offset))
|
|
+ return 0;
|
|
+
|
|
+ if (hash_k.k->p.offset < hash)
|
|
+ goto bad_hash;
|
|
+
|
|
+ for_each_btree_key_norestart(trans, iter, desc.btree_id,
|
|
+ SPOS(hash_k.k->p.inode, hash, hash_k.k->p.snapshot),
|
|
+ BTREE_ITER_slots, k, ret) {
|
|
+ if (bkey_eq(k.k->p, hash_k.k->p))
|
|
+ break;
|
|
+
|
|
+ if (k.k->type == desc.key_type &&
|
|
+ !desc.cmp_bkey(k, hash_k))
|
|
+ goto duplicate_entries;
|
|
+
|
|
+ if (bkey_deleted(k.k)) {
|
|
+ bch2_trans_iter_exit(trans, &iter);
|
|
+ goto bad_hash;
|
|
+ }
|
|
+ }
|
|
+out:
|
|
+ bch2_trans_iter_exit(trans, &iter);
|
|
+ printbuf_exit(&buf);
|
|
+ return ret;
|
|
+bad_hash:
|
|
+ if (fsck_err(trans, hash_table_key_wrong_offset,
|
|
+ "hash table key at wrong offset: btree %s inode %llu offset %llu, hashed to %llu\n %s",
|
|
+ bch2_btree_id_str(desc.btree_id), hash_k.k->p.inode, hash_k.k->p.offset, hash,
|
|
+ (printbuf_reset(&buf),
|
|
+ bch2_bkey_val_to_text(&buf, c, hash_k), buf.buf))) {
|
|
+ struct bkey_i *new = bch2_bkey_make_mut_noupdate(trans, hash_k);
|
|
+ if (IS_ERR(new))
|
|
+ return PTR_ERR(new);
|
|
+
|
|
+ k = bch2_hash_set_or_get_in_snapshot(trans, &iter, desc, hash_info,
|
|
+ (subvol_inum) { 0, hash_k.k->p.inode },
|
|
+ hash_k.k->p.snapshot, new,
|
|
+ STR_HASH_must_create|
|
|
+ BTREE_ITER_with_updates|
|
|
+ BTREE_UPDATE_internal_snapshot_node);
|
|
+ ret = bkey_err(k);
|
|
+ if (ret)
|
|
+ goto out;
|
|
+ if (k.k)
|
|
+ goto duplicate_entries;
|
|
+
|
|
+ ret = bch2_hash_delete_at(trans, desc, hash_info, k_iter,
|
|
+ BTREE_UPDATE_internal_snapshot_node) ?:
|
|
+ bch2_fsck_update_backpointers(trans, s, desc, hash_info, new) ?:
|
|
+ bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc) ?:
|
|
+ -BCH_ERR_transaction_restart_nested;
|
|
+ goto out;
|
|
+ }
|
|
+fsck_err:
|
|
+ goto out;
|
|
+duplicate_entries:
|
|
+ ret = hash_pick_winner(trans, desc, hash_info, hash_k, k);
|
|
+ if (ret < 0)
|
|
+ goto out;
|
|
+
|
|
+ if (!fsck_err(trans, hash_table_key_duplicate,
|
|
+ "duplicate hash table keys%s:\n%s",
|
|
+ ret != 2 ? "" : ", both point to valid inodes",
|
|
+ (printbuf_reset(&buf),
|
|
+ bch2_bkey_val_to_text(&buf, c, hash_k),
|
|
+ prt_newline(&buf),
|
|
+ bch2_bkey_val_to_text(&buf, c, k),
|
|
+ buf.buf)))
|
|
+ goto out;
|
|
+
|
|
+ switch (ret) {
|
|
+ case 0:
|
|
+ ret = bch2_hash_delete_at(trans, desc, hash_info, k_iter, 0);
|
|
+ break;
|
|
+ case 1:
|
|
+ ret = bch2_hash_delete_at(trans, desc, hash_info, &iter, 0);
|
|
+ break;
|
|
+ case 2:
|
|
+ ret = fsck_rename_dirent(trans, s, desc, hash_info, bkey_s_c_to_dirent(hash_k)) ?:
|
|
+ bch2_hash_delete_at(trans, desc, hash_info, k_iter, 0);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ ret = bch2_trans_commit(trans, NULL, NULL, 0) ?:
|
|
+ -BCH_ERR_transaction_restart_nested;
|
|
+ goto out;
|
|
+}
|
|
diff --git a/fs/bcachefs/str_hash.h b/fs/bcachefs/str_hash.h
|
|
index 00c785055d22..0c20f3af03f8 100644
|
|
--- a/fs/bcachefs/str_hash.h
|
|
+++ b/fs/bcachefs/str_hash.h
|
|
@@ -393,4 +393,11 @@ int bch2_hash_delete(struct btree_trans *trans,
|
|
return ret;
|
|
}
|
|
|
|
+struct snapshots_seen;
|
|
+int bch2_str_hash_check_key(struct btree_trans *,
|
|
+ struct snapshots_seen *,
|
|
+ const struct bch_hash_desc,
|
|
+ struct bch_hash_info *,
|
|
+ struct btree_iter *, struct bkey_s_c);
|
|
+
|
|
#endif /* _BCACHEFS_STR_HASH_H */
|
|
--
|
|
2.45.2
|
|
|