{
int ret;
- ret = __bch2_btree_iter_traverse(iter);
+ ret = bch2_trans_cond_resched(iter->trans) ?:
+ __bch2_btree_iter_traverse(iter);
if (unlikely(ret))
ret = __btree_iter_traverse_all(iter->trans, iter, ret);
return btree_iter_peek_uptodate(iter);
while (1) {
- ret = bch2_btree_iter_traverse(iter);
- if (unlikely(ret))
- return bkey_s_c_err(ret);
+ if (iter->uptodate >= BTREE_ITER_NEED_RELOCK) {
+ ret = bch2_btree_iter_traverse(iter);
+ if (unlikely(ret))
+ return bkey_s_c_err(ret);
+ }
k = __btree_iter_peek(iter, l);
if (likely(k.k))
bch2_btree_iter_checks(iter, BTREE_ITER_KEYS);
+ iter->pos = btree_type_successor(iter->btree_id, iter->k.p);
+
if (unlikely(iter->uptodate != BTREE_ITER_UPTODATE)) {
- k = bch2_btree_iter_peek(iter);
- if (IS_ERR_OR_NULL(k.k))
- return k;
+ /*
+ * XXX: when we just need to relock we should be able to avoid
+ * calling traverse, but we need to kill BTREE_ITER_NEED_PEEK
+ * for that to work
+ */
+ btree_iter_set_dirty(iter, BTREE_ITER_NEED_TRAVERSE);
+
+ return bch2_btree_iter_peek(iter);
}
do {
if (iter->uptodate == BTREE_ITER_UPTODATE)
return btree_iter_peek_uptodate(iter);
- ret = bch2_btree_iter_traverse(iter);
- if (unlikely(ret))
- return bkey_s_c_err(ret);
+ if (iter->uptodate >= BTREE_ITER_NEED_RELOCK) {
+ ret = bch2_btree_iter_traverse(iter);
+ if (unlikely(ret))
+ return bkey_s_c_err(ret);
+ }
return __bch2_btree_iter_peek_slot(iter);
}
* Unlocks before scheduling
* Note: does not revalidate iterator
*/
-static inline void bch2_trans_cond_resched(struct btree_trans *trans)
+static inline int bch2_trans_cond_resched(struct btree_trans *trans)
{
- if (need_resched()) {
+ if (need_resched() || race_fault()) {
bch2_trans_unlock(trans);
schedule();
- } else if (race_fault()) {
- bch2_trans_unlock(trans);
+ return bch2_trans_relock(trans) ? 0 : -EINTR;
+ } else {
+ return 0;
}
}
static inline struct bkey_s_c __bch2_btree_iter_next(struct btree_iter *iter,
unsigned flags)
{
- bch2_trans_cond_resched(iter->trans);
-
return flags & BTREE_ITER_SLOTS
? bch2_btree_iter_next_slot(iter)
: bch2_btree_iter_next(iter);