mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-12-08 00:00:12 +03:00
Update bcachefs sources to 4550c5c02d57 bcachefs: sysfs trigger_check_inconsistent_replicas
This commit is contained in:
parent
d05552cf02
commit
f13abfac80
@ -1 +1 @@
|
||||
4749aaded066f8efed6819bf616eb4097e25dac2
|
||||
4550c5c02d578afb066ae3949bc6f130f7e3e958
|
||||
|
||||
@ -27,6 +27,8 @@
|
||||
|
||||
#include "util/util.h"
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#ifdef CONFIG_BCACHEFS_DEBUG
|
||||
static int bch2_force_read_device = -1;
|
||||
|
||||
@ -34,6 +36,10 @@ module_param_named(force_read_device, bch2_force_read_device, int, 0644);
|
||||
MODULE_PARM_DESC(force_read_device, "");
|
||||
#endif
|
||||
|
||||
static int bch2_force_read_idx = -1;
|
||||
module_param_named(force_read_idx, bch2_force_read_idx, int, 0644);
|
||||
MODULE_PARM_DESC(force_read_idx, "");
|
||||
|
||||
static const char * const bch2_extent_flags_strs[] = {
|
||||
#define x(n, v) [BCH_EXTENT_FLAG_##n] = #n,
|
||||
BCH_EXTENT_FLAGS()
|
||||
@ -199,6 +205,29 @@ static inline bool ptr_better(struct bch_fs *c,
|
||||
return bch2_get_random_u64_below(p1_latency + p2_latency) > p1_latency;
|
||||
}
|
||||
|
||||
static int pick_read_device_idx(struct bch_fs *c, struct bkey_s_c k,
|
||||
struct extent_ptr_decoded *pick, unsigned idx_want)
|
||||
{
|
||||
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
|
||||
const union bch_extent_entry *entry;
|
||||
struct extent_ptr_decoded p;
|
||||
bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
|
||||
if (p.ptr.unwritten)
|
||||
break;
|
||||
|
||||
if (!idx_want--) {
|
||||
*pick = p;
|
||||
|
||||
struct bch_dev *ca = bch2_dev_rcu_noerror(c, p.ptr.dev);
|
||||
return ca &&
|
||||
bch2_dev_is_online(ca) &&
|
||||
!dev_ptr_stale_rcu(ca, &p.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This picks a non-stale pointer, preferably from a device other than @avoid.
|
||||
* Avoid can be NULL, meaning pick any. If there are no non-stale pointers to
|
||||
@ -215,12 +244,17 @@ int bch2_bkey_pick_read_device(struct bch_fs *c, struct bkey_s_c k,
|
||||
if (k.k->type == KEY_TYPE_error)
|
||||
return bch_err_throw(c, key_type_error);
|
||||
|
||||
rcu_read_lock();
|
||||
guard(rcu)();
|
||||
|
||||
if (unlikely(bch2_force_read_idx >= 0) &&
|
||||
!failed &&
|
||||
pick_read_device_idx(c, k, pick, bch2_force_read_idx))
|
||||
return 1;
|
||||
|
||||
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
|
||||
const union bch_extent_entry *entry;
|
||||
struct extent_ptr_decoded p;
|
||||
u64 pick_latency;
|
||||
|
||||
bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
|
||||
have_dirty_ptrs |= !p.ptr.cached;
|
||||
|
||||
@ -228,10 +262,8 @@ int bch2_bkey_pick_read_device(struct bch_fs *c, struct bkey_s_c k,
|
||||
* Unwritten extent: no need to actually read, treat it as a
|
||||
* hole and return 0s:
|
||||
*/
|
||||
if (p.ptr.unwritten) {
|
||||
rcu_read_unlock();
|
||||
if (p.ptr.unwritten)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Are we being asked to read from a specific device? */
|
||||
if (dev >= 0 && p.ptr.dev != dev)
|
||||
@ -297,7 +329,6 @@ int bch2_bkey_pick_read_device(struct bch_fs *c, struct bkey_s_c k,
|
||||
have_pick = true;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (have_pick)
|
||||
return 1;
|
||||
@ -627,8 +658,7 @@ bool bch2_bkey_narrow_crc(const struct bch_fs *c,
|
||||
{
|
||||
BUG_ON(crc_is_compressed(new));
|
||||
BUG_ON(new.offset);
|
||||
BUG_ON(new.live_size != k->k.size);
|
||||
|
||||
BUG_ON(new.uncompressed_size != new.live_size);
|
||||
|
||||
union bch_extent_entry *old_e = bkey_crc_find(c, k, old);
|
||||
if (!old_e)
|
||||
@ -1381,6 +1411,14 @@ void bch2_extent_crc_unpacked_to_text(struct printbuf *out, struct bch_extent_cr
|
||||
bch2_prt_compression_type(out, crc->compression_type);
|
||||
}
|
||||
|
||||
void bch2_extent_ptr_decoded_to_text(struct printbuf *out, struct bch_fs *c,
|
||||
struct extent_ptr_decoded *p)
|
||||
{
|
||||
bch2_extent_crc_unpacked_to_text(out, &p->crc);
|
||||
prt_newline(out);
|
||||
bch2_extent_ptr_to_text(out, c, &p->ptr);
|
||||
}
|
||||
|
||||
const char * const bch2_extent_entry_types[] = {
|
||||
#define x(t, n, ...) [n] = #t,
|
||||
BCH_EXTENT_ENTRY_TYPES()
|
||||
|
||||
@ -200,6 +200,8 @@ static inline bool crc_is_encoded(struct bch_extent_crc_unpacked crc)
|
||||
}
|
||||
|
||||
void bch2_extent_crc_unpacked_to_text(struct printbuf *, struct bch_extent_crc_unpacked *);
|
||||
void bch2_extent_ptr_decoded_to_text(struct printbuf *, struct bch_fs *,
|
||||
struct extent_ptr_decoded *);
|
||||
|
||||
/* bkey_ptrs: generically over any key type that has ptrs */
|
||||
|
||||
|
||||
@ -1309,6 +1309,14 @@ retry_pick:
|
||||
this_cpu_add(c->counters[BCH_COUNTER_io_move_read], bio_sectors(&rbio->bio));
|
||||
bch2_increment_clock(c, bio_sectors(&rbio->bio), READ);
|
||||
|
||||
if (trace_io_read_enabled()) {
|
||||
CLASS(printbuf, buf)();
|
||||
bch2_bkey_val_to_text(&buf, c, k);
|
||||
prt_printf(&buf, "\nreading from:\n");
|
||||
bch2_extent_ptr_decoded_to_text(&buf, c, &rbio->pick);
|
||||
trace_io_read(c, buf.buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's being moved internally, we don't want to flag it as a cache
|
||||
* hit:
|
||||
|
||||
@ -165,6 +165,7 @@ write_attribute(trigger_freelist_wakeup);
|
||||
write_attribute(trigger_recalc_capacity);
|
||||
write_attribute(trigger_delete_dead_snapshots);
|
||||
write_attribute(trigger_emergency_read_only);
|
||||
write_attribute(trigger_check_inconsistent_replicas);
|
||||
read_attribute(gc_gens_pos);
|
||||
|
||||
read_attribute(uuid);
|
||||
@ -314,6 +315,58 @@ static void bch2_fs_usage_base_to_text(struct printbuf *out, struct bch_fs *c)
|
||||
prt_printf(out, "reserved:\t\t%llu\n", b.reserved);
|
||||
}
|
||||
|
||||
static bool bkey_has_inconsistent_checksums(struct bch_fs *c, struct bkey_s_c k)
|
||||
{
|
||||
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
|
||||
const union bch_extent_entry *entry;
|
||||
struct extent_ptr_decoded p, prev;
|
||||
bool have_prev = false;
|
||||
|
||||
bkey_for_each_ptr_decode(k.k, ptrs, p, entry) {
|
||||
if (p.crc.uncompressed_size != p.crc.live_size)
|
||||
continue;
|
||||
|
||||
if (!have_prev) {
|
||||
prev = p;
|
||||
have_prev = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prev.crc.csum_type == p.crc.csum_type &&
|
||||
bch2_crc_cmp(prev.crc.csum, p.crc.csum))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int bkey_print_if_inconsistent_checksums(struct bch_fs *c, struct bkey_s_c k)
|
||||
{
|
||||
if (bkey_has_inconsistent_checksums(c, k)) {
|
||||
CLASS(printbuf, buf)();
|
||||
bch2_bkey_val_to_text(&buf, c, k);
|
||||
pr_info("%s", buf.buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bch2_check_inconsistent_replicas(struct bch_fs *c)
|
||||
{
|
||||
CLASS(btree_trans, trans)(c);
|
||||
for_each_btree_key(trans, iter,
|
||||
BTREE_ID_extents, POS_MIN,
|
||||
BTREE_ITER_all_snapshots, k, ({
|
||||
bkey_print_if_inconsistent_checksums(c, k);
|
||||
}));
|
||||
|
||||
for_each_btree_key(trans, iter,
|
||||
BTREE_ID_reflink, POS_MIN,
|
||||
BTREE_ITER_all_snapshots, k, ({
|
||||
bkey_print_if_inconsistent_checksums(c, k);
|
||||
}));
|
||||
}
|
||||
|
||||
SHOW(bch2_fs)
|
||||
{
|
||||
struct bch_fs *c = container_of(kobj, struct bch_fs, kobj);
|
||||
@ -486,6 +539,9 @@ STORE(bch2_fs)
|
||||
printbuf_exit(&buf);
|
||||
}
|
||||
|
||||
if (attr == &sysfs_trigger_check_inconsistent_replicas)
|
||||
bch2_check_inconsistent_replicas(c);
|
||||
|
||||
#ifdef CONFIG_BCACHEFS_TESTS
|
||||
if (attr == &sysfs_perf_test) {
|
||||
char *tmp __free(kfree) = kstrdup(buf, GFP_KERNEL), *p = tmp;
|
||||
@ -622,6 +678,7 @@ struct attribute *bch2_fs_internal_files[] = {
|
||||
&sysfs_trigger_recalc_capacity,
|
||||
&sysfs_trigger_delete_dead_snapshots,
|
||||
&sysfs_trigger_emergency_read_only,
|
||||
&sysfs_trigger_check_inconsistent_replicas,
|
||||
|
||||
&sysfs_gc_gens_pos,
|
||||
|
||||
|
||||
@ -287,6 +287,11 @@ TRACE_EVENT(write_super,
|
||||
|
||||
/* io.c: */
|
||||
|
||||
DEFINE_EVENT(fs_str, io_read,
|
||||
TP_PROTO(struct bch_fs *c, const char *str),
|
||||
TP_ARGS(c, str)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(bio, io_read_promote,
|
||||
TP_PROTO(struct bio *bio),
|
||||
TP_ARGS(bio)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user