aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-04-10 14:39:18 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-04-15 14:41:11 -0400
commit807b250927d9c6e829ddd1ff7eac57bf9b056dab (patch)
treec8c30549383c3b1950ac22fb927729bdd65234cf
parent7f102ee83d83fd918783ca542fac1574f9b2c623 (diff)
downloadbcachefs-tools-807b250927d9c6e829ddd1ff7eac57bf9b056dab.tar.gz
Update bcachefs sources to 504729f99c bcachefs: Allow answering y or n to all fsck errors of given type
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--.bcachefs_revision2
-rw-r--r--include/trace/events/bcachefs.h18
-rw-r--r--libbcachefs/data_update.c79
-rw-r--r--libbcachefs/error.c61
-rw-r--r--libbcachefs/error.h1
-rw-r--r--libbcachefs/fs-io.c28
-rw-r--r--libbcachefs/fs.c2
-rw-r--r--libbcachefs/recovery.c2
-rw-r--r--libbcachefs/sysfs.c4
9 files changed, 170 insertions, 27 deletions
diff --git a/.bcachefs_revision b/.bcachefs_revision
index febf3dcf..192f42ea 100644
--- a/.bcachefs_revision
+++ b/.bcachefs_revision
@@ -1 +1 @@
-8fd009dd764dabd79e2b42e1c85812a08ad1d6c0
+504729f99c4e1655be1da3e8c62d20b790483eba
diff --git a/include/trace/events/bcachefs.h b/include/trace/events/bcachefs.h
index 2f6acfc7..8f0f1606 100644
--- a/include/trace/events/bcachefs.h
+++ b/include/trace/events/bcachefs.h
@@ -682,9 +682,21 @@ DEFINE_EVENT(bkey, move_extent_finish,
TP_ARGS(k)
);
-DEFINE_EVENT(bkey, move_extent_fail,
- TP_PROTO(const struct bkey *k),
- TP_ARGS(k)
+TRACE_EVENT(move_extent_fail,
+ TP_PROTO(struct bch_fs *c, const char *msg),
+ TP_ARGS(c, msg),
+
+ TP_STRUCT__entry(
+ __field(dev_t, dev )
+ __string(msg, msg )
+ ),
+
+ TP_fast_assign(
+ __entry->dev = c->dev;
+ __assign_str(msg, msg);
+ ),
+
+ TP_printk("%d:%d %s", MAJOR(__entry->dev), MINOR(__entry->dev), __get_str(msg))
);
DEFINE_EVENT(bkey, move_extent_alloc_mem_fail,
diff --git a/libbcachefs/data_update.c b/libbcachefs/data_update.c
index de808fcc..6b0a5fbe 100644
--- a/libbcachefs/data_update.c
+++ b/libbcachefs/data_update.c
@@ -7,6 +7,7 @@
#include "buckets.h"
#include "data_update.h"
#include "ec.h"
+#include "error.h"
#include "extents.h"
#include "io.h"
#include "keylist.h"
@@ -92,6 +93,70 @@ static int insert_snapshot_whiteouts(struct btree_trans *trans,
return ret;
}
+static void trace_move_extent_fail2(struct data_update *m,
+ struct bkey_s_c new,
+ struct bkey_s_c wrote,
+ struct bkey_i *insert,
+ const char *msg)
+{
+ struct bch_fs *c = m->op.c;
+ struct bkey_s_c old = bkey_i_to_s_c(m->k.k);
+ const union bch_extent_entry *entry;
+ struct bch_extent_ptr *ptr;
+ struct extent_ptr_decoded p;
+ struct printbuf buf = PRINTBUF;
+ unsigned i, rewrites_found = 0;
+
+ if (!trace_move_extent_fail_enabled())
+ return;
+
+ prt_str(&buf, msg);
+
+ if (insert) {
+ i = 0;
+ bkey_for_each_ptr_decode(old.k, bch2_bkey_ptrs_c(old), p, entry) {
+ struct bkey_s new_s;
+ new_s.k = (void *) new.k;
+ new_s.v = (void *) new.v;
+
+ if (((1U << i) & m->data_opts.rewrite_ptrs) &&
+ (ptr = bch2_extent_has_ptr(old, p, bkey_i_to_s(insert))) &&
+ !ptr->cached)
+ rewrites_found |= 1U << i;
+ i++;
+ }
+ }
+
+ prt_printf(&buf, "\nrewrite ptrs: %u%u%u%u",
+ (m->data_opts.rewrite_ptrs & (1 << 0)) != 0,
+ (m->data_opts.rewrite_ptrs & (1 << 1)) != 0,
+ (m->data_opts.rewrite_ptrs & (1 << 2)) != 0,
+ (m->data_opts.rewrite_ptrs & (1 << 3)) != 0);
+
+ prt_printf(&buf, "\nrewrites found: %u%u%u%u",
+ (rewrites_found & (1 << 0)) != 0,
+ (rewrites_found & (1 << 1)) != 0,
+ (rewrites_found & (1 << 2)) != 0,
+ (rewrites_found & (1 << 3)) != 0);
+
+ prt_str(&buf, "\nold: ");
+ bch2_bkey_val_to_text(&buf, c, old);
+
+ prt_str(&buf, "\nnew: ");
+ bch2_bkey_val_to_text(&buf, c, new);
+
+ prt_str(&buf, "\nwrote: ");
+ bch2_bkey_val_to_text(&buf, c, wrote);
+
+ if (insert) {
+ prt_str(&buf, "\ninsert: ");
+ bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(insert));
+ }
+
+ trace_move_extent_fail(c, buf.buf);
+ printbuf_exit(&buf);
+}
+
static int __bch2_data_update_index_update(struct btree_trans *trans,
struct bch_write_op *op)
{
@@ -135,8 +200,11 @@ static int __bch2_data_update_index_update(struct btree_trans *trans,
new = bkey_i_to_extent(bch2_keylist_front(keys));
- if (!bch2_extents_match(k, old))
+ if (!bch2_extents_match(k, old)) {
+ trace_move_extent_fail2(m, k, bkey_i_to_s_c(&new->k_i),
+ NULL, "no match:");
goto nowork;
+ }
bkey_reassemble(_insert.k, k);
insert = _insert.k;
@@ -175,8 +243,10 @@ static int __bch2_data_update_index_update(struct btree_trans *trans,
if (m->data_opts.rewrite_ptrs &&
!rewrites_found &&
- bch2_bkey_durability(c, k) >= m->op.opts.data_replicas)
+ bch2_bkey_durability(c, k) >= m->op.opts.data_replicas) {
+ trace_move_extent_fail2(m, k, bkey_i_to_s_c(&new->k_i), insert, "no rewrites found:");
goto nowork;
+ }
/*
* A replica that we just wrote might conflict with a replica
@@ -190,8 +260,10 @@ restart_drop_conflicting_replicas:
goto restart_drop_conflicting_replicas;
}
- if (!bkey_val_u64s(&new->k))
+ if (!bkey_val_u64s(&new->k)) {
+ trace_move_extent_fail2(m, k, bkey_i_to_s_c(&new->k_i), insert, "new replicas conflicted:");
goto nowork;
+ }
/* Now, drop pointers that conflict with what we just wrote: */
extent_for_each_ptr_decode(extent_i_to_s(new), p, entry)
@@ -294,7 +366,6 @@ nowork:
}
this_cpu_add(c->counters[BCH_COUNTER_move_extent_fail], new->k.size);
- trace_move_extent_fail(&new->k);
bch2_btree_iter_advance(&iter);
goto next;
diff --git a/libbcachefs/error.c b/libbcachefs/error.c
index 1dae649f..b9076fee 100644
--- a/libbcachefs/error.c
+++ b/libbcachefs/error.c
@@ -65,10 +65,47 @@ void bch2_io_error(struct bch_dev *ca)
//queue_work(system_long_wq, &ca->io_error_work);
}
+enum ask_yn {
+ YN_NO,
+ YN_YES,
+ YN_ALLNO,
+ YN_ALLYES,
+};
+
#ifdef __KERNEL__
-#define ask_yn() false
+#define bch2_fsck_ask_yn() YN_NO
#else
-#include "tools-util.h"
+enum ask_yn bch2_fsck_ask_yn(void)
+{
+ char *buf = NULL;
+ size_t buflen = 0;
+ bool ret;
+
+ while (true) {
+ fputs(" (y,n,Y,N) ", stdout);
+ fflush(stdout);
+
+ if (getline(&buf, &buflen, stdin) < 0)
+ die("error reading from standard input");
+
+ if (strlen(buf) != 1)
+ continue;
+
+ switch (buf[0]) {
+ case 'n':
+ return YN_NO;
+ case 'y':
+ return YN_YES;
+ case 'N':
+ return YN_ALLNO;
+ case 'Y':
+ return YN_ALLYES;
+ }
+ }
+
+ free(buf);
+ return ret;
+}
#endif
static struct fsck_err_state *fsck_err_get(struct bch_fs *c, const char *fmt)
@@ -161,14 +198,28 @@ int bch2_fsck_err(struct bch_fs *c, unsigned flags, const char *fmt, ...)
prt_str(out, ", exiting");
ret = -BCH_ERR_fsck_errors_not_fixed;
} else if (flags & FSCK_CAN_FIX) {
- if (c->opts.fix_errors == FSCK_OPT_ASK) {
+ int fix = s && s->fix
+ ? s->fix
+ : c->opts.fix_errors;
+
+ if (fix == FSCK_OPT_ASK) {
+ int ask;
+
prt_str(out, ": fix?");
bch2_print_string_as_lines(KERN_ERR, out->buf);
print = false;
- ret = ask_yn()
+
+ ask = bch2_fsck_ask_yn();
+
+ if (ask >= YN_ALLNO && s)
+ s->fix = ask == YN_ALLNO
+ ? FSCK_OPT_NO
+ : FSCK_OPT_YES;
+
+ ret = ask & 1
? -BCH_ERR_fsck_fix
: -BCH_ERR_fsck_ignore;
- } else if (c->opts.fix_errors == FSCK_OPT_YES ||
+ } else if (fix == FSCK_OPT_YES ||
(c->opts.nochanges &&
!(flags & FSCK_CAN_IGNORE))) {
prt_str(out, ", fixing");
diff --git a/libbcachefs/error.h b/libbcachefs/error.h
index 91c7e4ee..edf12443 100644
--- a/libbcachefs/error.h
+++ b/libbcachefs/error.h
@@ -104,6 +104,7 @@ struct fsck_err_state {
u64 nr;
bool ratelimited;
int ret;
+ int fix;
char *last_msg;
};
diff --git a/libbcachefs/fs-io.c b/libbcachefs/fs-io.c
index db138570..f706a99a 100644
--- a/libbcachefs/fs-io.c
+++ b/libbcachefs/fs-io.c
@@ -35,7 +35,13 @@
#include <trace/events/bcachefs.h>
#include <trace/events/writeback.h>
-static inline loff_t folio_end_pos(struct folio *folio)
+/*
+ * Use u64 for the end pos and sector helpers because if the folio covers the
+ * max supported range of the mapping, the start offset of the next folio
+ * overflows loff_t. This breaks much of the range based processing in the
+ * buffered write path.
+ */
+static inline u64 folio_end_pos(struct folio *folio)
{
return folio_pos(folio) + folio_size(folio);
}
@@ -50,7 +56,7 @@ static inline loff_t folio_sector(struct folio *folio)
return folio_pos(folio) >> 9;
}
-static inline loff_t folio_end_sector(struct folio *folio)
+static inline u64 folio_end_sector(struct folio *folio)
{
return folio_end_pos(folio) >> 9;
}
@@ -58,12 +64,12 @@ static inline loff_t folio_end_sector(struct folio *folio)
typedef DARRAY(struct folio *) folios;
static int filemap_get_contig_folios_d(struct address_space *mapping,
- loff_t start, loff_t end,
+ loff_t start, u64 end,
int fgp_flags, gfp_t gfp,
folios *folios)
{
struct folio *f;
- loff_t pos = start;
+ u64 pos = start;
int ret = 0;
while (pos < end) {
@@ -1819,7 +1825,7 @@ static int __bch2_buffered_write(struct bch_inode_info *inode,
folios folios;
struct folio **fi, *f;
unsigned copied = 0, f_offset;
- loff_t end = pos + len, f_pos;
+ u64 end = pos + len, f_pos;
loff_t last_folio_pos = inode->v.i_size;
int ret = 0;
@@ -1861,7 +1867,7 @@ static int __bch2_buffered_write(struct bch_inode_info *inode,
f_offset = pos - folio_pos(darray_first(folios));
darray_for_each(folios, fi) {
struct folio *f = *fi;
- unsigned f_len = min(end, folio_end_pos(f)) - f_pos;
+ u64 f_len = min(end, folio_end_pos(f)) - f_pos;
if (!bch2_folio_create(f, __GFP_NOFAIL)->uptodate) {
ret = bch2_folio_set(c, inode_inum(inode), fi,
@@ -1900,7 +1906,7 @@ static int __bch2_buffered_write(struct bch_inode_info *inode,
f_offset = pos - folio_pos(darray_first(folios));
darray_for_each(folios, fi) {
struct folio *f = *fi;
- unsigned f_len = min(end, folio_end_pos(f)) - f_pos;
+ u64 f_len = min(end, folio_end_pos(f)) - f_pos;
unsigned f_copied = copy_folio_from_iter_atomic(f, f_offset, f_len, iter);
if (!f_copied) {
@@ -1942,7 +1948,7 @@ static int __bch2_buffered_write(struct bch_inode_info *inode,
f_offset = pos - folio_pos(darray_first(folios));
darray_for_each(folios, fi) {
struct folio *f = *fi;
- unsigned f_len = min(end, folio_end_pos(f)) - f_pos;
+ u64 f_len = min(end, folio_end_pos(f)) - f_pos;
if (!folio_test_uptodate(f))
folio_mark_uptodate(f);
@@ -2774,7 +2780,7 @@ static int __bch2_truncate_folio(struct bch_inode_info *inode,
struct folio *folio;
s64 i_sectors_delta = 0;
int ret = 0;
- loff_t end_pos;
+ u64 end_pos;
folio = filemap_lock_folio(mapping, index);
if (!folio) {
@@ -2800,7 +2806,7 @@ static int __bch2_truncate_folio(struct bch_inode_info *inode,
BUG_ON(end <= folio_pos(folio));
start_offset = max(start, folio_pos(folio)) - folio_pos(folio);
- end_offset = min(end, folio_end_pos(folio)) - folio_pos(folio);
+ end_offset = min_t(u64, end, folio_end_pos(folio)) - folio_pos(folio);
/* Folio boundary? Nothing to do */
if (start_offset == 0 &&
@@ -2851,7 +2857,7 @@ static int __bch2_truncate_folio(struct bch_inode_info *inode,
WARN_ON_ONCE(folio_pos(folio) >= inode->v.i_size);
end_pos = folio_end_pos(folio);
if (inode->v.i_size > folio_pos(folio))
- end_pos = min(inode->v.i_size, end_pos);
+ end_pos = min_t(u64, inode->v.i_size, end_pos);
ret = s->s[(end_pos - folio_pos(folio) - 1) >> 9].state >= SECTOR_dirty;
folio_zero_segment(folio, start_offset, end_offset);
diff --git a/libbcachefs/fs.c b/libbcachefs/fs.c
index fab80d9c..6dbbc6ff 100644
--- a/libbcachefs/fs.c
+++ b/libbcachefs/fs.c
@@ -1896,7 +1896,7 @@ out:
err_put_super:
deactivate_locked_super(sb);
- return ERR_PTR(ret);
+ return ERR_PTR(bch2_err_class(ret));
}
static void bch2_kill_sb(struct super_block *sb)
diff --git a/libbcachefs/recovery.c b/libbcachefs/recovery.c
index 8cc8af6d..91a66b59 100644
--- a/libbcachefs/recovery.c
+++ b/libbcachefs/recovery.c
@@ -543,6 +543,8 @@ static int journal_keys_sort(struct bch_fs *c)
if (!i || i->ignore)
continue;
+ cond_resched();
+
for_each_jset_key(k, entry, &i->j) {
if (keys->nr == keys->size) {
__journal_keys_sort(keys);
diff --git a/libbcachefs/sysfs.c b/libbcachefs/sysfs.c
index 1344ae4c..0f86a6c0 100644
--- a/libbcachefs/sysfs.c
+++ b/libbcachefs/sysfs.c
@@ -602,12 +602,12 @@ SHOW(bch2_fs_counters)
counter_since_mount = counter - c->counters_on_mount[BCH_COUNTER_##t];\
prt_printf(out, "since mount:"); \
prt_tab(out); \
- prt_human_readable_u64(out, counter_since_mount << 9); \
+ prt_human_readable_u64(out, counter_since_mount); \
prt_newline(out); \
\
prt_printf(out, "since filesystem creation:"); \
prt_tab(out); \
- prt_human_readable_u64(out, counter << 9); \
+ prt_human_readable_u64(out, counter); \
prt_newline(out); \
}
BCH_PERSISTENT_COUNTERS()