]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
Update bcachefs sources to f7ccf51390 bcachefs: durability
authorKent Overstreet <kent.overstreet@gmail.com>
Tue, 13 Mar 2018 07:22:35 +0000 (03:22 -0400)
committerKent Overstreet <kent.overstreet@gmail.com>
Tue, 13 Mar 2018 07:22:35 +0000 (03:22 -0400)
13 files changed:
.bcachefs_revision
libbcachefs/alloc.c
libbcachefs/alloc.h
libbcachefs/alloc_types.h
libbcachefs/bcachefs_format.h
libbcachefs/extents.c
libbcachefs/extents.h
libbcachefs/io.c
libbcachefs/migrate.c
libbcachefs/move.c
libbcachefs/super-io.h
libbcachefs/super_types.h
libbcachefs/sysfs.c

index 731adaa044ecf5078d206f23d3376ed523d71f1d..333e97a38fb6e1b31db939e52be42ef3f44e5da9 100644 (file)
@@ -1 +1 @@
-da224776eb43b7a47d8c7cd9314d5d1a8e97aabe
+f7ccf513908be42581e41b48b8b078a441a6a804
index 470ef207ac04c1c5ea82981a7aefd03ae6486dee..22dcaeb27563eae77888c816a09969264f548566 100644 (file)
@@ -1227,24 +1227,35 @@ static enum bucket_alloc_ret __bch2_bucket_alloc_set(struct bch_fs *c,
 {
        enum bucket_alloc_ret ret = NO_DEVICES;
        struct dev_alloc_list devs_sorted;
-       unsigned i;
+       struct bch_dev *ca;
+       unsigned i, nr_ptrs_effective = 0;
+       bool have_cache_dev = false;
 
        BUG_ON(nr_replicas > ARRAY_SIZE(wp->ptrs));
 
-       if (wp->nr_ptrs >= nr_replicas)
+       for (i = wp->first_ptr; i < wp->nr_ptrs; i++) {
+               ca = bch_dev_bkey_exists(c, wp->ptrs[i]->ptr.dev);
+
+               nr_ptrs_effective += ca->mi.durability;
+               have_cache_dev |= !ca->mi.durability;
+       }
+
+       if (nr_ptrs_effective >= nr_replicas)
                return ALLOC_SUCCESS;
 
        rcu_read_lock();
        devs_sorted = bch2_wp_alloc_list(c, wp, devs);
 
        for (i = 0; i < devs_sorted.nr; i++) {
-               struct bch_dev *ca =
-                       rcu_dereference(c->devs[devs_sorted.devs[i]]);
                int ob;
 
+               ca = rcu_dereference(c->devs[devs_sorted.devs[i]]);
                if (!ca)
                        continue;
 
+               if (have_cache_dev && !ca->mi.durability)
+                       continue;
+
                ob = bch2_bucket_alloc(c, ca, reserve,
                                       wp->type == BCH_DATA_USER, cl);
                if (ob < 0) {
@@ -1256,13 +1267,17 @@ static enum bucket_alloc_ret __bch2_bucket_alloc_set(struct bch_fs *c,
 
                BUG_ON(ob <= 0 || ob > U8_MAX);
                BUG_ON(wp->nr_ptrs >= ARRAY_SIZE(wp->ptrs));
+
                wp->ptrs[wp->nr_ptrs++] = c->open_buckets + ob;
 
                bch2_wp_rescale(c, ca, wp);
 
+               nr_ptrs_effective += ca->mi.durability;
+               have_cache_dev |= !ca->mi.durability;
+
                __clear_bit(ca->dev_idx, devs->d);
 
-               if (wp->nr_ptrs == nr_replicas) {
+               if (nr_ptrs_effective >= nr_replicas) {
                        ret = ALLOC_SUCCESS;
                        break;
                }
@@ -1318,37 +1333,46 @@ static int bch2_bucket_alloc_set(struct bch_fs *c, struct write_point *wp,
 
 /* Sector allocator */
 
-static void writepoint_drop_ptrs(struct bch_fs *c,
-                                struct write_point *wp,
-                                u16 target, bool in_target,
-                                unsigned nr_ptrs_dislike)
+static void writepoint_drop_ptr(struct bch_fs *c,
+                               struct write_point *wp,
+                               unsigned i)
 {
-       int i;
+       struct open_bucket *ob = wp->ptrs[i];
+       struct bch_dev *ca = bch_dev_bkey_exists(c, ob->ptr.dev);
 
-       if (!nr_ptrs_dislike)
-               return;
+       BUG_ON(ca->open_buckets_partial_nr >=
+              ARRAY_SIZE(ca->open_buckets_partial));
 
-       for (i = wp->nr_ptrs - 1; i >= 0; --i) {
-               struct open_bucket *ob = wp->ptrs[i];
-               struct bch_dev *ca = bch_dev_bkey_exists(c, ob->ptr.dev);
+       if (wp->type == BCH_DATA_USER) {
+               spin_lock(&c->freelist_lock);
+               ob->on_partial_list = true;
+               ca->open_buckets_partial[ca->open_buckets_partial_nr++] =
+                       ob - c->open_buckets;
+               spin_unlock(&c->freelist_lock);
 
-               if (nr_ptrs_dislike &&
-                   dev_in_target(ca, target) == in_target) {
-                       BUG_ON(ca->open_buckets_partial_nr >=
-                              ARRAY_SIZE(ca->open_buckets_partial));
+               closure_wake_up(&c->open_buckets_wait);
+               closure_wake_up(&c->freelist_wait);
+       } else {
+               bch2_open_bucket_put(c, ob);
+       }
 
-                       spin_lock(&c->freelist_lock);
-                       ob->on_partial_list = true;
-                       ca->open_buckets_partial[ca->open_buckets_partial_nr++] =
-                               ob - c->open_buckets;
-                       spin_unlock(&c->freelist_lock);
+       array_remove_item(wp->ptrs, wp->nr_ptrs, i);
 
-                       closure_wake_up(&c->open_buckets_wait);
-                       closure_wake_up(&c->freelist_wait);
+       if (i < wp->first_ptr)
+               wp->first_ptr--;
+}
 
-                       array_remove_item(wp->ptrs, wp->nr_ptrs, i);
-                       --nr_ptrs_dislike;
-               }
+static void writepoint_drop_ptrs(struct bch_fs *c,
+                                struct write_point *wp,
+                                u16 target, bool in_target)
+{
+       int i;
+
+       for (i = wp->first_ptr - 1; i >= 0; --i) {
+               struct bch_dev *ca = bch_dev_bkey_exists(c, wp->ptrs[i]->ptr.dev);
+
+               if (dev_in_target(ca, target) == in_target)
+                       writepoint_drop_ptr(c, wp, i);
        }
 }
 
@@ -1358,7 +1382,7 @@ static void verify_not_stale(struct bch_fs *c, const struct write_point *wp)
        struct open_bucket *ob;
        unsigned i;
 
-       writepoint_for_each_ptr(wp, ob, i) {
+       writepoint_for_each_ptr_all(wp, ob, i) {
                struct bch_dev *ca = bch_dev_bkey_exists(c, ob->ptr.dev);
 
                BUG_ON(ptr_stale(ca, &ob->ptr));
@@ -1378,14 +1402,11 @@ static int open_bucket_add_buckets(struct bch_fs *c,
        struct open_bucket *ob;
        unsigned i;
 
-       if (wp->nr_ptrs >= nr_replicas)
-               return 0;
-
        /* Don't allocate from devices we already have pointers to: */
        for (i = 0; i < devs_have->nr; i++)
                __clear_bit(devs_have->devs[i], devs.d);
 
-       writepoint_for_each_ptr(wp, ob, i)
+       writepoint_for_each_ptr_all(wp, ob, i)
                __clear_bit(ob->ptr.dev, devs.d);
 
        if (target) {
@@ -1487,76 +1508,123 @@ struct write_point *bch2_alloc_sectors_start(struct bch_fs *c,
 {
        struct write_point *wp;
        struct open_bucket *ob;
-       unsigned i, nr_ptrs_dislike = 0, nr_ptrs_have = 0;
-       int ret;
+       struct bch_dev *ca;
+       unsigned nr_ptrs_have, nr_ptrs_effective;
+       int ret, i, cache_idx = -1;
 
        BUG_ON(!nr_replicas || !nr_replicas_required);
 
        wp = writepoint_find(c, write_point.v);
 
-       /* does ob have ptrs we don't need? */
+       wp->first_ptr = 0;
+
+       /* does writepoint have ptrs we can't use? */
        writepoint_for_each_ptr(wp, ob, i)
-               if (bch2_dev_list_has_dev(*devs_have, ob->ptr.dev))
-                       nr_ptrs_have++;
-               else if (!dev_in_target(c->devs[ob->ptr.dev], target))
-                       nr_ptrs_dislike++;
+               if (bch2_dev_list_has_dev(*devs_have, ob->ptr.dev)) {
+                       swap(wp->ptrs[i], wp->ptrs[wp->first_ptr]);
+                       wp->first_ptr++;
+               }
+
+       nr_ptrs_have = wp->first_ptr;
+
+       /* does writepoint have ptrs we don't want to use? */
+       writepoint_for_each_ptr(wp, ob, i)
+               if (!dev_idx_in_target(c, ob->ptr.dev, target)) {
+                       swap(wp->ptrs[i], wp->ptrs[wp->first_ptr]);
+                       wp->first_ptr++;
+               }
 
        ret = open_bucket_add_buckets(c, target, wp, devs_have,
-                               nr_replicas + nr_ptrs_have + nr_ptrs_dislike,
-                               reserve, cl);
+                                     nr_replicas, reserve, cl);
        if (ret && ret != -EROFS)
                goto err;
 
-       if (flags & BCH_WRITE_ONLY_SPECIFIED_DEVS)
-               goto alloc_done;
+       if (flags & BCH_WRITE_ONLY_SPECIFIED_DEVS) {
+               ret = open_bucket_add_buckets(c, target, wp, devs_have,
+                                             nr_replicas, reserve, cl);
+       } else {
+               ret = open_bucket_add_buckets(c, target, wp, devs_have,
+                                             nr_replicas, reserve, NULL);
+               if (!ret)
+                       goto alloc_done;
+
+               wp->first_ptr = nr_ptrs_have;
 
-       ret = open_bucket_add_buckets(c, target, wp, devs_have,
-                               nr_replicas + nr_ptrs_have,
-                               reserve, cl);
-       if (ret && ret != -EROFS)
+               ret = open_bucket_add_buckets(c, 0, wp, devs_have,
+                                             nr_replicas, reserve, cl);
+       }
+
+       if (ret)
                goto err;
 alloc_done:
-       if (wp->nr_ptrs - nr_ptrs_have -
-           ((flags & BCH_WRITE_ONLY_SPECIFIED_DEVS) ? nr_ptrs_dislike : 0)
-           < nr_replicas_required) {
-               ret = -EROFS;
-               goto err;
+       /* check for more than one cache: */
+       for (i = wp->nr_ptrs - 1; i >= wp->first_ptr; --i) {
+               ca = bch_dev_bkey_exists(c, wp->ptrs[i]->ptr.dev);
+
+               if (ca->mi.durability)
+                       continue;
+
+               /*
+                * if we ended up with more than one cache device, prefer the
+                * one in the target we want:
+                */
+               if (cache_idx >= 0) {
+                       if (!dev_in_target(ca, target)) {
+                               writepoint_drop_ptr(c, wp, i);
+                       } else {
+                               writepoint_drop_ptr(c, wp, cache_idx);
+                               cache_idx = i;
+                       }
+               } else {
+                       cache_idx = i;
+               }
        }
 
-       if ((int) wp->nr_ptrs - nr_ptrs_dislike < nr_replicas)
-               nr_ptrs_dislike = clamp_t(int, wp->nr_ptrs - nr_replicas,
-                                         0, nr_ptrs_dislike);
+       /* we might have more effective replicas than required: */
+       nr_ptrs_effective = 0;
+       writepoint_for_each_ptr(wp, ob, i) {
+               ca = bch_dev_bkey_exists(c, ob->ptr.dev);
+               nr_ptrs_effective += ca->mi.durability;
+       }
 
-       /* Remove pointers we don't want to use: */
-       writepoint_drop_ptrs(c, wp, target, false, nr_ptrs_dislike);
+       if (nr_ptrs_effective > nr_replicas) {
+               writepoint_for_each_ptr(wp, ob, i) {
+                       ca = bch_dev_bkey_exists(c, ob->ptr.dev);
 
-       /*
-        * Move pointers to devices we already have to end of open bucket
-        * pointer list - note that removing pointers we don't want to use might
-        * have changed nr_ptrs_have:
-        */
-       if (nr_ptrs_have) {
-               i = nr_ptrs_have = 0;
-               while (i < wp->nr_ptrs - nr_ptrs_have)
-                       if (bch2_dev_list_has_dev(*devs_have, wp->ptrs[i]->ptr.dev)) {
-                               nr_ptrs_have++;
-                               swap(wp->ptrs[i], wp->ptrs[wp->nr_ptrs - nr_ptrs_have]);
-                       } else {
-                               i++;
+                       if (ca->mi.durability &&
+                           ca->mi.durability <= nr_ptrs_effective - nr_replicas &&
+                           !dev_idx_in_target(c, ob->ptr.dev, target)) {
+                               swap(wp->ptrs[i], wp->ptrs[wp->first_ptr]);
+                               wp->first_ptr++;
+                               nr_ptrs_effective -= ca->mi.durability;
                        }
+               }
        }
 
-       wp->nr_ptrs_can_use =
-               min_t(unsigned, nr_replicas, wp->nr_ptrs - nr_ptrs_have);
+       if (nr_ptrs_effective > nr_replicas) {
+               writepoint_for_each_ptr(wp, ob, i) {
+                       ca = bch_dev_bkey_exists(c, ob->ptr.dev);
 
-       BUG_ON(wp->nr_ptrs_can_use < nr_replicas_required ||
-              wp->nr_ptrs_can_use > wp->nr_ptrs);
+                       if (ca->mi.durability &&
+                           ca->mi.durability <= nr_ptrs_effective - nr_replicas) {
+                               swap(wp->ptrs[i], wp->ptrs[wp->first_ptr]);
+                               wp->first_ptr++;
+                               nr_ptrs_effective -= ca->mi.durability;
+                       }
+               }
+       }
+
+       /* Remove pointers we don't want to use: */
+       if (target)
+               writepoint_drop_ptrs(c, wp, target, false);
+
+       BUG_ON(wp->first_ptr >= wp->nr_ptrs);
+       BUG_ON(nr_ptrs_effective < nr_replicas_required);
 
        wp->sectors_free = UINT_MAX;
 
-       for (i = 0; i < wp->nr_ptrs_can_use; i++)
-               wp->sectors_free = min(wp->sectors_free,
-                                      wp->ptrs[i]->sectors_free);
+       writepoint_for_each_ptr(wp, ob, i)
+               wp->sectors_free = min(wp->sectors_free, ob->sectors_free);
 
        BUG_ON(!wp->sectors_free || wp->sectors_free == UINT_MAX);
 
@@ -1575,19 +1643,21 @@ err:
 void bch2_alloc_sectors_append_ptrs(struct bch_fs *c, struct write_point *wp,
                                    struct bkey_i_extent *e, unsigned sectors)
 {
+       struct open_bucket *ob;
        unsigned i;
 
        BUG_ON(sectors > wp->sectors_free);
        wp->sectors_free -= sectors;
 
-       for (i = 0; i < wp->nr_ptrs_can_use; i++) {
-               struct open_bucket *ob = wp->ptrs[i];
+       writepoint_for_each_ptr(wp, ob, i) {
                struct bch_dev *ca = bch_dev_bkey_exists(c, ob->ptr.dev);
                struct bch_extent_ptr tmp = ob->ptr;
 
                EBUG_ON(bch2_extent_has_device(extent_i_to_s_c(e), ob->ptr.dev));
 
-               tmp.cached = bkey_extent_is_cached(&e->k);
+               tmp.cached = bkey_extent_is_cached(&e->k) ||
+                       (!ca->mi.durability && wp->type == BCH_DATA_USER);
+
                tmp.offset += ca->mi.bucket_size - ob->sectors_free;
                extent_ptr_append(e, tmp);
 
@@ -1704,8 +1774,8 @@ static void bch2_stop_write_point(struct bch_fs *c, struct bch_dev *ca,
        bitmap_complement(not_self.d, ca->self.d, BCH_SB_MEMBERS_MAX);
 
        mutex_lock(&wp->lock);
-       writepoint_drop_ptrs(c, wp, dev_to_target(ca->dev_idx),
-                            true, wp->nr_ptrs);
+       wp->first_ptr = wp->nr_ptrs;
+       writepoint_drop_ptrs(c, wp, dev_to_target(ca->dev_idx), true);
        mutex_unlock(&wp->lock);
 }
 
index 5b58922344a8e2f60a587cb55cd84a784e3b4571..f914dbd56c2cfb6ac53526dadaca569ee8bd8107 100644 (file)
@@ -33,6 +33,17 @@ enum bucket_alloc_ret {
 int bch2_bucket_alloc(struct bch_fs *, struct bch_dev *, enum alloc_reserve, bool,
                      struct closure *);
 
+#define __writepoint_for_each_ptr(_wp, _ob, _i, _start)                        \
+       for ((_i) = (_start);                                           \
+            (_i) < (_wp)->nr_ptrs && ((_ob) = (_wp)->ptrs[_i], true);  \
+            (_i)++)
+
+#define writepoint_for_each_ptr_all(_wp, _ob, _i)                      \
+       __writepoint_for_each_ptr(_wp, _ob, _i, 0)
+
+#define writepoint_for_each_ptr(_wp, _ob, _i)                          \
+       __writepoint_for_each_ptr(_wp, _ob, _i, wp->first_ptr)
+
 void __bch2_open_bucket_put(struct bch_fs *, struct open_bucket *);
 
 static inline void bch2_open_bucket_put(struct bch_fs *c, struct open_bucket *ob)
@@ -55,11 +66,10 @@ static inline void bch2_open_bucket_get(struct bch_fs *c,
                                        struct write_point *wp,
                                        u8 *nr, u8 *refs)
 {
+       struct open_bucket *ob;
        unsigned i;
 
-       for (i = 0; i < wp->nr_ptrs_can_use; i++) {
-               struct open_bucket *ob = wp->ptrs[i];
-
+       writepoint_for_each_ptr(wp, ob, i) {
                atomic_inc(&ob->pin);
                refs[(*nr)++] = ob - c->open_buckets;
        }
@@ -88,11 +98,6 @@ static inline void bch2_wake_allocator(struct bch_dev *ca)
        rcu_read_unlock();
 }
 
-#define writepoint_for_each_ptr(_wp, _ob, _i)                          \
-       for ((_i) = 0;                                                  \
-            (_i) < (_wp)->nr_ptrs && ((_ob) = (_wp)->ptrs[_i], true);  \
-            (_i)++)
-
 static inline struct write_point_specifier writepoint_hashed(unsigned long v)
 {
        return (struct write_point_specifier) { .v = v | 1 };
index 6b0810403336c361b211c9920669af4bd3b64be9..f3bd470110257b36027c7bb3cf0bcada94c11989 100644 (file)
@@ -65,11 +65,8 @@ struct write_point {
        enum bch_data_type      type;
 
        u8                      nr_ptrs;
-       /*
-        * number of pointers in @ob we can't use, because we already had
-        * pointers to those devices:
-        */
-       u8                      nr_ptrs_can_use;
+       u8                      first_ptr;
+
        /* calculated based on how many pointers we're actually going to use: */
        unsigned                sectors_free;
 
index 0f2c9cecda724234121e6024eb23fd03e723f5e5..d89f7781acd9681b91f741ca4150c593dcaa6c1a 100644 (file)
@@ -829,6 +829,7 @@ LE64_BITMASK(BCH_MEMBER_REPLACEMENT,        struct bch_member, flags[0], 10, 14)
 LE64_BITMASK(BCH_MEMBER_DISCARD,       struct bch_member, flags[0], 14, 15)
 LE64_BITMASK(BCH_MEMBER_DATA_ALLOWED,  struct bch_member, flags[0], 15, 20)
 LE64_BITMASK(BCH_MEMBER_GROUP,         struct bch_member, flags[0], 20, 28)
+LE64_BITMASK(BCH_MEMBER_DURABILITY,    struct bch_member, flags[0], 28, 30)
 
 #define BCH_TIER_MAX                   4U
 
index b7d969b1a1c75da9f0dd14e4aad1c38629d8e385..ed33f9bf528a9628c9f1d3c5f1b0e2ed47f79a1d 100644 (file)
@@ -201,17 +201,31 @@ unsigned bch2_extent_nr_dirty_ptrs(struct bkey_s_c k)
        return nr_ptrs;
 }
 
-unsigned bch2_extent_nr_good_ptrs(struct bch_fs *c, struct bkey_s_c_extent e)
+unsigned bch2_extent_ptr_durability(struct bch_fs *c,
+                                   const struct bch_extent_ptr *ptr)
+{
+       struct bch_dev *ca;
+
+       if (ptr->cached)
+               return 0;
+
+       ca = bch_dev_bkey_exists(c, ptr->dev);
+
+       if (ca->mi.state == BCH_MEMBER_STATE_FAILED)
+               return 0;
+
+       return ca->mi.durability;
+}
+
+unsigned bch2_extent_durability(struct bch_fs *c, struct bkey_s_c_extent e)
 {
        const struct bch_extent_ptr *ptr;
-       unsigned nr_ptrs = 0;
+       unsigned durability = 0;
 
        extent_for_each_ptr(e, ptr)
-               nr_ptrs += (!ptr->cached &&
-                           bch_dev_bkey_exists(c, ptr->dev)->mi.state !=
-                           BCH_MEMBER_STATE_FAILED);
+               durability += bch2_extent_ptr_durability(c, ptr);
 
-       return nr_ptrs;
+       return durability;
 }
 
 unsigned bch2_extent_is_compressed(struct bkey_s_c k)
@@ -2008,21 +2022,29 @@ void bch2_extent_mark_replicas_cached(struct bch_fs *c,
                                      unsigned target)
 {
        struct bch_extent_ptr *ptr;
-       unsigned nr_cached = 0, nr_good = bch2_extent_nr_good_ptrs(c, e.c);
+       int extra = bch2_extent_durability(c, e.c) - nr_desired_replicas;
 
-       if (nr_good <= nr_desired_replicas)
+       if (extra <= 0)
                return;
 
-       nr_cached = nr_good - nr_desired_replicas;
+       extent_for_each_ptr(e, ptr) {
+               int n = bch2_extent_ptr_durability(c, ptr);
 
-       extent_for_each_ptr(e, ptr)
-               if (!ptr->cached &&
+               if (n && n <= extra &&
                    !dev_in_target(c->devs[ptr->dev], target)) {
                        ptr->cached = true;
-                       nr_cached--;
-                       if (!nr_cached)
-                               return;
+                       extra -= n;
+               }
+       }
+
+       extent_for_each_ptr(e, ptr) {
+               int n = bch2_extent_ptr_durability(c, ptr);
+
+               if (n && n <= extra) {
+                       ptr->cached = true;
+                       extra -= n;
                }
+       }
 }
 
 /*
index 1ce0d38d278af488589f795fd6897197d4d0748c..376e51c9381651cd0e44c91c77df546bfe685c81 100644 (file)
@@ -52,9 +52,12 @@ bch2_extent_has_target(struct bch_fs *, struct bkey_s_c_extent, unsigned);
 
 unsigned bch2_extent_nr_ptrs(struct bkey_s_c_extent);
 unsigned bch2_extent_nr_dirty_ptrs(struct bkey_s_c);
-unsigned bch2_extent_nr_good_ptrs(struct bch_fs *, struct bkey_s_c_extent);
 unsigned bch2_extent_is_compressed(struct bkey_s_c);
 
+unsigned bch2_extent_ptr_durability(struct bch_fs *,
+                                   const struct bch_extent_ptr *);
+unsigned bch2_extent_durability(struct bch_fs *, struct bkey_s_c_extent);
+
 bool bch2_extent_matches_ptr(struct bch_fs *, struct bkey_s_c_extent,
                             struct bch_extent_ptr, u64);
 
index 6624d8af574f7d40e817974d852faa98bd09f928..d1fb89c58ee33b832b16749d057a18d180e1acc2 100644 (file)
@@ -791,7 +791,7 @@ static void __bch2_write(struct closure *cl)
 
                ret = bch2_write_extent(op, wp);
 
-               BUG_ON(op->open_buckets_nr + wp->nr_ptrs_can_use >
+               BUG_ON(op->open_buckets_nr + wp->nr_ptrs - wp->first_ptr >
                       ARRAY_SIZE(op->open_buckets));
                bch2_open_bucket_get(c, wp,
                                     &op->open_buckets_nr,
index 9200ed9f591cf880e373c2b54e8d50e96d2962a5..1bc0e714222045db3f7825dd0fe01259bbfe8949 100644 (file)
@@ -23,7 +23,7 @@ static int drop_dev_ptrs(struct bch_fs *c, struct bkey_s_extent e,
 
        bch2_extent_drop_device(e, dev_idx);
 
-       nr_good = bch2_extent_nr_good_ptrs(c, e.c);
+       nr_good = bch2_extent_durability(c, e.c);
        if ((!nr_good && !(flags & lost)) ||
            (nr_good < replicas && !(flags & degraded)))
                return -EINVAL;
index a7c4c3ac1da5cc1fa83b642967f6814dc767c849..616844ae2e0b75c354254c3a25d8f8725fa46383 100644 (file)
@@ -688,7 +688,7 @@ static enum data_cmd rereplicate_pred(struct bch_fs *c, void *arg,
                                      struct bch_io_opts *io_opts,
                                      struct data_opts *data_opts)
 {
-       unsigned nr_good = bch2_extent_nr_good_ptrs(c, e);
+       unsigned nr_good = bch2_extent_durability(c, e);
        unsigned replicas = type == BKEY_TYPE_BTREE
                ? c->opts.metadata_replicas
                : io_opts->data_replicas;
index 2fa0719f1b99e15173beb5672309d9d21266ac0d..2514ac8a7b8cb0f40e54543f53517292ecca3543 100644 (file)
@@ -132,6 +132,9 @@ static inline struct bch_member_cpu bch2_mi_to_cpu(struct bch_member *mi)
                .replacement    = BCH_MEMBER_REPLACEMENT(mi),
                .discard        = BCH_MEMBER_DISCARD(mi),
                .data_allowed   = BCH_MEMBER_DATA_ALLOWED(mi),
+               .durability     = BCH_MEMBER_DURABILITY(mi)
+                       ? BCH_MEMBER_DURABILITY(mi) - 1
+                       : 1,
                .valid          = !bch2_is_zero(mi->uuid.b, sizeof(uuid_le)),
        };
 }
@@ -249,6 +252,17 @@ static inline bool dev_in_target(struct bch_dev *ca, unsigned target)
        }
 }
 
+static inline bool dev_idx_in_target(struct bch_fs *c, unsigned dev, unsigned target)
+{
+       bool ret;
+
+       rcu_read_lock();
+       ret = dev_in_target(rcu_dereference(c->devs[dev]), target);
+       rcu_read_unlock();
+
+       return ret;
+}
+
 const struct bch_devs_mask *bch2_target_to_mask(struct bch_fs *, unsigned);
 
 int __bch2_disk_group_find(struct bch_sb_field_disk_groups *, const char *);
index 3be05e9b08888032b7bf9455023cbbfc431de4b0..f5468182e4851387aadc2806569052c466f27ef5 100644 (file)
@@ -27,6 +27,7 @@ struct bch_member_cpu {
        u8                      replacement;
        u8                      discard;
        u8                      data_allowed;
+       u8                      durability;
        u8                      valid;
 };
 
index 601e270777a6244d58cf6d0796b1e88c8083700b..82457348d062144e5bfc2d7ca7b7827fa5c133f0 100644 (file)
@@ -138,6 +138,7 @@ read_attribute(block_size);
 read_attribute(btree_node_size);
 read_attribute(first_bucket);
 read_attribute(nbuckets);
+read_attribute(durability);
 read_attribute(iostats);
 read_attribute(read_priority_stats);
 read_attribute(write_priority_stats);
@@ -800,6 +801,7 @@ SHOW(bch2_dev)
        sysfs_print(block_size,         block_bytes(c));
        sysfs_print(first_bucket,       ca->mi.first_bucket);
        sysfs_print(nbuckets,           ca->mi.nbuckets);
+       sysfs_print(durability,         ca->mi.durability);
        sysfs_print(discard,            ca->mi.discard);
 
        if (attr == &sysfs_group) {
@@ -930,6 +932,7 @@ struct attribute *bch2_dev_files[] = {
        &sysfs_block_size,
        &sysfs_first_bucket,
        &sysfs_nbuckets,
+       &sysfs_durability,
 
        /* settings: */
        &sysfs_discard,