mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 04:29:11 -04:00
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:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user