bcachefs: bch2_dev_missing_bkey()

Part of the ongoing project to kill off bch2_(fs|trans)_inconsistent
calls - they generally need to be replaced with either

- a fsck_err() call that can repair the error, or

- logging an error of the appropriate type in the superblock, and
  flagging the appropriate recovery pass to repair the error

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet
2025-04-15 14:08:42 -04:00
parent 2085325171
commit 040c762152
3 changed files with 35 additions and 5 deletions

View File

@@ -158,7 +158,15 @@ int bch2_bkey_pick_read_device(struct bch_fs *c, struct bkey_s_c k,
if (dev >= 0 && p.ptr.dev != dev)
continue;
struct bch_dev *ca = bch2_dev_rcu(c, p.ptr.dev);
struct bch_dev *ca = bch2_dev_rcu_noerror(c, p.ptr.dev);
if (unlikely(!ca && p.ptr.dev != BCH_SB_MEMBER_INVALID)) {
rcu_read_unlock();
int ret = bch2_dev_missing_bkey(c, k, p.ptr.dev);
if (ret)
return ret;
rcu_read_lock();
}
if (p.ptr.cached && (!ca || dev_ptr_stale_rcu(ca, &p.ptr)))
continue;

View File

@@ -5,11 +5,31 @@
#include "disk_groups.h"
#include "error.h"
#include "opts.h"
#include "recovery_passes.h"
#include "replicas.h"
#include "sb-members.h"
#include "super-io.h"
void bch2_dev_missing(struct bch_fs *c, unsigned dev)
int bch2_dev_missing_bkey(struct bch_fs *c, struct bkey_s_c k, unsigned dev)
{
struct printbuf buf = PRINTBUF;
bch2_log_msg_start(c, &buf);
prt_printf(&buf, "pointer to nonexistent device %u in key\n", dev);
bch2_bkey_val_to_text(&buf, c, k);
bool print = bch2_count_fsck_err(c, ptr_to_invalid_device, &buf);
int ret = bch2_run_explicit_recovery_pass_printbuf(c, &buf,
BCH_RECOVERY_PASS_check_allocations);
if (print)
bch2_print_string_as_lines(KERN_ERR, buf.buf);
printbuf_exit(&buf);
return ret;
}
void bch2_dev_missing_atomic(struct bch_fs *c, unsigned dev)
{
if (dev != BCH_SB_MEMBER_INVALID)
bch2_fs_inconsistent(c, "pointer to nonexistent device %u", dev);

View File

@@ -218,13 +218,15 @@ static inline struct bch_dev *bch2_dev_rcu_noerror(struct bch_fs *c, unsigned de
: NULL;
}
void bch2_dev_missing(struct bch_fs *, unsigned);
int bch2_dev_missing_bkey(struct bch_fs *, struct bkey_s_c, unsigned);
void bch2_dev_missing_atomic(struct bch_fs *, unsigned);
static inline struct bch_dev *bch2_dev_rcu(struct bch_fs *c, unsigned dev)
{
struct bch_dev *ca = bch2_dev_rcu_noerror(c, dev);
if (unlikely(!ca))
bch2_dev_missing(c, dev);
bch2_dev_missing_atomic(c, dev);
return ca;
}
@@ -242,7 +244,7 @@ static inline struct bch_dev *bch2_dev_tryget(struct bch_fs *c, unsigned dev)
{
struct bch_dev *ca = bch2_dev_tryget_noerror(c, dev);
if (unlikely(!ca))
bch2_dev_missing(c, dev);
bch2_dev_missing_atomic(c, dev);
return ca;
}