bcachefs: bch2_extent_drop_ptrs()
authorKent Overstreet <kent.overstreet@gmail.com>
Sun, 30 Sep 2018 22:28:23 +0000 (18:28 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:10 +0000 (17:08 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_io.c
fs/bcachefs/extents.c
fs/bcachefs/extents.h
fs/bcachefs/io.c
fs/bcachefs/journal_io.c
fs/bcachefs/move.c

index 96bcdf5339e870d115dba62cef6bfb0ac2115381..e64e53e9d9ab1f6e8077420a5fbb9513b20eac96 100644 (file)
@@ -1570,9 +1570,9 @@ retry:
 
        new_key = bkey_i_to_extent(&tmp.k);
        e = extent_i_to_s(new_key);
-       extent_for_each_ptr_backwards(e, ptr)
-               if (bch2_dev_list_has_dev(wbio->wbio.failed, ptr->dev))
-                       bch2_extent_drop_ptr(e, ptr);
+
+       bch2_extent_drop_ptrs(e, ptr,
+               bch2_dev_list_has_dev(wbio->wbio.failed, ptr->dev));
 
        if (!bch2_extent_nr_ptrs(e.c))
                goto err;
index 0441e42bb1c498c071a0863b28249ae72efef573..8b84c5e00a26d158a236ff91213847cfcdab672e 100644 (file)
@@ -122,20 +122,11 @@ bch2_extent_has_device(struct bkey_s_c_extent e, unsigned dev)
        return NULL;
 }
 
-bool bch2_extent_drop_device(struct bkey_s_extent e, unsigned dev)
+void bch2_extent_drop_device(struct bkey_s_extent e, unsigned dev)
 {
        struct bch_extent_ptr *ptr;
-       bool dropped = false;
 
-       extent_for_each_ptr_backwards(e, ptr)
-               if (ptr->dev == dev) {
-                       __bch2_extent_drop_ptr(e, ptr);
-                       dropped = true;
-               }
-
-       if (dropped)
-               bch2_extent_drop_redundant_crcs(e);
-       return dropped;
+       bch2_extent_drop_ptrs(e, ptr, ptr->dev == dev);
 }
 
 const struct bch_extent_ptr *
@@ -267,21 +258,37 @@ bool bch2_extent_matches_ptr(struct bch_fs *c, struct bkey_s_c_extent e,
        return false;
 }
 
-/* Doesn't cleanup redundant crcs */
-void __bch2_extent_drop_ptr(struct bkey_s_extent e, struct bch_extent_ptr *ptr)
+union bch_extent_entry *bch2_extent_drop_ptr(struct bkey_s_extent e,
+                                            struct bch_extent_ptr *ptr)
 {
+       union bch_extent_entry *dst;
+       union bch_extent_entry *src;
+
        EBUG_ON(ptr < &e.v->start->ptr ||
                ptr >= &extent_entry_last(e)->ptr);
        EBUG_ON(ptr->type != 1 << BCH_EXTENT_ENTRY_ptr);
-       memmove_u64s_down(ptr, ptr + 1,
-                         (u64 *) extent_entry_last(e) - (u64 *) (ptr + 1));
-       e.k->u64s -= sizeof(*ptr) / sizeof(u64);
-}
 
-void bch2_extent_drop_ptr(struct bkey_s_extent e, struct bch_extent_ptr *ptr)
-{
-       __bch2_extent_drop_ptr(e, ptr);
-       bch2_extent_drop_redundant_crcs(e);
+       src = to_entry(ptr + 1);
+
+       if (src != extent_entry_last(e) &&
+           extent_entry_type(src) == BCH_EXTENT_ENTRY_ptr) {
+               dst = to_entry(ptr);
+       } else {
+               extent_for_each_entry(e, dst) {
+                       if (dst == to_entry(ptr))
+                               break;
+
+                       if (extent_entry_next(dst) == to_entry(ptr) &&
+                           extent_entry_is_crc(dst))
+                               break;
+               }
+       }
+
+       memmove_u64s_down(dst, src,
+                         (u64 *) extent_entry_last(e) - (u64 *) src);
+       e.k->u64s -= (u64 *) src - (u64 *) dst;
+
+       return dst;
 }
 
 static inline bool can_narrow_crc(struct bch_extent_crc_unpacked u,
@@ -349,7 +356,7 @@ restart_narrow_pointers:
                if (can_narrow_crc(p.crc, n)) {
                        i->ptr.offset += p.crc.offset;
                        extent_ptr_append(e, i->ptr);
-                       __bch2_extent_drop_ptr(extent_i_to_s(e), &i->ptr);
+                       bch2_extent_drop_ptr(extent_i_to_s(e), &i->ptr);
                        goto restart_narrow_pointers;
                }
 
@@ -431,27 +438,13 @@ drop:
        EBUG_ON(bkey_val_u64s(e.k) && !bch2_extent_nr_ptrs(e.c));
 }
 
-static bool should_drop_ptr(const struct bch_fs *c,
-                           struct bkey_s_c_extent e,
-                           const struct bch_extent_ptr *ptr)
-{
-       return ptr->cached && ptr_stale(bch_dev_bkey_exists(c, ptr->dev), ptr);
-}
-
 static void bch2_extent_drop_stale(struct bch_fs *c, struct bkey_s_extent e)
 {
-       struct bch_extent_ptr *ptr = &e.v->start->ptr;
-       bool dropped = false;
-
-       while ((ptr = extent_ptr_next(e, ptr)))
-               if (should_drop_ptr(c, e.c, ptr)) {
-                       __bch2_extent_drop_ptr(e, ptr);
-                       dropped = true;
-               } else
-                       ptr++;
+       struct bch_extent_ptr *ptr;
 
-       if (dropped)
-               bch2_extent_drop_redundant_crcs(e);
+       bch2_extent_drop_ptrs(e, ptr,
+               ptr->cached &&
+               ptr_stale(bch_dev_bkey_exists(c, ptr->dev), ptr));
 }
 
 bool bch2_ptr_normalize(struct bch_fs *c, struct btree *b, struct bkey_s k)
index b1b9c189867a4b0defd8ae9bac5babe283422764..c45d70657a8918c1bbcf6f83d8e0ff9d77302500 100644 (file)
@@ -84,7 +84,7 @@ void bch2_extent_mark_replicas_cached(struct bch_fs *, struct bkey_s_extent,
 
 const struct bch_extent_ptr *
 bch2_extent_has_device(struct bkey_s_c_extent, unsigned);
-bool bch2_extent_drop_device(struct bkey_s_extent, unsigned);
+void bch2_extent_drop_device(struct bkey_s_extent, unsigned);
 const struct bch_extent_ptr *
 bch2_extent_has_group(struct bch_fs *, struct bkey_s_c_extent, unsigned);
 const struct bch_extent_ptr *
@@ -400,29 +400,6 @@ out:                                                                       \
 
 /* Iterate over pointers backwards: */
 
-#define extent_ptr_prev(_e, _ptr)                                      \
-({                                                                     \
-       typeof(&(_e).v->start->ptr) _p;                                 \
-       typeof(&(_e).v->start->ptr) _prev = NULL;                       \
-                                                                       \
-       extent_for_each_ptr(_e, _p) {                                   \
-               if (_p == (_ptr))                                       \
-                       break;                                          \
-               _prev = _p;                                             \
-       }                                                               \
-                                                                       \
-       _prev;                                                          \
-})
-
-/*
- * Use this when you'll be dropping pointers as you iterate. Quadratic,
- * unfortunately:
- */
-#define extent_for_each_ptr_backwards(_e, _ptr)                                \
-       for ((_ptr) = extent_ptr_prev(_e, NULL);                        \
-            (_ptr);                                                    \
-            (_ptr) = extent_ptr_prev(_e, _ptr))
-
 void bch2_extent_crc_append(struct bkey_i_extent *,
                            struct bch_extent_crc_unpacked);
 
@@ -517,8 +494,22 @@ bool bch2_can_narrow_extent_crcs(struct bkey_s_c_extent,
 bool bch2_extent_narrow_crcs(struct bkey_i_extent *, struct bch_extent_crc_unpacked);
 void bch2_extent_drop_redundant_crcs(struct bkey_s_extent);
 
-void __bch2_extent_drop_ptr(struct bkey_s_extent, struct bch_extent_ptr *);
-void bch2_extent_drop_ptr(struct bkey_s_extent, struct bch_extent_ptr *);
+union bch_extent_entry *bch2_extent_drop_ptr(struct bkey_s_extent ,
+                                            struct bch_extent_ptr *);
+
+#define bch2_extent_drop_ptrs(_e, _ptr, _cond)                         \
+do {                                                                   \
+       _ptr = &(_e).v->start->ptr;                                     \
+                                                                       \
+       while ((_ptr = extent_ptr_next(e, _ptr))) {                     \
+               if (_cond) {                                            \
+                       _ptr = (void *) bch2_extent_drop_ptr(_e, _ptr); \
+                       continue;                                       \
+               }                                                       \
+                                                                       \
+               (_ptr)++;                                               \
+       }                                                               \
+} while (0)
 
 bool bch2_cut_front(struct bpos, struct bkey_i *);
 bool bch2_cut_back(struct bpos, struct bkey *);
index d64463751b844618555ea3f26c1fa3fbbbc89172..d17128f50f98b0be5108cb3dc98b4569f2de7058 100644 (file)
@@ -327,9 +327,9 @@ static void __bch2_write_index(struct bch_write_op *op)
                bkey_copy(dst, src);
 
                e = bkey_i_to_s_extent(dst);
-               extent_for_each_ptr_backwards(e, ptr)
-                       if (test_bit(ptr->dev, op->failed.d))
-                               bch2_extent_drop_ptr(e, ptr);
+
+               bch2_extent_drop_ptrs(e, ptr,
+                       test_bit(ptr->dev, op->failed.d));
 
                if (!bch2_extent_nr_ptrs(e.c)) {
                        ret = -EIO;
index 9dd881c0410e3e3d8dd35b559f66042d8ff5fe55..648c4ac58a2c3d613702af62a585a52c10574d52 100644 (file)
@@ -1067,14 +1067,19 @@ static int journal_write_alloc(struct journal *j, struct journal_buf *w,
         * entry - that's why we drop pointers to devices <= current free space,
         * i.e. whichever device was limiting the current journal entry size.
         */
-       extent_for_each_ptr_backwards(e, ptr) {
-                  ca = bch_dev_bkey_exists(c, ptr->dev);
+       bch2_extent_drop_ptrs(e, ptr, ({
+               ca = bch_dev_bkey_exists(c, ptr->dev);
 
-               if (ca->mi.state != BCH_MEMBER_STATE_RW ||
-                   ca->journal.sectors_free <= sectors)
-                       __bch2_extent_drop_ptr(e, ptr);
-               else
-                       ca->journal.sectors_free -= sectors;
+               ca->mi.state != BCH_MEMBER_STATE_RW ||
+               ca->journal.sectors_free <= sectors;
+       }));
+
+       extent_for_each_ptr(e, ptr) {
+               ca = bch_dev_bkey_exists(c, ptr->dev);
+
+               BUG_ON(ca->mi.state != BCH_MEMBER_STATE_RW ||
+                      ca->journal.sectors_free <= sectors);
+               ca->journal.sectors_free -= sectors;
        }
 
        replicas = bch2_extent_nr_ptrs(e.c);
index 1e63d0e5ce53d98634b2ee6f13044f3bdec98a05..edc45201faa6537ce3e19c9e55822f0ffc355df6 100644 (file)
@@ -98,13 +98,9 @@ static int bch2_migrate_index_update(struct bch_write_op *op)
                bch2_cut_back(new->k.p, &insert->k);
                bch2_cut_back(insert->k.p, &new->k);
 
-               if (m->data_cmd == DATA_REWRITE) {
-                       struct bch_extent_ptr *ptr = (void *)
-                               bch2_extent_has_device(extent_i_to_s_c(insert),
-                                                      m->data_opts.rewrite_dev);
-                       BUG_ON(!ptr);
-                       bch2_extent_drop_ptr(extent_i_to_s(insert), ptr);
-               }
+               if (m->data_cmd == DATA_REWRITE)
+                       bch2_extent_drop_device(extent_i_to_s(insert),
+                                               m->data_opts.rewrite_dev);
 
                extent_for_each_ptr_decode(extent_i_to_s(new), p, entry) {
                        if (bch2_extent_has_device(extent_i_to_s_c(insert), p.ptr.dev)) {