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;
}
* 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;
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))
}
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;
}
*/
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);
}
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;
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 =
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;
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;
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,