struct btree_iter_level *,
struct bkey *);
-#define BTREE_ITER_NOT_END ((struct btree *) 1)
+#define BTREE_ITER_NO_NODE_GET_LOCKS ((struct btree *) 1)
+#define BTREE_ITER_NO_NODE_DROP ((struct btree *) 2)
+#define BTREE_ITER_NO_NODE_LOCK_ROOT ((struct btree *) 3)
+#define BTREE_ITER_NO_NODE_UP ((struct btree *) 4)
+#define BTREE_ITER_NO_NODE_DOWN ((struct btree *) 5)
+#define BTREE_ITER_NO_NODE_INIT ((struct btree *) 6)
+#define BTREE_ITER_NO_NODE_ERROR ((struct btree *) 7)
static inline bool is_btree_node(struct btree_iter *iter, unsigned l)
{
return l < BTREE_MAX_DEPTH &&
- iter->l[l].b &&
- iter->l[l].b != BTREE_ITER_NOT_END;
+ (unsigned long) iter->l[l].b >= 128;
}
/* Returns < 0 if @k is before iter pos, > 0 if @k is after */
struct btree *b = btree_iter_node(iter, level);
int want = __btree_lock_want(iter, level);
- if (!b || b == BTREE_ITER_NOT_END)
+ if (!is_btree_node(iter, level))
return false;
if (race_fault())
return false;
- if (!six_relock_type(&b->c.lock, want, iter->l[level].lock_seq) &&
- !(iter->l[level].lock_seq >> 1 == b->c.lock.state.seq >> 1 &&
- btree_node_lock_increment(iter, b, level, want)))
+ if (six_relock_type(&b->c.lock, want, iter->l[level].lock_seq) ||
+ (btree_node_lock_seq_matches(iter, b, level) &&
+ btree_node_lock_increment(iter, b, level, want))) {
+ mark_btree_node_locked(iter, level, want);
+ return true;
+ } else {
return false;
-
- mark_btree_node_locked(iter, level, want);
- return true;
+ }
}
static bool bch2_btree_node_upgrade(struct btree_iter *iter, unsigned level)
: six_relock_type(&b->c.lock, SIX_LOCK_intent, iter->l[level].lock_seq))
goto success;
- if (iter->l[level].lock_seq >> 1 == b->c.lock.state.seq >> 1 &&
+ if (btree_node_lock_seq_matches(iter, b, level) &&
btree_node_lock_increment(iter, b, level, BTREE_NODE_INTENT_LOCKED)) {
btree_node_unlock(iter, level);
goto success;
if (!(upgrade
? bch2_btree_node_upgrade(iter, l)
: bch2_btree_node_relock(iter, l))) {
+ if (upgrade)
+ trace_node_upgrade_fail(l, iter->l[l].lock_seq,
+ is_btree_node(iter, l)
+ ? 0
+ : (unsigned long) iter->l[l].b,
+ is_btree_node(iter, l)
+ ? iter->l[l].b->c.lock.state.seq
+ : 0);
+ else
+ trace_node_relock_fail(l, iter->l[l].lock_seq,
+ is_btree_node(iter, l)
+ ? 0
+ : (unsigned long) iter->l[l].b,
+ is_btree_node(iter, l)
+ ? iter->l[l].b->c.lock.state.seq
+ : 0);
+
fail_idx = l;
btree_iter_set_dirty(iter, BTREE_ITER_NEED_TRAVERSE);
}
*/
while (fail_idx >= 0) {
btree_node_unlock(iter, fail_idx);
- iter->l[fail_idx].b = BTREE_ITER_NOT_END;
+ iter->l[fail_idx].b = BTREE_ITER_NO_NODE_GET_LOCKS;
--fail_idx;
}
trans_for_each_iter(iter->trans, linked)
if (linked->l[level].b == b) {
__btree_node_unlock(linked, level);
- linked->l[level].b = BTREE_ITER_NOT_END;
+ linked->l[level].b = BTREE_ITER_NO_NODE_DROP;
}
}
* that depth
*/
iter->level = depth_want;
- iter->l[iter->level].b = NULL;
+ for (i = iter->level; i < BTREE_MAX_DEPTH; i++)
+ iter->l[i].b = NULL;
return 1;
}
b->c.level == iter->level &&
!race_fault())) {
for (i = 0; i < iter->level; i++)
- iter->l[i].b = BTREE_ITER_NOT_END;
+ iter->l[i].b = BTREE_ITER_NO_NODE_LOCK_ROOT;
iter->l[iter->level].b = b;
+ for (i = iter->level + 1; i < BTREE_MAX_DEPTH; i++)
+ iter->l[i].b = NULL;
mark_btree_node_locked(iter, iter->level, lock_type);
btree_iter_node_set(iter, b);
return 0;
-
}
six_unlock_type(&b->c.lock, lock_type);
if (unlikely(ret == -EIO)) {
trans->error = true;
iter->flags |= BTREE_ITER_ERROR;
- iter->l[iter->level].b = BTREE_ITER_NOT_END;
+ iter->l[iter->level].b = BTREE_ITER_NO_NODE_ERROR;
goto out;
}
unsigned l = iter->level;
while (btree_iter_node(iter, l) &&
- !(is_btree_node(iter, l) &&
- bch2_btree_node_relock(iter, l) &&
- (!check_pos ||
- btree_iter_pos_in_node(iter, iter->l[l].b)))) {
+ (!is_btree_node(iter, l) ||
+ !bch2_btree_node_relock(iter, l) ||
+ (check_pos &&
+ !btree_iter_pos_in_node(iter, iter->l[l].b)))) {
btree_node_unlock(iter, l);
- iter->l[l].b = BTREE_ITER_NOT_END;
+ iter->l[l].b = BTREE_ITER_NO_NODE_UP;
l++;
}
return 0;
iter->level = depth_want;
- iter->l[iter->level].b = BTREE_ITER_NOT_END;
+ iter->l[iter->level].b = BTREE_ITER_NO_NODE_DOWN;
return ret;
}
}
iter->nodes_intent_locked = 0;
for (i = 0; i < ARRAY_SIZE(iter->l); i++)
iter->l[i].b = NULL;
- iter->l[iter->level].b = BTREE_ITER_NOT_END;
+ iter->l[iter->level].b = BTREE_ITER_NO_NODE_INIT;
prefetch(c->btree_roots[btree_id].b);
}
for (i = 0; i < ARRAY_SIZE(iter->l); i++)
iter->l[i].b = NULL;
- iter->l[iter->level].b = BTREE_ITER_NOT_END;
+ iter->l[iter->level].b = BTREE_ITER_NO_NODE_INIT;
return iter;
}
TP_ARGS(c, ip)
);
+DEFINE_EVENT(transaction_restart, trans_restart_mark,
+ TP_PROTO(struct bch_fs *c, unsigned long ip),
+ TP_ARGS(c, ip)
+);
+
+DEFINE_EVENT(transaction_restart, trans_restart_upgrade,
+ TP_PROTO(struct bch_fs *c, unsigned long ip),
+ TP_ARGS(c, ip)
+);
+
+DEFINE_EVENT(transaction_restart, trans_restart_iter_upgrade,
+ TP_PROTO(struct bch_fs *c, unsigned long ip),
+ TP_ARGS(c, ip)
+);
+
DEFINE_EVENT(transaction_restart, trans_restart_traverse,
TP_PROTO(struct bch_fs *c, unsigned long ip),
TP_ARGS(c, ip)
TP_ARGS(c, ip)
);
+DECLARE_EVENT_CLASS(node_lock_fail,
+ TP_PROTO(unsigned level, u32 iter_seq, unsigned node, u32 node_seq),
+ TP_ARGS(level, iter_seq, node, node_seq),
+
+ TP_STRUCT__entry(
+ __field(u32, level)
+ __field(u32, iter_seq)
+ __field(u32, node)
+ __field(u32, node_seq)
+ ),
+
+ TP_fast_assign(
+ __entry->level = level;
+ __entry->iter_seq = iter_seq;
+ __entry->node = node;
+ __entry->node_seq = node_seq;
+ ),
+
+ TP_printk("level %u iter seq %u node %u node seq %u",
+ __entry->level, __entry->iter_seq,
+ __entry->node, __entry->node_seq)
+);
+
+DEFINE_EVENT(node_lock_fail, node_upgrade_fail,
+ TP_PROTO(unsigned level, u32 iter_seq, unsigned node, u32 node_seq),
+ TP_ARGS(level, iter_seq, node, node_seq)
+);
+
+DEFINE_EVENT(node_lock_fail, node_relock_fail,
+ TP_PROTO(unsigned level, u32 iter_seq, unsigned node, u32 node_seq),
+ TP_ARGS(level, iter_seq, node, node_seq)
+);
+
#endif /* _TRACE_BCACHEFS_H */
/* This part must be outside protection */