bcachefs: check for failure to downgrade
authorKent Overstreet <kent.overstreet@linux.dev>
Sat, 23 Dec 2023 02:58:43 +0000 (21:58 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Mon, 1 Jan 2024 16:47:42 +0000 (11:47 -0500)
With the upcoming member seq patch, it's now critical that we don't ever
write to a superblock that hasn't been version downgraded - failure to
update member seq fields will cause split brain detection to fire
erroniously.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/errcode.h
fs/bcachefs/super-io.c

index c39bea441983f6e7516ff7e864851fb246ecea43..d7dc8f644a05c05f53a6ca9c5a7877af0b19ab30 100644 (file)
        x(BCH_ERR_invalid,              invalid_bkey)                           \
        x(BCH_ERR_operation_blocked,    nocow_lock_blocked)                     \
        x(EIO,                          btree_node_read_err)                    \
+       x(EIO,                          sb_not_downgraded)                      \
        x(BCH_ERR_btree_node_read_err,  btree_node_read_err_fixable)            \
        x(BCH_ERR_btree_node_read_err,  btree_node_read_err_want_retry)         \
        x(BCH_ERR_btree_node_read_err,  btree_node_read_err_must_retry)         \
index 55e560c198dee5d09e8cb4b3483d59e215cac1c6..b610dfb0287aebb7ef100289a72767d2a7d0e9bf 100644 (file)
@@ -987,6 +987,18 @@ int bch2_write_super(struct bch_fs *c)
        if (!BCH_SB_INITIALIZED(c->disk_sb.sb))
                goto out;
 
+       if (le16_to_cpu(c->disk_sb.sb->version) > bcachefs_metadata_version_current) {
+               struct printbuf buf = PRINTBUF;
+               prt_printf(&buf, "attempting to write superblock that wasn't version downgraded (");
+               bch2_version_to_text(&buf, le16_to_cpu(c->disk_sb.sb->version));
+               prt_str(&buf, " > ");
+               bch2_version_to_text(&buf, bcachefs_metadata_version_current);
+               prt_str(&buf, ")");
+               bch2_fs_fatal_error(c, "%s", buf.buf);
+               printbuf_exit(&buf);
+               return -BCH_ERR_sb_not_downgraded;
+       }
+
        for_each_online_member(ca, c, i) {
                __set_bit(ca->dev_idx, sb_written.d);
                ca->sb_write_error = 0;