]> git.dujemihanovic.xyz Git - linux.git/commitdiff
bcachefs: Don't drop devices with stripe pointers
authorKent Overstreet <kent.overstreet@linux.dev>
Sat, 7 Sep 2024 00:22:26 +0000 (20:22 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 21 Sep 2024 15:39:49 +0000 (11:39 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/data_update.c
fs/bcachefs/ec.c
fs/bcachefs/extents.c
fs/bcachefs/extents.h

index 004894ad41470125462e225b963e7b0a61c9566a..757b9884ef558243cf8c44e2aab0c663f982f0a5 100644 (file)
@@ -571,7 +571,7 @@ int bch2_extent_drop_ptrs(struct btree_trans *trans,
        while (data_opts.kill_ptrs) {
                unsigned i = 0, drop = __fls(data_opts.kill_ptrs);
 
-               bch2_bkey_drop_ptrs(bkey_i_to_s(n), ptr, i++ == drop);
+               bch2_bkey_drop_ptrs_noerror(bkey_i_to_s(n), ptr, i++ == drop);
                data_opts.kill_ptrs ^= 1U << drop;
        }
 
index f167ea454ded17a6245655f5fbfc57cf05e8d2b4..1587c6e1866ae6cebb0a501cf838a18f279d4620 100644 (file)
@@ -1322,7 +1322,7 @@ static int ec_stripe_update_extent(struct btree_trans *trans,
 
        bkey_reassemble(n, k);
 
-       bch2_bkey_drop_ptrs(bkey_i_to_s(n), ptr, ptr->dev != dev);
+       bch2_bkey_drop_ptrs_noerror(bkey_i_to_s(n), ptr, ptr->dev != dev);
        ec_ptr = bch2_bkey_has_device(bkey_i_to_s(n), dev);
        BUG_ON(!ec_ptr);
 
index d370d679e0155bebf4022b9ee1e9d96a0b9eb7e3..cc0d22085aef42d61711a02b0aea1d1cecb320f9 100644 (file)
@@ -818,6 +818,18 @@ void bch2_bkey_drop_ptr_noerror(struct bkey_s k, struct bch_extent_ptr *ptr)
 
 void bch2_bkey_drop_ptr(struct bkey_s k, struct bch_extent_ptr *ptr)
 {
+       if (k.k->type != KEY_TYPE_stripe) {
+               struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k.s_c);
+               const union bch_extent_entry *entry;
+               struct extent_ptr_decoded p;
+
+               bkey_for_each_ptr_decode(k.k, ptrs, p, entry)
+                       if (p.ptr.dev == ptr->dev && p.has_ec) {
+                               ptr->dev = BCH_SB_MEMBER_INVALID;
+                               return;
+                       }
+       }
+
        bool have_dirty = bch2_bkey_dirty_devs(k.s_c).nr;
 
        bch2_bkey_drop_ptr_noerror(k, ptr);
@@ -845,10 +857,7 @@ void bch2_bkey_drop_device(struct bkey_s k, unsigned dev)
 
 void bch2_bkey_drop_device_noerror(struct bkey_s k, unsigned dev)
 {
-       struct bch_extent_ptr *ptr = bch2_bkey_has_device(k, dev);
-
-       if (ptr)
-               bch2_bkey_drop_ptr_noerror(k, ptr);
+       bch2_bkey_drop_ptrs_noerror(k, ptr, ptr->dev == dev);
 }
 
 const struct bch_extent_ptr *bch2_bkey_has_device_c(struct bkey_s_c k, unsigned dev)
index 412e1c5b05a0817837c335cc7f399bc0e5ebf42b..ed5001dd662eb9397588c053113f76f144556677 100644 (file)
@@ -611,9 +611,6 @@ unsigned bch2_extent_ptr_desired_durability(struct bch_fs *, struct extent_ptr_d
 unsigned bch2_extent_ptr_durability(struct bch_fs *, struct extent_ptr_decoded *);
 unsigned bch2_bkey_durability(struct bch_fs *, struct bkey_s_c);
 
-void bch2_bkey_drop_device(struct bkey_s, unsigned);
-void bch2_bkey_drop_device_noerror(struct bkey_s, unsigned);
-
 const struct bch_extent_ptr *bch2_bkey_has_device_c(struct bkey_s_c, unsigned);
 
 static inline struct bch_extent_ptr *bch2_bkey_has_device(struct bkey_s k, unsigned dev)
@@ -652,6 +649,23 @@ void bch2_extent_ptr_decoded_append(struct bkey_i *,
 void bch2_bkey_drop_ptr_noerror(struct bkey_s, struct bch_extent_ptr *);
 void bch2_bkey_drop_ptr(struct bkey_s, struct bch_extent_ptr *);
 
+void bch2_bkey_drop_device_noerror(struct bkey_s, unsigned);
+void bch2_bkey_drop_device(struct bkey_s, unsigned);
+
+#define bch2_bkey_drop_ptrs_noerror(_k, _ptr, _cond)                   \
+do {                                                                   \
+       __label__ _again;                                               \
+       struct bkey_ptrs _ptrs;                                         \
+_again:                                                                        \
+       _ptrs = bch2_bkey_ptrs(_k);                                     \
+                                                                       \
+       bkey_for_each_ptr(_ptrs, _ptr)                                  \
+               if (_cond) {                                            \
+                       bch2_bkey_drop_ptr_noerror(_k, _ptr);           \
+                       goto _again;                                    \
+               }                                                       \
+} while (0)
+
 #define bch2_bkey_drop_ptrs(_k, _ptr, _cond)                           \
 do {                                                                   \
        __label__ _again;                                               \