Commit 549d173c authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: EINTR -> BCH_ERR_transaction_restart

Now that we have error codes, with subtypes, we can switch to our own
error code for transaction restarts - and even better, a distinct error
code for each transaction restart reason: clearer code and better
debugging.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@gmail.com>
parent 0990efae
...@@ -234,7 +234,7 @@ struct posix_acl *bch2_get_acl(struct mnt_idmap *idmap, ...@@ -234,7 +234,7 @@ struct posix_acl *bch2_get_acl(struct mnt_idmap *idmap,
&X_SEARCH(acl_to_xattr_type(type), "", 0), &X_SEARCH(acl_to_xattr_type(type), "", 0),
0); 0);
if (ret) { if (ret) {
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
if (ret != -ENOENT) if (ret != -ENOENT)
acl = ERR_PTR(ret); acl = ERR_PTR(ret);
...@@ -334,7 +334,7 @@ int bch2_set_acl(struct mnt_idmap *idmap, ...@@ -334,7 +334,7 @@ int bch2_set_acl(struct mnt_idmap *idmap,
btree_err: btree_err:
bch2_trans_iter_exit(&trans, &inode_iter); bch2_trans_iter_exit(&trans, &inode_iter);
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
if (unlikely(ret)) if (unlikely(ret))
goto err; goto err;
......
...@@ -995,7 +995,7 @@ static int bch2_discard_one_bucket(struct btree_trans *trans, ...@@ -995,7 +995,7 @@ static int bch2_discard_one_bucket(struct btree_trans *trans,
GFP_KERNEL); GFP_KERNEL);
*discard_pos_done = iter.pos; *discard_pos_done = iter.pos;
ret = bch2_trans_relock(trans) ? 0 : -EINTR; ret = bch2_trans_relock(trans);
if (ret) if (ret)
goto out; goto out;
} }
......
...@@ -470,8 +470,9 @@ static struct open_bucket *bch2_bucket_alloc_freelist(struct btree_trans *trans, ...@@ -470,8 +470,9 @@ static struct open_bucket *bch2_bucket_alloc_freelist(struct btree_trans *trans,
for (alloc_cursor = max(alloc_cursor, bkey_start_offset(k.k)); for (alloc_cursor = max(alloc_cursor, bkey_start_offset(k.k));
alloc_cursor < k.k->p.offset; alloc_cursor < k.k->p.offset;
alloc_cursor++) { alloc_cursor++) {
if (btree_trans_too_many_iters(trans)) { ret = btree_trans_too_many_iters(trans);
ob = ERR_PTR(-EINTR); if (ret) {
ob = ERR_PTR(ret);
break; break;
} }
...@@ -488,7 +489,8 @@ static struct open_bucket *bch2_bucket_alloc_freelist(struct btree_trans *trans, ...@@ -488,7 +489,8 @@ static struct open_bucket *bch2_bucket_alloc_freelist(struct btree_trans *trans,
break; break;
} }
} }
if (ob)
if (ob || ret)
break; break;
} }
bch2_trans_iter_exit(trans, &iter); bch2_trans_iter_exit(trans, &iter);
...@@ -738,7 +740,7 @@ static int bch2_bucket_alloc_set_trans(struct btree_trans *trans, ...@@ -738,7 +740,7 @@ static int bch2_bucket_alloc_set_trans(struct btree_trans *trans,
ret = PTR_ERR_OR_ZERO(ob); ret = PTR_ERR_OR_ZERO(ob);
if (ret) { if (ret) {
if (ret == -EINTR || cl) if (bch2_err_matches(ret, BCH_ERR_transaction_restart) || cl)
break; break;
continue; continue;
} }
...@@ -925,7 +927,7 @@ static int open_bucket_add_buckets(struct btree_trans *trans, ...@@ -925,7 +927,7 @@ static int open_bucket_add_buckets(struct btree_trans *trans,
target, erasure_code, target, erasure_code,
nr_replicas, nr_effective, nr_replicas, nr_effective,
have_cache, flags, _cl); have_cache, flags, _cl);
if (ret == -EINTR || if (bch2_err_matches(ret, BCH_ERR_transaction_restart) ||
bch2_err_matches(ret, BCH_ERR_freelist_empty) || bch2_err_matches(ret, BCH_ERR_freelist_empty) ||
bch2_err_matches(ret, BCH_ERR_open_buckets_empty)) bch2_err_matches(ret, BCH_ERR_open_buckets_empty))
return ret; return ret;
...@@ -949,7 +951,7 @@ static int open_bucket_add_buckets(struct btree_trans *trans, ...@@ -949,7 +951,7 @@ static int open_bucket_add_buckets(struct btree_trans *trans,
nr_replicas, nr_effective, have_cache, nr_replicas, nr_effective, have_cache,
reserve, flags, cl); reserve, flags, cl);
if (ret && if (ret &&
ret != -EINTR && !bch2_err_matches(ret, BCH_ERR_transaction_restart) &&
!bch2_err_matches(ret, BCH_ERR_insufficient_devices) && !bch2_err_matches(ret, BCH_ERR_insufficient_devices) &&
!cl && _cl) { !cl && _cl) {
cl = _cl; cl = _cl;
...@@ -1191,7 +1193,8 @@ int bch2_alloc_sectors_start_trans(struct btree_trans *trans, ...@@ -1191,7 +1193,8 @@ int bch2_alloc_sectors_start_trans(struct btree_trans *trans,
nr_replicas, &nr_effective, nr_replicas, &nr_effective,
&have_cache, reserve, &have_cache, reserve,
ob_flags, NULL); ob_flags, NULL);
if (!ret || ret == -EINTR) if (!ret ||
bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto alloc_done; goto alloc_done;
ret = open_bucket_add_buckets(trans, &ptrs, wp, devs_have, ret = open_bucket_add_buckets(trans, &ptrs, wp, devs_have,
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "btree_iter.h" #include "btree_iter.h"
#include "btree_locking.h" #include "btree_locking.h"
#include "debug.h" #include "debug.h"
#include "errcode.h"
#include "error.h" #include "error.h"
#include "trace.h" #include "trace.h"
...@@ -692,8 +693,7 @@ static noinline struct btree *bch2_btree_node_fill(struct bch_fs *c, ...@@ -692,8 +693,7 @@ static noinline struct btree *bch2_btree_node_fill(struct bch_fs *c,
if (trans && !bch2_btree_node_relock(trans, path, level + 1)) { if (trans && !bch2_btree_node_relock(trans, path, level + 1)) {
trace_trans_restart_relock_parent_for_fill(trans->fn, trace_trans_restart_relock_parent_for_fill(trans->fn,
_THIS_IP_, btree_id, &path->pos); _THIS_IP_, btree_id, &path->pos);
btree_trans_restart(trans); return ERR_PTR(btree_trans_restart(trans, BCH_ERR_transaction_restart_fill_relock));
return ERR_PTR(-EINTR);
} }
b = bch2_btree_node_mem_alloc(c, level != 0); b = bch2_btree_node_mem_alloc(c, level != 0);
...@@ -702,8 +702,8 @@ static noinline struct btree *bch2_btree_node_fill(struct bch_fs *c, ...@@ -702,8 +702,8 @@ static noinline struct btree *bch2_btree_node_fill(struct bch_fs *c,
trans->memory_allocation_failure = true; trans->memory_allocation_failure = true;
trace_trans_restart_memory_allocation_failure(trans->fn, trace_trans_restart_memory_allocation_failure(trans->fn,
_THIS_IP_, btree_id, &path->pos); _THIS_IP_, btree_id, &path->pos);
btree_trans_restart(trans);
return ERR_PTR(-EINTR); return ERR_PTR(btree_trans_restart(trans, BCH_ERR_transaction_restart_fill_mem_alloc_fail));
} }
if (IS_ERR(b)) if (IS_ERR(b))
...@@ -740,18 +740,19 @@ static noinline struct btree *bch2_btree_node_fill(struct bch_fs *c, ...@@ -740,18 +740,19 @@ static noinline struct btree *bch2_btree_node_fill(struct bch_fs *c,
if (!sync) if (!sync)
return NULL; return NULL;
if (trans && if (trans) {
(!bch2_trans_relock(trans) || int ret = bch2_trans_relock(trans) ?:
!bch2_btree_path_relock_intent(trans, path))) { bch2_btree_path_relock_intent(trans, path);
BUG_ON(!trans->restarted); if (ret) {
return ERR_PTR(-EINTR); BUG_ON(!trans->restarted);
return ERR_PTR(ret);
}
} }
if (!six_relock_type(&b->c.lock, lock_type, seq)) { if (!six_relock_type(&b->c.lock, lock_type, seq)) {
trace_trans_restart_relock_after_fill(trans->fn, _THIS_IP_, trace_trans_restart_relock_after_fill(trans->fn, _THIS_IP_,
btree_id, &path->pos); btree_id, &path->pos);
btree_trans_restart(trans); return ERR_PTR(btree_trans_restart(trans, BCH_ERR_transaction_restart_relock_after_fill));
return ERR_PTR(-EINTR);
} }
return b; return b;
...@@ -762,7 +763,9 @@ static int lock_node_check_fn(struct six_lock *lock, void *p) ...@@ -762,7 +763,9 @@ static int lock_node_check_fn(struct six_lock *lock, void *p)
struct btree *b = container_of(lock, struct btree, c.lock); struct btree *b = container_of(lock, struct btree, c.lock);
const struct bkey_i *k = p; const struct bkey_i *k = p;
return b->hash_val == btree_ptr_hash_val(k) ? 0 : -1; if (b->hash_val != btree_ptr_hash_val(k))
return BCH_ERR_lock_fail_node_reused;
return 0;
} }
static noinline void btree_bad_header(struct bch_fs *c, struct btree *b) static noinline void btree_bad_header(struct bch_fs *c, struct btree *b)
...@@ -821,6 +824,7 @@ struct btree *bch2_btree_node_get(struct btree_trans *trans, struct btree_path * ...@@ -821,6 +824,7 @@ struct btree *bch2_btree_node_get(struct btree_trans *trans, struct btree_path *
struct btree_cache *bc = &c->btree_cache; struct btree_cache *bc = &c->btree_cache;
struct btree *b; struct btree *b;
struct bset_tree *t; struct bset_tree *t;
int ret;
EBUG_ON(level >= BTREE_MAX_DEPTH); EBUG_ON(level >= BTREE_MAX_DEPTH);
...@@ -885,11 +889,14 @@ struct btree *bch2_btree_node_get(struct btree_trans *trans, struct btree_path * ...@@ -885,11 +889,14 @@ struct btree *bch2_btree_node_get(struct btree_trans *trans, struct btree_path *
if (btree_node_read_locked(path, level + 1)) if (btree_node_read_locked(path, level + 1))
btree_node_unlock(trans, path, level + 1); btree_node_unlock(trans, path, level + 1);
if (!btree_node_lock(trans, path, b, k->k.p, level, lock_type, ret = btree_node_lock(trans, path, b, k->k.p, level, lock_type,
lock_node_check_fn, (void *) k, trace_ip)) { lock_node_check_fn, (void *) k, trace_ip);
if (!trans->restarted) if (unlikely(ret)) {
if (bch2_err_matches(ret, BCH_ERR_lock_fail_node_reused))
goto retry; goto retry;
return ERR_PTR(-EINTR); if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
return ERR_PTR(ret);
BUG();
} }
if (unlikely(b->hash_val != btree_ptr_hash_val(k) || if (unlikely(b->hash_val != btree_ptr_hash_val(k) ||
...@@ -903,8 +910,7 @@ struct btree *bch2_btree_node_get(struct btree_trans *trans, struct btree_path * ...@@ -903,8 +910,7 @@ struct btree *bch2_btree_node_get(struct btree_trans *trans, struct btree_path *
trace_ip, trace_ip,
path->btree_id, path->btree_id,
&path->pos); &path->pos);
btree_trans_restart(trans); return ERR_PTR(btree_trans_restart(trans, BCH_ERR_transaction_restart_lock_node_reused));
return ERR_PTR(-EINTR);
} }
} }
...@@ -920,11 +926,13 @@ struct btree *bch2_btree_node_get(struct btree_trans *trans, struct btree_path * ...@@ -920,11 +926,13 @@ struct btree *bch2_btree_node_get(struct btree_trans *trans, struct btree_path *
* should_be_locked is not set on this path yet, so we need to * should_be_locked is not set on this path yet, so we need to
* relock it specifically: * relock it specifically:
*/ */
if (trans && if (trans) {
(!bch2_trans_relock(trans) || int ret = bch2_trans_relock(trans) ?:
!bch2_btree_path_relock_intent(trans, path))) { bch2_btree_path_relock_intent(trans, path);
BUG_ON(!trans->restarted); if (ret) {
return ERR_PTR(-EINTR); BUG_ON(!trans->restarted);
return ERR_PTR(ret);
}
} }
if (!six_relock_type(&b->c.lock, lock_type, seq)) if (!six_relock_type(&b->c.lock, lock_type, seq))
......
...@@ -34,7 +34,7 @@ static inline int bch2_trans_cond_resched(struct btree_trans *trans) ...@@ -34,7 +34,7 @@ static inline int bch2_trans_cond_resched(struct btree_trans *trans)
if (need_resched() || race_fault()) { if (need_resched() || race_fault()) {
bch2_trans_unlock(trans); bch2_trans_unlock(trans);
schedule(); schedule();
return bch2_trans_relock(trans) ? 0 : -EINTR; return bch2_trans_relock(trans);
} else { } else {
return 0; return 0;
} }
...@@ -285,13 +285,13 @@ static struct bpos btree_node_pos(struct btree_bkey_cached_common *_b, ...@@ -285,13 +285,13 @@ static struct bpos btree_node_pos(struct btree_bkey_cached_common *_b,
} }
/* Slowpath: */ /* Slowpath: */
bool __bch2_btree_node_lock(struct btree_trans *trans, int __bch2_btree_node_lock(struct btree_trans *trans,
struct btree_path *path, struct btree_path *path,
struct btree *b, struct btree *b,
struct bpos pos, unsigned level, struct bpos pos, unsigned level,
enum six_lock_type type, enum six_lock_type type,
six_lock_should_sleep_fn should_sleep_fn, void *p, six_lock_should_sleep_fn should_sleep_fn, void *p,
unsigned long ip) unsigned long ip)
{ {
struct btree_path *linked; struct btree_path *linked;
unsigned reason; unsigned reason;
...@@ -369,8 +369,7 @@ bool __bch2_btree_node_lock(struct btree_trans *trans, ...@@ -369,8 +369,7 @@ bool __bch2_btree_node_lock(struct btree_trans *trans,
path->btree_id, path->btree_id,
path->cached, path->cached,
&pos); &pos);
btree_trans_restart(trans); return btree_trans_restart(trans, BCH_ERR_transaction_restart_would_deadlock);
return false;
} }
/* Btree iterator locking: */ /* Btree iterator locking: */
...@@ -408,8 +407,8 @@ static inline void bch2_btree_path_verify_locks(struct btree_path *path) {} ...@@ -408,8 +407,8 @@ static inline void bch2_btree_path_verify_locks(struct btree_path *path) {}
/* /*
* Only for btree_cache.c - only relocks intent locks * Only for btree_cache.c - only relocks intent locks
*/ */
bool bch2_btree_path_relock_intent(struct btree_trans *trans, int bch2_btree_path_relock_intent(struct btree_trans *trans,
struct btree_path *path) struct btree_path *path)
{ {
unsigned l; unsigned l;
...@@ -421,16 +420,15 @@ bool bch2_btree_path_relock_intent(struct btree_trans *trans, ...@@ -421,16 +420,15 @@ bool bch2_btree_path_relock_intent(struct btree_trans *trans,
btree_path_set_dirty(path, BTREE_ITER_NEED_TRAVERSE); btree_path_set_dirty(path, BTREE_ITER_NEED_TRAVERSE);
trace_trans_restart_relock_path_intent(trans->fn, _RET_IP_, trace_trans_restart_relock_path_intent(trans->fn, _RET_IP_,
path->btree_id, &path->pos); path->btree_id, &path->pos);
btree_trans_restart(trans); return btree_trans_restart(trans, BCH_ERR_transaction_restart_relock_path_intent);
return false;
} }
} }
return true; return 0;
} }
noinline __flatten noinline __flatten
static bool __bch2_btree_path_relock(struct btree_trans *trans, static int __bch2_btree_path_relock(struct btree_trans *trans,
struct btree_path *path, unsigned long trace_ip) struct btree_path *path, unsigned long trace_ip)
{ {
bool ret = btree_path_get_locks(trans, path, false); bool ret = btree_path_get_locks(trans, path, false);
...@@ -438,16 +436,17 @@ static bool __bch2_btree_path_relock(struct btree_trans *trans, ...@@ -438,16 +436,17 @@ static bool __bch2_btree_path_relock(struct btree_trans *trans,
if (!ret) { if (!ret) {
trace_trans_restart_relock_path(trans->fn, trace_ip, trace_trans_restart_relock_path(trans->fn, trace_ip,
path->btree_id, &path->pos); path->btree_id, &path->pos);
btree_trans_restart(trans); return btree_trans_restart(trans, BCH_ERR_transaction_restart_relock_path);
} }
return ret;
return 0;
} }
static inline bool bch2_btree_path_relock(struct btree_trans *trans, static inline int bch2_btree_path_relock(struct btree_trans *trans,
struct btree_path *path, unsigned long trace_ip) struct btree_path *path, unsigned long trace_ip)
{ {
return btree_node_locked(path, path->level) return btree_node_locked(path, path->level)
? true ? 0
: __bch2_btree_path_relock(trans, path, trace_ip); : __bch2_btree_path_relock(trans, path, trace_ip);
} }
...@@ -532,22 +531,22 @@ void bch2_trans_downgrade(struct btree_trans *trans) ...@@ -532,22 +531,22 @@ void bch2_trans_downgrade(struct btree_trans *trans)
/* Btree transaction locking: */ /* Btree transaction locking: */
bool bch2_trans_relock(struct btree_trans *trans) int bch2_trans_relock(struct btree_trans *trans)
{ {
struct btree_path *path; struct btree_path *path;
if (unlikely(trans->restarted)) if (unlikely(trans->restarted))
return false; return -BCH_ERR_transaction_restart_relock;
trans_for_each_path(trans, path) trans_for_each_path(trans, path)
if (path->should_be_locked && if (path->should_be_locked &&
!bch2_btree_path_relock(trans, path, _RET_IP_)) { bch2_btree_path_relock(trans, path, _RET_IP_)) {
trace_trans_restart_relock(trans->fn, _RET_IP_, trace_trans_restart_relock(trans->fn, _RET_IP_,
path->btree_id, &path->pos); path->btree_id, &path->pos);
BUG_ON(!trans->restarted); BUG_ON(!trans->restarted);
return false; return -BCH_ERR_transaction_restart_relock;
} }
return true; return 0;
} }
void bch2_trans_unlock(struct btree_trans *trans) void bch2_trans_unlock(struct btree_trans *trans)
...@@ -1187,7 +1186,9 @@ static int lock_root_check_fn(struct six_lock *lock, void *p) ...@@ -1187,7 +1186,9 @@ static int lock_root_check_fn(struct six_lock *lock, void *p)
struct btree *b = container_of(lock, struct btree, c.lock); struct btree *b = container_of(lock, struct btree, c.lock);
struct btree **rootp = p; struct btree **rootp = p;
return b == *rootp ? 0 : -1; if (b != *rootp)
return BCH_ERR_lock_fail_root_changed;
return 0;
} }
static inline int btree_path_lock_root(struct btree_trans *trans, static inline int btree_path_lock_root(struct btree_trans *trans,
...@@ -1199,6 +1200,7 @@ static inline int btree_path_lock_root(struct btree_trans *trans, ...@@ -1199,6 +1200,7 @@ static inline int btree_path_lock_root(struct btree_trans *trans,
struct btree *b, **rootp = &c->btree_roots[path->btree_id].b; struct btree *b, **rootp = &c->btree_roots[path->btree_id].b;
enum six_lock_type lock_type; enum six_lock_type lock_type;
unsigned i; unsigned i;
int ret;
EBUG_ON(path->nodes_locked); EBUG_ON(path->nodes_locked);
...@@ -1220,13 +1222,16 @@ static inline int btree_path_lock_root(struct btree_trans *trans, ...@@ -1220,13 +1222,16 @@ static inline int btree_path_lock_root(struct btree_trans *trans,
} }
lock_type = __btree_lock_want(path, path->level); lock_type = __btree_lock_want(path, path->level);
if (unlikely(!btree_node_lock(trans, path, b, SPOS_MAX, ret = btree_node_lock(trans, path, b, SPOS_MAX,
path->level, lock_type, path->level, lock_type,
lock_root_check_fn, rootp, lock_root_check_fn, rootp,
trace_ip))) { trace_ip);
if (trans->restarted) if (unlikely(ret)) {
return -EINTR; if (bch2_err_matches(ret, BCH_ERR_lock_fail_root_changed))
continue; continue;
if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
return ret;
BUG();
} }
if (likely(b == READ_ONCE(*rootp) && if (likely(b == READ_ONCE(*rootp) &&
...@@ -1431,12 +1436,12 @@ static int bch2_btree_path_traverse_all(struct btree_trans *trans) ...@@ -1431,12 +1436,12 @@ static int bch2_btree_path_traverse_all(struct btree_trans *trans)
int i, ret = 0; int i, ret = 0;
if (trans->in_traverse_all) if (trans->in_traverse_all)
return -EINTR; return -BCH_ERR_transaction_restart_in_traverse_all;
trans->in_traverse_all = true; trans->in_traverse_all = true;
retry_all: retry_all:
prev = NULL; prev = NULL;
trans->restarted = false; trans->restarted = 0;
trans_for_each_path(trans, path) trans_for_each_path(trans, path)
path->should_be_locked = false; path->should_be_locked = false;
...@@ -1480,7 +1485,8 @@ static int bch2_btree_path_traverse_all(struct btree_trans *trans) ...@@ -1480,7 +1485,8 @@ static int bch2_btree_path_traverse_all(struct btree_trans *trans)
*/ */
if (path->uptodate) { if (path->uptodate) {
ret = btree_path_traverse_one(trans, path, 0, _THIS_IP_); ret = btree_path_traverse_one(trans, path, 0, _THIS_IP_);
if (ret == -EINTR || ret == -ENOMEM) if (bch2_err_matches(ret, BCH_ERR_transaction_restart) ||
ret == -ENOMEM)
goto retry_all; goto retry_all;
if (ret) if (ret)
goto err; goto err;
...@@ -1587,19 +1593,17 @@ static int btree_path_traverse_one(struct btree_trans *trans, ...@@ -1587,19 +1593,17 @@ static int btree_path_traverse_one(struct btree_trans *trans,
unsigned long trace_ip) unsigned long trace_ip)
{ {
unsigned depth_want = path->level; unsigned depth_want = path->level;
int ret = 0; int ret = trans->restarted;
if (unlikely(trans->restarted)) { if (unlikely(ret))
ret = -EINTR;
goto out; goto out;
}
/* /*
* Ensure we obey path->should_be_locked: if it's set, we can't unlock * Ensure we obey path->should_be_locked: if it's set, we can't unlock
* and re-traverse the path without a transaction restart: * and re-traverse the path without a transaction restart:
*/ */
if (path->should_be_locked) { if (path->should_be_locked) {
ret = bch2_btree_path_relock(trans, path, trace_ip) ? 0 : -EINTR; ret = bch2_btree_path_relock(trans, path, trace_ip);
goto out; goto out;
} }
...@@ -1648,7 +1652,7 @@ static int btree_path_traverse_one(struct btree_trans *trans, ...@@ -1648,7 +1652,7 @@ static int btree_path_traverse_one(struct btree_trans *trans,
path->uptodate = BTREE_ITER_UPTODATE; path->uptodate = BTREE_ITER_UPTODATE;
out: out:
BUG_ON((ret == -EINTR) != !!trans->restarted); BUG_ON(bch2_err_matches(ret, BCH_ERR_transaction_restart) != !!trans->restarted);
bch2_btree_path_verify(trans, path); bch2_btree_path_verify(trans, path);
return ret; return ret;
} }
...@@ -2135,8 +2139,7 @@ struct btree *bch2_btree_iter_next_node(struct btree_iter *iter) ...@@ -2135,8 +2139,7 @@ struct btree *bch2_btree_iter_next_node(struct btree_iter *iter)
btree_path_set_dirty(path, BTREE_ITER_NEED_TRAVERSE); btree_path_set_dirty(path, BTREE_ITER_NEED_TRAVERSE);
trace_trans_restart_relock_next_node(trans->fn, _THIS_IP_, trace_trans_restart_relock_next_node(trans->fn, _THIS_IP_,
path->btree_id, &path->pos); path->btree_id, &path->pos);
btree_trans_restart(trans); ret = btree_trans_restart(trans, BCH_ERR_transaction_restart_relock);
ret = -EINTR;
goto err; goto err;
} }
...@@ -2517,8 +2520,9 @@ struct bkey_s_c bch2_btree_iter_peek_upto(struct btree_iter *iter, struct bpos e ...@@ -2517,8 +2520,9 @@ struct bkey_s_c bch2_btree_iter_peek_upto(struct btree_iter *iter, struct bpos e
BUG_ON(!iter->path->nodes_locked); BUG_ON(!iter->path->nodes_locked);
out: out:
if (iter->update_path) { if (iter->update_path) {
if (unlikely(!bch2_btree_path_relock(trans, iter->update_path, _THIS_IP_))) { ret = bch2_btree_path_relock(trans, iter->update_path, _THIS_IP_);
k = bkey_s_c_err(-EINTR); if (unlikely(ret)) {
k = bkey_s_c_err(ret);
} else { } else {
BUG_ON(!(iter->update_path->nodes_locked & 1)); BUG_ON(!(iter->update_path->nodes_locked & 1));
iter->update_path->should_be_locked = true; iter->update_path->should_be_locked = true;
...@@ -3169,8 +3173,7 @@ void *bch2_trans_kmalloc(struct btree_trans *trans, size_t size) ...@@ -3169,8 +3173,7 @@ void *bch2_trans_kmalloc(struct btree_trans *trans, size_t size)
if (old_bytes) { if (old_bytes) {
trace_trans_restart_mem_realloced(trans->fn, _RET_IP_, new_bytes); trace_trans_restart_mem_realloced(trans->fn, _RET_IP_, new_bytes);
btree_trans_restart(trans); return ERR_PTR(btree_trans_restart(trans, BCH_ERR_transaction_restart_mem_realloced));
return ERR_PTR(-EINTR);
} }
} }
...@@ -3184,9 +3187,9 @@ void *bch2_trans_kmalloc(struct btree_trans *trans, size_t size) ...@@ -3184,9 +3187,9 @@ void *bch2_trans_kmalloc(struct btree_trans *trans, size_t size)
* bch2_trans_begin() - reset a transaction after a interrupted attempt * bch2_trans_begin() - reset a transaction after a interrupted attempt
* @trans: transaction to reset * @trans: transaction to reset
* *
* While iterating over nodes or updating nodes a attempt to lock a btree * While iterating over nodes or updating nodes a attempt to lock a btree node
* node may return EINTR when the trylock fails. When this occurs * may return BCH_ERR_transaction_restart when the trylock fails. When this
* bch2_trans_begin() should be called and the transaction retried. * occurs bch2_trans_begin() should be called and the transaction retried.
*/ */
u32 bch2_trans_begin(struct btree_trans *trans) u32 bch2_trans_begin(struct btree_trans *trans)
{ {
......
...@@ -197,27 +197,36 @@ void bch2_btree_node_iter_fix(struct btree_trans *trans, struct btree_path *, ...@@ -197,27 +197,36 @@ void bch2_btree_node_iter_fix(struct btree_trans *trans, struct btree_path *,
struct btree *, struct btree_node_iter *, struct btree *, struct btree_node_iter *,
struct bkey_packed *, unsigned, unsigned); struct bkey_packed *, unsigned, unsigned);
bool bch2_btree_path_relock_intent(struct btree_trans *, struct btree_path *); int bch2_btree_path_relock_intent(struct btree_trans *, struct btree_path *);
void bch2_path_put(struct btree_trans *, struct btree_path *, bool); void bch2_path_put(struct btree_trans *, struct btree_path *, bool);
bool bch2_trans_relock(struct btree_trans *); int bch2_trans_relock(struct btree_trans *);
void bch2_trans_unlock(struct btree_trans *); void bch2_trans_unlock(struct btree_trans *);
static inline int trans_was_restarted(struct btree_trans *trans, u32 restart_count) static inline bool trans_was_restarted(struct btree_trans *trans, u32 restart_count)
{ {
return restart_count != trans->restart_count ? -EINTR : 0; return restart_count != trans->restart_count;
} }
void bch2_trans_verify_not_restarted(struct btree_trans *, u32); void bch2_trans_verify_not_restarted(struct btree_trans *, u32);
__always_inline __always_inline
static inline int btree_trans_restart(struct btree_trans *trans) static inline int btree_trans_restart_nounlock(struct btree_trans *trans, int err)
{ {
trans->restarted = true; BUG_ON(err <= 0);
BUG_ON(!bch2_err_matches(err, BCH_ERR_transaction_restart));
trans->restarted = err;
trans->restart_count++; trans->restart_count++;
bch2_trans_unlock(trans); return -err;
return -EINTR; }
__always_inline
static inline int btree_trans_restart(struct btree_trans *trans, int err)
{
btree_trans_restart_nounlock(trans, err);
return -err;
} }
bool bch2_btree_node_upgrade(struct btree_trans *, bool bch2_btree_node_upgrade(struct btree_trans *,
...@@ -338,7 +347,7 @@ __btree_iter_peek_node_and_restart(struct btree_trans *trans, struct btree_iter ...@@ -338,7 +347,7 @@ __btree_iter_peek_node_and_restart(struct btree_trans *trans, struct btree_iter
struct btree *b; struct btree *b;
while (b = bch2_btree_iter_peek_node(iter), while (b = bch2_btree_iter_peek_node(iter),
PTR_ERR_OR_ZERO(b) == -EINTR) bch2_err_matches(PTR_ERR_OR_ZERO(b), BCH_ERR_transaction_restart))
bch2_trans_begin(trans); bch2_trans_begin(trans);
return b; return b;
...@@ -387,7 +396,7 @@ static inline int btree_trans_too_many_iters(struct btree_trans *trans) ...@@ -387,7 +396,7 @@ static inline int btree_trans_too_many_iters(struct btree_trans *trans)
{ {
if (hweight64(trans->paths_allocated) > BTREE_ITER_MAX / 2) { if (hweight64(trans->paths_allocated) > BTREE_ITER_MAX / 2) {
trace_trans_restart_too_many_iters(trans->fn, _THIS_IP_); trace_trans_restart_too_many_iters(trans->fn, _THIS_IP_);
return btree_trans_restart(trans); return btree_trans_restart(trans, BCH_ERR_transaction_restart_too_many_iters);
} }
return 0; return 0;
...@@ -401,7 +410,7 @@ __bch2_btree_iter_peek_and_restart(struct btree_trans *trans, ...@@ -401,7 +410,7 @@ __bch2_btree_iter_peek_and_restart(struct btree_trans *trans,
while (btree_trans_too_many_iters(trans) || while (btree_trans_too_many_iters(trans) ||
(k = bch2_btree_iter_peek_type(iter, flags), (k = bch2_btree_iter_peek_type(iter, flags),
bkey_err(k) == -EINTR)) bch2_err_matches(bkey_err(k), BCH_ERR_transaction_restart)))
bch2_trans_begin(trans); bch2_trans_begin(trans);
return k; return k;
...@@ -414,7 +423,7 @@ __bch2_btree_iter_peek_and_restart(struct btree_trans *trans, ...@@ -414,7 +423,7 @@ __bch2_btree_iter_peek_and_restart(struct btree_trans *trans,
do { \ do { \
bch2_trans_begin(_trans); \ bch2_trans_begin(_trans); \
_ret = (_do); \ _ret = (_do); \
} while (_ret == -EINTR); \ } while (bch2_err_matches(_ret, BCH_ERR_transaction_restart)); \
\ \
_ret; \ _ret; \
}) })
...@@ -425,7 +434,8 @@ __bch2_btree_iter_peek_and_restart(struct btree_trans *trans, ...@@ -425,7 +434,8 @@ __bch2_btree_iter_peek_and_restart(struct btree_trans *trans,
* These are like lockrestart_do() and commit_do(), with two differences: * These are like lockrestart_do() and commit_do(), with two differences:
* *
* - We don't call bch2_trans_begin() unless we had a transaction restart * - We don't call bch2_trans_begin() unless we had a transaction restart
* - We return -EINTR if we succeeded after a transaction restart * - We return -BCH_ERR_transaction_restart_nested if we succeeded after a
* transaction restart
*/ */
#define nested_lockrestart_do(_trans, _do) \ #define nested_lockrestart_do(_trans, _do) \
({ \ ({ \
...@@ -434,13 +444,16 @@ __bch2_btree_iter_peek_and_restart(struct btree_trans *trans, ...@@ -434,13 +444,16 @@ __bch2_btree_iter_peek_and_restart(struct btree_trans *trans,
\ \
_restart_count = _orig_restart_count = (_trans)->restart_count; \ _restart_count = _orig_restart_count = (_trans)->restart_count; \
\ \
while ((_ret = (_do)) == -EINTR) \ while (bch2_err_matches(_ret = (_do), BCH_ERR_transaction_restart))\
_restart_count = bch2_trans_begin(_trans); \ _restart_count = bch2_trans_begin(_trans); \
\ \
if (!_ret) \ if (!_ret) \
bch2_trans_verify_not_restarted(_trans, _restart_count);\ bch2_trans_verify_not_restarted(_trans, _restart_count);\
\ \
_ret ?: trans_was_restarted(_trans, _orig_restart_count); \ if (!_ret && trans_was_restarted(_trans, _orig_restart_count)) \
_ret = -BCH_ERR_transaction_restart_nested; \
\
_ret; \
}) })
#define for_each_btree_key2(_trans, _iter, _btree_id, \ #define for_each_btree_key2(_trans, _iter, _btree_id, \
...@@ -451,7 +464,7 @@ __bch2_btree_iter_peek_and_restart(struct btree_trans *trans, ...@@ -451,7 +464,7 @@ __bch2_btree_iter_peek_and_restart(struct btree_trans *trans,
bch2_trans_iter_init((_trans), &(_iter), (_btree_id), \ bch2_trans_iter_init((_trans), &(_iter), (_btree_id), \
(_start), (_flags)); \ (_start), (_flags)); \
\ \
do { \ while (1) { \
bch2_trans_begin(_trans); \ bch2_trans_begin(_trans); \
(_k) = bch2_btree_iter_peek_type(&(_iter), (_flags)); \ (_k) = bch2_btree_iter_peek_type(&(_iter), (_flags)); \
if (!(_k).k) { \ if (!(_k).k) { \
...@@ -460,9 +473,12 @@ __bch2_btree_iter_peek_and_restart(struct btree_trans *trans, ...@@ -460,9 +473,12 @@ __bch2_btree_iter_peek_and_restart(struct btree_trans *trans,
} \ } \
\ \
_ret = bkey_err(_k) ?: (_do); \ _ret = bkey_err(_k) ?: (_do); \
if (!_ret) \ if (bch2_err_matches(_ret, BCH_ERR_transaction_restart))\
bch2_btree_iter_advance(&(_iter)); \ continue; \
} while (_ret == 0 || _ret == -EINTR); \ if (_ret) \
break; \
bch2_btree_iter_advance(&(_iter)); \
} \
\ \
bch2_trans_iter_exit((_trans), &(_iter)); \ bch2_trans_iter_exit((_trans), &(_iter)); \
_ret; \ _ret; \
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "btree_key_cache.h" #include "btree_key_cache.h"
#include "btree_locking.h" #include "btree_locking.h"
#include "btree_update.h" #include "btree_update.h"
#include "errcode.h"
#include "error.h" #include "error.h"
#include "journal.h" #include "journal.h"
#include "journal_reclaim.h" #include "journal_reclaim.h"
...@@ -292,7 +293,7 @@ static int btree_key_cache_fill(struct btree_trans *trans, ...@@ -292,7 +293,7 @@ static int btree_key_cache_fill(struct btree_trans *trans,
if (!bch2_btree_node_relock(trans, ck_path, 0)) { if (!bch2_btree_node_relock(trans, ck_path, 0)) {
trace_trans_restart_relock_key_cache_fill(trans->fn, trace_trans_restart_relock_key_cache_fill(trans->fn,
_THIS_IP_, ck_path->btree_id, &ck_path->pos); _THIS_IP_, ck_path->btree_id, &ck_path->pos);
ret = btree_trans_restart(trans); ret = btree_trans_restart(trans, BCH_ERR_transaction_restart_key_cache_raced);
goto err; goto err;
} }
...@@ -347,8 +348,10 @@ static int bkey_cached_check_fn(struct six_lock *lock, void *p) ...@@ -347,8 +348,10 @@ static int bkey_cached_check_fn(struct six_lock *lock, void *p)
struct bkey_cached *ck = container_of(lock, struct bkey_cached, c.lock); struct bkey_cached *ck = container_of(lock, struct bkey_cached, c.lock);
const struct btree_path *path = p; const struct btree_path *path = p;
return ck->key.btree_id == path->btree_id && if (ck->key.btree_id != path->btree_id &&
!bpos_cmp(ck->key.pos, path->pos) ? 0 : -1; bpos_cmp(ck->key.pos, path->pos))
return BCH_ERR_lock_fail_node_reused;
return 0;
} }
__flatten __flatten
...@@ -387,14 +390,15 @@ int bch2_btree_path_traverse_cached(struct btree_trans *trans, struct btree_path ...@@ -387,14 +390,15 @@ int bch2_btree_path_traverse_cached(struct btree_trans *trans, struct btree_path
} else { } else {
enum six_lock_type lock_want = __btree_lock_want(path, 0); enum six_lock_type lock_want = __btree_lock_want(path, 0);
if (!btree_node_lock(trans, path, (void *) ck, path->pos, 0, ret = btree_node_lock(trans, path, (void *) ck, path->pos, 0,
lock_want, lock_want,
bkey_cached_check_fn, path, _THIS_IP_)) { bkey_cached_check_fn, path, _THIS_IP_);
if (!trans->restarted) if (ret) {
if (bch2_err_matches(ret, BCH_ERR_lock_fail_node_reused))
goto retry; goto retry;
if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
ret = -EINTR; goto err;
goto err; BUG();
} }
if (ck->key.btree_id != path->btree_id || if (ck->key.btree_id != path->btree_id ||
...@@ -413,7 +417,7 @@ int bch2_btree_path_traverse_cached(struct btree_trans *trans, struct btree_path ...@@ -413,7 +417,7 @@ int bch2_btree_path_traverse_cached(struct btree_trans *trans, struct btree_path
if (!path->locks_want && if (!path->locks_want &&
!__bch2_btree_path_upgrade(trans, path, 1)) { !__bch2_btree_path_upgrade(trans, path, 1)) {
trace_transaction_restart_ip(trans->fn, _THIS_IP_); trace_transaction_restart_ip(trans->fn, _THIS_IP_);
ret = btree_trans_restart(trans); ret = btree_trans_restart(trans, BCH_ERR_transaction_restart_upgrade);
goto err; goto err;
} }
...@@ -430,7 +434,7 @@ int bch2_btree_path_traverse_cached(struct btree_trans *trans, struct btree_path ...@@ -430,7 +434,7 @@ int bch2_btree_path_traverse_cached(struct btree_trans *trans, struct btree_path
return ret; return ret;
err: err:
if (ret != -EINTR) { if (!bch2_err_matches(ret, BCH_ERR_transaction_restart)) {
btree_node_unlock(trans, path, 0); btree_node_unlock(trans, path, 0);
path->l[0].b = BTREE_ITER_NO_NODE_ERROR; path->l[0].b = BTREE_ITER_NO_NODE_ERROR;
} }
...@@ -497,13 +501,14 @@ static int btree_key_cache_flush_pos(struct btree_trans *trans, ...@@ -497,13 +501,14 @@ static int btree_key_cache_flush_pos(struct btree_trans *trans,
? JOURNAL_WATERMARK_reserved ? JOURNAL_WATERMARK_reserved
: 0)| : 0)|
commit_flags); commit_flags);
if (ret) {
bch2_fs_fatal_err_on(ret != -EINTR && bch2_fs_fatal_err_on(ret &&
ret != -EAGAIN && !bch2_err_matches(ret, BCH_ERR_transaction_restart) &&
!bch2_journal_error(j), c, !bch2_err_matches(ret, BCH_ERR_journal_reclaim_would_deadlock) &&
"error flushing key cache: %i", ret); !bch2_journal_error(j), c,
"error flushing key cache: %s", bch2_err_str(ret));
if (ret)
goto out; goto out;
}
bch2_journal_pin_drop(j, &ck->journal); bch2_journal_pin_drop(j, &ck->journal);
bch2_journal_preres_put(j, &ck->res); bch2_journal_preres_put(j, &ck->res);
......
...@@ -152,7 +152,7 @@ static inline enum bch_time_stats lock_to_time_stat(enum six_lock_type type) ...@@ -152,7 +152,7 @@ static inline enum bch_time_stats lock_to_time_stat(enum six_lock_type type)
} }
} }
static inline bool btree_node_lock_type(struct btree_trans *trans, static inline int btree_node_lock_type(struct btree_trans *trans,
struct btree_path *path, struct btree_path *path,
struct btree *b, struct btree *b,
struct bpos pos, unsigned level, struct bpos pos, unsigned level,
...@@ -161,10 +161,10 @@ static inline bool btree_node_lock_type(struct btree_trans *trans, ...@@ -161,10 +161,10 @@ static inline bool btree_node_lock_type(struct btree_trans *trans,
{ {
struct bch_fs *c = trans->c; struct bch_fs *c = trans->c;
u64 start_time; u64 start_time;
bool ret; int ret;
if (six_trylock_type(&b->c.lock, type)) if (six_trylock_type(&b->c.lock, type))
return true; return 0;
start_time = local_clock(); start_time = local_clock();
...@@ -174,13 +174,14 @@ static inline bool btree_node_lock_type(struct btree_trans *trans, ...@@ -174,13 +174,14 @@ static inline bool btree_node_lock_type(struct btree_trans *trans,
trans->locking_level = level; trans->locking_level = level;
trans->locking_lock_type = type; trans->locking_lock_type = type;
trans->locking = b; trans->locking = b;
ret = six_lock_type(&b->c.lock, type, should_sleep_fn, p) == 0; ret = six_lock_type(&b->c.lock, type, should_sleep_fn, p);
trans->locking = NULL; trans->locking = NULL;
if (ret) if (ret)
bch2_time_stats_update(&c->times[lock_to_time_stat(type)], start_time); return ret;
return ret; bch2_time_stats_update(&c->times[lock_to_time_stat(type)], start_time);
return 0;
} }
/* /*
...@@ -203,33 +204,34 @@ static inline bool btree_node_lock_increment(struct btree_trans *trans, ...@@ -203,33 +204,34 @@ static inline bool btree_node_lock_increment(struct btree_trans *trans,
return false; return false;
} }
bool __bch2_btree_node_lock(struct btree_trans *, struct btree_path *, int __bch2_btree_node_lock(struct btree_trans *, struct btree_path *,
struct btree *, struct bpos, unsigned, struct btree *, struct bpos, unsigned,
enum six_lock_type, enum six_lock_type,
six_lock_should_sleep_fn, void *, six_lock_should_sleep_fn, void *,
unsigned long); unsigned long);
static inline bool btree_node_lock(struct btree_trans *trans, static inline int btree_node_lock(struct btree_trans *trans,
struct btree_path *path, struct btree_path *path,
struct btree *b, struct bpos pos, unsigned level, struct btree *b, struct bpos pos, unsigned level,
enum six_lock_type type, enum six_lock_type type,
six_lock_should_sleep_fn should_sleep_fn, void *p, six_lock_should_sleep_fn should_sleep_fn, void *p,
unsigned long ip) unsigned long ip)
{ {
int ret = 0;
EBUG_ON(level >= BTREE_MAX_DEPTH); EBUG_ON(level >= BTREE_MAX_DEPTH);
EBUG_ON(!(trans->paths_allocated & (1ULL << path->idx))); EBUG_ON(!(trans->paths_allocated & (1ULL << path->idx)));
if (likely(six_trylock_type(&b->c.lock, type)) || if (likely(six_trylock_type(&b->c.lock, type)) ||
btree_node_lock_increment(trans, b, level, type) || btree_node_lock_increment(trans, b, level, type) ||
__bch2_btree_node_lock(trans, path, b, pos, level, type, !(ret = __bch2_btree_node_lock(trans, path, b, pos, level, type,
should_sleep_fn, p, ip)) { should_sleep_fn, p, ip))) {
#ifdef CONFIG_BCACHEFS_LOCK_TIME_STATS #ifdef CONFIG_BCACHEFS_LOCK_TIME_STATS
path->l[b->c.level].lock_taken_time = ktime_get_ns(); path->l[b->c.level].lock_taken_time = ktime_get_ns();
#endif #endif
return true;
} else {
return false;
} }
return ret;
} }
bool __bch2_btree_node_relock(struct btree_trans *, struct btree_path *, unsigned); bool __bch2_btree_node_relock(struct btree_trans *, struct btree_path *, unsigned);
......
...@@ -405,11 +405,11 @@ struct btree_trans { ...@@ -405,11 +405,11 @@ struct btree_trans {
u8 nr_updates; u8 nr_updates;
bool used_mempool:1; bool used_mempool:1;
bool in_traverse_all:1; bool in_traverse_all:1;
bool restarted:1;
bool paths_sorted:1; bool paths_sorted:1;
bool memory_allocation_failure:1; bool memory_allocation_failure:1;
bool journal_transaction_names:1; bool journal_transaction_names:1;
bool journal_replay_not_finished:1; bool journal_replay_not_finished:1;
enum bch_errcode restarted:16;
u32 restart_count; u32 restart_count;
unsigned long last_restarted_ip; unsigned long last_restarted_ip;
......
...@@ -90,7 +90,6 @@ int bch2_trans_log_msg(struct btree_trans *, const char *); ...@@ -90,7 +90,6 @@ int bch2_trans_log_msg(struct btree_trans *, const char *);
* This is main entry point for btree updates. * This is main entry point for btree updates.
* *
* Return values: * Return values:
* -EINTR: locking changed, this function should be called again.
* -EROFS: filesystem read only * -EROFS: filesystem read only
* -EIO: journal or btree node IO error * -EIO: journal or btree node IO error
*/ */
......
...@@ -996,7 +996,7 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path, ...@@ -996,7 +996,7 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
if (!bch2_btree_path_upgrade(trans, path, U8_MAX)) { if (!bch2_btree_path_upgrade(trans, path, U8_MAX)) {
trace_trans_restart_iter_upgrade(trans->fn, _RET_IP_, trace_trans_restart_iter_upgrade(trans->fn, _RET_IP_,
path->btree_id, &path->pos); path->btree_id, &path->pos);
ret = btree_trans_restart(trans); ret = btree_trans_restart(trans, BCH_ERR_transaction_restart_upgrade);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
...@@ -1005,9 +1005,10 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path, ...@@ -1005,9 +1005,10 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
else if (!down_read_trylock(&c->gc_lock)) { else if (!down_read_trylock(&c->gc_lock)) {
bch2_trans_unlock(trans); bch2_trans_unlock(trans);
down_read(&c->gc_lock); down_read(&c->gc_lock);
if (!bch2_trans_relock(trans)) { ret = bch2_trans_relock(trans);
if (ret) {
up_read(&c->gc_lock); up_read(&c->gc_lock);
return ERR_PTR(-EINTR); return ERR_PTR(ret);
} }
} }
...@@ -1053,7 +1054,7 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path, ...@@ -1053,7 +1054,7 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
journal_flags); journal_flags);
if (ret) { if (ret) {
trace_trans_restart_journal_preres_get(trans->fn, _RET_IP_); trace_trans_restart_journal_preres_get(trans->fn, _RET_IP_);
btree_trans_restart(trans); ret = btree_trans_restart(trans, BCH_ERR_transaction_restart_journal_preres_get);
goto err; goto err;
} }
...@@ -1090,10 +1091,9 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path, ...@@ -1090,10 +1091,9 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
goto err; goto err;
} }
if (!bch2_trans_relock(trans)) { ret = bch2_trans_relock(trans);
ret = -EINTR; if (ret)
goto err; goto err;
}
return as; return as;
err: err:
...@@ -2030,10 +2030,8 @@ int bch2_btree_node_update_key(struct btree_trans *trans, struct btree_iter *ite ...@@ -2030,10 +2030,8 @@ int bch2_btree_node_update_key(struct btree_trans *trans, struct btree_iter *ite
int ret = 0; int ret = 0;
if (!btree_node_intent_locked(path, b->c.level) && if (!btree_node_intent_locked(path, b->c.level) &&
!bch2_btree_path_upgrade(trans, path, b->c.level + 1)) { !bch2_btree_path_upgrade(trans, path, b->c.level + 1))
btree_trans_restart(trans); return btree_trans_restart(trans, BCH_ERR_transaction_restart_upgrade);
return -EINTR;
}
closure_init_stack(&cl); closure_init_stack(&cl);
...@@ -2046,8 +2044,9 @@ int bch2_btree_node_update_key(struct btree_trans *trans, struct btree_iter *ite ...@@ -2046,8 +2044,9 @@ int bch2_btree_node_update_key(struct btree_trans *trans, struct btree_iter *ite
if (ret) { if (ret) {
bch2_trans_unlock(trans); bch2_trans_unlock(trans);
closure_sync(&cl); closure_sync(&cl);
if (!bch2_trans_relock(trans)) ret = bch2_trans_relock(trans);
return -EINTR; if (ret)
return ret;
} }
new_hash = bch2_btree_node_mem_alloc(c, false); new_hash = bch2_btree_node_mem_alloc(c, false);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "btree_locking.h" #include "btree_locking.h"
#include "buckets.h" #include "buckets.h"
#include "debug.h" #include "debug.h"
#include "errcode.h"
#include "error.h" #include "error.h"
#include "extent_update.h" #include "extent_update.h"
#include "journal.h" #include "journal.h"
...@@ -282,9 +283,10 @@ bch2_trans_journal_preres_get_cold(struct btree_trans *trans, unsigned u64s, ...@@ -282,9 +283,10 @@ bch2_trans_journal_preres_get_cold(struct btree_trans *trans, unsigned u64s,
if (ret) if (ret)
return ret; return ret;
if (!bch2_trans_relock(trans)) { ret = bch2_trans_relock(trans);
if (ret) {
trace_trans_restart_journal_preres_get(trans->fn, trace_ip); trace_trans_restart_journal_preres_get(trans->fn, trace_ip);
return -EINTR; return ret;
} }
return 0; return 0;
...@@ -376,12 +378,7 @@ btree_key_can_insert_cached(struct btree_trans *trans, ...@@ -376,12 +378,7 @@ btree_key_can_insert_cached(struct btree_trans *trans,
trace_trans_restart_key_cache_key_realloced(trans->fn, _RET_IP_, trace_trans_restart_key_cache_key_realloced(trans->fn, _RET_IP_,
path->btree_id, &path->pos, path->btree_id, &path->pos,
old_u64s, new_u64s); old_u64s, new_u64s);
/* return btree_trans_restart_nounlock(trans, BCH_ERR_transaction_restart_key_cache_realloced);
* Not using btree_trans_restart() because we can't unlock here, we have
* write locks held:
*/
trans->restarted = true;
return -EINTR;
} }
/* Triggers: */ /* Triggers: */
...@@ -573,8 +570,7 @@ bch2_trans_commit_write_locked(struct btree_trans *trans, ...@@ -573,8 +570,7 @@ bch2_trans_commit_write_locked(struct btree_trans *trans,
if (race_fault()) { if (race_fault()) {
trace_trans_restart_fault_inject(trans->fn, trace_ip); trace_trans_restart_fault_inject(trans->fn, trace_ip);
trans->restarted = true; return btree_trans_restart_nounlock(trans, BCH_ERR_transaction_restart_fault_inject);
return -EINTR;
} }
/* /*
...@@ -812,6 +808,7 @@ static inline bool have_conflicting_read_lock(struct btree_trans *trans, struct ...@@ -812,6 +808,7 @@ static inline bool have_conflicting_read_lock(struct btree_trans *trans, struct
static inline int trans_lock_write(struct btree_trans *trans) static inline int trans_lock_write(struct btree_trans *trans)
{ {
struct btree_insert_entry *i; struct btree_insert_entry *i;
int ret;
trans_for_each_update(trans, i) { trans_for_each_update(trans, i) {
if (same_leaf_as_prev(trans, i)) if (same_leaf_as_prev(trans, i))
...@@ -821,10 +818,11 @@ static inline int trans_lock_write(struct btree_trans *trans) ...@@ -821,10 +818,11 @@ static inline int trans_lock_write(struct btree_trans *trans)
if (have_conflicting_read_lock(trans, i->path)) if (have_conflicting_read_lock(trans, i->path))
goto fail; goto fail;
btree_node_lock_type(trans, i->path, ret = btree_node_lock_type(trans, i->path,
insert_l(i)->b, insert_l(i)->b,
i->path->pos, i->level, i->path->pos, i->level,
SIX_LOCK_write, NULL, NULL); SIX_LOCK_write, NULL, NULL);
BUG_ON(ret);
} }
bch2_btree_node_prep_for_write(trans, i->path, insert_l(i)->b); bch2_btree_node_prep_for_write(trans, i->path, insert_l(i)->b);
...@@ -840,7 +838,7 @@ static inline int trans_lock_write(struct btree_trans *trans) ...@@ -840,7 +838,7 @@ static inline int trans_lock_write(struct btree_trans *trans)
} }
trace_trans_restart_would_deadlock_write(trans->fn); trace_trans_restart_would_deadlock_write(trans->fn);
return btree_trans_restart(trans); return btree_trans_restart(trans, BCH_ERR_transaction_restart_would_deadlock_write);
} }
static noinline void bch2_drop_overwrites_from_journal(struct btree_trans *trans) static noinline void bch2_drop_overwrites_from_journal(struct btree_trans *trans)
...@@ -971,10 +969,7 @@ int bch2_trans_commit_error(struct btree_trans *trans, ...@@ -971,10 +969,7 @@ int bch2_trans_commit_error(struct btree_trans *trans,
switch (ret) { switch (ret) {
case BTREE_INSERT_BTREE_NODE_FULL: case BTREE_INSERT_BTREE_NODE_FULL:
ret = bch2_btree_split_leaf(trans, i->path, trans->flags); ret = bch2_btree_split_leaf(trans, i->path, trans->flags);
if (!ret) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
return 0;
if (ret == -EINTR)
trace_trans_restart_btree_node_split(trans->fn, trace_ip, trace_trans_restart_btree_node_split(trans->fn, trace_ip,
i->btree_id, &i->path->pos); i->btree_id, &i->path->pos);
break; break;
...@@ -985,19 +980,16 @@ int bch2_trans_commit_error(struct btree_trans *trans, ...@@ -985,19 +980,16 @@ int bch2_trans_commit_error(struct btree_trans *trans,
if (ret) if (ret)
break; break;
if (bch2_trans_relock(trans)) ret = bch2_trans_relock(trans);
return 0; if (ret)
trace_trans_restart_mark_replicas(trans->fn, trace_ip);
trace_trans_restart_mark_replicas(trans->fn, trace_ip);
ret = -EINTR;
break; break;
case BTREE_INSERT_NEED_JOURNAL_RES: case BTREE_INSERT_NEED_JOURNAL_RES:
bch2_trans_unlock(trans); bch2_trans_unlock(trans);
if ((trans->flags & BTREE_INSERT_JOURNAL_RECLAIM) && if ((trans->flags & BTREE_INSERT_JOURNAL_RECLAIM) &&
!(trans->flags & JOURNAL_WATERMARK_reserved)) { !(trans->flags & JOURNAL_WATERMARK_reserved)) {
trans->restarted = true; ret = -BCH_ERR_journal_reclaim_would_deadlock;
ret = -EAGAIN;
break; break;
} }
...@@ -1005,11 +997,9 @@ int bch2_trans_commit_error(struct btree_trans *trans, ...@@ -1005,11 +997,9 @@ int bch2_trans_commit_error(struct btree_trans *trans,
if (ret) if (ret)
break; break;
if (bch2_trans_relock(trans)) ret = bch2_trans_relock(trans);
return 0; if (ret)
trace_trans_restart_journal_res_get(trans->fn, trace_ip);
trace_trans_restart_journal_res_get(trans->fn, trace_ip);
ret = -EINTR;
break; break;
case BTREE_INSERT_NEED_JOURNAL_RECLAIM: case BTREE_INSERT_NEED_JOURNAL_RECLAIM:
bch2_trans_unlock(trans); bch2_trans_unlock(trans);
...@@ -1021,18 +1011,16 @@ int bch2_trans_commit_error(struct btree_trans *trans, ...@@ -1021,18 +1011,16 @@ int bch2_trans_commit_error(struct btree_trans *trans,
if (ret < 0) if (ret < 0)
break; break;
if (bch2_trans_relock(trans)) ret = bch2_trans_relock(trans);
return 0; if (ret)
trace_trans_restart_journal_reclaim(trans->fn, trace_ip);
trace_trans_restart_journal_reclaim(trans->fn, trace_ip);
ret = -EINTR;
break; break;
default: default:
BUG_ON(ret >= 0); BUG_ON(ret >= 0);
break; break;
} }
BUG_ON((ret == EINTR || ret == -EAGAIN) && !trans->restarted); BUG_ON(bch2_err_matches(ret, BCH_ERR_transaction_restart) != !!trans->restarted);
BUG_ON(ret == -ENOSPC && BUG_ON(ret == -ENOSPC &&
!(trans->flags & BTREE_INSERT_NOWAIT) && !(trans->flags & BTREE_INSERT_NOWAIT) &&
(trans->flags & BTREE_INSERT_NOFAIL)); (trans->flags & BTREE_INSERT_NOFAIL));
...@@ -1052,13 +1040,11 @@ bch2_trans_commit_get_rw_cold(struct btree_trans *trans) ...@@ -1052,13 +1040,11 @@ bch2_trans_commit_get_rw_cold(struct btree_trans *trans)
bch2_trans_unlock(trans); bch2_trans_unlock(trans);
ret = bch2_fs_read_write_early(c); ret = bch2_fs_read_write_early(c) ?:
bch2_trans_relock(trans);
if (ret) if (ret)
return ret; return ret;
if (!bch2_trans_relock(trans))
return -EINTR;
percpu_ref_get(&c->writes); percpu_ref_get(&c->writes);
return 0; return 0;
} }
...@@ -1132,7 +1118,7 @@ int __bch2_trans_commit(struct btree_trans *trans) ...@@ -1132,7 +1118,7 @@ int __bch2_trans_commit(struct btree_trans *trans)
if (unlikely(!bch2_btree_path_upgrade(trans, i->path, i->level + 1))) { if (unlikely(!bch2_btree_path_upgrade(trans, i->path, i->level + 1))) {
trace_trans_restart_upgrade(trans->fn, _RET_IP_, trace_trans_restart_upgrade(trans->fn, _RET_IP_,
i->btree_id, &i->path->pos); i->btree_id, &i->path->pos);
ret = btree_trans_restart(trans); ret = btree_trans_restart(trans, BCH_ERR_transaction_restart_upgrade);
goto out; goto out;
} }
...@@ -1654,8 +1640,7 @@ int __must_check bch2_trans_update(struct btree_trans *trans, struct btree_iter ...@@ -1654,8 +1640,7 @@ int __must_check bch2_trans_update(struct btree_trans *trans, struct btree_iter
if (test_bit(BKEY_CACHED_DIRTY, &ck->flags)) { if (test_bit(BKEY_CACHED_DIRTY, &ck->flags)) {
trace_trans_restart_key_cache_raced(trans->fn, _RET_IP_); trace_trans_restart_key_cache_raced(trans->fn, _RET_IP_);
btree_trans_restart(trans); return btree_trans_restart(trans, BCH_ERR_transaction_restart_key_cache_raced);
return -EINTR;
} }
iter->key_cache_path->should_be_locked = true; iter->key_cache_path->should_be_locked = true;
...@@ -1783,7 +1768,7 @@ int bch2_btree_delete_range_trans(struct btree_trans *trans, enum btree_id id, ...@@ -1783,7 +1768,7 @@ int bch2_btree_delete_range_trans(struct btree_trans *trans, enum btree_id id,
break; break;
} }
if (ret == -EINTR) { if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) {
ret = 0; ret = 0;
goto retry; goto retry;
} }
......
...@@ -236,7 +236,7 @@ int bch2_data_update_index_update(struct bch_write_op *op) ...@@ -236,7 +236,7 @@ int bch2_data_update_index_update(struct bch_write_op *op)
bch2_ob_add_backpointer(c, ec_ob, &insert->k); bch2_ob_add_backpointer(c, ec_ob, &insert->k);
} }
err: err:
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
ret = 0; ret = 0;
if (ret) if (ret)
break; break;
...@@ -264,7 +264,7 @@ int bch2_data_update_index_update(struct bch_write_op *op) ...@@ -264,7 +264,7 @@ int bch2_data_update_index_update(struct bch_write_op *op)
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&_insert, c); bch2_bkey_buf_exit(&_insert, c);
bch2_bkey_buf_exit(&_new, c); bch2_bkey_buf_exit(&_new, c);
BUG_ON(ret == -EINTR); BUG_ON(bch2_err_matches(ret, BCH_ERR_transaction_restart));
return ret; return ret;
} }
......
...@@ -471,7 +471,7 @@ u64 bch2_dirent_lookup(struct bch_fs *c, subvol_inum dir, ...@@ -471,7 +471,7 @@ u64 bch2_dirent_lookup(struct bch_fs *c, subvol_inum dir,
ret = __bch2_dirent_lookup_trans(&trans, &iter, dir, hash_info, ret = __bch2_dirent_lookup_trans(&trans, &iter, dir, hash_info,
name, inum, 0); name, inum, 0);
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
if (!ret) if (!ret)
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
...@@ -556,7 +556,7 @@ int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx) ...@@ -556,7 +556,7 @@ int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx)
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
err: err:
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
......
...@@ -572,18 +572,14 @@ static int ec_stripe_mem_alloc(struct btree_trans *trans, ...@@ -572,18 +572,14 @@ static int ec_stripe_mem_alloc(struct btree_trans *trans,
struct btree_iter *iter) struct btree_iter *iter)
{ {
size_t idx = iter->pos.offset; size_t idx = iter->pos.offset;
int ret = 0;
if (!__ec_stripe_mem_alloc(trans->c, idx, GFP_NOWAIT|__GFP_NOWARN)) if (!__ec_stripe_mem_alloc(trans->c, idx, GFP_NOWAIT|__GFP_NOWARN))
return ret; return 0;
bch2_trans_unlock(trans); bch2_trans_unlock(trans);
ret = -EINTR;
if (!__ec_stripe_mem_alloc(trans->c, idx, GFP_KERNEL)) return __ec_stripe_mem_alloc(trans->c, idx, GFP_KERNEL) ?:
return ret; bch2_trans_relock(trans);
return -ENOMEM;
} }
static ssize_t stripe_idx_to_delete(struct bch_fs *c) static ssize_t stripe_idx_to_delete(struct bch_fs *c)
......
...@@ -7,7 +7,30 @@ ...@@ -7,7 +7,30 @@
x(0, freelist_empty) \ x(0, freelist_empty) \
x(freelist_empty, no_buckets_found) \ x(freelist_empty, no_buckets_found) \
x(0, insufficient_devices) \ x(0, insufficient_devices) \
x(0, need_snapshot_cleanup) x(0, need_snapshot_cleanup) \
x(0, transaction_restart) \
x(transaction_restart, transaction_restart_fault_inject) \
x(transaction_restart, transaction_restart_relock) \
x(transaction_restart, transaction_restart_relock_path) \
x(transaction_restart, transaction_restart_relock_path_intent) \
x(transaction_restart, transaction_restart_relock_after_fill) \
x(transaction_restart, transaction_restart_too_many_iters) \
x(transaction_restart, transaction_restart_lock_node_reused) \
x(transaction_restart, transaction_restart_fill_relock) \
x(transaction_restart, transaction_restart_fill_mem_alloc_fail)\
x(transaction_restart, transaction_restart_mem_realloced) \
x(transaction_restart, transaction_restart_in_traverse_all) \
x(transaction_restart, transaction_restart_would_deadlock) \
x(transaction_restart, transaction_restart_would_deadlock_write)\
x(transaction_restart, transaction_restart_upgrade) \
x(transaction_restart, transaction_restart_key_cache_fill) \
x(transaction_restart, transaction_restart_key_cache_raced) \
x(transaction_restart, transaction_restart_key_cache_realloced)\
x(transaction_restart, transaction_restart_journal_preres_get) \
x(transaction_restart, transaction_restart_nested) \
x(0, lock_fail_node_reused) \
x(0, lock_fail_root_changed) \
x(0, journal_reclaim_would_deadlock)
enum bch_errcode { enum bch_errcode {
BCH_ERR_START = 2048, BCH_ERR_START = 2048,
......
...@@ -408,7 +408,7 @@ static int bch2_page_state_set(struct bch_fs *c, subvol_inum inum, ...@@ -408,7 +408,7 @@ static int bch2_page_state_set(struct bch_fs *c, subvol_inum inum,
offset = iter.pos.offset; offset = iter.pos.offset;
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
err: err:
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
...@@ -1018,10 +1018,9 @@ static void bchfs_read(struct btree_trans *trans, ...@@ -1018,10 +1018,9 @@ static void bchfs_read(struct btree_trans *trans,
* read_extent -> io_time_reset may cause a transaction restart * read_extent -> io_time_reset may cause a transaction restart
* without returning an error, we need to check for that here: * without returning an error, we need to check for that here:
*/ */
if (!bch2_trans_relock(trans)) { ret = bch2_trans_relock(trans);
ret = -EINTR; if (ret)
break; break;
}
bch2_btree_iter_set_pos(&iter, bch2_btree_iter_set_pos(&iter,
POS(inum.inum, rbio->bio.bi_iter.bi_sector)); POS(inum.inum, rbio->bio.bi_iter.bi_sector));
...@@ -1074,7 +1073,7 @@ static void bchfs_read(struct btree_trans *trans, ...@@ -1074,7 +1073,7 @@ static void bchfs_read(struct btree_trans *trans,
err: err:
bch2_trans_iter_exit(trans, &iter); bch2_trans_iter_exit(trans, &iter);
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
if (ret) { if (ret) {
...@@ -2035,7 +2034,7 @@ static bool bch2_check_range_allocated(struct bch_fs *c, subvol_inum inum, ...@@ -2035,7 +2034,7 @@ static bool bch2_check_range_allocated(struct bch_fs *c, subvol_inum inum,
offset = iter.pos.offset; offset = iter.pos.offset;
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
err: err:
if (err == -EINTR) if (bch2_err_matches(err, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
...@@ -2427,7 +2426,7 @@ static inline int range_has_data(struct bch_fs *c, u32 subvol, ...@@ -2427,7 +2426,7 @@ static inline int range_has_data(struct bch_fs *c, u32 subvol,
start = iter.pos; start = iter.pos;
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
err: err:
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
...@@ -2817,7 +2816,8 @@ static long bchfs_fcollapse_finsert(struct bch_inode_info *inode, ...@@ -2817,7 +2816,8 @@ static long bchfs_fcollapse_finsert(struct bch_inode_info *inode,
bch2_trans_copy_iter(&dst, &src); bch2_trans_copy_iter(&dst, &src);
bch2_trans_copy_iter(&del, &src); bch2_trans_copy_iter(&del, &src);
while (ret == 0 || ret == -EINTR) { while (ret == 0 ||
bch2_err_matches(ret, BCH_ERR_transaction_restart)) {
struct disk_reservation disk_res = struct disk_reservation disk_res =
bch2_disk_reservation_init(c, 0); bch2_disk_reservation_init(c, 0);
struct bkey_i delete; struct bkey_i delete;
...@@ -3019,7 +3019,7 @@ static int __bchfs_fallocate(struct bch_inode_info *inode, int mode, ...@@ -3019,7 +3019,7 @@ static int __bchfs_fallocate(struct bch_inode_info *inode, int mode,
bkey_err: bkey_err:
bch2_quota_reservation_put(c, inode, &quota_res); bch2_quota_reservation_put(c, inode, &quota_res);
bch2_disk_reservation_put(c, &disk_res); bch2_disk_reservation_put(c, &disk_res);
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
ret = 0; ret = 0;
} }
...@@ -3301,7 +3301,7 @@ static loff_t bch2_seek_data(struct file *file, u64 offset) ...@@ -3301,7 +3301,7 @@ static loff_t bch2_seek_data(struct file *file, u64 offset)
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
err: err:
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
...@@ -3416,7 +3416,7 @@ static loff_t bch2_seek_hole(struct file *file, u64 offset) ...@@ -3416,7 +3416,7 @@ static loff_t bch2_seek_hole(struct file *file, u64 offset)
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
err: err:
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
......
...@@ -154,7 +154,7 @@ int __must_check bch2_write_inode(struct bch_fs *c, ...@@ -154,7 +154,7 @@ int __must_check bch2_write_inode(struct bch_fs *c,
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
...@@ -324,7 +324,7 @@ __bch2_create(struct mnt_idmap *idmap, ...@@ -324,7 +324,7 @@ __bch2_create(struct mnt_idmap *idmap,
bch2_quota_acct(c, bch_qid(&inode_u), Q_INO, -1, bch2_quota_acct(c, bch_qid(&inode_u), Q_INO, -1,
KEY_TYPE_QUOTA_WARN); KEY_TYPE_QUOTA_WARN);
err_before_quota: err_before_quota:
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
goto err_trans; goto err_trans;
} }
...@@ -755,7 +755,7 @@ int bch2_setattr_nonsize(struct mnt_idmap *idmap, ...@@ -755,7 +755,7 @@ int bch2_setattr_nonsize(struct mnt_idmap *idmap,
btree_err: btree_err:
bch2_trans_iter_exit(&trans, &inode_iter); bch2_trans_iter_exit(&trans, &inode_iter);
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
if (unlikely(ret)) if (unlikely(ret))
goto err_trans; goto err_trans;
...@@ -987,7 +987,7 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info, ...@@ -987,7 +987,7 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
start = iter.pos.offset; start = iter.pos.offset;
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
err: err:
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
if (!ret && have_extent) if (!ret && have_extent)
...@@ -1337,7 +1337,7 @@ static int bch2_get_name(struct dentry *parent, char *name, struct dentry *child ...@@ -1337,7 +1337,7 @@ static int bch2_get_name(struct dentry *parent, char *name, struct dentry *child
memcpy(name, d.v->d_name, name_len); memcpy(name, d.v->d_name, name_len);
name[name_len] = '\0'; name[name_len] = '\0';
err: err:
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_iter_exit(&trans, &iter1); bch2_trans_iter_exit(&trans, &iter1);
......
...@@ -136,7 +136,7 @@ static int lookup_first_inode(struct btree_trans *trans, u64 inode_nr, ...@@ -136,7 +136,7 @@ static int lookup_first_inode(struct btree_trans *trans, u64 inode_nr,
ret = bch2_inode_unpack(k, inode); ret = bch2_inode_unpack(k, inode);
err: err:
if (ret && ret != -EINTR) if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart))
bch_err(trans->c, "error fetching inode %llu: %s", bch_err(trans->c, "error fetching inode %llu: %s",
inode_nr, bch2_err_str(ret)); inode_nr, bch2_err_str(ret));
bch2_trans_iter_exit(trans, &iter); bch2_trans_iter_exit(trans, &iter);
...@@ -164,7 +164,7 @@ static int __lookup_inode(struct btree_trans *trans, u64 inode_nr, ...@@ -164,7 +164,7 @@ static int __lookup_inode(struct btree_trans *trans, u64 inode_nr,
if (!ret) if (!ret)
*snapshot = iter.pos.snapshot; *snapshot = iter.pos.snapshot;
err: err:
if (ret && ret != -EINTR) if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart))
bch_err(trans->c, "error fetching inode %llu:%u: %s", bch_err(trans->c, "error fetching inode %llu:%u: %s",
inode_nr, *snapshot, bch2_err_str(ret)); inode_nr, *snapshot, bch2_err_str(ret));
bch2_trans_iter_exit(trans, &iter); bch2_trans_iter_exit(trans, &iter);
...@@ -287,7 +287,7 @@ static int fsck_inode_rm(struct btree_trans *trans, u64 inum, u32 snapshot) ...@@ -287,7 +287,7 @@ static int fsck_inode_rm(struct btree_trans *trans, u64 inum, u32 snapshot)
BTREE_INSERT_NOFAIL); BTREE_INSERT_NOFAIL);
err: err:
bch2_trans_iter_exit(trans, &iter); bch2_trans_iter_exit(trans, &iter);
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
return ret; return ret;
...@@ -314,7 +314,7 @@ static int __remove_dirent(struct btree_trans *trans, struct bpos pos) ...@@ -314,7 +314,7 @@ static int __remove_dirent(struct btree_trans *trans, struct bpos pos)
BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE); BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE);
bch2_trans_iter_exit(trans, &iter); bch2_trans_iter_exit(trans, &iter);
err: err:
if (ret && ret != -EINTR) if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart))
bch_err(c, "error from __remove_dirent(): %s", bch2_err_str(ret)); bch_err(c, "error from __remove_dirent(): %s", bch2_err_str(ret));
return ret; return ret;
} }
...@@ -350,7 +350,7 @@ static int lookup_lostfound(struct btree_trans *trans, u32 subvol, ...@@ -350,7 +350,7 @@ static int lookup_lostfound(struct btree_trans *trans, u32 subvol,
goto create_lostfound; goto create_lostfound;
} }
if (ret && ret != -EINTR) if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart))
bch_err(c, "error looking up lost+found: %s", bch2_err_str(ret)); bch_err(c, "error looking up lost+found: %s", bch2_err_str(ret));
if (ret) if (ret)
return ret; return ret;
...@@ -373,7 +373,7 @@ static int lookup_lostfound(struct btree_trans *trans, u32 subvol, ...@@ -373,7 +373,7 @@ static int lookup_lostfound(struct btree_trans *trans, u32 subvol,
lostfound, &lostfound_str, lostfound, &lostfound_str,
0, 0, S_IFDIR|0700, 0, NULL, NULL, 0, 0, S_IFDIR|0700, 0, NULL, NULL,
(subvol_inum) { }, 0); (subvol_inum) { }, 0);
if (ret && ret != -EINTR) if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart))
bch_err(c, "error creating lost+found: %s", bch2_err_str(ret)); bch_err(c, "error creating lost+found: %s", bch2_err_str(ret));
return ret; return ret;
} }
...@@ -843,10 +843,10 @@ static int hash_check_key(struct btree_trans *trans, ...@@ -843,10 +843,10 @@ static int hash_check_key(struct btree_trans *trans,
ret = hash_redo_key(trans, desc, hash_info, k_iter, hash_k); ret = hash_redo_key(trans, desc, hash_info, k_iter, hash_k);
if (ret) { if (ret) {
bch_err(c, "hash_redo_key err %i", ret); bch_err(c, "hash_redo_key err %s", bch2_err_str(ret));
return ret; return ret;
} }
ret = -EINTR; ret = -BCH_ERR_transaction_restart_nested;
fsck_err: fsck_err:
goto out; goto out;
} }
...@@ -1144,7 +1144,7 @@ static int check_i_sectors(struct btree_trans *trans, struct inode_walker *w) ...@@ -1144,7 +1144,7 @@ static int check_i_sectors(struct btree_trans *trans, struct inode_walker *w)
ret = write_inode(trans, &i->inode, i->snapshot); ret = write_inode(trans, &i->inode, i->snapshot);
if (ret) if (ret)
break; break;
ret2 = -EINTR; ret2 = -BCH_ERR_transaction_restart_nested;
} }
fsck_err: fsck_err:
if (ret) if (ret)
...@@ -1191,7 +1191,7 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter, ...@@ -1191,7 +1191,7 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
* it shouldn't be but we need to fix the new i_sectors check * it shouldn't be but we need to fix the new i_sectors check
* code and delete the old bch2_count_inode_sectors() first * code and delete the old bch2_count_inode_sectors() first
*/ */
return -EINTR; return -BCH_ERR_transaction_restart_nested;
} }
#if 0 #if 0
if (bkey_cmp(prev.k->k.p, bkey_start_pos(k.k)) > 0) { if (bkey_cmp(prev.k->k.p, bkey_start_pos(k.k)) > 0) {
...@@ -1202,7 +1202,8 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter, ...@@ -1202,7 +1202,8 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
bch2_bkey_val_to_text(&PBUF(buf2), c, k); bch2_bkey_val_to_text(&PBUF(buf2), c, k);
if (fsck_err(c, "overlapping extents:\n%s\n%s", buf1, buf2)) { if (fsck_err(c, "overlapping extents:\n%s\n%s", buf1, buf2)) {
ret = fix_overlapping_extent(trans, k, prev.k->k.p) ?: -EINTR; ret = fix_overlapping_extent(trans, k, prev.k->k.p)
?: -BCH_ERR_transaction_restart_nested;
goto out; goto out;
} }
} }
...@@ -1287,8 +1288,8 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter, ...@@ -1287,8 +1288,8 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
fsck_err: fsck_err:
printbuf_exit(&buf); printbuf_exit(&buf);
if (ret && ret != -EINTR) if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart))
bch_err(c, "error %i from check_extent()", ret); bch_err(c, "error from check_extent(): %s", bch2_err_str(ret));
return ret; return ret;
} }
...@@ -1364,7 +1365,7 @@ static int check_subdir_count(struct btree_trans *trans, struct inode_walker *w) ...@@ -1364,7 +1365,7 @@ static int check_subdir_count(struct btree_trans *trans, struct inode_walker *w)
ret = write_inode(trans, &i->inode, i->snapshot); ret = write_inode(trans, &i->inode, i->snapshot);
if (ret) if (ret)
break; break;
ret2 = -EINTR; ret2 = -BCH_ERR_transaction_restart_nested;
} }
} }
fsck_err: fsck_err:
...@@ -1487,7 +1488,7 @@ static int check_dirent_target(struct btree_trans *trans, ...@@ -1487,7 +1488,7 @@ static int check_dirent_target(struct btree_trans *trans,
fsck_err: fsck_err:
printbuf_exit(&buf); printbuf_exit(&buf);
if (ret && ret != -EINTR) if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart))
bch_err(c, "error from check_target(): %s", bch2_err_str(ret)); bch_err(c, "error from check_target(): %s", bch2_err_str(ret));
return ret; return ret;
} }
...@@ -1530,7 +1531,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter, ...@@ -1530,7 +1531,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
if (!iter->path->should_be_locked) { if (!iter->path->should_be_locked) {
/* hack: see check_extent() */ /* hack: see check_extent() */
return -EINTR; return -BCH_ERR_transaction_restart_nested;
} }
ret = __walk_inode(trans, dir, equiv); ret = __walk_inode(trans, dir, equiv);
...@@ -1660,7 +1661,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter, ...@@ -1660,7 +1661,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
fsck_err: fsck_err:
printbuf_exit(&buf); printbuf_exit(&buf);
if (ret && ret != -EINTR) if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart))
bch_err(c, "error from check_dirent(): %s", bch2_err_str(ret)); bch_err(c, "error from check_dirent(): %s", bch2_err_str(ret));
return ret; return ret;
} }
...@@ -1735,7 +1736,7 @@ static int check_xattr(struct btree_trans *trans, struct btree_iter *iter, ...@@ -1735,7 +1736,7 @@ static int check_xattr(struct btree_trans *trans, struct btree_iter *iter,
ret = hash_check_key(trans, bch2_xattr_hash_desc, hash_info, iter, k); ret = hash_check_key(trans, bch2_xattr_hash_desc, hash_info, iter, k);
fsck_err: fsck_err:
if (ret && ret != -EINTR) if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart))
bch_err(c, "error from check_xattr(): %s", bch2_err_str(ret)); bch_err(c, "error from check_xattr(): %s", bch2_err_str(ret));
return ret; return ret;
} }
...@@ -2016,8 +2017,6 @@ static int check_directory_structure(struct bch_fs *c) ...@@ -2016,8 +2017,6 @@ static int check_directory_structure(struct bch_fs *c)
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
BUG_ON(ret == -EINTR);
darray_exit(&path); darray_exit(&path);
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
......
...@@ -619,7 +619,7 @@ static int bch2_inode_delete_keys(struct btree_trans *trans, ...@@ -619,7 +619,7 @@ static int bch2_inode_delete_keys(struct btree_trans *trans,
bch2_trans_commit(trans, NULL, NULL, bch2_trans_commit(trans, NULL, NULL,
BTREE_INSERT_NOFAIL); BTREE_INSERT_NOFAIL);
err: err:
if (ret && ret != -EINTR) if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart))
break; break;
} }
...@@ -690,7 +690,7 @@ int bch2_inode_rm(struct bch_fs *c, subvol_inum inum) ...@@ -690,7 +690,7 @@ int bch2_inode_rm(struct bch_fs *c, subvol_inum inum)
BTREE_INSERT_NOFAIL); BTREE_INSERT_NOFAIL);
err: err:
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
......
...@@ -390,7 +390,7 @@ int bch2_extent_update(struct btree_trans *trans, ...@@ -390,7 +390,7 @@ int bch2_extent_update(struct btree_trans *trans,
} }
/* /*
* Returns -EINTR if we had to drop locks: * Returns -BCH_ERR_transacton_restart if we had to drop locks:
*/ */
int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter, int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter,
subvol_inum inum, u64 end, subvol_inum inum, u64 end,
...@@ -403,7 +403,8 @@ int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter, ...@@ -403,7 +403,8 @@ int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter,
int ret = 0, ret2 = 0; int ret = 0, ret2 = 0;
u32 snapshot; u32 snapshot;
while (!ret || ret == -EINTR) { while (!ret ||
bch2_err_matches(ret, BCH_ERR_transaction_restart)) {
struct disk_reservation disk_res = struct disk_reservation disk_res =
bch2_disk_reservation_init(c, 0); bch2_disk_reservation_init(c, 0);
struct bkey_i delete; struct bkey_i delete;
...@@ -462,7 +463,10 @@ int bch2_fpunch(struct bch_fs *c, subvol_inum inum, u64 start, u64 end, ...@@ -462,7 +463,10 @@ int bch2_fpunch(struct bch_fs *c, subvol_inum inum, u64 start, u64 end,
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
return ret == -EINTR ? 0 : ret; if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
ret = 0;
return ret;
} }
static int bch2_write_index_default(struct bch_write_op *op) static int bch2_write_index_default(struct bch_write_op *op)
...@@ -493,7 +497,7 @@ static int bch2_write_index_default(struct bch_write_op *op) ...@@ -493,7 +497,7 @@ static int bch2_write_index_default(struct bch_write_op *op)
ret = bch2_subvolume_get_snapshot(&trans, inum.subvol, ret = bch2_subvolume_get_snapshot(&trans, inum.subvol,
&sk.k->k.p.snapshot); &sk.k->k.p.snapshot);
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
continue; continue;
if (ret) if (ret)
break; break;
...@@ -508,7 +512,7 @@ static int bch2_write_index_default(struct bch_write_op *op) ...@@ -508,7 +512,7 @@ static int bch2_write_index_default(struct bch_write_op *op)
op->flags & BCH_WRITE_CHECK_ENOSPC); op->flags & BCH_WRITE_CHECK_ENOSPC);
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
continue; continue;
if (ret) if (ret)
break; break;
...@@ -663,7 +667,7 @@ static void __bch2_write_index(struct bch_write_op *op) ...@@ -663,7 +667,7 @@ static void __bch2_write_index(struct bch_write_op *op)
? bch2_write_index_default(op) ? bch2_write_index_default(op)
: bch2_data_update_index_update(op); : bch2_data_update_index_update(op);
BUG_ON(ret == -EINTR); BUG_ON(bch2_err_matches(ret, BCH_ERR_transaction_restart));
BUG_ON(keylist_sectors(keys) && !ret); BUG_ON(keylist_sectors(keys) && !ret);
op->written += sectors_start - keylist_sectors(keys); op->written += sectors_start - keylist_sectors(keys);
...@@ -2429,10 +2433,9 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, ...@@ -2429,10 +2433,9 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio,
* read_extent -> io_time_reset may cause a transaction restart * read_extent -> io_time_reset may cause a transaction restart
* without returning an error, we need to check for that here: * without returning an error, we need to check for that here:
*/ */
if (!bch2_trans_relock(&trans)) { ret = bch2_trans_relock(&trans);
ret = -EINTR; if (ret)
break; break;
}
bch2_btree_iter_set_pos(&iter, bch2_btree_iter_set_pos(&iter,
POS(inum.inum, bvec_iter.bi_sector)); POS(inum.inum, bvec_iter.bi_sector));
...@@ -2486,7 +2489,9 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio, ...@@ -2486,7 +2489,9 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio,
err: err:
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
if (ret == -EINTR || ret == READ_RETRY || ret == READ_RETRY_AVOID) if (bch2_err_matches(ret, BCH_ERR_transaction_restart) ||
ret == READ_RETRY ||
ret == READ_RETRY_AVOID)
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
......
...@@ -272,7 +272,7 @@ void bch2_blacklist_entries_gc(struct work_struct *work) ...@@ -272,7 +272,7 @@ void bch2_blacklist_entries_gc(struct work_struct *work)
!test_bit(BCH_FS_STOPPING, &c->flags)) !test_bit(BCH_FS_STOPPING, &c->flags))
b = bch2_btree_iter_next_node(&iter); b = bch2_btree_iter_next_node(&iter);
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
......
...@@ -146,7 +146,7 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags) ...@@ -146,7 +146,7 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags)
} }
ret = bch2_btree_node_update_key(&trans, &iter, b, k.k, false); ret = bch2_btree_node_update_key(&trans, &iter, b, k.k, false);
if (ret == -EINTR) { if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) {
ret = 0; ret = 0;
continue; continue;
} }
...@@ -159,7 +159,7 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags) ...@@ -159,7 +159,7 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags)
next: next:
bch2_btree_iter_next_node(&iter); bch2_btree_iter_next_node(&iter);
} }
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
...@@ -174,7 +174,7 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags) ...@@ -174,7 +174,7 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags)
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&k, c); bch2_bkey_buf_exit(&k, c);
BUG_ON(ret == -EINTR); BUG_ON(bch2_err_matches(ret, BCH_ERR_transaction_restart));
return ret; return ret;
} }
......
...@@ -387,7 +387,7 @@ static int __bch2_move_data(struct moving_context *ctxt, ...@@ -387,7 +387,7 @@ static int __bch2_move_data(struct moving_context *ctxt,
break; break;
ret = bkey_err(k); ret = bkey_err(k);
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
continue; continue;
if (ret) if (ret)
break; break;
...@@ -409,7 +409,7 @@ static int __bch2_move_data(struct moving_context *ctxt, ...@@ -409,7 +409,7 @@ static int __bch2_move_data(struct moving_context *ctxt,
ret = lookup_inode(&trans, ret = lookup_inode(&trans,
SPOS(0, k.k->p.inode, k.k->p.snapshot), SPOS(0, k.k->p.inode, k.k->p.snapshot),
&inode); &inode);
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
continue; continue;
if (!ret) if (!ret)
...@@ -432,7 +432,7 @@ static int __bch2_move_data(struct moving_context *ctxt, ...@@ -432,7 +432,7 @@ static int __bch2_move_data(struct moving_context *ctxt,
ret2 = bch2_move_extent(&trans, ctxt, io_opts, ret2 = bch2_move_extent(&trans, ctxt, io_opts,
btree_id, k, data_opts); btree_id, k, data_opts);
if (ret2) { if (ret2) {
if (ret2 == -EINTR) if (bch2_err_matches(ret2, BCH_ERR_transaction_restart))
continue; continue;
if (ret2 == -ENOMEM) { if (ret2 == -ENOMEM) {
...@@ -546,14 +546,14 @@ static int bch2_move_btree(struct bch_fs *c, ...@@ -546,14 +546,14 @@ static int bch2_move_btree(struct bch_fs *c,
goto next; goto next;
ret = bch2_btree_node_rewrite(&trans, &iter, b, 0) ?: ret; ret = bch2_btree_node_rewrite(&trans, &iter, b, 0) ?: ret;
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
continue; continue;
if (ret) if (ret)
break; break;
next: next:
bch2_btree_iter_next_node(&iter); bch2_btree_iter_next_node(&iter);
} }
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
......
...@@ -299,7 +299,8 @@ s64 bch2_remap_range(struct bch_fs *c, ...@@ -299,7 +299,8 @@ s64 bch2_remap_range(struct bch_fs *c,
bch2_trans_iter_init(&trans, &dst_iter, BTREE_ID_extents, dst_start, bch2_trans_iter_init(&trans, &dst_iter, BTREE_ID_extents, dst_start,
BTREE_ITER_INTENT); BTREE_ITER_INTENT);
while ((ret == 0 || ret == -EINTR) && while ((ret == 0 ||
bch2_err_matches(ret, BCH_ERR_transaction_restart)) &&
bkey_cmp(dst_iter.pos, dst_end) < 0) { bkey_cmp(dst_iter.pos, dst_end) < 0) {
struct disk_reservation disk_res = { 0 }; struct disk_reservation disk_res = { 0 };
...@@ -409,7 +410,7 @@ s64 bch2_remap_range(struct bch_fs *c, ...@@ -409,7 +410,7 @@ s64 bch2_remap_range(struct bch_fs *c,
} }
bch2_trans_iter_exit(&trans, &inode_iter); bch2_trans_iter_exit(&trans, &inode_iter);
} while (ret2 == -EINTR); } while (bch2_err_matches(ret2, BCH_ERR_transaction_restart));
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&new_src, c); bch2_bkey_buf_exit(&new_src, c);
......
...@@ -315,7 +315,7 @@ static int check_subvol(struct btree_trans *trans, ...@@ -315,7 +315,7 @@ static int check_subvol(struct btree_trans *trans,
if (BCH_SUBVOLUME_UNLINKED(subvol.v)) { if (BCH_SUBVOLUME_UNLINKED(subvol.v)) {
ret = bch2_subvolume_delete(trans, iter->pos.offset); ret = bch2_subvolume_delete(trans, iter->pos.offset);
if (ret && ret != -EINTR) if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart))
bch_err(trans->c, "error deleting subvolume %llu: %s", bch_err(trans->c, "error deleting subvolume %llu: %s",
iter->pos.offset, bch2_err_str(ret)); iter->pos.offset, bch2_err_str(ret));
if (ret) if (ret)
......
...@@ -640,7 +640,7 @@ static int rand_mixed_trans(struct btree_trans *trans, ...@@ -640,7 +640,7 @@ static int rand_mixed_trans(struct btree_trans *trans,
k = bch2_btree_iter_peek(iter); k = bch2_btree_iter_peek(iter);
ret = bkey_err(k); ret = bkey_err(k);
if (ret && ret != -EINTR) if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart))
bch_err(trans->c, "lookup error in rand_mixed: %s", bch2_err_str(ret)); bch_err(trans->c, "lookup error in rand_mixed: %s", bch2_err_str(ret));
if (ret) if (ret)
return ret; return ret;
......
...@@ -344,7 +344,7 @@ ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size) ...@@ -344,7 +344,7 @@ ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
offset = iter.pos.offset; offset = iter.pos.offset;
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(&trans, &iter);
err: err:
if (ret == -EINTR) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_exit(&trans);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment