bcachefs: Fix promoting to cache devices (durability = 0)
authorKent Overstreet <kent.overstreet@gmail.com>
Mon, 10 Jun 2019 15:31:07 +0000 (11:31 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:23 +0000 (17:08 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/alloc_foreground.c
fs/bcachefs/io.c

index 334bc6576b3a377c2121aab6d65e39aff5b0cdc2..e3e9383c94eeb46e7dd50b8ecd1574e932a2835c 100644 (file)
@@ -377,6 +377,25 @@ void bch2_dev_stripe_increment(struct bch_fs *c, struct bch_dev *ca,
 #define BUCKET_MAY_ALLOC_PARTIAL       (1 << 0)
 #define BUCKET_ALLOC_USE_DURABILITY    (1 << 1)
 
+static void add_new_bucket(struct bch_fs *c,
+                          struct open_buckets *ptrs,
+                          struct bch_devs_mask *devs_may_alloc,
+                          unsigned *nr_effective,
+                          bool *have_cache,
+                          unsigned flags,
+                          struct open_bucket *ob)
+{
+       unsigned durability =
+               bch_dev_bkey_exists(c, ob->ptr.dev)->mi.durability;
+
+       __clear_bit(ob->ptr.dev, devs_may_alloc->d);
+       *nr_effective   += (flags & BUCKET_ALLOC_USE_DURABILITY)
+               ? durability : 1;
+       *have_cache     |= !durability;
+
+       ob_push(c, ptrs, ob);
+}
+
 static int bch2_bucket_alloc_set(struct bch_fs *c,
                                 struct open_buckets *ptrs,
                                 struct dev_stripe_state *stripe,
@@ -392,7 +411,7 @@ static int bch2_bucket_alloc_set(struct bch_fs *c,
                bch2_dev_alloc_list(c, stripe, devs_may_alloc);
        struct bch_dev *ca;
        bool alloc_failure = false;
-       unsigned i, durability;
+       unsigned i;
 
        BUG_ON(*nr_effective >= nr_replicas);
 
@@ -422,14 +441,8 @@ static int bch2_bucket_alloc_set(struct bch_fs *c,
                        continue;
                }
 
-               durability = (flags & BUCKET_ALLOC_USE_DURABILITY)
-                       ? ca->mi.durability : 1;
-
-               __clear_bit(ca->dev_idx, devs_may_alloc->d);
-               *nr_effective   += durability;
-               *have_cache     |= !durability;
-
-               ob_push(c, ptrs, ob);
+               add_new_bucket(c, ptrs, devs_may_alloc,
+                              nr_effective, have_cache, flags, ob);
 
                bch2_dev_stripe_increment(c, ca, stripe);
 
@@ -524,7 +537,8 @@ static void bucket_alloc_from_stripe(struct bch_fs *c,
                                     unsigned erasure_code,
                                     unsigned nr_replicas,
                                     unsigned *nr_effective,
-                                    bool *have_cache)
+                                    bool *have_cache,
+                                    unsigned flags)
 {
        struct dev_alloc_list devs_sorted;
        struct ec_stripe_head *h;
@@ -564,11 +578,8 @@ got_bucket:
        ob->ec_idx      = ec_idx;
        ob->ec          = h->s;
 
-       __clear_bit(ob->ptr.dev, devs_may_alloc->d);
-       *nr_effective   += ca->mi.durability;
-       *have_cache     |= !ca->mi.durability;
-
-       ob_push(c, ptrs, ob);
+       add_new_bucket(c, ptrs, devs_may_alloc,
+                      nr_effective, have_cache, flags, ob);
        atomic_inc(&h->s->pin);
 out_put_head:
        bch2_ec_stripe_head_put(h);
@@ -583,6 +594,7 @@ static void get_buckets_from_writepoint(struct bch_fs *c,
                                        unsigned nr_replicas,
                                        unsigned *nr_effective,
                                        bool *have_cache,
+                                       unsigned flags,
                                        bool need_ec)
 {
        struct open_buckets ptrs_skip = { .nr = 0 };
@@ -597,11 +609,9 @@ static void get_buckets_from_writepoint(struct bch_fs *c,
                    (ca->mi.durability ||
                     (wp->type == BCH_DATA_USER && !*have_cache)) &&
                    (ob->ec || !need_ec)) {
-                       __clear_bit(ob->ptr.dev, devs_may_alloc->d);
-                       *nr_effective   += ca->mi.durability;
-                       *have_cache     |= !ca->mi.durability;
-
-                       ob_push(c, ptrs, ob);
+                       add_new_bucket(c, ptrs, devs_may_alloc,
+                                      nr_effective, have_cache,
+                                      flags, ob);
                } else {
                        ob_push(c, &ptrs_skip, ob);
                }
@@ -619,17 +629,15 @@ static int open_bucket_add_buckets(struct bch_fs *c,
                                   unsigned *nr_effective,
                                   bool *have_cache,
                                   enum alloc_reserve reserve,
+                                  unsigned flags,
                                   struct closure *_cl)
 {
        struct bch_devs_mask devs;
        struct open_bucket *ob;
        struct closure *cl = NULL;
-       unsigned i, flags = BUCKET_ALLOC_USE_DURABILITY;
+       unsigned i;
        int ret;
 
-       if (wp->type == BCH_DATA_USER)
-               flags |= BUCKET_MAY_ALLOC_PARTIAL;
-
        rcu_read_lock();
        devs = target_rw_devs(c, wp->type, target);
        rcu_read_unlock();
@@ -644,21 +652,21 @@ static int open_bucket_add_buckets(struct bch_fs *c,
        if (erasure_code) {
                get_buckets_from_writepoint(c, ptrs, wp, &devs,
                                            nr_replicas, nr_effective,
-                                           have_cache, true);
+                                           have_cache, flags, true);
                if (*nr_effective >= nr_replicas)
                        return 0;
 
                bucket_alloc_from_stripe(c, ptrs, wp, &devs,
                                         target, erasure_code,
                                         nr_replicas, nr_effective,
-                                        have_cache);
+                                        have_cache, flags);
                if (*nr_effective >= nr_replicas)
                        return 0;
        }
 
        get_buckets_from_writepoint(c, ptrs, wp, &devs,
                                    nr_replicas, nr_effective,
-                                   have_cache, false);
+                                   have_cache, flags, false);
        if (*nr_effective >= nr_replicas)
                return 0;
 
@@ -863,9 +871,13 @@ struct write_point *bch2_alloc_sectors_start(struct bch_fs *c,
        struct open_bucket *ob;
        struct open_buckets ptrs;
        unsigned nr_effective, write_points_nr;
+       unsigned ob_flags = 0;
        bool have_cache;
        int ret, i;
 
+       if (!(flags & BCH_WRITE_ONLY_SPECIFIED_DEVS))
+               ob_flags |= BUCKET_ALLOC_USE_DURABILITY;
+
        BUG_ON(!nr_replicas || !nr_replicas_required);
 retry:
        ptrs.nr         = 0;
@@ -875,6 +887,9 @@ retry:
 
        wp = writepoint_find(c, write_point.v);
 
+       if (wp->type == BCH_DATA_USER)
+               ob_flags |= BUCKET_MAY_ALLOC_PARTIAL;
+
        /* metadata may not allocate on cache devices: */
        if (wp->type != BCH_DATA_USER)
                have_cache = true;
@@ -883,19 +898,22 @@ retry:
                ret = open_bucket_add_buckets(c, &ptrs, wp, devs_have,
                                              target, erasure_code,
                                              nr_replicas, &nr_effective,
-                                             &have_cache, reserve, cl);
+                                             &have_cache, reserve,
+                                             ob_flags, cl);
        } else {
                ret = open_bucket_add_buckets(c, &ptrs, wp, devs_have,
                                              target, erasure_code,
                                              nr_replicas, &nr_effective,
-                                             &have_cache, reserve, NULL);
+                                             &have_cache, reserve,
+                                             ob_flags, NULL);
                if (!ret)
                        goto alloc_done;
 
                ret = open_bucket_add_buckets(c, &ptrs, wp, devs_have,
                                              0, erasure_code,
                                              nr_replicas, &nr_effective,
-                                             &have_cache, reserve, cl);
+                                             &have_cache, reserve,
+                                             ob_flags, cl);
        }
 alloc_done:
        BUG_ON(!ret && nr_effective < nr_replicas);
index 11cdaddb155186aa8997ad47fe3950cba6edf8fd..9cd9bbc5cce4ca47d21f3140cbade8a05abfbea1 100644 (file)
@@ -1013,23 +1013,23 @@ static inline bool should_promote(struct bch_fs *c, struct bkey_s_c k,
                                  struct bch_io_opts opts,
                                  unsigned flags)
 {
-       if (!opts.promote_target)
+       if (!bkey_extent_is_data(k.k))
                return false;
 
        if (!(flags & BCH_READ_MAY_PROMOTE))
                return false;
 
-       if (percpu_ref_is_dying(&c->writes))
-               return false;
-
-       if (!bkey_extent_is_data(k.k))
+       if (!opts.promote_target)
                return false;
 
-       if (bch2_extent_has_target(c, bkey_s_c_to_extent(k), opts.promote_target))
+       if (bch2_extent_has_target(c, bkey_s_c_to_extent(k),
+                                  opts.promote_target))
                return false;
 
-       if (bch2_target_congested(c, opts.promote_target))
+       if (bch2_target_congested(c, opts.promote_target)) {
+               /* XXX trace this */
                return false;
+       }
 
        if (rhashtable_lookup_fast(&c->promote_table, &pos,
                                   bch_promote_params))