bcachefs: Clamp replicas_required to replicas
authorKent Overstreet <kent.overstreet@linux.dev>
Sun, 11 Feb 2024 02:01:40 +0000 (21:01 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Wed, 14 Feb 2024 01:33:38 +0000 (20:33 -0500)
This prevents going emergency read only when the user has specified
replicas_required > replicas.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/bcachefs.h
fs/bcachefs/btree_update_interior.c
fs/bcachefs/io_write.c
fs/bcachefs/journal_io.c
fs/bcachefs/journal_reclaim.c
fs/bcachefs/super.c

index b80c6c9efd8cef95b46b5b45b21f639e18373755..69d0d60d50e366edf9e56ba101dda047536f5338 100644 (file)
@@ -1249,6 +1249,18 @@ static inline struct stdio_redirect *bch2_fs_stdio_redirect(struct bch_fs *c)
        return stdio;
 }
 
+static inline unsigned metadata_replicas_required(struct bch_fs *c)
+{
+       return min(c->opts.metadata_replicas,
+                  c->opts.metadata_replicas_required);
+}
+
+static inline unsigned data_replicas_required(struct bch_fs *c)
+{
+       return min(c->opts.data_replicas,
+                  c->opts.data_replicas_required);
+}
+
 #define BKEY_PADDED_ONSTACK(key, pad)                          \
        struct { struct bkey_i key; __u64 key ## _pad[pad]; }
 
index 17a5938aa71a6b43b45c12383e4690df146ee2a3..4530b14ff2c3717ec15e92615385c04e185e28e1 100644 (file)
@@ -280,7 +280,8 @@ retry:
                                      writepoint_ptr(&c->btree_write_point),
                                      &devs_have,
                                      res->nr_replicas,
-                                     c->opts.metadata_replicas_required,
+                                     min(res->nr_replicas,
+                                         c->opts.metadata_replicas_required),
                                      watermark, 0, cl, &wp);
        if (unlikely(ret))
                return ERR_PTR(ret);
index ef3a53f9045af2591ab1f9e272dd9d6151250444..2c098ac017b30b6a4b5d016e9f5dde93ee258f2f 100644 (file)
@@ -1564,6 +1564,7 @@ CLOSURE_CALLBACK(bch2_write)
        BUG_ON(!op->write_point.v);
        BUG_ON(bkey_eq(op->pos, POS_MAX));
 
+       op->nr_replicas_required = min_t(unsigned, op->nr_replicas_required, op->nr_replicas);
        op->start_time = local_clock();
        bch2_keylist_init(&op->insert_keys, op->inline_keys);
        wbio_init(bio)->put_bio = false;
index bfd6585e746da45880da9b5ad8fb502586cbf933..47805193f18cc72c941f72f5b82cfb461eb8982c 100644 (file)
@@ -1478,6 +1478,8 @@ static int journal_write_alloc(struct journal *j, struct journal_buf *w)
                c->opts.foreground_target;
        unsigned i, replicas = 0, replicas_want =
                READ_ONCE(c->opts.metadata_replicas);
+       unsigned replicas_need = min_t(unsigned, replicas_want,
+                                      READ_ONCE(c->opts.metadata_replicas_required));
 
        rcu_read_lock();
 retry:
@@ -1526,7 +1528,7 @@ done:
 
        BUG_ON(bkey_val_u64s(&w->key.k) > BCH_REPLICAS_MAX);
 
-       return replicas >= c->opts.metadata_replicas_required ? 0 : -EROFS;
+       return replicas >= replicas_need ? 0 : -EROFS;
 }
 
 static void journal_buf_realloc(struct journal *j, struct journal_buf *buf)
index 820d25e19e5fe3ee6a45e70f23eb74fc1d558e88..2cf626315652c0054df96ffce536ecc3d11f0969 100644 (file)
@@ -205,7 +205,7 @@ void bch2_journal_space_available(struct journal *j)
 
        j->can_discard = can_discard;
 
-       if (nr_online < c->opts.metadata_replicas_required) {
+       if (nr_online < metadata_replicas_required(c)) {
                ret = JOURNAL_ERR_insufficient_devices;
                goto out;
        }
index b9911402b1753baa986a1673339c4454eba87431..6b23e11825e6d47ef46c7f294add46fa455e6a8f 100644 (file)
@@ -1428,10 +1428,10 @@ bool bch2_dev_state_allowed(struct bch_fs *c, struct bch_dev *ca,
 
                required = max(!(flags & BCH_FORCE_IF_METADATA_DEGRADED)
                               ? c->opts.metadata_replicas
-                              : c->opts.metadata_replicas_required,
+                              : metadata_replicas_required(c),
                               !(flags & BCH_FORCE_IF_DATA_DEGRADED)
                               ? c->opts.data_replicas
-                              : c->opts.data_replicas_required);
+                              : data_replicas_required(c));
 
                return nr_rw >= required;
        case BCH_MEMBER_STATE_failed: