bcachefs: Fix bch2_btree_iter_peek_prev()
authorKent Overstreet <kent.overstreet@gmail.com>
Mon, 8 Feb 2021 02:11:49 +0000 (21:11 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:53 +0000 (17:08 -0400)
This makes bch2_btree_iter_peek_prev() and bch2_btree_iter_prev()
consistent with peek() and next(), w.r.t. iter->pos.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_iter.c
fs/bcachefs/fs-io.c

index 294c591b504742264e2b1e0378cecd99be878c68..4012a2c0f0080ba23364bfe8d401ed621e375fa9 100644 (file)
@@ -1519,13 +1519,27 @@ void bch2_btree_iter_set_pos(struct btree_iter *iter, struct bpos new_pos)
 
 static inline bool bch2_btree_iter_advance_pos(struct btree_iter *iter)
 {
-       if (unlikely(!bkey_cmp(iter->k.p, POS_MAX)))
+       struct bpos pos = iter->k.p;
+
+       if (unlikely(!bkey_cmp(pos, POS_MAX)))
+               return false;
+
+       if (!(iter->flags & BTREE_ITER_IS_EXTENTS))
+               pos = bkey_successor(pos);
+       bch2_btree_iter_set_pos(iter, pos);
+       return true;
+}
+
+static inline bool bch2_btree_iter_rewind_pos(struct btree_iter *iter)
+{
+       struct bpos pos = bkey_start_pos(&iter->k);
+
+       if (unlikely(!bkey_cmp(pos, POS_MIN)))
                return false;
 
-       bch2_btree_iter_set_pos(iter,
-               (iter->flags & BTREE_ITER_IS_EXTENTS)
-               ? iter->k.p
-               : bkey_successor(iter->k.p));
+       if (!(iter->flags & BTREE_ITER_IS_EXTENTS))
+               pos = bkey_predecessor(pos);
+       bch2_btree_iter_set_pos(iter, pos);
        return true;
 }
 
@@ -1619,8 +1633,7 @@ struct bkey_s_c bch2_btree_iter_peek(struct btree_iter *iter)
         * iter->pos should always be equal to the key we just
         * returned - except extents can straddle iter->pos:
         */
-       if (!(iter->flags & BTREE_ITER_IS_EXTENTS) ||
-           bkey_cmp(bkey_start_pos(k.k), iter->pos) > 0)
+       if (bkey_cmp(bkey_start_pos(k.k), iter->pos) > 0)
                iter->pos = bkey_start_pos(k.k);
 
        iter->uptodate = BTREE_ITER_UPTODATE;
@@ -1743,7 +1756,10 @@ struct bkey_s_c bch2_btree_iter_peek_prev(struct btree_iter *iter)
                        return bkey_s_c_err(ret);
 
                k = __btree_iter_peek(iter, l);
-               if (!k.k || bkey_cmp(bkey_start_pos(k.k), pos) > 0)
+               if (!k.k ||
+                   ((iter->flags & BTREE_ITER_IS_EXTENTS)
+                    ? bkey_cmp(bkey_start_pos(k.k), pos) >= 0
+                    : bkey_cmp(bkey_start_pos(k.k), pos) > 0))
                        k = __btree_iter_prev(iter, l);
 
                if (likely(k.k))
@@ -1754,8 +1770,13 @@ struct bkey_s_c bch2_btree_iter_peek_prev(struct btree_iter *iter)
        }
 
        EBUG_ON(bkey_cmp(bkey_start_pos(k.k), pos) > 0);
-       iter->pos       = bkey_start_pos(k.k);
+
+       /* Extents can straddle iter->pos: */
+       if (bkey_cmp(k.k->p, pos) < 0)
+               iter->pos = k.k->p;
        iter->uptodate  = BTREE_ITER_UPTODATE;
+
+       bch2_btree_iter_verify_level(iter, 0);
        return k;
 }
 
@@ -1765,16 +1786,9 @@ struct bkey_s_c bch2_btree_iter_peek_prev(struct btree_iter *iter)
  */
 struct bkey_s_c bch2_btree_iter_prev(struct btree_iter *iter)
 {
-       struct bpos pos = bkey_start_pos(&iter->k);
-
-       EBUG_ON(btree_iter_type(iter) != BTREE_ITER_KEYS);
-       bch2_btree_iter_checks(iter);
-
-       if (unlikely(!bkey_cmp(pos, POS_MIN)))
+       if (!bch2_btree_iter_rewind_pos(iter))
                return bkey_s_c_null;
 
-       bch2_btree_iter_set_pos(iter, bkey_predecessor(pos));
-
        return bch2_btree_iter_peek_prev(iter);
 }
 
index 79f1f0f37e18aea8da49ff5605590cdf1f0bfbc2..80ef9d6df28787c21a037e8cdc9f97d1afe979ac 100644 (file)
@@ -2454,7 +2454,7 @@ static long bchfs_fcollapse_finsert(struct bch_inode_info *inode,
        struct address_space *mapping = inode->v.i_mapping;
        struct bkey_buf copy;
        struct btree_trans trans;
-       struct btree_iter *src, *dst;
+       struct btree_iter *src, *dst, *del;
        loff_t shift, new_size;
        u64 src_start;
        int ret;
@@ -2524,6 +2524,7 @@ static long bchfs_fcollapse_finsert(struct bch_inode_info *inode,
                        POS(inode->v.i_ino, src_start >> 9),
                        BTREE_ITER_INTENT);
        dst = bch2_trans_copy_iter(&trans, src);
+       del = bch2_trans_copy_iter(&trans, src);
 
        while (1) {
                struct disk_reservation disk_res =
@@ -2544,8 +2545,6 @@ static long bchfs_fcollapse_finsert(struct bch_inode_info *inode,
                if (!k.k || k.k->p.inode != inode->v.i_ino)
                        break;
 
-               BUG_ON(bkey_cmp(src->pos, bkey_start_pos(k.k)));
-
                if (insert &&
                    bkey_cmp(k.k->p, POS(inode->v.i_ino, offset >> 9)) <= 0)
                        break;
@@ -2577,6 +2576,7 @@ reassemble:
                delete.k.p = copy.k->k.p;
                delete.k.size = copy.k->k.size;
                delete.k.p.offset -= shift >> 9;
+               bch2_btree_iter_set_pos(del, bkey_start_pos(&delete.k));
 
                next_pos = insert ? bkey_start_pos(&delete.k) : delete.k.p;
 
@@ -2597,9 +2597,7 @@ reassemble:
                        BUG_ON(ret);
                }
 
-               bch2_btree_iter_set_pos(src, bkey_start_pos(&delete.k));
-
-               ret =   bch2_trans_update(&trans, src, &delete, trigger_flags) ?:
+               ret =   bch2_trans_update(&trans, del, &delete, trigger_flags) ?:
                        bch2_trans_update(&trans, dst, copy.k, trigger_flags) ?:
                        bch2_trans_commit(&trans, &disk_res,
                                          &inode->ei_journal_seq,