]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
Update bcachefs sources to 504729f99c bcachefs: Allow answering y or n to all fsck...
authorKent Overstreet <kent.overstreet@linux.dev>
Mon, 10 Apr 2023 18:39:18 +0000 (14:39 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 15 Apr 2023 18:41:11 +0000 (14:41 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
.bcachefs_revision
include/trace/events/bcachefs.h
libbcachefs/data_update.c
libbcachefs/error.c
libbcachefs/error.h
libbcachefs/fs-io.c
libbcachefs/fs.c
libbcachefs/recovery.c
libbcachefs/sysfs.c

index febf3dcf912ee699a4413fc281bd521264a22d1d..192f42ea9bbc57652a8344a95ea453d518b7e30e 100644 (file)
@@ -1 +1 @@
-8fd009dd764dabd79e2b42e1c85812a08ad1d6c0
+504729f99c4e1655be1da3e8c62d20b790483eba
index 2f6acfc7c15829be95400ffbdc1723e19d72d5ae..8f0f1606128542f5bdd2d57ac76c13a27859cf02 100644 (file)
@@ -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,
index de808fcc64f11f3773239c3277827c336fdf5d7c..6b0a5fbe377ca59607fcdac49dd4c4984332fac0 100644 (file)
@@ -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;
index 1dae649ff0e223386eefe0e1992ddd564f020197..b9076fee44082b4a50697e20e49699e62ae58941 100644 (file)
@@ -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");
index 91c7e4ee8f7266ea193414461a145236e7dc5277..edf12443822c2599fe99651b3fd1855d40f18c00 100644 (file)
@@ -104,6 +104,7 @@ struct fsck_err_state {
        u64                     nr;
        bool                    ratelimited;
        int                     ret;
+       int                     fix;
        char                    *last_msg;
 };
 
index db1385701f0827d86da1b30901b3b98944f55a83..f706a99ad5c5a3d1540b9f557c5e5b693dbac6f4 100644 (file)
 #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);
index fab80d9cfb1a35ff4802117b9f3cb47b49291aba..6dbbc6ff4cb8a5e51959621bc3cefe5c5cfd3b3c 100644 (file)
@@ -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)
index 8cc8af6d29ef0ad6106a8b151627be14edc67a73..91a66b5916eb7ed0d2629c0ee64424678ae7ec3b 100644 (file)
@@ -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);
index 1344ae4cb28f6657c7caf0f8c925fc956524c56c..0f86a6c0c9d8420fd8a7493d6422b414f453674f 100644 (file)
@@ -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()