bcachefs: Heap allocate btree_trans

We're using more stack than we'd like in a number of functions, and
btree_trans is the biggest object that we stack allocate.

But we have to do a heap allocatation to initialize it anyways, so
there's no real downside to heap allocating the entire thing.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2023-09-12 17:16:02 -04:00
parent 96dea3d599
commit 6bd68ec266
47 changed files with 731 additions and 877 deletions

View File

@ -279,18 +279,16 @@ struct posix_acl *bch2_get_acl(struct mnt_idmap *idmap,
struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct bch_hash_info hash = bch2_hash_info_init(c, &inode->ei_inode); struct bch_hash_info hash = bch2_hash_info_init(c, &inode->ei_inode);
struct xattr_search_key search = X_SEARCH(acl_to_xattr_type(type), "", 0); struct xattr_search_key search = X_SEARCH(acl_to_xattr_type(type), "", 0);
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter = { NULL }; struct btree_iter iter = { NULL };
struct bkey_s_c_xattr xattr; struct bkey_s_c_xattr xattr;
struct posix_acl *acl = NULL; struct posix_acl *acl = NULL;
struct bkey_s_c k; struct bkey_s_c k;
int ret; int ret;
bch2_trans_init(&trans, c, 0, 0);
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
ret = bch2_hash_lookup(&trans, &iter, bch2_xattr_hash_desc, ret = bch2_hash_lookup(trans, &iter, bch2_xattr_hash_desc,
&hash, inode_inum(inode), &search, 0); &hash, inode_inum(inode), &search, 0);
if (ret) { if (ret) {
if (!bch2_err_matches(ret, ENOENT)) if (!bch2_err_matches(ret, ENOENT))
@ -306,7 +304,7 @@ retry:
} }
xattr = bkey_s_c_to_xattr(k); xattr = bkey_s_c_to_xattr(k);
acl = bch2_acl_from_disk(&trans, xattr_val(xattr.v), acl = bch2_acl_from_disk(trans, xattr_val(xattr.v),
le16_to_cpu(xattr.v->x_val_len)); le16_to_cpu(xattr.v->x_val_len));
if (!IS_ERR(acl)) if (!IS_ERR(acl))
@ -315,8 +313,8 @@ out:
if (bch2_err_matches(PTR_ERR_OR_ZERO(acl), BCH_ERR_transaction_restart)) if (bch2_err_matches(PTR_ERR_OR_ZERO(acl), BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans); bch2_trans_put(trans);
return acl; return acl;
} }
@ -356,7 +354,7 @@ int bch2_set_acl(struct mnt_idmap *idmap,
{ {
struct bch_inode_info *inode = to_bch_ei(dentry->d_inode); struct bch_inode_info *inode = to_bch_ei(dentry->d_inode);
struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter inode_iter = { NULL }; struct btree_iter inode_iter = { NULL };
struct bch_inode_unpacked inode_u; struct bch_inode_unpacked inode_u;
struct posix_acl *acl; struct posix_acl *acl;
@ -364,12 +362,11 @@ int bch2_set_acl(struct mnt_idmap *idmap,
int ret; int ret;
mutex_lock(&inode->ei_update_lock); mutex_lock(&inode->ei_update_lock);
bch2_trans_init(&trans, c, 0, 0);
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
acl = _acl; acl = _acl;
ret = bch2_inode_peek(&trans, &inode_iter, &inode_u, inode_inum(inode), ret = bch2_inode_peek(trans, &inode_iter, &inode_u, inode_inum(inode),
BTREE_ITER_INTENT); BTREE_ITER_INTENT);
if (ret) if (ret)
goto btree_err; goto btree_err;
@ -382,30 +379,30 @@ retry:
goto btree_err; goto btree_err;
} }
ret = bch2_set_acl_trans(&trans, inode_inum(inode), &inode_u, acl, type); ret = bch2_set_acl_trans(trans, inode_inum(inode), &inode_u, acl, type);
if (ret) if (ret)
goto btree_err; goto btree_err;
inode_u.bi_ctime = bch2_current_time(c); inode_u.bi_ctime = bch2_current_time(c);
inode_u.bi_mode = mode; inode_u.bi_mode = mode;
ret = bch2_inode_write(&trans, &inode_iter, &inode_u) ?: ret = bch2_inode_write(trans, &inode_iter, &inode_u) ?:
bch2_trans_commit(&trans, NULL, NULL, 0); bch2_trans_commit(trans, NULL, NULL, 0);
btree_err: btree_err:
bch2_trans_iter_exit(&trans, &inode_iter); bch2_trans_iter_exit(trans, &inode_iter);
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
if (unlikely(ret)) if (unlikely(ret))
goto err; goto err;
bch2_inode_update_after_write(&trans, inode, &inode_u, bch2_inode_update_after_write(trans, inode, &inode_u,
ATTR_CTIME|ATTR_MODE); ATTR_CTIME|ATTR_MODE);
set_cached_acl(&inode->v, type, acl); set_cached_acl(&inode->v, type, acl);
err: err:
bch2_trans_exit(&trans);
mutex_unlock(&inode->ei_update_lock); mutex_unlock(&inode->ei_update_lock);
bch2_trans_put(trans);
return ret; return ret;
} }

View File

@ -548,7 +548,7 @@ void bch2_bucket_gens_to_text(struct printbuf *out, struct bch_fs *c, struct bke
int bch2_bucket_gens_init(struct bch_fs *c) int bch2_bucket_gens_init(struct bch_fs *c)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bch_alloc_v4 a; struct bch_alloc_v4 a;
@ -559,9 +559,7 @@ int bch2_bucket_gens_init(struct bch_fs *c)
u8 gen; u8 gen;
int ret; int ret;
bch2_trans_init(&trans, c, 0, 0); for_each_btree_key(trans, iter, BTREE_ID_alloc, POS_MIN,
for_each_btree_key(&trans, iter, BTREE_ID_alloc, POS_MIN,
BTREE_ITER_PREFETCH, k, ret) { BTREE_ITER_PREFETCH, k, ret) {
/* /*
* Not a fsck error because this is checked/repaired by * Not a fsck error because this is checked/repaired by
@ -574,10 +572,10 @@ int bch2_bucket_gens_init(struct bch_fs *c)
pos = alloc_gens_pos(iter.pos, &offset); pos = alloc_gens_pos(iter.pos, &offset);
if (have_bucket_gens_key && bkey_cmp(iter.pos, pos)) { if (have_bucket_gens_key && bkey_cmp(iter.pos, pos)) {
ret = commit_do(&trans, NULL, NULL, ret = commit_do(trans, NULL, NULL,
BTREE_INSERT_NOFAIL| BTREE_INSERT_NOFAIL|
BTREE_INSERT_LAZY_RW, BTREE_INSERT_LAZY_RW,
bch2_btree_insert_trans(&trans, BTREE_ID_bucket_gens, &g.k_i, 0)); bch2_btree_insert_trans(trans, BTREE_ID_bucket_gens, &g.k_i, 0));
if (ret) if (ret)
break; break;
have_bucket_gens_key = false; have_bucket_gens_key = false;
@ -591,15 +589,15 @@ int bch2_bucket_gens_init(struct bch_fs *c)
g.v.gens[offset] = gen; g.v.gens[offset] = gen;
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
if (have_bucket_gens_key && !ret) if (have_bucket_gens_key && !ret)
ret = commit_do(&trans, NULL, NULL, ret = commit_do(trans, NULL, NULL,
BTREE_INSERT_NOFAIL| BTREE_INSERT_NOFAIL|
BTREE_INSERT_LAZY_RW, BTREE_INSERT_LAZY_RW,
bch2_btree_insert_trans(&trans, BTREE_ID_bucket_gens, &g.k_i, 0)); bch2_btree_insert_trans(trans, BTREE_ID_bucket_gens, &g.k_i, 0));
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
@ -608,20 +606,19 @@ int bch2_bucket_gens_init(struct bch_fs *c)
int bch2_alloc_read(struct bch_fs *c) int bch2_alloc_read(struct bch_fs *c)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bch_dev *ca; struct bch_dev *ca;
int ret; int ret;
down_read(&c->gc_lock); down_read(&c->gc_lock);
bch2_trans_init(&trans, c, 0, 0);
if (c->sb.version_upgrade_complete >= bcachefs_metadata_version_bucket_gens) { if (c->sb.version_upgrade_complete >= bcachefs_metadata_version_bucket_gens) {
const struct bch_bucket_gens *g; const struct bch_bucket_gens *g;
u64 b; u64 b;
for_each_btree_key(&trans, iter, BTREE_ID_bucket_gens, POS_MIN, for_each_btree_key(trans, iter, BTREE_ID_bucket_gens, POS_MIN,
BTREE_ITER_PREFETCH, k, ret) { BTREE_ITER_PREFETCH, k, ret) {
u64 start = bucket_gens_pos_to_alloc(k.k->p, 0).offset; u64 start = bucket_gens_pos_to_alloc(k.k->p, 0).offset;
u64 end = bucket_gens_pos_to_alloc(bpos_nosnap_successor(k.k->p), 0).offset; u64 end = bucket_gens_pos_to_alloc(bpos_nosnap_successor(k.k->p), 0).offset;
@ -645,11 +642,11 @@ int bch2_alloc_read(struct bch_fs *c)
b++) b++)
*bucket_gen(ca, b) = g->gens[b & KEY_TYPE_BUCKET_GENS_MASK]; *bucket_gen(ca, b) = g->gens[b & KEY_TYPE_BUCKET_GENS_MASK];
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
} else { } else {
struct bch_alloc_v4 a; struct bch_alloc_v4 a;
for_each_btree_key(&trans, iter, BTREE_ID_alloc, POS_MIN, for_each_btree_key(trans, iter, BTREE_ID_alloc, POS_MIN,
BTREE_ITER_PREFETCH, k, ret) { BTREE_ITER_PREFETCH, k, ret) {
/* /*
* Not a fsck error because this is checked/repaired by * Not a fsck error because this is checked/repaired by
@ -662,10 +659,10 @@ int bch2_alloc_read(struct bch_fs *c)
*bucket_gen(ca, k.k->p.offset) = bch2_alloc_to_v4(k, &a)->gen; *bucket_gen(ca, k.k->p.offset) = bch2_alloc_to_v4(k, &a)->gen;
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
} }
bch2_trans_exit(&trans); bch2_trans_put(trans);
up_read(&c->gc_lock); up_read(&c->gc_lock);
if (ret) if (ret)
@ -1371,27 +1368,25 @@ fsck_err:
int bch2_check_alloc_info(struct bch_fs *c) int bch2_check_alloc_info(struct bch_fs *c)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter, discard_iter, freespace_iter, bucket_gens_iter; struct btree_iter iter, discard_iter, freespace_iter, bucket_gens_iter;
struct bkey hole; struct bkey hole;
struct bkey_s_c k; struct bkey_s_c k;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c, 0, 0); bch2_trans_iter_init(trans, &iter, BTREE_ID_alloc, POS_MIN,
bch2_trans_iter_init(&trans, &iter, BTREE_ID_alloc, POS_MIN,
BTREE_ITER_PREFETCH); BTREE_ITER_PREFETCH);
bch2_trans_iter_init(&trans, &discard_iter, BTREE_ID_need_discard, POS_MIN, bch2_trans_iter_init(trans, &discard_iter, BTREE_ID_need_discard, POS_MIN,
BTREE_ITER_PREFETCH); BTREE_ITER_PREFETCH);
bch2_trans_iter_init(&trans, &freespace_iter, BTREE_ID_freespace, POS_MIN, bch2_trans_iter_init(trans, &freespace_iter, BTREE_ID_freespace, POS_MIN,
BTREE_ITER_PREFETCH); BTREE_ITER_PREFETCH);
bch2_trans_iter_init(&trans, &bucket_gens_iter, BTREE_ID_bucket_gens, POS_MIN, bch2_trans_iter_init(trans, &bucket_gens_iter, BTREE_ID_bucket_gens, POS_MIN,
BTREE_ITER_PREFETCH); BTREE_ITER_PREFETCH);
while (1) { while (1) {
struct bpos next; struct bpos next;
bch2_trans_begin(&trans); bch2_trans_begin(trans);
k = bch2_get_key_or_real_bucket_hole(&iter, &hole); k = bch2_get_key_or_real_bucket_hole(&iter, &hole);
ret = bkey_err(k); ret = bkey_err(k);
@ -1404,7 +1399,7 @@ int bch2_check_alloc_info(struct bch_fs *c)
if (k.k->type) { if (k.k->type) {
next = bpos_nosnap_successor(k.k->p); next = bpos_nosnap_successor(k.k->p);
ret = bch2_check_alloc_key(&trans, ret = bch2_check_alloc_key(trans,
k, &iter, k, &iter,
&discard_iter, &discard_iter,
&freespace_iter, &freespace_iter,
@ -1414,11 +1409,11 @@ int bch2_check_alloc_info(struct bch_fs *c)
} else { } else {
next = k.k->p; next = k.k->p;
ret = bch2_check_alloc_hole_freespace(&trans, ret = bch2_check_alloc_hole_freespace(trans,
bkey_start_pos(k.k), bkey_start_pos(k.k),
&next, &next,
&freespace_iter) ?: &freespace_iter) ?:
bch2_check_alloc_hole_bucket_gens(&trans, bch2_check_alloc_hole_bucket_gens(trans,
bkey_start_pos(k.k), bkey_start_pos(k.k),
&next, &next,
&bucket_gens_iter); &bucket_gens_iter);
@ -1426,7 +1421,7 @@ int bch2_check_alloc_info(struct bch_fs *c)
goto bkey_err; goto bkey_err;
} }
ret = bch2_trans_commit(&trans, NULL, NULL, ret = bch2_trans_commit(trans, NULL, NULL,
BTREE_INSERT_NOFAIL| BTREE_INSERT_NOFAIL|
BTREE_INSERT_LAZY_RW); BTREE_INSERT_LAZY_RW);
if (ret) if (ret)
@ -1439,29 +1434,29 @@ bkey_err:
if (ret) if (ret)
break; break;
} }
bch2_trans_iter_exit(&trans, &bucket_gens_iter); bch2_trans_iter_exit(trans, &bucket_gens_iter);
bch2_trans_iter_exit(&trans, &freespace_iter); bch2_trans_iter_exit(trans, &freespace_iter);
bch2_trans_iter_exit(&trans, &discard_iter); bch2_trans_iter_exit(trans, &discard_iter);
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
if (ret < 0) if (ret < 0)
goto err; goto err;
ret = for_each_btree_key2(&trans, iter, ret = for_each_btree_key2(trans, iter,
BTREE_ID_need_discard, POS_MIN, BTREE_ID_need_discard, POS_MIN,
BTREE_ITER_PREFETCH, k, BTREE_ITER_PREFETCH, k,
bch2_check_discard_freespace_key(&trans, &iter, k.k->p)) ?: bch2_check_discard_freespace_key(trans, &iter, k.k->p)) ?:
for_each_btree_key2(&trans, iter, for_each_btree_key2(trans, iter,
BTREE_ID_freespace, POS_MIN, BTREE_ID_freespace, POS_MIN,
BTREE_ITER_PREFETCH, k, BTREE_ITER_PREFETCH, k,
bch2_check_discard_freespace_key(&trans, &iter, k.k->p)) ?: bch2_check_discard_freespace_key(trans, &iter, k.k->p)) ?:
for_each_btree_key_commit(&trans, iter, for_each_btree_key_commit(trans, iter,
BTREE_ID_bucket_gens, POS_MIN, BTREE_ID_bucket_gens, POS_MIN,
BTREE_ITER_PREFETCH, k, BTREE_ITER_PREFETCH, k,
NULL, NULL, BTREE_INSERT_NOFAIL|BTREE_INSERT_LAZY_RW, NULL, NULL, BTREE_INSERT_NOFAIL|BTREE_INSERT_LAZY_RW,
bch2_check_bucket_gens_key(&trans, &iter, k)); bch2_check_bucket_gens_key(trans, &iter, k));
err: err:
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
return ret; return ret;
@ -1547,10 +1542,10 @@ int bch2_check_alloc_to_lru_refs(struct bch_fs *c)
int ret = 0; int ret = 0;
ret = bch2_trans_run(c, ret = bch2_trans_run(c,
for_each_btree_key_commit(&trans, iter, BTREE_ID_alloc, for_each_btree_key_commit(trans, iter, BTREE_ID_alloc,
POS_MIN, BTREE_ITER_PREFETCH, k, POS_MIN, BTREE_ITER_PREFETCH, k,
NULL, NULL, BTREE_INSERT_NOFAIL|BTREE_INSERT_LAZY_RW, NULL, NULL, BTREE_INSERT_NOFAIL|BTREE_INSERT_LAZY_RW,
bch2_check_alloc_to_lru_ref(&trans, &iter))); bch2_check_alloc_to_lru_ref(trans, &iter)));
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
return ret; return ret;
@ -1675,29 +1670,25 @@ out:
static void bch2_do_discards_work(struct work_struct *work) static void bch2_do_discards_work(struct work_struct *work)
{ {
struct bch_fs *c = container_of(work, struct bch_fs, discard_work); struct bch_fs *c = container_of(work, struct bch_fs, discard_work);
struct btree_trans trans;
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
u64 seen = 0, open = 0, need_journal_commit = 0, discarded = 0; u64 seen = 0, open = 0, need_journal_commit = 0, discarded = 0;
struct bpos discard_pos_done = POS_MAX; struct bpos discard_pos_done = POS_MAX;
int ret; int ret;
bch2_trans_init(&trans, c, 0, 0);
/* /*
* We're doing the commit in bch2_discard_one_bucket instead of using * We're doing the commit in bch2_discard_one_bucket instead of using
* for_each_btree_key_commit() so that we can increment counters after * for_each_btree_key_commit() so that we can increment counters after
* successful commit: * successful commit:
*/ */
ret = for_each_btree_key2(&trans, iter, ret = bch2_trans_run(c,
BTREE_ID_need_discard, POS_MIN, 0, k, for_each_btree_key2(trans, iter,
bch2_discard_one_bucket(&trans, &iter, &discard_pos_done, BTREE_ID_need_discard, POS_MIN, 0, k,
&seen, bch2_discard_one_bucket(trans, &iter, &discard_pos_done,
&open, &seen,
&need_journal_commit, &open,
&discarded)); &need_journal_commit,
&discarded)));
bch2_trans_exit(&trans);
if (need_journal_commit * 2 > seen) if (need_journal_commit * 2 > seen)
bch2_journal_flush_async(&c->journal, NULL); bch2_journal_flush_async(&c->journal, NULL);
@ -1803,15 +1794,13 @@ static void bch2_do_invalidates_work(struct work_struct *work)
{ {
struct bch_fs *c = container_of(work, struct bch_fs, invalidate_work); struct bch_fs *c = container_of(work, struct bch_fs, invalidate_work);
struct bch_dev *ca; struct bch_dev *ca;
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
unsigned i; unsigned i;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c, 0, 0); ret = bch2_btree_write_buffer_flush(trans);
ret = bch2_btree_write_buffer_flush(&trans);
if (ret) if (ret)
goto err; goto err;
@ -1819,11 +1808,11 @@ static void bch2_do_invalidates_work(struct work_struct *work)
s64 nr_to_invalidate = s64 nr_to_invalidate =
should_invalidate_buckets(ca, bch2_dev_usage_read(ca)); should_invalidate_buckets(ca, bch2_dev_usage_read(ca));
ret = for_each_btree_key2_upto(&trans, iter, BTREE_ID_lru, ret = for_each_btree_key2_upto(trans, iter, BTREE_ID_lru,
lru_pos(ca->dev_idx, 0, 0), lru_pos(ca->dev_idx, 0, 0),
lru_pos(ca->dev_idx, U64_MAX, LRU_TIME_MAX), lru_pos(ca->dev_idx, U64_MAX, LRU_TIME_MAX),
BTREE_ITER_INTENT, k, BTREE_ITER_INTENT, k,
invalidate_one_bucket(&trans, &iter, k, &nr_to_invalidate)); invalidate_one_bucket(trans, &iter, k, &nr_to_invalidate));
if (ret < 0) { if (ret < 0) {
percpu_ref_put(&ca->ref); percpu_ref_put(&ca->ref);
@ -1831,7 +1820,7 @@ static void bch2_do_invalidates_work(struct work_struct *work)
} }
} }
err: err:
bch2_trans_exit(&trans); bch2_trans_put(trans);
bch2_write_ref_put(c, BCH_WRITE_REF_invalidate); bch2_write_ref_put(c, BCH_WRITE_REF_invalidate);
} }
@ -1845,7 +1834,7 @@ void bch2_do_invalidates(struct bch_fs *c)
static int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca, static int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca,
unsigned long *last_updated) unsigned long *last_updated)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bkey hole; struct bkey hole;
@ -1853,9 +1842,7 @@ static int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca,
struct bch_member *m; struct bch_member *m;
int ret; int ret;
bch2_trans_init(&trans, c, 0, 0); bch2_trans_iter_init(trans, &iter, BTREE_ID_alloc,
bch2_trans_iter_init(&trans, &iter, BTREE_ID_alloc,
POS(ca->dev_idx, ca->mi.first_bucket), POS(ca->dev_idx, ca->mi.first_bucket),
BTREE_ITER_PREFETCH); BTREE_ITER_PREFETCH);
/* /*
@ -1869,7 +1856,7 @@ static int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca,
*last_updated = jiffies; *last_updated = jiffies;
} }
bch2_trans_begin(&trans); bch2_trans_begin(trans);
if (bkey_ge(iter.pos, end)) { if (bkey_ge(iter.pos, end)) {
ret = 0; ret = 0;
@ -1889,8 +1876,8 @@ static int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca,
struct bch_alloc_v4 a_convert; struct bch_alloc_v4 a_convert;
const struct bch_alloc_v4 *a = bch2_alloc_to_v4(k, &a_convert); const struct bch_alloc_v4 *a = bch2_alloc_to_v4(k, &a_convert);
ret = bch2_bucket_do_index(&trans, k, a, true) ?: ret = bch2_bucket_do_index(trans, k, a, true) ?:
bch2_trans_commit(&trans, NULL, NULL, bch2_trans_commit(trans, NULL, NULL,
BTREE_INSERT_LAZY_RW| BTREE_INSERT_LAZY_RW|
BTREE_INSERT_NOFAIL); BTREE_INSERT_NOFAIL);
if (ret) if (ret)
@ -1900,7 +1887,7 @@ static int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca,
} else { } else {
struct bkey_i *freespace; struct bkey_i *freespace;
freespace = bch2_trans_kmalloc(&trans, sizeof(*freespace)); freespace = bch2_trans_kmalloc(trans, sizeof(*freespace));
ret = PTR_ERR_OR_ZERO(freespace); ret = PTR_ERR_OR_ZERO(freespace);
if (ret) if (ret)
goto bkey_err; goto bkey_err;
@ -1910,8 +1897,8 @@ static int bch2_dev_freespace_init(struct bch_fs *c, struct bch_dev *ca,
freespace->k.p = k.k->p; freespace->k.p = k.k->p;
freespace->k.size = k.k->size; freespace->k.size = k.k->size;
ret = bch2_btree_insert_trans(&trans, BTREE_ID_freespace, freespace, 0) ?: ret = bch2_btree_insert_trans(trans, BTREE_ID_freespace, freespace, 0) ?:
bch2_trans_commit(&trans, NULL, NULL, bch2_trans_commit(trans, NULL, NULL,
BTREE_INSERT_LAZY_RW| BTREE_INSERT_LAZY_RW|
BTREE_INSERT_NOFAIL); BTREE_INSERT_NOFAIL);
if (ret) if (ret)
@ -1926,8 +1913,8 @@ bkey_err:
break; break;
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (ret < 0) { if (ret < 0) {
bch_err_msg(ca, ret, "initializing free space"); bch_err_msg(ca, ret, "initializing free space");

View File

@ -602,7 +602,7 @@ struct open_bucket *bch2_bucket_alloc(struct bch_fs *c, struct bch_dev *ca,
struct open_bucket *ob; struct open_bucket *ob;
bch2_trans_do(c, NULL, NULL, 0, bch2_trans_do(c, NULL, NULL, 0,
PTR_ERR_OR_ZERO(ob = bch2_bucket_alloc_trans(&trans, ca, watermark, PTR_ERR_OR_ZERO(ob = bch2_bucket_alloc_trans(trans, ca, watermark,
cl, &usage))); cl, &usage)));
return ob; return ob;
} }

View File

@ -390,10 +390,10 @@ int bch2_check_btree_backpointers(struct bch_fs *c)
int ret; int ret;
ret = bch2_trans_run(c, ret = bch2_trans_run(c,
for_each_btree_key_commit(&trans, iter, for_each_btree_key_commit(trans, iter,
BTREE_ID_backpointers, POS_MIN, 0, k, BTREE_ID_backpointers, POS_MIN, 0, k,
NULL, NULL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL, NULL, NULL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL,
bch2_check_btree_backpointer(&trans, &iter, k))); bch2_check_btree_backpointer(trans, &iter, k)));
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
return ret; return ret;
@ -723,13 +723,12 @@ static int bch2_get_alloc_in_memory_pos(struct btree_trans *trans,
int bch2_check_extents_to_backpointers(struct bch_fs *c) int bch2_check_extents_to_backpointers(struct bch_fs *c)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct bpos start = POS_MIN, end; struct bpos start = POS_MIN, end;
int ret; int ret;
bch2_trans_init(&trans, c, 0, 0);
while (1) { while (1) {
ret = bch2_get_alloc_in_memory_pos(&trans, start, &end); ret = bch2_get_alloc_in_memory_pos(trans, start, &end);
if (ret) if (ret)
break; break;
@ -749,13 +748,13 @@ int bch2_check_extents_to_backpointers(struct bch_fs *c)
printbuf_exit(&buf); printbuf_exit(&buf);
} }
ret = bch2_check_extents_to_backpointers_pass(&trans, start, end); ret = bch2_check_extents_to_backpointers_pass(trans, start, end);
if (ret || bpos_eq(end, SPOS_MAX)) if (ret || bpos_eq(end, SPOS_MAX))
break; break;
start = bpos_successor(end); start = bpos_successor(end);
} }
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
@ -824,13 +823,12 @@ static int bch2_check_backpointers_to_extents_pass(struct btree_trans *trans,
int bch2_check_backpointers_to_extents(struct bch_fs *c) int bch2_check_backpointers_to_extents(struct bch_fs *c)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct bbpos start = (struct bbpos) { .btree = 0, .pos = POS_MIN, }, end; struct bbpos start = (struct bbpos) { .btree = 0, .pos = POS_MIN, }, end;
int ret; int ret;
bch2_trans_init(&trans, c, 0, 0);
while (1) { while (1) {
ret = bch2_get_btree_in_memory_pos(&trans, ret = bch2_get_btree_in_memory_pos(trans,
(1U << BTREE_ID_extents)| (1U << BTREE_ID_extents)|
(1U << BTREE_ID_reflink), (1U << BTREE_ID_reflink),
~0, ~0,
@ -856,13 +854,13 @@ int bch2_check_backpointers_to_extents(struct bch_fs *c)
printbuf_exit(&buf); printbuf_exit(&buf);
} }
ret = bch2_check_backpointers_to_extents_pass(&trans, start, end); ret = bch2_check_backpointers_to_extents_pass(trans, start, end);
if (ret || !bbpos_cmp(end, BBPOS_MAX)) if (ret || !bbpos_cmp(end, BBPOS_MAX))
break; break;
start = bbpos_successor(end); start = bbpos_successor(end);
} }
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);

View File

@ -627,8 +627,8 @@ struct journal_keys {
size_t size; size_t size;
}; };
struct btree_path_buf { struct btree_trans_buf {
struct btree_path *path; struct btree_trans *trans;
}; };
#define REPLICAS_DELTA_LIST_MAX (1U << 16) #define REPLICAS_DELTA_LIST_MAX (1U << 16)
@ -787,9 +787,9 @@ struct bch_fs {
/* btree_iter.c: */ /* btree_iter.c: */
struct seqmutex btree_trans_lock; struct seqmutex btree_trans_lock;
struct list_head btree_trans_list; struct list_head btree_trans_list;
mempool_t btree_paths_pool; mempool_t btree_trans_pool;
mempool_t btree_trans_mem_pool; mempool_t btree_trans_mem_pool;
struct btree_path_buf __percpu *btree_paths_bufs; struct btree_trans_buf __percpu *btree_trans_bufs;
struct srcu_struct btree_trans_barrier; struct srcu_struct btree_trans_barrier;
bool btree_trans_barrier_initialized; bool btree_trans_barrier_initialized;

View File

@ -529,13 +529,11 @@ fsck_err:
int bch2_check_topology(struct bch_fs *c) int bch2_check_topology(struct bch_fs *c)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree *b; struct btree *b;
unsigned i; unsigned i;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c, 0, 0);
for (i = 0; i < btree_id_nr_alive(c) && !ret; i++) { for (i = 0; i < btree_id_nr_alive(c) && !ret; i++) {
struct btree_root *r = bch2_btree_id_root(c, i); struct btree_root *r = bch2_btree_id_root(c, i);
@ -546,8 +544,8 @@ int bch2_check_topology(struct bch_fs *c)
if (btree_node_fake(b)) if (btree_node_fake(b))
continue; continue;
btree_node_lock_nopath_nofail(&trans, &b->c, SIX_LOCK_read); btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_read);
ret = bch2_btree_repair_topology_recurse(&trans, b); ret = bch2_btree_repair_topology_recurse(trans, b);
six_unlock_read(&b->c.lock); six_unlock_read(&b->c.lock);
if (ret == DROP_THIS_NODE) { if (ret == DROP_THIS_NODE) {
@ -556,7 +554,7 @@ int bch2_check_topology(struct bch_fs *c)
} }
} }
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
@ -1068,35 +1066,33 @@ static inline int btree_id_gc_phase_cmp(enum btree_id l, enum btree_id r)
static int bch2_gc_btrees(struct bch_fs *c, bool initial, bool metadata_only) static int bch2_gc_btrees(struct bch_fs *c, bool initial, bool metadata_only)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
enum btree_id ids[BTREE_ID_NR]; enum btree_id ids[BTREE_ID_NR];
unsigned i; unsigned i;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c, 0, 0);
for (i = 0; i < BTREE_ID_NR; i++) for (i = 0; i < BTREE_ID_NR; i++)
ids[i] = i; ids[i] = i;
bubble_sort(ids, BTREE_ID_NR, btree_id_gc_phase_cmp); bubble_sort(ids, BTREE_ID_NR, btree_id_gc_phase_cmp);
for (i = 0; i < BTREE_ID_NR && !ret; i++) for (i = 0; i < BTREE_ID_NR && !ret; i++)
ret = initial ret = initial
? bch2_gc_btree_init(&trans, ids[i], metadata_only) ? bch2_gc_btree_init(trans, ids[i], metadata_only)
: bch2_gc_btree(&trans, ids[i], initial, metadata_only); : bch2_gc_btree(trans, ids[i], initial, metadata_only);
for (i = BTREE_ID_NR; i < btree_id_nr_alive(c) && !ret; i++) { for (i = BTREE_ID_NR; i < btree_id_nr_alive(c) && !ret; i++) {
if (!bch2_btree_id_root(c, i)->alive) if (!bch2_btree_id_root(c, i)->alive)
continue; continue;
ret = initial ret = initial
? bch2_gc_btree_init(&trans, i, metadata_only) ? bch2_gc_btree_init(trans, i, metadata_only)
: bch2_gc_btree(&trans, i, initial, metadata_only); : bch2_gc_btree(trans, i, initial, metadata_only);
} }
if (ret < 0) if (ret < 0)
bch_err_fn(c, ret); bch_err_fn(c, ret);
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
@ -1458,21 +1454,19 @@ fsck_err:
static int bch2_gc_alloc_done(struct bch_fs *c, bool metadata_only) static int bch2_gc_alloc_done(struct bch_fs *c, bool metadata_only)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bch_dev *ca; struct bch_dev *ca;
unsigned i; unsigned i;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c, 0, 0);
for_each_member_device(ca, c, i) { for_each_member_device(ca, c, i) {
ret = for_each_btree_key_commit(&trans, iter, BTREE_ID_alloc, ret = for_each_btree_key_commit(trans, iter, BTREE_ID_alloc,
POS(ca->dev_idx, ca->mi.first_bucket), POS(ca->dev_idx, ca->mi.first_bucket),
BTREE_ITER_SLOTS|BTREE_ITER_PREFETCH, k, BTREE_ITER_SLOTS|BTREE_ITER_PREFETCH, k,
NULL, NULL, BTREE_INSERT_LAZY_RW, NULL, NULL, BTREE_INSERT_LAZY_RW,
bch2_alloc_write_key(&trans, &iter, k, metadata_only)); bch2_alloc_write_key(trans, &iter, k, metadata_only));
if (ret < 0) { if (ret < 0) {
bch_err_fn(c, ret); bch_err_fn(c, ret);
@ -1481,14 +1475,14 @@ static int bch2_gc_alloc_done(struct bch_fs *c, bool metadata_only)
} }
} }
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
} }
static int bch2_gc_alloc_start(struct bch_fs *c, bool metadata_only) static int bch2_gc_alloc_start(struct bch_fs *c, bool metadata_only)
{ {
struct bch_dev *ca; struct bch_dev *ca;
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bucket *g; struct bucket *g;
@ -1504,7 +1498,8 @@ static int bch2_gc_alloc_start(struct bch_fs *c, bool metadata_only)
if (!buckets) { if (!buckets) {
percpu_ref_put(&ca->ref); percpu_ref_put(&ca->ref);
bch_err(c, "error allocating ca->buckets[gc]"); bch_err(c, "error allocating ca->buckets[gc]");
return -BCH_ERR_ENOMEM_gc_alloc_start; ret = -BCH_ERR_ENOMEM_gc_alloc_start;
goto err;
} }
buckets->first_bucket = ca->mi.first_bucket; buckets->first_bucket = ca->mi.first_bucket;
@ -1512,9 +1507,7 @@ static int bch2_gc_alloc_start(struct bch_fs *c, bool metadata_only)
rcu_assign_pointer(ca->buckets_gc, buckets); rcu_assign_pointer(ca->buckets_gc, buckets);
} }
bch2_trans_init(&trans, c, 0, 0); for_each_btree_key(trans, iter, BTREE_ID_alloc, POS_MIN,
for_each_btree_key(&trans, iter, BTREE_ID_alloc, POS_MIN,
BTREE_ITER_PREFETCH, k, ret) { BTREE_ITER_PREFETCH, k, ret) {
ca = bch_dev_bkey_exists(c, k.k->p.inode); ca = bch_dev_bkey_exists(c, k.k->p.inode);
g = gc_bucket(ca, k.k->p.offset); g = gc_bucket(ca, k.k->p.offset);
@ -1535,13 +1528,11 @@ static int bch2_gc_alloc_start(struct bch_fs *c, bool metadata_only)
g->stripe_redundancy = a->stripe_redundancy; g->stripe_redundancy = a->stripe_redundancy;
} }
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
err:
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
return ret; return ret;
} }
@ -1616,7 +1607,7 @@ fsck_err:
static int bch2_gc_reflink_done(struct bch_fs *c, bool metadata_only) static int bch2_gc_reflink_done(struct bch_fs *c, bool metadata_only)
{ {
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
size_t idx = 0; size_t idx = 0;
@ -1625,23 +1616,23 @@ static int bch2_gc_reflink_done(struct bch_fs *c, bool metadata_only)
if (metadata_only) if (metadata_only)
return 0; return 0;
bch2_trans_init(&trans, c, 0, 0); trans = bch2_trans_get(c);
ret = for_each_btree_key_commit(&trans, iter, ret = for_each_btree_key_commit(trans, iter,
BTREE_ID_reflink, POS_MIN, BTREE_ID_reflink, POS_MIN,
BTREE_ITER_PREFETCH, k, BTREE_ITER_PREFETCH, k,
NULL, NULL, BTREE_INSERT_NOFAIL, NULL, NULL, BTREE_INSERT_NOFAIL,
bch2_gc_write_reflink_key(&trans, &iter, k, &idx)); bch2_gc_write_reflink_key(trans, &iter, k, &idx));
c->reflink_gc_nr = 0; c->reflink_gc_nr = 0;
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
static int bch2_gc_reflink_start(struct bch_fs *c, static int bch2_gc_reflink_start(struct bch_fs *c,
bool metadata_only) bool metadata_only)
{ {
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct reflink_gc *r; struct reflink_gc *r;
@ -1650,10 +1641,10 @@ static int bch2_gc_reflink_start(struct bch_fs *c,
if (metadata_only) if (metadata_only)
return 0; return 0;
bch2_trans_init(&trans, c, 0, 0); trans = bch2_trans_get(c);
c->reflink_gc_nr = 0; c->reflink_gc_nr = 0;
for_each_btree_key(&trans, iter, BTREE_ID_reflink, POS_MIN, for_each_btree_key(trans, iter, BTREE_ID_reflink, POS_MIN,
BTREE_ITER_PREFETCH, k, ret) { BTREE_ITER_PREFETCH, k, ret) {
const __le64 *refcount = bkey_refcount_c(k); const __le64 *refcount = bkey_refcount_c(k);
@ -1671,9 +1662,9 @@ static int bch2_gc_reflink_start(struct bch_fs *c,
r->size = k.k->size; r->size = k.k->size;
r->refcount = 0; r->refcount = 0;
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
@ -1740,7 +1731,7 @@ fsck_err:
static int bch2_gc_stripes_done(struct bch_fs *c, bool metadata_only) static int bch2_gc_stripes_done(struct bch_fs *c, bool metadata_only)
{ {
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
int ret = 0; int ret = 0;
@ -1748,15 +1739,15 @@ static int bch2_gc_stripes_done(struct bch_fs *c, bool metadata_only)
if (metadata_only) if (metadata_only)
return 0; return 0;
bch2_trans_init(&trans, c, 0, 0); trans = bch2_trans_get(c);
ret = for_each_btree_key_commit(&trans, iter, ret = for_each_btree_key_commit(trans, iter,
BTREE_ID_stripes, POS_MIN, BTREE_ID_stripes, POS_MIN,
BTREE_ITER_PREFETCH, k, BTREE_ITER_PREFETCH, k,
NULL, NULL, BTREE_INSERT_NOFAIL, NULL, NULL, BTREE_INSERT_NOFAIL,
bch2_gc_write_stripes_key(&trans, &iter, k)); bch2_gc_write_stripes_key(trans, &iter, k));
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
@ -1942,7 +1933,7 @@ static int bch2_alloc_write_oldest_gen(struct btree_trans *trans, struct btree_i
int bch2_gc_gens(struct bch_fs *c) int bch2_gc_gens(struct bch_fs *c)
{ {
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bch_dev *ca; struct bch_dev *ca;
@ -1960,7 +1951,7 @@ int bch2_gc_gens(struct bch_fs *c)
trace_and_count(c, gc_gens_start, c); trace_and_count(c, gc_gens_start, c);
down_read(&c->gc_lock); down_read(&c->gc_lock);
bch2_trans_init(&trans, c, 0, 0); trans = bch2_trans_get(c);
for_each_member_device(ca, c, i) { for_each_member_device(ca, c, i) {
struct bucket_gens *gens; struct bucket_gens *gens;
@ -1986,26 +1977,26 @@ int bch2_gc_gens(struct bch_fs *c)
c->gc_gens_btree = i; c->gc_gens_btree = i;
c->gc_gens_pos = POS_MIN; c->gc_gens_pos = POS_MIN;
ret = for_each_btree_key_commit(&trans, iter, i, ret = for_each_btree_key_commit(trans, iter, i,
POS_MIN, POS_MIN,
BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS,
k, k,
NULL, NULL, NULL, NULL,
BTREE_INSERT_NOFAIL, BTREE_INSERT_NOFAIL,
gc_btree_gens_key(&trans, &iter, k)); gc_btree_gens_key(trans, &iter, k));
if (ret && !bch2_err_matches(ret, EROFS)) if (ret && !bch2_err_matches(ret, EROFS))
bch_err_fn(c, ret); bch_err_fn(c, ret);
if (ret) if (ret)
goto err; goto err;
} }
ret = for_each_btree_key_commit(&trans, iter, BTREE_ID_alloc, ret = for_each_btree_key_commit(trans, iter, BTREE_ID_alloc,
POS_MIN, POS_MIN,
BTREE_ITER_PREFETCH, BTREE_ITER_PREFETCH,
k, k,
NULL, NULL, NULL, NULL,
BTREE_INSERT_NOFAIL, BTREE_INSERT_NOFAIL,
bch2_alloc_write_oldest_gen(&trans, &iter, k)); bch2_alloc_write_oldest_gen(trans, &iter, k));
if (ret && !bch2_err_matches(ret, EROFS)) if (ret && !bch2_err_matches(ret, EROFS))
bch_err_fn(c, ret); bch_err_fn(c, ret);
if (ret) if (ret)
@ -2024,7 +2015,7 @@ err:
ca->oldest_gen = NULL; ca->oldest_gen = NULL;
} }
bch2_trans_exit(&trans); bch2_trans_put(trans);
up_read(&c->gc_lock); up_read(&c->gc_lock);
mutex_unlock(&c->gc_gens_lock); mutex_unlock(&c->gc_gens_lock);
return ret; return ret;

View File

@ -1628,8 +1628,7 @@ err:
int bch2_btree_root_read(struct bch_fs *c, enum btree_id id, int bch2_btree_root_read(struct bch_fs *c, enum btree_id id,
const struct bkey_i *k, unsigned level) const struct bkey_i *k, unsigned level)
{ {
return bch2_trans_run(c, __bch2_btree_root_read(&trans, id, k, level)); return bch2_trans_run(c, __bch2_btree_root_read(trans, id, k, level));
} }
void bch2_btree_complete_write(struct bch_fs *c, struct btree *b, void bch2_btree_complete_write(struct bch_fs *c, struct btree *b,
@ -1691,15 +1690,13 @@ static void __btree_node_write_done(struct bch_fs *c, struct btree *b)
static void btree_node_write_done(struct bch_fs *c, struct btree *b) static void btree_node_write_done(struct bch_fs *c, struct btree *b)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
bch2_trans_init(&trans, c, 0, 0); btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_read);
btree_node_lock_nopath_nofail(&trans, &b->c, SIX_LOCK_read);
__btree_node_write_done(c, b); __btree_node_write_done(c, b);
six_unlock_read(&b->c.lock); six_unlock_read(&b->c.lock);
bch2_trans_exit(&trans); bch2_trans_put(trans);
} }
static void btree_node_write_work(struct work_struct *work) static void btree_node_write_work(struct work_struct *work)
@ -1728,7 +1725,7 @@ static void btree_node_write_work(struct work_struct *work)
} }
} else { } else {
ret = bch2_trans_do(c, NULL, NULL, 0, ret = bch2_trans_do(c, NULL, NULL, 0,
bch2_btree_node_update_key_get_iter(&trans, b, &wbio->key, bch2_btree_node_update_key_get_iter(trans, b, &wbio->key,
BCH_WATERMARK_reclaim| BCH_WATERMARK_reclaim|
BTREE_INSERT_JOURNAL_RECLAIM| BTREE_INSERT_JOURNAL_RECLAIM|
BTREE_INSERT_NOFAIL| BTREE_INSERT_NOFAIL|

View File

@ -2906,28 +2906,23 @@ u32 bch2_trans_begin(struct btree_trans *trans)
return trans->restart_count; return trans->restart_count;
} }
static void bch2_trans_alloc_paths(struct btree_trans *trans, struct bch_fs *c) static struct btree_trans *bch2_trans_alloc(struct bch_fs *c)
{ {
size_t paths_bytes = sizeof(struct btree_path) * BTREE_ITER_MAX; struct btree_trans *trans;
size_t updates_bytes = sizeof(struct btree_insert_entry) * BTREE_ITER_MAX;
void *p = NULL;
BUG_ON(trans->used_mempool); if (IS_ENABLED(__KERNEL__)) {
trans = this_cpu_xchg(c->btree_trans_bufs->trans, NULL);
#ifdef __KERNEL__ if (trans)
p = this_cpu_xchg(c->btree_paths_bufs->path, NULL); return trans;
#endif
if (!p) {
p = mempool_alloc(&trans->c->btree_paths_pool, GFP_NOFS);
/*
* paths need to be zeroed, bch2_check_for_deadlock looks at
* paths in other threads
*/
memset(p, 0, paths_bytes);
} }
trans->paths = p; p += paths_bytes; trans = mempool_alloc(&c->btree_trans_pool, GFP_NOFS);
trans->updates = p; p += updates_bytes; /*
* paths need to be zeroed, bch2_check_for_deadlock looks at
* paths in other threads
*/
memset(&trans->paths, 0, sizeof(trans->paths));
return trans;
} }
const char *bch2_btree_transaction_fns[BCH_TRANSACTIONS_NR]; const char *bch2_btree_transaction_fns[BCH_TRANSACTIONS_NR];
@ -2947,11 +2942,14 @@ unsigned bch2_trans_get_fn_idx(const char *fn)
return i; return i;
} }
void __bch2_trans_init(struct btree_trans *trans, struct bch_fs *c, unsigned fn_idx) struct btree_trans *__bch2_trans_get(struct bch_fs *c, unsigned fn_idx)
__acquires(&c->btree_trans_barrier) __acquires(&c->btree_trans_barrier)
{ {
struct btree_trans *trans;
struct btree_transaction_stats *s; struct btree_transaction_stats *s;
trans = bch2_trans_alloc(c);
memset(trans, 0, sizeof(*trans)); memset(trans, 0, sizeof(*trans));
trans->c = c; trans->c = c;
trans->fn = fn_idx < ARRAY_SIZE(bch2_btree_transaction_fns) trans->fn = fn_idx < ARRAY_SIZE(bch2_btree_transaction_fns)
@ -2963,8 +2961,6 @@ void __bch2_trans_init(struct btree_trans *trans, struct bch_fs *c, unsigned fn_
!test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags); !test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags);
closure_init_stack(&trans->ref); closure_init_stack(&trans->ref);
bch2_trans_alloc_paths(trans, c);
s = btree_trans_stats(trans); s = btree_trans_stats(trans);
if (s && s->max_mem) { if (s && s->max_mem) {
unsigned expected_mem_bytes = roundup_pow_of_two(s->max_mem); unsigned expected_mem_bytes = roundup_pow_of_two(s->max_mem);
@ -3010,6 +3006,8 @@ void __bch2_trans_init(struct btree_trans *trans, struct bch_fs *c, unsigned fn_
list_add_done: list_add_done:
seqmutex_unlock(&c->btree_trans_lock); seqmutex_unlock(&c->btree_trans_lock);
} }
return trans;
} }
static void check_btree_paths_leaked(struct btree_trans *trans) static void check_btree_paths_leaked(struct btree_trans *trans)
@ -3034,7 +3032,7 @@ leaked:
#endif #endif
} }
void bch2_trans_exit(struct btree_trans *trans) void bch2_trans_put(struct btree_trans *trans)
__releases(&c->btree_trans_barrier) __releases(&c->btree_trans_barrier)
{ {
struct btree_insert_entry *i; struct btree_insert_entry *i;
@ -3080,18 +3078,11 @@ void bch2_trans_exit(struct btree_trans *trans)
else else
kfree(trans->mem); kfree(trans->mem);
#ifdef __KERNEL__ /* Userspace doesn't have a real percpu implementation: */
/* if (IS_ENABLED(__KERNEL__))
* Userspace doesn't have a real percpu implementation: trans = this_cpu_xchg(c->btree_trans_bufs->trans, trans);
*/ if (trans)
trans->paths = this_cpu_xchg(c->btree_paths_bufs->path, trans->paths); mempool_free(trans, &c->btree_trans_pool);
#endif
if (trans->paths)
mempool_free(trans->paths, &c->btree_paths_pool);
trans->mem = (void *) 0x1;
trans->paths = (void *) 0x1;
} }
static void __maybe_unused static void __maybe_unused
@ -3169,6 +3160,17 @@ void bch2_btree_trans_to_text(struct printbuf *out, struct btree_trans *trans)
void bch2_fs_btree_iter_exit(struct bch_fs *c) void bch2_fs_btree_iter_exit(struct bch_fs *c)
{ {
struct btree_transaction_stats *s; struct btree_transaction_stats *s;
struct btree_trans *trans;
int cpu;
trans = list_first_entry_or_null(&c->btree_trans_list, struct btree_trans, list);
if (trans)
panic("%s leaked btree_trans\n", trans->fn);
if (c->btree_trans_bufs)
for_each_possible_cpu(cpu)
kfree(per_cpu_ptr(c->btree_trans_bufs, cpu)->trans);
free_percpu(c->btree_trans_bufs);
for (s = c->btree_transaction_stats; for (s = c->btree_transaction_stats;
s < c->btree_transaction_stats + ARRAY_SIZE(c->btree_transaction_stats); s < c->btree_transaction_stats + ARRAY_SIZE(c->btree_transaction_stats);
@ -3180,13 +3182,12 @@ void bch2_fs_btree_iter_exit(struct bch_fs *c)
if (c->btree_trans_barrier_initialized) if (c->btree_trans_barrier_initialized)
cleanup_srcu_struct(&c->btree_trans_barrier); cleanup_srcu_struct(&c->btree_trans_barrier);
mempool_exit(&c->btree_trans_mem_pool); mempool_exit(&c->btree_trans_mem_pool);
mempool_exit(&c->btree_paths_pool); mempool_exit(&c->btree_trans_pool);
} }
int bch2_fs_btree_iter_init(struct bch_fs *c) int bch2_fs_btree_iter_init(struct bch_fs *c)
{ {
struct btree_transaction_stats *s; struct btree_transaction_stats *s;
unsigned nr = BTREE_ITER_MAX;
int ret; int ret;
for (s = c->btree_transaction_stats; for (s = c->btree_transaction_stats;
@ -3199,9 +3200,12 @@ int bch2_fs_btree_iter_init(struct bch_fs *c)
INIT_LIST_HEAD(&c->btree_trans_list); INIT_LIST_HEAD(&c->btree_trans_list);
seqmutex_init(&c->btree_trans_lock); seqmutex_init(&c->btree_trans_lock);
ret = mempool_init_kmalloc_pool(&c->btree_paths_pool, 1, c->btree_trans_bufs = alloc_percpu(struct btree_trans_buf);
sizeof(struct btree_path) * nr + if (!c->btree_trans_bufs)
sizeof(struct btree_insert_entry) * nr) ?: return -ENOMEM;
ret = mempool_init_kmalloc_pool(&c->btree_trans_pool, 1,
sizeof(struct btree_trans)) ?:
mempool_init_kmalloc_pool(&c->btree_trans_mem_pool, 1, mempool_init_kmalloc_pool(&c->btree_trans_mem_pool, 1,
BTREE_TRANS_MEM_MAX) ?: BTREE_TRANS_MEM_MAX) ?:
init_srcu_struct(&c->btree_trans_barrier); init_srcu_struct(&c->btree_trans_barrier);

View File

@ -915,21 +915,21 @@ void bch2_btree_path_to_text(struct printbuf *, struct btree_path *);
void bch2_trans_paths_to_text(struct printbuf *, struct btree_trans *); void bch2_trans_paths_to_text(struct printbuf *, struct btree_trans *);
void bch2_dump_trans_updates(struct btree_trans *); void bch2_dump_trans_updates(struct btree_trans *);
void bch2_dump_trans_paths_updates(struct btree_trans *); void bch2_dump_trans_paths_updates(struct btree_trans *);
void __bch2_trans_init(struct btree_trans *, struct bch_fs *, unsigned);
void bch2_trans_exit(struct btree_trans *); struct btree_trans *__bch2_trans_get(struct bch_fs *, unsigned);
void bch2_trans_put(struct btree_trans *);
extern const char *bch2_btree_transaction_fns[BCH_TRANSACTIONS_NR]; extern const char *bch2_btree_transaction_fns[BCH_TRANSACTIONS_NR];
unsigned bch2_trans_get_fn_idx(const char *); unsigned bch2_trans_get_fn_idx(const char *);
#define bch2_trans_init(_trans, _c, _nr_iters, _mem) \ #define bch2_trans_get(_c) \
do { \ ({ \
static unsigned trans_fn_idx; \ static unsigned trans_fn_idx; \
\ \
if (unlikely(!trans_fn_idx)) \ if (unlikely(!trans_fn_idx)) \
trans_fn_idx = bch2_trans_get_fn_idx(__func__); \ trans_fn_idx = bch2_trans_get_fn_idx(__func__); \
\ __bch2_trans_get(_c, trans_fn_idx); \
__bch2_trans_init(_trans, _c, trans_fn_idx); \ })
} while (0)
void bch2_btree_trans_to_text(struct printbuf *, struct btree_trans *); void bch2_btree_trans_to_text(struct printbuf *, struct btree_trans *);

View File

@ -704,13 +704,11 @@ int bch2_btree_key_cache_journal_flush(struct journal *j,
struct bkey_cached *ck = struct bkey_cached *ck =
container_of(pin, struct bkey_cached, journal); container_of(pin, struct bkey_cached, journal);
struct bkey_cached_key key; struct bkey_cached_key key;
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
int srcu_idx = srcu_read_lock(&c->btree_trans_barrier); int srcu_idx = srcu_read_lock(&c->btree_trans_barrier);
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c, 0, 0); btree_node_lock_nopath_nofail(trans, &ck->c, SIX_LOCK_read);
btree_node_lock_nopath_nofail(&trans, &ck->c, SIX_LOCK_read);
key = ck->key; key = ck->key;
if (ck->journal.seq != seq || if (ck->journal.seq != seq ||
@ -727,13 +725,13 @@ int bch2_btree_key_cache_journal_flush(struct journal *j,
} }
six_unlock_read(&ck->c.lock); six_unlock_read(&ck->c.lock);
ret = commit_do(&trans, NULL, NULL, 0, ret = commit_do(trans, NULL, NULL, 0,
btree_key_cache_flush_pos(&trans, key, seq, btree_key_cache_flush_pos(trans, key, seq,
BTREE_INSERT_JOURNAL_RECLAIM, false)); BTREE_INSERT_JOURNAL_RECLAIM, false));
unlock: unlock:
srcu_read_unlock(&c->btree_trans_barrier, srcu_idx); srcu_read_unlock(&c->btree_trans_barrier, srcu_idx);
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }

View File

@ -163,13 +163,11 @@ static int __btree_node_flush(struct journal *j, struct journal_entry_pin *pin,
struct bch_fs *c = container_of(j, struct bch_fs, journal); struct bch_fs *c = container_of(j, struct bch_fs, journal);
struct btree_write *w = container_of(pin, struct btree_write, journal); struct btree_write *w = container_of(pin, struct btree_write, journal);
struct btree *b = container_of(w, struct btree, writes[i]); struct btree *b = container_of(w, struct btree, writes[i]);
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
unsigned long old, new, v; unsigned long old, new, v;
unsigned idx = w - b->writes; unsigned idx = w - b->writes;
bch2_trans_init(&trans, c, 0, 0); btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_read);
btree_node_lock_nopath_nofail(&trans, &b->c, SIX_LOCK_read);
v = READ_ONCE(b->flags); v = READ_ONCE(b->flags);
do { do {
@ -188,7 +186,7 @@ static int __btree_node_flush(struct journal *j, struct journal_entry_pin *pin,
btree_node_write_if_need(c, b, SIX_LOCK_read); btree_node_write_if_need(c, b, SIX_LOCK_read);
six_unlock_read(&b->c.lock); six_unlock_read(&b->c.lock);
bch2_trans_exit(&trans); bch2_trans_put(trans);
return 0; return 0;
} }

View File

@ -452,8 +452,8 @@ struct btree_trans {
void *mem; void *mem;
u8 sorted[BTREE_ITER_MAX + 8]; u8 sorted[BTREE_ITER_MAX + 8];
struct btree_path *paths; struct btree_path paths[BTREE_ITER_MAX];
struct btree_insert_entry *updates; struct btree_insert_entry updates[BTREE_ITER_MAX];
struct btree_write_buffered_key *wb_updates; struct btree_write_buffered_key *wb_updates;
/* update path: */ /* update path: */

View File

@ -692,7 +692,7 @@ int bch2_btree_insert(struct bch_fs *c, enum btree_id id, struct bkey_i *k,
struct disk_reservation *disk_res, int flags) struct disk_reservation *disk_res, int flags)
{ {
return bch2_trans_do(c, disk_res, NULL, flags, return bch2_trans_do(c, disk_res, NULL, flags,
bch2_btree_insert_trans(&trans, id, k, 0)); bch2_btree_insert_trans(trans, id, k, 0));
} }
int bch2_btree_delete_extent_at(struct btree_trans *trans, struct btree_iter *iter, int bch2_btree_delete_extent_at(struct btree_trans *trans, struct btree_iter *iter,
@ -824,7 +824,7 @@ int bch2_btree_delete_range(struct bch_fs *c, enum btree_id id,
u64 *journal_seq) u64 *journal_seq)
{ {
int ret = bch2_trans_run(c, int ret = bch2_trans_run(c,
bch2_btree_delete_range_trans(&trans, id, start, end, bch2_btree_delete_range_trans(trans, id, start, end,
update_flags, journal_seq)); update_flags, journal_seq));
if (ret == -BCH_ERR_transaction_restart_nested) if (ret == -BCH_ERR_transaction_restart_nested)
ret = 0; ret = 0;
@ -898,7 +898,7 @@ __bch2_fs_log_msg(struct bch_fs *c, unsigned commit_flags, const char *fmt,
} else { } else {
ret = bch2_trans_do(c, NULL, NULL, ret = bch2_trans_do(c, NULL, NULL,
BTREE_INSERT_LAZY_RW|commit_flags, BTREE_INSERT_LAZY_RW|commit_flags,
__bch2_trans_log_msg(&trans.extra_journal_entries, fmt, args)); __bch2_trans_log_msg(&trans->extra_journal_entries, fmt, args));
} }
return ret; return ret;

View File

@ -146,29 +146,16 @@ static inline int bch2_trans_commit(struct btree_trans *trans,
nested_lockrestart_do(_trans, _do ?: bch2_trans_commit(_trans, (_disk_res),\ nested_lockrestart_do(_trans, _do ?: bch2_trans_commit(_trans, (_disk_res),\
(_journal_seq), (_flags))) (_journal_seq), (_flags)))
#define bch2_trans_do(_c, _disk_res, _journal_seq, _flags, _do) \ #define bch2_trans_run(_c, _do) \
({ \ ({ \
struct btree_trans trans; \ struct btree_trans *trans = bch2_trans_get(_c); \
int _ret; \ int _ret = (_do); \
\ bch2_trans_put(trans); \
bch2_trans_init(&trans, (_c), 0, 0); \
_ret = commit_do(&trans, _disk_res, _journal_seq, _flags, _do); \
bch2_trans_exit(&trans); \
\
_ret; \ _ret; \
}) })
#define bch2_trans_run(_c, _do) \ #define bch2_trans_do(_c, _disk_res, _journal_seq, _flags, _do) \
({ \ bch2_trans_run(_c, commit_do(trans, _disk_res, _journal_seq, _flags, _do))
struct btree_trans trans; \
int _ret; \
\
bch2_trans_init(&trans, (_c), 0, 0); \
_ret = (_do); \
bch2_trans_exit(&trans); \
\
_ret; \
})
#define trans_for_each_update(_trans, _i) \ #define trans_for_each_update(_trans, _i) \
for ((_i) = (_trans)->updates; \ for ((_i) = (_trans)->updates; \

View File

@ -597,12 +597,11 @@ static void btree_update_nodes_written(struct btree_update *as)
{ {
struct bch_fs *c = as->c; struct bch_fs *c = as->c;
struct btree *b; struct btree *b;
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
u64 journal_seq = 0; u64 journal_seq = 0;
unsigned i; unsigned i;
int ret; int ret;
bch2_trans_init(&trans, c, 0, 512);
/* /*
* If we're already in an error state, it might be because a btree node * If we're already in an error state, it might be because a btree node
* was never written, and we might be trying to free that same btree * was never written, and we might be trying to free that same btree
@ -623,7 +622,7 @@ static void btree_update_nodes_written(struct btree_update *as)
b = as->old_nodes[i]; b = as->old_nodes[i];
btree_node_lock_nopath_nofail(&trans, &b->c, SIX_LOCK_read); btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_read);
seq = b->data ? b->data->keys.seq : 0; seq = b->data ? b->data->keys.seq : 0;
six_unlock_read(&b->c.lock); six_unlock_read(&b->c.lock);
@ -645,13 +644,13 @@ static void btree_update_nodes_written(struct btree_update *as)
* journal reclaim does btree updates when flushing bkey_cached entries, * journal reclaim does btree updates when flushing bkey_cached entries,
* which may require allocations as well. * which may require allocations as well.
*/ */
ret = commit_do(&trans, &as->disk_res, &journal_seq, ret = commit_do(trans, &as->disk_res, &journal_seq,
BCH_WATERMARK_reclaim| BCH_WATERMARK_reclaim|
BTREE_INSERT_NOFAIL| BTREE_INSERT_NOFAIL|
BTREE_INSERT_NOCHECK_RW| BTREE_INSERT_NOCHECK_RW|
BTREE_INSERT_JOURNAL_RECLAIM, BTREE_INSERT_JOURNAL_RECLAIM,
btree_update_nodes_written_trans(&trans, as)); btree_update_nodes_written_trans(trans, as));
bch2_trans_unlock(&trans); bch2_trans_unlock(trans);
bch2_fs_fatal_err_on(ret && !bch2_journal_error(&c->journal), c, bch2_fs_fatal_err_on(ret && !bch2_journal_error(&c->journal), c,
"%s(): error %s", __func__, bch2_err_str(ret)); "%s(): error %s", __func__, bch2_err_str(ret));
@ -660,7 +659,7 @@ err:
struct btree_path *path; struct btree_path *path;
b = as->b; b = as->b;
path = get_unlocked_mut_path(&trans, as->btree_id, b->c.level, b->key.k.p); path = get_unlocked_mut_path(trans, as->btree_id, b->c.level, b->key.k.p);
/* /*
* @b is the node we did the final insert into: * @b is the node we did the final insert into:
* *
@ -683,13 +682,13 @@ err:
* we may rarely end up with a locked path besides the one we * we may rarely end up with a locked path besides the one we
* have here: * have here:
*/ */
bch2_trans_unlock(&trans); bch2_trans_unlock(trans);
btree_node_lock_nopath_nofail(&trans, &b->c, SIX_LOCK_intent); btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_intent);
mark_btree_node_locked(&trans, path, b->c.level, BTREE_NODE_INTENT_LOCKED); mark_btree_node_locked(trans, path, b->c.level, BTREE_NODE_INTENT_LOCKED);
path->l[b->c.level].lock_seq = six_lock_seq(&b->c.lock); path->l[b->c.level].lock_seq = six_lock_seq(&b->c.lock);
path->l[b->c.level].b = b; path->l[b->c.level].b = b;
bch2_btree_node_lock_write_nofail(&trans, path, &b->c); bch2_btree_node_lock_write_nofail(trans, path, &b->c);
mutex_lock(&c->btree_interior_update_lock); mutex_lock(&c->btree_interior_update_lock);
@ -729,8 +728,8 @@ err:
six_unlock_write(&b->c.lock); six_unlock_write(&b->c.lock);
btree_node_write_if_need(c, b, SIX_LOCK_intent); btree_node_write_if_need(c, b, SIX_LOCK_intent);
btree_node_unlock(&trans, path, b->c.level); btree_node_unlock(trans, path, b->c.level);
bch2_path_put(&trans, path, true); bch2_path_put(trans, path, true);
} }
bch2_journal_pin_drop(&c->journal, &as->journal); bch2_journal_pin_drop(&c->journal, &as->journal);
@ -750,7 +749,7 @@ err:
for (i = 0; i < as->nr_new_nodes; i++) { for (i = 0; i < as->nr_new_nodes; i++) {
b = as->new_nodes[i]; b = as->new_nodes[i];
btree_node_lock_nopath_nofail(&trans, &b->c, SIX_LOCK_read); btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_read);
btree_node_write_if_need(c, b, SIX_LOCK_read); btree_node_write_if_need(c, b, SIX_LOCK_read);
six_unlock_read(&b->c.lock); six_unlock_read(&b->c.lock);
} }
@ -758,8 +757,8 @@ err:
for (i = 0; i < as->nr_open_buckets; i++) for (i = 0; i < as->nr_open_buckets; i++)
bch2_open_bucket_put(c, c->open_buckets + as->open_buckets[i]); bch2_open_bucket_put(c, c->open_buckets + as->open_buckets[i]);
bch2_btree_update_free(as, &trans); bch2_btree_update_free(as, trans);
bch2_trans_exit(&trans); bch2_trans_put(trans);
} }
static void btree_interior_update_work(struct work_struct *work) static void btree_interior_update_work(struct work_struct *work)
@ -2049,7 +2048,7 @@ static void async_btree_node_rewrite_work(struct work_struct *work)
int ret; int ret;
ret = bch2_trans_do(c, NULL, NULL, 0, ret = bch2_trans_do(c, NULL, NULL, 0,
async_btree_node_rewrite_trans(&trans, a)); async_btree_node_rewrite_trans(trans, a));
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
bch2_write_ref_put(c, BCH_WRITE_REF_node_rewrite); bch2_write_ref_put(c, BCH_WRITE_REF_node_rewrite);
@ -2365,7 +2364,7 @@ static int __bch2_btree_root_alloc(struct btree_trans *trans, enum btree_id id)
void bch2_btree_root_alloc(struct bch_fs *c, enum btree_id id) void bch2_btree_root_alloc(struct bch_fs *c, enum btree_id id)
{ {
bch2_trans_run(c, __bch2_btree_root_alloc(&trans, id)); bch2_trans_run(c, __bch2_btree_root_alloc(trans, id));
} }
void bch2_btree_updates_to_text(struct printbuf *out, struct bch_fs *c) void bch2_btree_updates_to_text(struct printbuf *out, struct bch_fs *c)

View File

@ -296,7 +296,7 @@ static int bch2_btree_write_buffer_journal_flush(struct journal *j,
mutex_lock(&wb->flush_lock); mutex_lock(&wb->flush_lock);
return bch2_trans_run(c, return bch2_trans_run(c,
__bch2_btree_write_buffer_flush(&trans, BTREE_INSERT_NOCHECK_RW, true)); __bch2_btree_write_buffer_flush(trans, BTREE_INSERT_NOCHECK_RW, true));
} }
static inline u64 btree_write_buffer_ref(int idx) static inline u64 btree_write_buffer_ref(int idx)

View File

@ -1923,7 +1923,7 @@ static int __bch2_trans_mark_dev_sb(struct btree_trans *trans,
int bch2_trans_mark_dev_sb(struct bch_fs *c, struct bch_dev *ca) int bch2_trans_mark_dev_sb(struct bch_fs *c, struct bch_dev *ca)
{ {
int ret = bch2_trans_run(c, __bch2_trans_mark_dev_sb(&trans, ca)); int ret = bch2_trans_run(c, __bch2_trans_mark_dev_sb(trans, ca));
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);

View File

@ -303,7 +303,7 @@ out:
int bch2_data_update_index_update(struct bch_write_op *op) int bch2_data_update_index_update(struct bch_write_op *op)
{ {
return bch2_trans_run(op->c, __bch2_data_update_index_update(&trans, op)); return bch2_trans_run(op->c, __bch2_data_update_index_update(trans, op));
} }
void bch2_data_update_read_done(struct data_update *m, void bch2_data_update_read_done(struct data_update *m,

View File

@ -366,7 +366,7 @@ static ssize_t bch2_read_btree(struct file *file, char __user *buf,
size_t size, loff_t *ppos) size_t size, loff_t *ppos)
{ {
struct dump_iter *i = file->private_data; struct dump_iter *i = file->private_data;
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
ssize_t ret; ssize_t ret;
@ -379,17 +379,17 @@ static ssize_t bch2_read_btree(struct file *file, char __user *buf,
if (ret) if (ret)
return ret; return ret;
bch2_trans_init(&trans, i->c, 0, 0); trans = bch2_trans_get(i->c);
ret = for_each_btree_key2(&trans, iter, i->id, i->from, ret = for_each_btree_key2(trans, iter, i->id, i->from,
BTREE_ITER_PREFETCH| BTREE_ITER_PREFETCH|
BTREE_ITER_ALL_SNAPSHOTS, k, ({ BTREE_ITER_ALL_SNAPSHOTS, k, ({
bch2_bkey_val_to_text(&i->buf, i->c, k); bch2_bkey_val_to_text(&i->buf, i->c, k);
prt_newline(&i->buf); prt_newline(&i->buf);
drop_locks_do(&trans, flush_buf(i)); drop_locks_do(trans, flush_buf(i));
})); }));
i->from = iter.pos; i->from = iter.pos;
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (!ret) if (!ret)
ret = flush_buf(i); ret = flush_buf(i);
@ -408,7 +408,7 @@ static ssize_t bch2_read_btree_formats(struct file *file, char __user *buf,
size_t size, loff_t *ppos) size_t size, loff_t *ppos)
{ {
struct dump_iter *i = file->private_data; struct dump_iter *i = file->private_data;
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter iter; struct btree_iter iter;
struct btree *b; struct btree *b;
ssize_t ret; ssize_t ret;
@ -424,26 +424,26 @@ static ssize_t bch2_read_btree_formats(struct file *file, char __user *buf,
if (bpos_eq(SPOS_MAX, i->from)) if (bpos_eq(SPOS_MAX, i->from))
return i->ret; return i->ret;
bch2_trans_init(&trans, i->c, 0, 0); trans = bch2_trans_get(i->c);
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
for_each_btree_node(&trans, iter, i->id, i->from, 0, b, ret) { for_each_btree_node(trans, iter, i->id, i->from, 0, b, ret) {
bch2_btree_node_to_text(&i->buf, i->c, b); bch2_btree_node_to_text(&i->buf, i->c, b);
i->from = !bpos_eq(SPOS_MAX, b->key.k.p) i->from = !bpos_eq(SPOS_MAX, b->key.k.p)
? bpos_successor(b->key.k.p) ? bpos_successor(b->key.k.p)
: b->key.k.p; : b->key.k.p;
ret = drop_locks_do(&trans, flush_buf(i)); ret = drop_locks_do(trans, flush_buf(i));
if (ret) if (ret)
break; break;
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (!ret) if (!ret)
ret = flush_buf(i); ret = flush_buf(i);
@ -462,7 +462,7 @@ static ssize_t bch2_read_bfloat_failed(struct file *file, char __user *buf,
size_t size, loff_t *ppos) size_t size, loff_t *ppos)
{ {
struct dump_iter *i = file->private_data; struct dump_iter *i = file->private_data;
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
ssize_t ret; ssize_t ret;
@ -475,9 +475,9 @@ static ssize_t bch2_read_bfloat_failed(struct file *file, char __user *buf,
if (ret) if (ret)
return ret; return ret;
bch2_trans_init(&trans, i->c, 0, 0); trans = bch2_trans_get(i->c);
ret = for_each_btree_key2(&trans, iter, i->id, i->from, ret = for_each_btree_key2(trans, iter, i->id, i->from,
BTREE_ITER_PREFETCH| BTREE_ITER_PREFETCH|
BTREE_ITER_ALL_SNAPSHOTS, k, ({ BTREE_ITER_ALL_SNAPSHOTS, k, ({
struct btree_path_level *l = &iter.path->l[0]; struct btree_path_level *l = &iter.path->l[0];
@ -490,11 +490,11 @@ static ssize_t bch2_read_bfloat_failed(struct file *file, char __user *buf,
} }
bch2_bfloat_to_text(&i->buf, l->b, _k); bch2_bfloat_to_text(&i->buf, l->b, _k);
drop_locks_do(&trans, flush_buf(i)); drop_locks_do(trans, flush_buf(i));
})); }));
i->from = iter.pos; i->from = iter.pos;
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (!ret) if (!ret)
ret = flush_buf(i); ret = flush_buf(i);

View File

@ -479,21 +479,19 @@ u64 bch2_dirent_lookup(struct bch_fs *c, subvol_inum dir,
const struct bch_hash_info *hash_info, const struct bch_hash_info *hash_info,
const struct qstr *name, subvol_inum *inum) const struct qstr *name, subvol_inum *inum)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
int ret; int ret;
bch2_trans_init(&trans, c, 0, 0);
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
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 (bch2_err_matches(ret, BCH_ERR_transaction_restart)) 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);
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
@ -522,7 +520,7 @@ int bch2_empty_dir_trans(struct btree_trans *trans, subvol_inum dir)
int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx) int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bkey_s_c_dirent dirent; struct bkey_s_c_dirent dirent;
@ -533,15 +531,14 @@ int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx)
int ret; int ret;
bch2_bkey_buf_init(&sk); bch2_bkey_buf_init(&sk);
bch2_trans_init(&trans, c, 0, 0);
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
ret = bch2_subvolume_get_snapshot(&trans, inum.subvol, &snapshot); ret = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot);
if (ret) if (ret)
goto err; goto err;
for_each_btree_key_upto_norestart(&trans, iter, BTREE_ID_dirents, for_each_btree_key_upto_norestart(trans, iter, BTREE_ID_dirents,
SPOS(inum.inum, ctx->pos, snapshot), SPOS(inum.inum, ctx->pos, snapshot),
POS(inum.inum, U64_MAX), 0, k, ret) { POS(inum.inum, U64_MAX), 0, k, ret) {
if (k.k->type != KEY_TYPE_dirent) if (k.k->type != KEY_TYPE_dirent)
@ -549,7 +546,7 @@ retry:
dirent = bkey_s_c_to_dirent(k); dirent = bkey_s_c_to_dirent(k);
ret = bch2_dirent_read_target(&trans, inum, dirent, &target); ret = bch2_dirent_read_target(trans, inum, dirent, &target);
if (ret < 0) if (ret < 0)
break; break;
if (ret) if (ret)
@ -558,7 +555,7 @@ retry:
/* dir_emit() can fault and block: */ /* dir_emit() can fault and block: */
bch2_bkey_buf_reassemble(&sk, c, k); bch2_bkey_buf_reassemble(&sk, c, k);
dirent = bkey_i_to_s_c_dirent(sk.k); dirent = bkey_i_to_s_c_dirent(sk.k);
bch2_trans_unlock(&trans); bch2_trans_unlock(trans);
name = bch2_dirent_get_name(dirent); name = bch2_dirent_get_name(dirent);
@ -574,16 +571,16 @@ retry:
* read_target looks up subvolumes, we can overflow paths if the * read_target looks up subvolumes, we can overflow paths if the
* directory has many subvolumes in it * directory has many subvolumes in it
*/ */
ret = btree_trans_too_many_iters(&trans); ret = btree_trans_too_many_iters(trans);
if (ret) if (ret)
break; break;
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
err: err:
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_put(trans);
bch2_bkey_buf_exit(&sk, c); bch2_bkey_buf_exit(&sk, c);
return ret; return ret;

View File

@ -476,7 +476,7 @@ err:
static int get_stripe_key(struct bch_fs *c, u64 idx, struct ec_stripe_buf *stripe) static int get_stripe_key(struct bch_fs *c, u64 idx, struct ec_stripe_buf *stripe)
{ {
return bch2_trans_run(c, get_stripe_key_trans(&trans, idx, stripe)); return bch2_trans_run(c, get_stripe_key_trans(trans, idx, stripe));
} }
/* recovery read path: */ /* recovery read path: */
@ -788,12 +788,10 @@ static void ec_stripe_delete_work(struct work_struct *work)
{ {
struct bch_fs *c = struct bch_fs *c =
container_of(work, struct bch_fs, ec_stripe_delete_work); container_of(work, struct bch_fs, ec_stripe_delete_work);
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
int ret; int ret;
u64 idx; u64 idx;
bch2_trans_init(&trans, c, 0, 0);
while (1) { while (1) {
mutex_lock(&c->ec_stripes_heap_lock); mutex_lock(&c->ec_stripes_heap_lock);
idx = stripe_idx_to_delete(c); idx = stripe_idx_to_delete(c);
@ -802,15 +800,15 @@ static void ec_stripe_delete_work(struct work_struct *work)
if (!idx) if (!idx)
break; break;
ret = commit_do(&trans, NULL, NULL, BTREE_INSERT_NOFAIL, ret = commit_do(trans, NULL, NULL, BTREE_INSERT_NOFAIL,
ec_stripe_delete(&trans, idx)); ec_stripe_delete(trans, idx));
if (ret) { if (ret) {
bch_err_fn(c, ret); bch_err_fn(c, ret);
break; break;
} }
} }
bch2_trans_exit(&trans); bch2_trans_put(trans);
bch2_write_ref_put(c, BCH_WRITE_REF_stripe_delete); bch2_write_ref_put(c, BCH_WRITE_REF_stripe_delete);
} }
@ -999,24 +997,22 @@ static int ec_stripe_update_bucket(struct btree_trans *trans, struct ec_stripe_b
static int ec_stripe_update_extents(struct bch_fs *c, struct ec_stripe_buf *s) static int ec_stripe_update_extents(struct bch_fs *c, struct ec_stripe_buf *s)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct bch_stripe *v = &bkey_i_to_stripe(&s->key)->v; struct bch_stripe *v = &bkey_i_to_stripe(&s->key)->v;
unsigned i, nr_data = v->nr_blocks - v->nr_redundant; unsigned i, nr_data = v->nr_blocks - v->nr_redundant;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c, 0, 0); ret = bch2_btree_write_buffer_flush(trans);
ret = bch2_btree_write_buffer_flush(&trans);
if (ret) if (ret)
goto err; goto err;
for (i = 0; i < nr_data; i++) { for (i = 0; i < nr_data; i++) {
ret = ec_stripe_update_bucket(&trans, s, i); ret = ec_stripe_update_bucket(trans, s, i);
if (ret) if (ret)
break; break;
} }
err: err:
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
@ -1124,7 +1120,7 @@ static void ec_stripe_create(struct ec_stripe_new *s)
ret = bch2_trans_do(c, &s->res, NULL, ret = bch2_trans_do(c, &s->res, NULL,
BTREE_INSERT_NOCHECK_RW| BTREE_INSERT_NOCHECK_RW|
BTREE_INSERT_NOFAIL, BTREE_INSERT_NOFAIL,
ec_stripe_key_update(&trans, ec_stripe_key_update(trans,
bkey_i_to_stripe(&s->new_stripe.key), bkey_i_to_stripe(&s->new_stripe.key),
!s->have_existing_stripe)); !s->have_existing_stripe));
if (ret) { if (ret) {
@ -1822,7 +1818,7 @@ void bch2_fs_ec_flush(struct bch_fs *c)
int bch2_stripes_read(struct bch_fs *c) int bch2_stripes_read(struct bch_fs *c)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
const struct bch_stripe *s; const struct bch_stripe *s;
@ -1830,9 +1826,7 @@ int bch2_stripes_read(struct bch_fs *c)
unsigned i; unsigned i;
int ret; int ret;
bch2_trans_init(&trans, c, 0, 0); for_each_btree_key(trans, iter, BTREE_ID_stripes, POS_MIN,
for_each_btree_key(&trans, iter, BTREE_ID_stripes, POS_MIN,
BTREE_ITER_PREFETCH, k, ret) { BTREE_ITER_PREFETCH, k, ret) {
if (k.k->type != KEY_TYPE_stripe) if (k.k->type != KEY_TYPE_stripe)
continue; continue;
@ -1855,9 +1849,9 @@ int bch2_stripes_read(struct bch_fs *c)
bch2_stripes_heap_insert(c, m, k.k->p.offset); bch2_stripes_heap_insert(c, m, k.k->p.offset);
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);

View File

@ -270,7 +270,7 @@ void bch2_readahead(struct readahead_control *ractl)
struct bch_inode_info *inode = to_bch_ei(ractl->mapping->host); struct bch_inode_info *inode = to_bch_ei(ractl->mapping->host);
struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct bch_io_opts opts; struct bch_io_opts opts;
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct folio *folio; struct folio *folio;
struct readpages_iter readpages_iter; struct readpages_iter readpages_iter;
int ret; int ret;
@ -280,8 +280,6 @@ void bch2_readahead(struct readahead_control *ractl)
ret = readpages_iter_init(&readpages_iter, ractl); ret = readpages_iter_init(&readpages_iter, ractl);
BUG_ON(ret); BUG_ON(ret);
bch2_trans_init(&trans, c, 0, 0);
bch2_pagecache_add_get(inode); bch2_pagecache_add_get(inode);
while ((folio = readpage_iter_peek(&readpages_iter))) { while ((folio = readpage_iter_peek(&readpages_iter))) {
@ -300,31 +298,27 @@ void bch2_readahead(struct readahead_control *ractl)
rbio->bio.bi_end_io = bch2_readpages_end_io; rbio->bio.bi_end_io = bch2_readpages_end_io;
BUG_ON(!bio_add_folio(&rbio->bio, folio, folio_size(folio), 0)); BUG_ON(!bio_add_folio(&rbio->bio, folio, folio_size(folio), 0));
bchfs_read(&trans, rbio, inode_inum(inode), bchfs_read(trans, rbio, inode_inum(inode),
&readpages_iter); &readpages_iter);
bch2_trans_unlock(&trans); bch2_trans_unlock(trans);
} }
bch2_pagecache_add_put(inode); bch2_pagecache_add_put(inode);
bch2_trans_exit(&trans); bch2_trans_put(trans);
darray_exit(&readpages_iter.folios); darray_exit(&readpages_iter.folios);
} }
static void __bchfs_readfolio(struct bch_fs *c, struct bch_read_bio *rbio, static void __bchfs_readfolio(struct bch_fs *c, struct bch_read_bio *rbio,
subvol_inum inum, struct folio *folio) subvol_inum inum, struct folio *folio)
{ {
struct btree_trans trans;
bch2_folio_create(folio, __GFP_NOFAIL); bch2_folio_create(folio, __GFP_NOFAIL);
rbio->bio.bi_opf = REQ_OP_READ|REQ_SYNC; rbio->bio.bi_opf = REQ_OP_READ|REQ_SYNC;
rbio->bio.bi_iter.bi_sector = folio_sector(folio); rbio->bio.bi_iter.bi_sector = folio_sector(folio);
BUG_ON(!bio_add_folio(&rbio->bio, folio, folio_size(folio), 0)); BUG_ON(!bio_add_folio(&rbio->bio, folio, folio_size(folio), 0));
bch2_trans_init(&trans, c, 0, 0); bch2_trans_run(c, (bchfs_read(trans, rbio, inum, NULL), 0));
bchfs_read(&trans, rbio, inum, NULL);
bch2_trans_exit(&trans);
} }
static void bch2_read_single_folio_end_io(struct bio *bio) static void bch2_read_single_folio_end_io(struct bio *bio)

View File

@ -234,23 +234,21 @@ static bool bch2_check_range_allocated(struct bch_fs *c, subvol_inum inum,
u64 offset, u64 size, u64 offset, u64 size,
unsigned nr_replicas, bool compressed) unsigned nr_replicas, bool compressed)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
u64 end = offset + size; u64 end = offset + size;
u32 snapshot; u32 snapshot;
bool ret = true; bool ret = true;
int err; int err;
bch2_trans_init(&trans, c, 0, 0);
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
err = bch2_subvolume_get_snapshot(&trans, inum.subvol, &snapshot); err = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot);
if (err) if (err)
goto err; goto err;
for_each_btree_key_norestart(&trans, iter, BTREE_ID_extents, for_each_btree_key_norestart(trans, iter, BTREE_ID_extents,
SPOS(inum.inum, offset, snapshot), SPOS(inum.inum, offset, snapshot),
BTREE_ITER_SLOTS, k, err) { BTREE_ITER_SLOTS, k, err) {
if (bkey_ge(bkey_start_pos(k.k), POS(inum.inum, end))) if (bkey_ge(bkey_start_pos(k.k), POS(inum.inum, end)))
@ -265,11 +263,11 @@ retry:
} }
offset = iter.pos.offset; offset = iter.pos.offset;
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
err: err:
if (bch2_err_matches(err, BCH_ERR_transaction_restart)) if (bch2_err_matches(err, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_put(trans);
return err ? false : ret; return err ? false : ret;
} }

View File

@ -182,7 +182,7 @@ static void __bch2_folio_set(struct folio *folio,
int bch2_folio_set(struct bch_fs *c, subvol_inum inum, int bch2_folio_set(struct bch_fs *c, subvol_inum inum,
struct folio **fs, unsigned nr_folios) struct folio **fs, unsigned nr_folios)
{ {
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bch_folio *s; struct bch_folio *s;
@ -204,15 +204,15 @@ int bch2_folio_set(struct bch_fs *c, subvol_inum inum,
return 0; return 0;
folio_idx = 0; folio_idx = 0;
bch2_trans_init(&trans, c, 0, 0); trans = bch2_trans_get(c);
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
ret = bch2_subvolume_get_snapshot(&trans, inum.subvol, &snapshot); ret = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot);
if (ret) if (ret)
goto err; goto err;
for_each_btree_key_norestart(&trans, iter, BTREE_ID_extents, for_each_btree_key_norestart(trans, iter, BTREE_ID_extents,
SPOS(inum.inum, offset, snapshot), SPOS(inum.inum, offset, snapshot),
BTREE_ITER_SLOTS, k, ret) { BTREE_ITER_SLOTS, k, ret) {
unsigned nr_ptrs = bch2_bkey_nr_ptrs_fully_allocated(k); unsigned nr_ptrs = bch2_bkey_nr_ptrs_fully_allocated(k);
@ -243,11 +243,11 @@ retry:
} }
offset = iter.pos.offset; offset = iter.pos.offset;
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
err: err:
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }

View File

@ -207,31 +207,29 @@ static inline int range_has_data(struct bch_fs *c, u32 subvol,
struct bpos start, struct bpos start,
struct bpos end) struct bpos end)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c, 0, 0);
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
ret = bch2_subvolume_get_snapshot(&trans, subvol, &start.snapshot); ret = bch2_subvolume_get_snapshot(trans, subvol, &start.snapshot);
if (ret) if (ret)
goto err; goto err;
for_each_btree_key_upto_norestart(&trans, iter, BTREE_ID_extents, start, end, 0, k, ret) for_each_btree_key_upto_norestart(trans, iter, BTREE_ID_extents, start, end, 0, k, ret)
if (bkey_extent_is_data(k.k) && !bkey_extent_is_unwritten(k)) { if (bkey_extent_is_data(k.k) && !bkey_extent_is_unwritten(k)) {
ret = 1; ret = 1;
break; break;
} }
start = iter.pos; start = iter.pos;
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
err: err:
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
@ -582,16 +580,15 @@ static int __bchfs_fallocate(struct bch_inode_info *inode, int mode,
u64 start_sector, u64 end_sector) u64 start_sector, u64 end_sector)
{ {
struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bpos end_pos = POS(inode->v.i_ino, end_sector); struct bpos end_pos = POS(inode->v.i_ino, end_sector);
struct bch_io_opts opts; struct bch_io_opts opts;
int ret = 0; int ret = 0;
bch2_inode_opts_get(&opts, c, &inode->ei_inode); bch2_inode_opts_get(&opts, c, &inode->ei_inode);
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 512);
bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents, bch2_trans_iter_init(trans, &iter, BTREE_ID_extents,
POS(inode->v.i_ino, start_sector), POS(inode->v.i_ino, start_sector),
BTREE_ITER_SLOTS|BTREE_ITER_INTENT); BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
@ -604,9 +601,9 @@ static int __bchfs_fallocate(struct bch_inode_info *inode, int mode,
u64 hole_start, hole_end; u64 hole_start, hole_end;
u32 snapshot; u32 snapshot;
bch2_trans_begin(&trans); bch2_trans_begin(trans);
ret = bch2_subvolume_get_snapshot(&trans, ret = bch2_subvolume_get_snapshot(trans,
inode->ei_subvol, &snapshot); inode->ei_subvol, &snapshot);
if (ret) if (ret)
goto bkey_err; goto bkey_err;
@ -643,7 +640,7 @@ static int __bchfs_fallocate(struct bch_inode_info *inode, int mode,
&hole_start, &hole_start,
&hole_end, &hole_end,
opts.data_replicas, true)) opts.data_replicas, true))
ret = drop_locks_do(&trans, ret = drop_locks_do(trans,
(bch2_clamp_data_hole(&inode->v, (bch2_clamp_data_hole(&inode->v,
&hole_start, &hole_start,
&hole_end, &hole_end,
@ -666,7 +663,7 @@ static int __bchfs_fallocate(struct bch_inode_info *inode, int mode,
goto bkey_err; goto bkey_err;
} }
ret = bch2_extent_fallocate(&trans, inode_inum(inode), &iter, ret = bch2_extent_fallocate(trans, inode_inum(inode), &iter,
sectors, opts, &i_sectors_delta, sectors, opts, &i_sectors_delta,
writepoint_hashed((unsigned long) current)); writepoint_hashed((unsigned long) current));
if (ret) if (ret)
@ -674,7 +671,7 @@ static int __bchfs_fallocate(struct bch_inode_info *inode, int mode,
bch2_i_sectors_acct(c, inode, &quota_res, i_sectors_delta); bch2_i_sectors_acct(c, inode, &quota_res, i_sectors_delta);
drop_locks_do(&trans, drop_locks_do(trans,
(bch2_mark_pagecache_reserved(inode, hole_start, iter.pos.offset), 0)); (bch2_mark_pagecache_reserved(inode, hole_start, iter.pos.offset), 0));
bkey_err: bkey_err:
bch2_quota_reservation_put(c, inode, &quota_res); bch2_quota_reservation_put(c, inode, &quota_res);
@ -686,14 +683,14 @@ bkey_err:
struct quota_res quota_res = { 0 }; struct quota_res quota_res = { 0 };
s64 i_sectors_delta = 0; s64 i_sectors_delta = 0;
bch2_fpunch_at(&trans, &iter, inode_inum(inode), bch2_fpunch_at(trans, &iter, inode_inum(inode),
end_sector, &i_sectors_delta); end_sector, &i_sectors_delta);
bch2_i_sectors_acct(c, inode, &quota_res, i_sectors_delta); bch2_i_sectors_acct(c, inode, &quota_res, i_sectors_delta);
bch2_quota_reservation_put(c, inode, &quota_res); bch2_quota_reservation_put(c, inode, &quota_res);
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
@ -799,26 +796,24 @@ static int quota_reserve_range(struct bch_inode_info *inode,
u64 start, u64 end) u64 start, u64 end)
{ {
struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
u32 snapshot; u32 snapshot;
u64 sectors = end - start; u64 sectors = end - start;
u64 pos = start; u64 pos = start;
int ret; int ret;
bch2_trans_init(&trans, c, 0, 0);
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
ret = bch2_subvolume_get_snapshot(&trans, inode->ei_subvol, &snapshot); ret = bch2_subvolume_get_snapshot(trans, inode->ei_subvol, &snapshot);
if (ret) if (ret)
goto err; goto err;
bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents, bch2_trans_iter_init(trans, &iter, BTREE_ID_extents,
SPOS(inode->v.i_ino, pos, snapshot), 0); SPOS(inode->v.i_ino, pos, snapshot), 0);
while (!(ret = btree_trans_too_many_iters(&trans)) && while (!(ret = btree_trans_too_many_iters(trans)) &&
(k = bch2_btree_iter_peek_upto(&iter, POS(inode->v.i_ino, end - 1))).k && (k = bch2_btree_iter_peek_upto(&iter, POS(inode->v.i_ino, end - 1))).k &&
!(ret = bkey_err(k))) { !(ret = bkey_err(k))) {
if (bkey_extent_is_allocation(k.k)) { if (bkey_extent_is_allocation(k.k)) {
@ -830,17 +825,14 @@ retry:
bch2_btree_iter_advance(&iter); bch2_btree_iter_advance(&iter);
} }
pos = iter.pos.offset; pos = iter.pos.offset;
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
err: err:
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (ret) return ret ?: bch2_quota_reservation_add(c, inode, res, sectors, true);
return ret;
return bch2_quota_reservation_add(c, inode, res, sectors, true);
} }
loff_t bch2_remap_file_range(struct file *file_src, loff_t pos_src, loff_t bch2_remap_file_range(struct file *file_src, loff_t pos_src,
@ -933,7 +925,7 @@ static loff_t bch2_seek_data(struct file *file, u64 offset)
{ {
struct bch_inode_info *inode = file_bch_inode(file); struct bch_inode_info *inode = file_bch_inode(file);
struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
subvol_inum inum = inode_inum(inode); subvol_inum inum = inode_inum(inode);
@ -945,15 +937,15 @@ static loff_t bch2_seek_data(struct file *file, u64 offset)
if (offset >= isize) if (offset >= isize)
return -ENXIO; return -ENXIO;
bch2_trans_init(&trans, c, 0, 0); trans = bch2_trans_get(c);
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
ret = bch2_subvolume_get_snapshot(&trans, inum.subvol, &snapshot); ret = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot);
if (ret) if (ret)
goto err; goto err;
for_each_btree_key_upto_norestart(&trans, iter, BTREE_ID_extents, for_each_btree_key_upto_norestart(trans, iter, BTREE_ID_extents,
SPOS(inode->v.i_ino, offset >> 9, snapshot), SPOS(inode->v.i_ino, offset >> 9, snapshot),
POS(inode->v.i_ino, U64_MAX), POS(inode->v.i_ino, U64_MAX),
0, k, ret) { 0, k, ret) {
@ -963,12 +955,12 @@ retry:
} else if (k.k->p.offset >> 9 > isize) } else if (k.k->p.offset >> 9 > isize)
break; break;
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
err: err:
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (ret) if (ret)
return ret; return ret;
@ -986,7 +978,7 @@ static loff_t bch2_seek_hole(struct file *file, u64 offset)
{ {
struct bch_inode_info *inode = file_bch_inode(file); struct bch_inode_info *inode = file_bch_inode(file);
struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
subvol_inum inum = inode_inum(inode); subvol_inum inum = inode_inum(inode);
@ -998,15 +990,15 @@ static loff_t bch2_seek_hole(struct file *file, u64 offset)
if (offset >= isize) if (offset >= isize)
return -ENXIO; return -ENXIO;
bch2_trans_init(&trans, c, 0, 0); trans = bch2_trans_get(c);
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
ret = bch2_subvolume_get_snapshot(&trans, inum.subvol, &snapshot); ret = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot);
if (ret) if (ret)
goto err; goto err;
for_each_btree_key_norestart(&trans, iter, BTREE_ID_extents, for_each_btree_key_norestart(trans, iter, BTREE_ID_extents,
SPOS(inode->v.i_ino, offset >> 9, snapshot), SPOS(inode->v.i_ino, offset >> 9, snapshot),
BTREE_ITER_SLOTS, k, ret) { BTREE_ITER_SLOTS, k, ret) {
if (k.k->p.inode != inode->v.i_ino) { if (k.k->p.inode != inode->v.i_ino) {
@ -1024,12 +1016,12 @@ retry:
offset = max(offset, bkey_start_offset(k.k) << 9); offset = max(offset, bkey_start_offset(k.k) << 9);
} }
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
err: err:
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (ret) if (ret)
return ret; return ret;

View File

@ -82,29 +82,27 @@ int __must_check bch2_write_inode(struct bch_fs *c,
inode_set_fn set, inode_set_fn set,
void *p, unsigned fields) void *p, unsigned fields)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter = { NULL }; struct btree_iter iter = { NULL };
struct bch_inode_unpacked inode_u; struct bch_inode_unpacked inode_u;
int ret; int ret;
bch2_trans_init(&trans, c, 0, 512);
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
ret = bch2_inode_peek(&trans, &iter, &inode_u, inode_inum(inode), ret = bch2_inode_peek(trans, &iter, &inode_u, inode_inum(inode),
BTREE_ITER_INTENT) ?: BTREE_ITER_INTENT) ?:
(set ? set(&trans, inode, &inode_u, p) : 0) ?: (set ? set(trans, inode, &inode_u, p) : 0) ?:
bch2_inode_write(&trans, &iter, &inode_u) ?: bch2_inode_write(trans, &iter, &inode_u) ?:
bch2_trans_commit(&trans, NULL, NULL, BTREE_INSERT_NOFAIL); bch2_trans_commit(trans, NULL, NULL, BTREE_INSERT_NOFAIL);
/* /*
* the btree node lock protects inode->ei_inode, not ei_update_lock; * the btree node lock protects inode->ei_inode, not ei_update_lock;
* this is important for inode updates via bchfs_write_index_update * this is important for inode updates via bchfs_write_index_update
*/ */
if (!ret) if (!ret)
bch2_inode_update_after_write(&trans, inode, &inode_u, fields); bch2_inode_update_after_write(trans, inode, &inode_u, fields);
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
@ -114,7 +112,7 @@ retry:
inode_inum(inode).subvol, inode_inum(inode).subvol,
inode_inum(inode).inum); inode_inum(inode).inum);
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
} }
@ -182,7 +180,7 @@ struct inode *bch2_vfs_inode_get(struct bch_fs *c, subvol_inum inum)
{ {
struct bch_inode_unpacked inode_u; struct bch_inode_unpacked inode_u;
struct bch_inode_info *inode; struct bch_inode_info *inode;
struct btree_trans trans; struct btree_trans *trans;
struct bch_subvolume subvol; struct bch_subvolume subvol;
int ret; int ret;
@ -196,14 +194,14 @@ struct inode *bch2_vfs_inode_get(struct bch_fs *c, subvol_inum inum)
if (!(inode->v.i_state & I_NEW)) if (!(inode->v.i_state & I_NEW))
return &inode->v; return &inode->v;
bch2_trans_init(&trans, c, 8, 0); trans = bch2_trans_get(c);
ret = lockrestart_do(&trans, ret = lockrestart_do(trans,
bch2_subvolume_get(&trans, inum.subvol, true, 0, &subvol) ?: bch2_subvolume_get(trans, inum.subvol, true, 0, &subvol) ?:
bch2_inode_find_by_inum_trans(&trans, inum, &inode_u)); bch2_inode_find_by_inum_trans(trans, inum, &inode_u));
if (!ret) if (!ret)
bch2_vfs_inode_init(&trans, inum, inode, &inode_u, &subvol); bch2_vfs_inode_init(trans, inum, inode, &inode_u, &subvol);
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (ret) { if (ret) {
iget_failed(&inode->v); iget_failed(&inode->v);
@ -226,7 +224,7 @@ __bch2_create(struct mnt_idmap *idmap,
unsigned flags) unsigned flags)
{ {
struct bch_fs *c = dir->v.i_sb->s_fs_info; struct bch_fs *c = dir->v.i_sb->s_fs_info;
struct btree_trans trans; struct btree_trans *trans;
struct bch_inode_unpacked dir_u; struct bch_inode_unpacked dir_u;
struct bch_inode_info *inode, *old; struct bch_inode_info *inode, *old;
struct bch_inode_unpacked inode_u; struct bch_inode_unpacked inode_u;
@ -256,13 +254,11 @@ __bch2_create(struct mnt_idmap *idmap,
if (!(flags & BCH_CREATE_TMPFILE)) if (!(flags & BCH_CREATE_TMPFILE))
mutex_lock(&dir->ei_update_lock); mutex_lock(&dir->ei_update_lock);
bch2_trans_init(&trans, c, 8, trans = bch2_trans_get(c);
2048 + (!(flags & BCH_CREATE_TMPFILE)
? dentry->d_name.len : 0));
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
ret = bch2_create_trans(&trans, ret = bch2_create_trans(trans,
inode_inum(dir), &dir_u, &inode_u, inode_inum(dir), &dir_u, &inode_u,
!(flags & BCH_CREATE_TMPFILE) !(flags & BCH_CREATE_TMPFILE)
? &dentry->d_name : NULL, ? &dentry->d_name : NULL,
@ -278,9 +274,9 @@ retry:
inum.subvol = inode_u.bi_subvol ?: dir->ei_subvol; inum.subvol = inode_u.bi_subvol ?: dir->ei_subvol;
inum.inum = inode_u.bi_inum; inum.inum = inode_u.bi_inum;
ret = bch2_subvolume_get(&trans, inum.subvol, true, ret = bch2_subvolume_get(trans, inum.subvol, true,
BTREE_ITER_WITH_UPDATES, &subvol) ?: BTREE_ITER_WITH_UPDATES, &subvol) ?:
bch2_trans_commit(&trans, NULL, &journal_seq, 0); bch2_trans_commit(trans, NULL, &journal_seq, 0);
if (unlikely(ret)) { if (unlikely(ret)) {
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);
@ -291,13 +287,13 @@ err_before_quota:
} }
if (!(flags & BCH_CREATE_TMPFILE)) { if (!(flags & BCH_CREATE_TMPFILE)) {
bch2_inode_update_after_write(&trans, dir, &dir_u, bch2_inode_update_after_write(trans, dir, &dir_u,
ATTR_MTIME|ATTR_CTIME); ATTR_MTIME|ATTR_CTIME);
mutex_unlock(&dir->ei_update_lock); mutex_unlock(&dir->ei_update_lock);
} }
bch2_iget5_set(&inode->v, &inum); bch2_iget5_set(&inode->v, &inum);
bch2_vfs_inode_init(&trans, inum, inode, &inode_u, &subvol); bch2_vfs_inode_init(trans, inum, inode, &inode_u, &subvol);
set_cached_acl(&inode->v, ACL_TYPE_ACCESS, acl); set_cached_acl(&inode->v, ACL_TYPE_ACCESS, acl);
set_cached_acl(&inode->v, ACL_TYPE_DEFAULT, default_acl); set_cached_acl(&inode->v, ACL_TYPE_DEFAULT, default_acl);
@ -337,7 +333,7 @@ err_before_quota:
unlock_new_inode(&inode->v); unlock_new_inode(&inode->v);
} }
bch2_trans_exit(&trans); bch2_trans_put(trans);
err: err:
posix_acl_release(default_acl); posix_acl_release(default_acl);
posix_acl_release(acl); posix_acl_release(acl);
@ -346,7 +342,7 @@ err_trans:
if (!(flags & BCH_CREATE_TMPFILE)) if (!(flags & BCH_CREATE_TMPFILE))
mutex_unlock(&dir->ei_update_lock); mutex_unlock(&dir->ei_update_lock);
bch2_trans_exit(&trans); bch2_trans_put(trans);
make_bad_inode(&inode->v); make_bad_inode(&inode->v);
iput(&inode->v); iput(&inode->v);
inode = ERR_PTR(ret); inode = ERR_PTR(ret);
@ -401,26 +397,25 @@ static int __bch2_link(struct bch_fs *c,
struct bch_inode_info *dir, struct bch_inode_info *dir,
struct dentry *dentry) struct dentry *dentry)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct bch_inode_unpacked dir_u, inode_u; struct bch_inode_unpacked dir_u, inode_u;
int ret; int ret;
mutex_lock(&inode->ei_update_lock); mutex_lock(&inode->ei_update_lock);
bch2_trans_init(&trans, c, 4, 1024);
ret = commit_do(&trans, NULL, NULL, 0, ret = commit_do(trans, NULL, NULL, 0,
bch2_link_trans(&trans, bch2_link_trans(trans,
inode_inum(dir), &dir_u, inode_inum(dir), &dir_u,
inode_inum(inode), &inode_u, inode_inum(inode), &inode_u,
&dentry->d_name)); &dentry->d_name));
if (likely(!ret)) { if (likely(!ret)) {
bch2_inode_update_after_write(&trans, dir, &dir_u, bch2_inode_update_after_write(trans, dir, &dir_u,
ATTR_MTIME|ATTR_CTIME); ATTR_MTIME|ATTR_CTIME);
bch2_inode_update_after_write(&trans, inode, &inode_u, ATTR_CTIME); bch2_inode_update_after_write(trans, inode, &inode_u, ATTR_CTIME);
} }
bch2_trans_exit(&trans); bch2_trans_put(trans);
mutex_unlock(&inode->ei_update_lock); mutex_unlock(&inode->ei_update_lock);
return ret; return ret;
} }
@ -451,24 +446,23 @@ int __bch2_unlink(struct inode *vdir, struct dentry *dentry,
struct bch_inode_info *dir = to_bch_ei(vdir); struct bch_inode_info *dir = to_bch_ei(vdir);
struct bch_inode_info *inode = to_bch_ei(dentry->d_inode); struct bch_inode_info *inode = to_bch_ei(dentry->d_inode);
struct bch_inode_unpacked dir_u, inode_u; struct bch_inode_unpacked dir_u, inode_u;
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
int ret; int ret;
bch2_lock_inodes(INODE_UPDATE_LOCK, dir, inode); bch2_lock_inodes(INODE_UPDATE_LOCK, dir, inode);
bch2_trans_init(&trans, c, 4, 1024);
ret = commit_do(&trans, NULL, NULL, ret = commit_do(trans, NULL, NULL,
BTREE_INSERT_NOFAIL, BTREE_INSERT_NOFAIL,
bch2_unlink_trans(&trans, bch2_unlink_trans(trans,
inode_inum(dir), &dir_u, inode_inum(dir), &dir_u,
&inode_u, &dentry->d_name, &inode_u, &dentry->d_name,
deleting_snapshot)); deleting_snapshot));
if (unlikely(ret)) if (unlikely(ret))
goto err; goto err;
bch2_inode_update_after_write(&trans, dir, &dir_u, bch2_inode_update_after_write(trans, dir, &dir_u,
ATTR_MTIME|ATTR_CTIME); ATTR_MTIME|ATTR_CTIME);
bch2_inode_update_after_write(&trans, inode, &inode_u, bch2_inode_update_after_write(trans, inode, &inode_u,
ATTR_MTIME); ATTR_MTIME);
if (inode_u.bi_subvol) { if (inode_u.bi_subvol) {
@ -479,8 +473,8 @@ int __bch2_unlink(struct inode *vdir, struct dentry *dentry,
set_nlink(&inode->v, 0); set_nlink(&inode->v, 0);
} }
err: err:
bch2_trans_exit(&trans);
bch2_unlock_inodes(INODE_UPDATE_LOCK, dir, inode); bch2_unlock_inodes(INODE_UPDATE_LOCK, dir, inode);
bch2_trans_put(trans);
return ret; return ret;
} }
@ -543,7 +537,7 @@ static int bch2_rename2(struct mnt_idmap *idmap,
struct bch_inode_info *dst_inode = to_bch_ei(dst_dentry->d_inode); struct bch_inode_info *dst_inode = to_bch_ei(dst_dentry->d_inode);
struct bch_inode_unpacked dst_dir_u, src_dir_u; struct bch_inode_unpacked dst_dir_u, src_dir_u;
struct bch_inode_unpacked src_inode_u, dst_inode_u; struct bch_inode_unpacked src_inode_u, dst_inode_u;
struct btree_trans trans; struct btree_trans *trans;
enum bch_rename_mode mode = flags & RENAME_EXCHANGE enum bch_rename_mode mode = flags & RENAME_EXCHANGE
? BCH_RENAME_EXCHANGE ? BCH_RENAME_EXCHANGE
: dst_dentry->d_inode : dst_dentry->d_inode
@ -560,7 +554,7 @@ static int bch2_rename2(struct mnt_idmap *idmap,
return ret; return ret;
} }
bch2_trans_init(&trans, c, 8, 2048); trans = bch2_trans_get(c);
bch2_lock_inodes(INODE_UPDATE_LOCK, bch2_lock_inodes(INODE_UPDATE_LOCK,
src_dir, src_dir,
@ -587,8 +581,8 @@ static int bch2_rename2(struct mnt_idmap *idmap,
goto err; goto err;
} }
ret = commit_do(&trans, NULL, NULL, 0, ret = commit_do(trans, NULL, NULL, 0,
bch2_rename_trans(&trans, bch2_rename_trans(trans,
inode_inum(src_dir), &src_dir_u, inode_inum(src_dir), &src_dir_u,
inode_inum(dst_dir), &dst_dir_u, inode_inum(dst_dir), &dst_dir_u,
&src_inode_u, &src_inode_u,
@ -603,21 +597,21 @@ static int bch2_rename2(struct mnt_idmap *idmap,
BUG_ON(dst_inode && BUG_ON(dst_inode &&
dst_inode->v.i_ino != dst_inode_u.bi_inum); dst_inode->v.i_ino != dst_inode_u.bi_inum);
bch2_inode_update_after_write(&trans, src_dir, &src_dir_u, bch2_inode_update_after_write(trans, src_dir, &src_dir_u,
ATTR_MTIME|ATTR_CTIME); ATTR_MTIME|ATTR_CTIME);
if (src_dir != dst_dir) if (src_dir != dst_dir)
bch2_inode_update_after_write(&trans, dst_dir, &dst_dir_u, bch2_inode_update_after_write(trans, dst_dir, &dst_dir_u,
ATTR_MTIME|ATTR_CTIME); ATTR_MTIME|ATTR_CTIME);
bch2_inode_update_after_write(&trans, src_inode, &src_inode_u, bch2_inode_update_after_write(trans, src_inode, &src_inode_u,
ATTR_CTIME); ATTR_CTIME);
if (dst_inode) if (dst_inode)
bch2_inode_update_after_write(&trans, dst_inode, &dst_inode_u, bch2_inode_update_after_write(trans, dst_inode, &dst_inode_u,
ATTR_CTIME); ATTR_CTIME);
err: err:
bch2_trans_exit(&trans); bch2_trans_put(trans);
bch2_fs_quota_transfer(c, src_inode, bch2_fs_quota_transfer(c, src_inode,
bch_qid(&src_inode->ei_inode), bch_qid(&src_inode->ei_inode),
@ -680,7 +674,7 @@ int bch2_setattr_nonsize(struct mnt_idmap *idmap,
{ {
struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct bch_qid qid; struct bch_qid qid;
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter inode_iter = { NULL }; struct btree_iter inode_iter = { NULL };
struct bch_inode_unpacked inode_u; struct bch_inode_unpacked inode_u;
struct posix_acl *acl = NULL; struct posix_acl *acl = NULL;
@ -701,13 +695,13 @@ int bch2_setattr_nonsize(struct mnt_idmap *idmap,
if (ret) if (ret)
goto err; goto err;
bch2_trans_init(&trans, c, 0, 0); trans = bch2_trans_get(c);
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
kfree(acl); kfree(acl);
acl = NULL; acl = NULL;
ret = bch2_inode_peek(&trans, &inode_iter, &inode_u, inode_inum(inode), ret = bch2_inode_peek(trans, &inode_iter, &inode_u, inode_inum(inode),
BTREE_ITER_INTENT); BTREE_ITER_INTENT);
if (ret) if (ret)
goto btree_err; goto btree_err;
@ -715,29 +709,29 @@ retry:
bch2_setattr_copy(idmap, inode, &inode_u, attr); bch2_setattr_copy(idmap, inode, &inode_u, attr);
if (attr->ia_valid & ATTR_MODE) { if (attr->ia_valid & ATTR_MODE) {
ret = bch2_acl_chmod(&trans, inode_inum(inode), &inode_u, ret = bch2_acl_chmod(trans, inode_inum(inode), &inode_u,
inode_u.bi_mode, &acl); inode_u.bi_mode, &acl);
if (ret) if (ret)
goto btree_err; goto btree_err;
} }
ret = bch2_inode_write(&trans, &inode_iter, &inode_u) ?: ret = bch2_inode_write(trans, &inode_iter, &inode_u) ?:
bch2_trans_commit(&trans, NULL, NULL, bch2_trans_commit(trans, NULL, NULL,
BTREE_INSERT_NOFAIL); BTREE_INSERT_NOFAIL);
btree_err: btree_err:
bch2_trans_iter_exit(&trans, &inode_iter); bch2_trans_iter_exit(trans, &inode_iter);
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) 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;
bch2_inode_update_after_write(&trans, inode, &inode_u, attr->ia_valid); bch2_inode_update_after_write(trans, inode, &inode_u, attr->ia_valid);
if (acl) if (acl)
set_cached_acl(&inode->v, ACL_TYPE_ACCESS, acl); set_cached_acl(&inode->v, ACL_TYPE_ACCESS, acl);
err_trans: err_trans:
bch2_trans_exit(&trans); bch2_trans_put(trans);
err: err:
mutex_unlock(&inode->ei_update_lock); mutex_unlock(&inode->ei_update_lock);
@ -879,7 +873,7 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
{ {
struct bch_fs *c = vinode->i_sb->s_fs_info; struct bch_fs *c = vinode->i_sb->s_fs_info;
struct bch_inode_info *ei = to_bch_ei(vinode); struct bch_inode_info *ei = to_bch_ei(vinode);
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bkey_buf cur, prev; struct bkey_buf cur, prev;
@ -900,18 +894,18 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info,
bch2_bkey_buf_init(&cur); bch2_bkey_buf_init(&cur);
bch2_bkey_buf_init(&prev); bch2_bkey_buf_init(&prev);
bch2_trans_init(&trans, c, 0, 0); trans = bch2_trans_get(c);
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
ret = bch2_subvolume_get_snapshot(&trans, ei->ei_subvol, &snapshot); ret = bch2_subvolume_get_snapshot(trans, ei->ei_subvol, &snapshot);
if (ret) if (ret)
goto err; goto err;
bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents, bch2_trans_iter_init(trans, &iter, BTREE_ID_extents,
SPOS(ei->v.i_ino, start, snapshot), 0); SPOS(ei->v.i_ino, start, snapshot), 0);
while (!(ret = btree_trans_too_many_iters(&trans)) && while (!(ret = btree_trans_too_many_iters(trans)) &&
(k = bch2_btree_iter_peek_upto(&iter, end)).k && (k = bch2_btree_iter_peek_upto(&iter, end)).k &&
!(ret = bkey_err(k))) { !(ret = bkey_err(k))) {
enum btree_id data_btree = BTREE_ID_extents; enum btree_id data_btree = BTREE_ID_extents;
@ -928,7 +922,7 @@ retry:
bch2_bkey_buf_reassemble(&cur, c, k); bch2_bkey_buf_reassemble(&cur, c, k);
ret = bch2_read_indirect_extent(&trans, &data_btree, ret = bch2_read_indirect_extent(trans, &data_btree,
&offset_into_extent, &cur); &offset_into_extent, &cur);
if (ret) if (ret)
break; break;
@ -947,7 +941,7 @@ retry:
cur.k->k.p.offset += cur.k->k.size; cur.k->k.p.offset += cur.k->k.size;
if (have_extent) { if (have_extent) {
bch2_trans_unlock(&trans); bch2_trans_unlock(trans);
ret = bch2_fill_extent(c, info, ret = bch2_fill_extent(c, info,
bkey_i_to_s_c(prev.k), 0); bkey_i_to_s_c(prev.k), 0);
if (ret) if (ret)
@ -961,18 +955,18 @@ retry:
POS(iter.pos.inode, iter.pos.offset + sectors)); POS(iter.pos.inode, iter.pos.offset + sectors));
} }
start = iter.pos.offset; start = iter.pos.offset;
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
err: err:
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
if (!ret && have_extent) { if (!ret && have_extent) {
bch2_trans_unlock(&trans); bch2_trans_unlock(trans);
ret = bch2_fill_extent(c, info, bkey_i_to_s_c(prev.k), ret = bch2_fill_extent(c, info, bkey_i_to_s_c(prev.k),
FIEMAP_EXTENT_LAST); FIEMAP_EXTENT_LAST);
} }
bch2_trans_exit(&trans); bch2_trans_put(trans);
bch2_bkey_buf_exit(&cur, c); bch2_bkey_buf_exit(&cur, c);
bch2_bkey_buf_exit(&prev, c); bch2_bkey_buf_exit(&prev, c);
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
@ -1230,7 +1224,7 @@ static int bch2_get_name(struct dentry *parent, char *name, struct dentry *child
struct bch_inode_info *inode = to_bch_ei(child->d_inode); struct bch_inode_info *inode = to_bch_ei(child->d_inode);
struct bch_inode_info *dir = to_bch_ei(parent->d_inode); struct bch_inode_info *dir = to_bch_ei(parent->d_inode);
struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter iter1; struct btree_iter iter1;
struct btree_iter iter2; struct btree_iter iter2;
struct bkey_s_c k; struct bkey_s_c k;
@ -1245,23 +1239,23 @@ static int bch2_get_name(struct dentry *parent, char *name, struct dentry *child
if (!S_ISDIR(dir->v.i_mode)) if (!S_ISDIR(dir->v.i_mode))
return -EINVAL; return -EINVAL;
bch2_trans_init(&trans, c, 0, 0); trans = bch2_trans_get(c);
bch2_trans_iter_init(&trans, &iter1, BTREE_ID_dirents, bch2_trans_iter_init(trans, &iter1, BTREE_ID_dirents,
POS(dir->ei_inode.bi_inum, 0), 0); POS(dir->ei_inode.bi_inum, 0), 0);
bch2_trans_iter_init(&trans, &iter2, BTREE_ID_dirents, bch2_trans_iter_init(trans, &iter2, BTREE_ID_dirents,
POS(dir->ei_inode.bi_inum, 0), 0); POS(dir->ei_inode.bi_inum, 0), 0);
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
ret = bch2_subvolume_get_snapshot(&trans, dir->ei_subvol, &snapshot); ret = bch2_subvolume_get_snapshot(trans, dir->ei_subvol, &snapshot);
if (ret) if (ret)
goto err; goto err;
bch2_btree_iter_set_snapshot(&iter1, snapshot); bch2_btree_iter_set_snapshot(&iter1, snapshot);
bch2_btree_iter_set_snapshot(&iter2, snapshot); bch2_btree_iter_set_snapshot(&iter2, snapshot);
ret = bch2_inode_find_by_inum_trans(&trans, inode_inum(inode), &inode_u); ret = bch2_inode_find_by_inum_trans(trans, inode_inum(inode), &inode_u);
if (ret) if (ret)
goto err; goto err;
@ -1279,7 +1273,7 @@ retry:
} }
d = bkey_s_c_to_dirent(k); d = bkey_s_c_to_dirent(k);
ret = bch2_dirent_read_target(&trans, inode_inum(dir), d, &target); ret = bch2_dirent_read_target(trans, inode_inum(dir), d, &target);
if (ret > 0) if (ret > 0)
ret = -BCH_ERR_ENOENT_dirent_doesnt_match_inode; ret = -BCH_ERR_ENOENT_dirent_doesnt_match_inode;
if (ret) if (ret)
@ -1301,7 +1295,7 @@ retry:
continue; continue;
d = bkey_s_c_to_dirent(k); d = bkey_s_c_to_dirent(k);
ret = bch2_dirent_read_target(&trans, inode_inum(dir), d, &target); ret = bch2_dirent_read_target(trans, inode_inum(dir), d, &target);
if (ret < 0) if (ret < 0)
break; break;
if (ret) if (ret)
@ -1325,9 +1319,9 @@ err:
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) 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);
bch2_trans_iter_exit(&trans, &iter2); bch2_trans_iter_exit(trans, &iter2);
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }

View File

@ -987,7 +987,7 @@ noinline_for_stack
int bch2_check_inodes(struct bch_fs *c) int bch2_check_inodes(struct bch_fs *c)
{ {
bool full = c->opts.fsck; bool full = c->opts.fsck;
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bch_inode_unpacked prev = { 0 }; struct bch_inode_unpacked prev = { 0 };
struct snapshots_seen s; struct snapshots_seen s;
@ -995,16 +995,15 @@ int bch2_check_inodes(struct bch_fs *c)
int ret; int ret;
snapshots_seen_init(&s); snapshots_seen_init(&s);
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0);
ret = for_each_btree_key_commit(&trans, iter, BTREE_ID_inodes, ret = for_each_btree_key_commit(trans, iter, BTREE_ID_inodes,
POS_MIN, POS_MIN,
BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k, BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k,
NULL, NULL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL, NULL, NULL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL,
check_inode(&trans, &iter, k, &prev, &s, full)); check_inode(trans, &iter, k, &prev, &s, full));
bch2_trans_exit(&trans);
snapshots_seen_exit(&s); snapshots_seen_exit(&s);
bch2_trans_put(trans);
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
return ret; return ret;
@ -1437,7 +1436,7 @@ int bch2_check_extents(struct bch_fs *c)
{ {
struct inode_walker w = inode_walker_init(); struct inode_walker w = inode_walker_init();
struct snapshots_seen s; struct snapshots_seen s;
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct extent_ends extent_ends; struct extent_ends extent_ends;
@ -1446,23 +1445,22 @@ int bch2_check_extents(struct bch_fs *c)
snapshots_seen_init(&s); snapshots_seen_init(&s);
extent_ends_init(&extent_ends); extent_ends_init(&extent_ends);
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 4096);
ret = for_each_btree_key_commit(&trans, iter, BTREE_ID_extents, ret = for_each_btree_key_commit(trans, iter, BTREE_ID_extents,
POS(BCACHEFS_ROOT_INO, 0), POS(BCACHEFS_ROOT_INO, 0),
BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k, BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k,
&res, NULL, &res, NULL,
BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL, ({ BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL, ({
bch2_disk_reservation_put(c, &res); bch2_disk_reservation_put(c, &res);
check_extent(&trans, &iter, k, &w, &s, &extent_ends); check_extent(trans, &iter, k, &w, &s, &extent_ends);
})) ?: })) ?:
check_i_sectors(&trans, &w); check_i_sectors(trans, &w);
bch2_disk_reservation_put(c, &res); bch2_disk_reservation_put(c, &res);
extent_ends_exit(&extent_ends); extent_ends_exit(&extent_ends);
inode_walker_exit(&w); inode_walker_exit(&w);
bch2_trans_exit(&trans);
snapshots_seen_exit(&s); snapshots_seen_exit(&s);
bch2_trans_put(trans);
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
@ -1803,23 +1801,22 @@ int bch2_check_dirents(struct bch_fs *c)
struct inode_walker target = inode_walker_init(); struct inode_walker target = inode_walker_init();
struct snapshots_seen s; struct snapshots_seen s;
struct bch_hash_info hash_info; struct bch_hash_info hash_info;
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
int ret = 0; int ret = 0;
snapshots_seen_init(&s); snapshots_seen_init(&s);
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0);
ret = for_each_btree_key_commit(&trans, iter, BTREE_ID_dirents, ret = for_each_btree_key_commit(trans, iter, BTREE_ID_dirents,
POS(BCACHEFS_ROOT_INO, 0), POS(BCACHEFS_ROOT_INO, 0),
BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS,
k, k,
NULL, NULL, NULL, NULL,
BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL,
check_dirent(&trans, &iter, k, &hash_info, &dir, &target, &s)); check_dirent(trans, &iter, k, &hash_info, &dir, &target, &s));
bch2_trans_exit(&trans); bch2_trans_put(trans);
snapshots_seen_exit(&s); snapshots_seen_exit(&s);
inode_walker_exit(&dir); inode_walker_exit(&dir);
inode_walker_exit(&target); inode_walker_exit(&target);
@ -1873,23 +1870,18 @@ int bch2_check_xattrs(struct bch_fs *c)
{ {
struct inode_walker inode = inode_walker_init(); struct inode_walker inode = inode_walker_init();
struct bch_hash_info hash_info; struct bch_hash_info hash_info;
struct btree_trans trans;
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0); ret = bch2_trans_run(c,
for_each_btree_key_commit(trans, iter, BTREE_ID_xattrs,
ret = for_each_btree_key_commit(&trans, iter, BTREE_ID_xattrs,
POS(BCACHEFS_ROOT_INO, 0), POS(BCACHEFS_ROOT_INO, 0),
BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS,
k, k,
NULL, NULL, NULL, NULL,
BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL,
check_xattr(&trans, &iter, k, &hash_info, &inode)); check_xattr(trans, &iter, k, &hash_info, &inode)));
bch2_trans_exit(&trans);
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
return ret; return ret;
@ -1958,7 +1950,7 @@ int bch2_check_root(struct bch_fs *c)
ret = bch2_trans_do(c, NULL, NULL, ret = bch2_trans_do(c, NULL, NULL,
BTREE_INSERT_NOFAIL| BTREE_INSERT_NOFAIL|
BTREE_INSERT_LAZY_RW, BTREE_INSERT_LAZY_RW,
check_root_trans(&trans)); check_root_trans(trans));
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
@ -2110,16 +2102,14 @@ fsck_err:
*/ */
int bch2_check_directory_structure(struct bch_fs *c) int bch2_check_directory_structure(struct bch_fs *c)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bch_inode_unpacked u; struct bch_inode_unpacked u;
pathbuf path = { 0, }; pathbuf path = { 0, };
int ret; int ret;
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0); for_each_btree_key(trans, iter, BTREE_ID_inodes, POS_MIN,
for_each_btree_key(&trans, iter, BTREE_ID_inodes, POS_MIN,
BTREE_ITER_INTENT| BTREE_ITER_INTENT|
BTREE_ITER_PREFETCH| BTREE_ITER_PREFETCH|
BTREE_ITER_ALL_SNAPSHOTS, k, ret) { BTREE_ITER_ALL_SNAPSHOTS, k, ret) {
@ -2136,12 +2126,12 @@ int bch2_check_directory_structure(struct bch_fs *c)
if (u.bi_flags & BCH_INODE_UNLINKED) if (u.bi_flags & BCH_INODE_UNLINKED)
continue; continue;
ret = check_path(&trans, &path, &u, iter.pos.snapshot); ret = check_path(trans, &path, &u, iter.pos.snapshot);
if (ret) if (ret)
break; break;
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans); bch2_trans_put(trans);
darray_exit(&path); darray_exit(&path);
if (ret) if (ret)
@ -2230,15 +2220,13 @@ static int check_nlinks_find_hardlinks(struct bch_fs *c,
struct nlink_table *t, struct nlink_table *t,
u64 start, u64 *end) u64 start, u64 *end)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bch_inode_unpacked u; struct bch_inode_unpacked u;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0); for_each_btree_key(trans, iter, BTREE_ID_inodes,
for_each_btree_key(&trans, iter, BTREE_ID_inodes,
POS(0, start), POS(0, start),
BTREE_ITER_INTENT| BTREE_ITER_INTENT|
BTREE_ITER_PREFETCH| BTREE_ITER_PREFETCH|
@ -2267,8 +2255,8 @@ static int check_nlinks_find_hardlinks(struct bch_fs *c,
} }
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (ret) if (ret)
bch_err(c, "error in fsck: btree error %i while walking inodes", ret); bch_err(c, "error in fsck: btree error %i while walking inodes", ret);
@ -2280,7 +2268,7 @@ noinline_for_stack
static int check_nlinks_walk_dirents(struct bch_fs *c, struct nlink_table *links, static int check_nlinks_walk_dirents(struct bch_fs *c, struct nlink_table *links,
u64 range_start, u64 range_end) u64 range_start, u64 range_end)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct snapshots_seen s; struct snapshots_seen s;
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
@ -2289,9 +2277,7 @@ static int check_nlinks_walk_dirents(struct bch_fs *c, struct nlink_table *links
snapshots_seen_init(&s); snapshots_seen_init(&s);
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0); for_each_btree_key(trans, iter, BTREE_ID_dirents, POS_MIN,
for_each_btree_key(&trans, iter, BTREE_ID_dirents, POS_MIN,
BTREE_ITER_INTENT| BTREE_ITER_INTENT|
BTREE_ITER_PREFETCH| BTREE_ITER_PREFETCH|
BTREE_ITER_ALL_SNAPSHOTS, k, ret) { BTREE_ITER_ALL_SNAPSHOTS, k, ret) {
@ -2311,12 +2297,12 @@ static int check_nlinks_walk_dirents(struct bch_fs *c, struct nlink_table *links
break; break;
} }
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
if (ret) if (ret)
bch_err(c, "error in fsck: btree error %i while walking dirents", ret); bch_err(c, "error in fsck: btree error %i while walking dirents", ret);
bch2_trans_exit(&trans); bch2_trans_put(trans);
snapshots_seen_exit(&s); snapshots_seen_exit(&s);
return ret; return ret;
} }
@ -2367,22 +2353,17 @@ static int check_nlinks_update_hardlinks(struct bch_fs *c,
struct nlink_table *links, struct nlink_table *links,
u64 range_start, u64 range_end) u64 range_start, u64 range_end)
{ {
struct btree_trans trans;
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
size_t idx = 0; size_t idx = 0;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0); ret = bch2_trans_run(c,
for_each_btree_key_commit(trans, iter, BTREE_ID_inodes,
ret = for_each_btree_key_commit(&trans, iter, BTREE_ID_inodes, POS(0, range_start),
POS(0, range_start), BTREE_ITER_INTENT|BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k,
BTREE_ITER_INTENT|BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k, NULL, NULL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL,
NULL, NULL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL, check_nlinks_update_inode(trans, &iter, k, links, &idx, range_end)));
check_nlinks_update_inode(&trans, &iter, k, links, &idx, range_end));
bch2_trans_exit(&trans);
if (ret < 0) { if (ret < 0) {
bch_err(c, "error in fsck: btree error %i while walking inodes", ret); bch_err(c, "error in fsck: btree error %i while walking inodes", ret);
return ret; return ret;
@ -2464,13 +2445,12 @@ int bch2_fix_reflink_p(struct bch_fs *c)
return 0; return 0;
ret = bch2_trans_run(c, ret = bch2_trans_run(c,
for_each_btree_key_commit(&trans, iter, for_each_btree_key_commit(trans, iter,
BTREE_ID_extents, POS_MIN, BTREE_ID_extents, POS_MIN,
BTREE_ITER_INTENT|BTREE_ITER_PREFETCH| BTREE_ITER_INTENT|BTREE_ITER_PREFETCH|
BTREE_ITER_ALL_SNAPSHOTS, k, BTREE_ITER_ALL_SNAPSHOTS, k,
NULL, NULL, BTREE_INSERT_NOFAIL|BTREE_INSERT_LAZY_RW, NULL, NULL, BTREE_INSERT_NOFAIL|BTREE_INSERT_LAZY_RW,
fix_reflink_p_key(&trans, &iter, k))); fix_reflink_p_key(trans, &iter, k)));
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
return ret; return ret;

View File

@ -826,7 +826,7 @@ err:
int bch2_inode_rm(struct bch_fs *c, subvol_inum inum) int bch2_inode_rm(struct bch_fs *c, subvol_inum inum)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter = { NULL }; struct btree_iter iter = { NULL };
struct bkey_i_inode_generation delete; struct bkey_i_inode_generation delete;
struct bch_inode_unpacked inode_u; struct bch_inode_unpacked inode_u;
@ -834,8 +834,6 @@ int bch2_inode_rm(struct bch_fs *c, subvol_inum inum)
u32 snapshot; u32 snapshot;
int ret; int ret;
bch2_trans_init(&trans, c, 0, 1024);
/* /*
* If this was a directory, there shouldn't be any real dirents left - * If this was a directory, there shouldn't be any real dirents left -
* but there could be whiteouts (from hash collisions) that we should * but there could be whiteouts (from hash collisions) that we should
@ -844,19 +842,19 @@ int bch2_inode_rm(struct bch_fs *c, subvol_inum inum)
* XXX: the dirent could ideally would delete whiteouts when they're no * XXX: the dirent could ideally would delete whiteouts when they're no
* longer needed * longer needed
*/ */
ret = bch2_inode_delete_keys(&trans, inum, BTREE_ID_extents) ?: ret = bch2_inode_delete_keys(trans, inum, BTREE_ID_extents) ?:
bch2_inode_delete_keys(&trans, inum, BTREE_ID_xattrs) ?: bch2_inode_delete_keys(trans, inum, BTREE_ID_xattrs) ?:
bch2_inode_delete_keys(&trans, inum, BTREE_ID_dirents); bch2_inode_delete_keys(trans, inum, BTREE_ID_dirents);
if (ret) if (ret)
goto err; goto err;
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
ret = bch2_subvolume_get_snapshot(&trans, inum.subvol, &snapshot); ret = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot);
if (ret) if (ret)
goto err; goto err;
k = bch2_bkey_get_iter(&trans, &iter, BTREE_ID_inodes, k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_inodes,
SPOS(0, inum.inum, snapshot), SPOS(0, inum.inum, snapshot),
BTREE_ITER_INTENT|BTREE_ITER_CACHED); BTREE_ITER_INTENT|BTREE_ITER_CACHED);
ret = bkey_err(k); ret = bkey_err(k);
@ -864,7 +862,7 @@ retry:
goto err; goto err;
if (!bkey_is_inode(k.k)) { if (!bkey_is_inode(k.k)) {
bch2_fs_inconsistent(trans.c, bch2_fs_inconsistent(c,
"inode %llu:%u not found when deleting", "inode %llu:%u not found when deleting",
inum.inum, snapshot); inum.inum, snapshot);
ret = -EIO; ret = -EIO;
@ -877,15 +875,15 @@ retry:
delete.k.p = iter.pos; delete.k.p = iter.pos;
delete.v.bi_generation = cpu_to_le32(inode_u.bi_generation + 1); delete.v.bi_generation = cpu_to_le32(inode_u.bi_generation + 1);
ret = bch2_trans_update(&trans, &iter, &delete.k_i, 0) ?: ret = bch2_trans_update(trans, &iter, &delete.k_i, 0) ?:
bch2_trans_commit(&trans, NULL, NULL, bch2_trans_commit(trans, NULL, NULL,
BTREE_INSERT_NOFAIL); BTREE_INSERT_NOFAIL);
err: err:
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
@ -919,7 +917,7 @@ int bch2_inode_find_by_inum(struct bch_fs *c, subvol_inum inum,
struct bch_inode_unpacked *inode) struct bch_inode_unpacked *inode)
{ {
return bch2_trans_do(c, NULL, NULL, 0, return bch2_trans_do(c, NULL, NULL, 0,
bch2_inode_find_by_inum_trans(&trans, inum, inode)); bch2_inode_find_by_inum_trans(trans, inum, inode));
} }
int bch2_inode_nlink_inc(struct bch_inode_unpacked *bi) int bch2_inode_nlink_inc(struct bch_inode_unpacked *bi)
@ -1091,14 +1089,12 @@ delete:
int bch2_delete_dead_inodes(struct bch_fs *c) int bch2_delete_dead_inodes(struct bch_fs *c)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
int ret; int ret;
bch2_trans_init(&trans, c, 0, 0); ret = bch2_btree_write_buffer_flush_sync(trans);
ret = bch2_btree_write_buffer_flush_sync(&trans);
if (ret) if (ret)
goto err; goto err;
@ -1108,26 +1104,26 @@ int bch2_delete_dead_inodes(struct bch_fs *c)
* but we can't retry because the btree write buffer won't have been * but we can't retry because the btree write buffer won't have been
* flushed and we'd spin: * flushed and we'd spin:
*/ */
for_each_btree_key(&trans, iter, BTREE_ID_deleted_inodes, POS_MIN, for_each_btree_key(trans, iter, BTREE_ID_deleted_inodes, POS_MIN,
BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k, ret) { BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k, ret) {
ret = lockrestart_do(&trans, may_delete_deleted_inode(&trans, k.k->p)); ret = lockrestart_do(trans, may_delete_deleted_inode(trans, k.k->p));
if (ret < 0) if (ret < 0)
break; break;
if (ret) { if (ret) {
if (!test_bit(BCH_FS_RW, &c->flags)) { if (!test_bit(BCH_FS_RW, &c->flags)) {
bch2_trans_unlock(&trans); bch2_trans_unlock(trans);
bch2_fs_lazy_rw(c); bch2_fs_lazy_rw(c);
} }
ret = bch2_inode_rm_snapshot(&trans, k.k->p.offset, k.k->p.snapshot); ret = bch2_inode_rm_snapshot(trans, k.k->p.offset, k.k->p.snapshot);
if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart)) if (ret && !bch2_err_matches(ret, BCH_ERR_transaction_restart))
break; break;
} }
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
err: err:
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }

View File

@ -198,19 +198,18 @@ int bch2_fpunch_at(struct btree_trans *trans, struct btree_iter *iter,
int bch2_fpunch(struct bch_fs *c, subvol_inum inum, u64 start, u64 end, int bch2_fpunch(struct bch_fs *c, subvol_inum inum, u64 start, u64 end,
s64 *i_sectors_delta) s64 *i_sectors_delta)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
int ret; int ret;
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 1024); bch2_trans_iter_init(trans, &iter, BTREE_ID_extents,
bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents,
POS(inum.inum, start), POS(inum.inum, start),
BTREE_ITER_INTENT); BTREE_ITER_INTENT);
ret = bch2_fpunch_at(&trans, &iter, inum, end, i_sectors_delta); ret = bch2_fpunch_at(trans, &iter, inum, end, i_sectors_delta);
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
ret = 0; ret = 0;
@ -289,8 +288,8 @@ int bch2_truncate(struct bch_fs *c, subvol_inum inum, u64 new_i_size, u64 *i_sec
op.v.new_i_size = cpu_to_le64(new_i_size); op.v.new_i_size = cpu_to_le64(new_i_size);
return bch2_trans_run(c, return bch2_trans_run(c,
bch2_logged_op_start(&trans, &op.k_i) ?: bch2_logged_op_start(trans, &op.k_i) ?:
__bch2_resume_logged_op_truncate(&trans, &op.k_i, i_sectors_delta)); __bch2_resume_logged_op_truncate(trans, &op.k_i, i_sectors_delta));
} }
/* finsert/fcollapse: */ /* finsert/fcollapse: */
@ -493,6 +492,6 @@ int bch2_fcollapse_finsert(struct bch_fs *c, subvol_inum inum,
op.v.pos = cpu_to_le64(insert ? U64_MAX : offset); op.v.pos = cpu_to_le64(insert ? U64_MAX : offset);
return bch2_trans_run(c, return bch2_trans_run(c,
bch2_logged_op_start(&trans, &op.k_i) ?: bch2_logged_op_start(trans, &op.k_i) ?:
__bch2_resume_logged_op_finsert(&trans, &op.k_i, i_sectors_delta)); __bch2_resume_logged_op_finsert(trans, &op.k_i, i_sectors_delta));
} }

View File

@ -359,7 +359,7 @@ static void bch2_read_retry_nodecode(struct bch_fs *c, struct bch_read_bio *rbio
struct bch_io_failures *failed, struct bch_io_failures *failed,
unsigned flags) unsigned flags)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_buf sk; struct bkey_buf sk;
struct bkey_s_c k; struct bkey_s_c k;
@ -369,9 +369,8 @@ static void bch2_read_retry_nodecode(struct bch_fs *c, struct bch_read_bio *rbio
flags |= BCH_READ_MUST_CLONE; flags |= BCH_READ_MUST_CLONE;
bch2_bkey_buf_init(&sk); bch2_bkey_buf_init(&sk);
bch2_trans_init(&trans, c, 0, 0);
bch2_trans_iter_init(&trans, &iter, rbio->data_btree, bch2_trans_iter_init(trans, &iter, rbio->data_btree,
rbio->read_pos, BTREE_ITER_SLOTS); rbio->read_pos, BTREE_ITER_SLOTS);
retry: retry:
rbio->bio.bi_status = 0; rbio->bio.bi_status = 0;
@ -382,7 +381,7 @@ retry:
bch2_bkey_buf_reassemble(&sk, c, k); bch2_bkey_buf_reassemble(&sk, c, k);
k = bkey_i_to_s_c(sk.k); k = bkey_i_to_s_c(sk.k);
bch2_trans_unlock(&trans); bch2_trans_unlock(trans);
if (!bch2_bkey_matches_ptr(c, k, if (!bch2_bkey_matches_ptr(c, k,
rbio->pick.ptr, rbio->pick.ptr,
@ -393,7 +392,7 @@ retry:
goto out; goto out;
} }
ret = __bch2_read_extent(&trans, rbio, bvec_iter, ret = __bch2_read_extent(trans, rbio, bvec_iter,
rbio->read_pos, rbio->read_pos,
rbio->data_btree, rbio->data_btree,
k, 0, failed, flags); k, 0, failed, flags);
@ -403,8 +402,8 @@ retry:
goto err; goto err;
out: out:
bch2_rbio_done(rbio); bch2_rbio_done(rbio);
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans); bch2_trans_put(trans);
bch2_bkey_buf_exit(&sk, c); bch2_bkey_buf_exit(&sk, c);
return; return;
err: err:
@ -526,7 +525,7 @@ out:
static noinline void bch2_rbio_narrow_crcs(struct bch_read_bio *rbio) static noinline void bch2_rbio_narrow_crcs(struct bch_read_bio *rbio)
{ {
bch2_trans_do(rbio->c, NULL, NULL, BTREE_INSERT_NOFAIL, bch2_trans_do(rbio->c, NULL, NULL, BTREE_INSERT_NOFAIL,
__bch2_rbio_narrow_crcs(&trans, rbio)); __bch2_rbio_narrow_crcs(trans, rbio));
} }
/* Inner part that may run in process context */ /* Inner part that may run in process context */
@ -1082,7 +1081,7 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio,
struct bvec_iter bvec_iter, subvol_inum inum, struct bvec_iter bvec_iter, subvol_inum inum,
struct bch_io_failures *failed, unsigned flags) struct bch_io_failures *failed, unsigned flags)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_buf sk; struct bkey_buf sk;
struct bkey_s_c k; struct bkey_s_c k;
@ -1092,16 +1091,15 @@ void __bch2_read(struct bch_fs *c, struct bch_read_bio *rbio,
BUG_ON(flags & BCH_READ_NODECODE); BUG_ON(flags & BCH_READ_NODECODE);
bch2_bkey_buf_init(&sk); bch2_bkey_buf_init(&sk);
bch2_trans_init(&trans, c, 0, 0);
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
iter = (struct btree_iter) { NULL }; iter = (struct btree_iter) { NULL };
ret = bch2_subvolume_get_snapshot(&trans, inum.subvol, &snapshot); ret = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot);
if (ret) if (ret)
goto err; goto err;
bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents, bch2_trans_iter_init(trans, &iter, BTREE_ID_extents,
SPOS(inum.inum, bvec_iter.bi_sector, snapshot), SPOS(inum.inum, bvec_iter.bi_sector, snapshot),
BTREE_ITER_SLOTS); BTREE_ITER_SLOTS);
while (1) { while (1) {
@ -1112,7 +1110,7 @@ retry:
* 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:
*/ */
ret = bch2_trans_relock(&trans); ret = bch2_trans_relock(trans);
if (ret) if (ret)
break; break;
@ -1130,7 +1128,7 @@ retry:
bch2_bkey_buf_reassemble(&sk, c, k); bch2_bkey_buf_reassemble(&sk, c, k);
ret = bch2_read_indirect_extent(&trans, &data_btree, ret = bch2_read_indirect_extent(trans, &data_btree,
&offset_into_extent, &sk); &offset_into_extent, &sk);
if (ret) if (ret)
break; break;
@ -1149,7 +1147,7 @@ retry:
if (bvec_iter.bi_size == bytes) if (bvec_iter.bi_size == bytes)
flags |= BCH_READ_LAST_FRAGMENT; flags |= BCH_READ_LAST_FRAGMENT;
ret = __bch2_read_extent(&trans, rbio, bvec_iter, iter.pos, ret = __bch2_read_extent(trans, rbio, bvec_iter, iter.pos,
data_btree, k, data_btree, k,
offset_into_extent, failed, flags); offset_into_extent, failed, flags);
if (ret) if (ret)
@ -1161,19 +1159,19 @@ retry:
swap(bvec_iter.bi_size, bytes); swap(bvec_iter.bi_size, bytes);
bio_advance_iter(&rbio->bio, &bvec_iter, bytes); bio_advance_iter(&rbio->bio, &bvec_iter, bytes);
ret = btree_trans_too_many_iters(&trans); ret = btree_trans_too_many_iters(trans);
if (ret) if (ret)
break; break;
} }
err: err:
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
if (bch2_err_matches(ret, BCH_ERR_transaction_restart) || if (bch2_err_matches(ret, BCH_ERR_transaction_restart) ||
ret == READ_RETRY || ret == READ_RETRY ||
ret == READ_RETRY_AVOID) ret == READ_RETRY_AVOID)
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_put(trans);
bch2_bkey_buf_exit(&sk, c); bch2_bkey_buf_exit(&sk, c);
if (ret) { if (ret) {

View File

@ -322,7 +322,7 @@ static int bch2_write_index_default(struct bch_write_op *op)
struct bkey_buf sk; struct bkey_buf sk;
struct keylist *keys = &op->insert_keys; struct keylist *keys = &op->insert_keys;
struct bkey_i *k = bch2_keylist_front(keys); struct bkey_i *k = bch2_keylist_front(keys);
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
subvol_inum inum = { subvol_inum inum = {
.subvol = op->subvol, .subvol = op->subvol,
@ -333,30 +333,29 @@ static int bch2_write_index_default(struct bch_write_op *op)
BUG_ON(!inum.subvol); BUG_ON(!inum.subvol);
bch2_bkey_buf_init(&sk); bch2_bkey_buf_init(&sk);
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 1024);
do { do {
bch2_trans_begin(&trans); bch2_trans_begin(trans);
k = bch2_keylist_front(keys); k = bch2_keylist_front(keys);
bch2_bkey_buf_copy(&sk, c, k); bch2_bkey_buf_copy(&sk, c, k);
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 (bch2_err_matches(ret, BCH_ERR_transaction_restart)) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
continue; continue;
if (ret) if (ret)
break; break;
bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents, bch2_trans_iter_init(trans, &iter, BTREE_ID_extents,
bkey_start_pos(&sk.k->k), bkey_start_pos(&sk.k->k),
BTREE_ITER_SLOTS|BTREE_ITER_INTENT); BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
ret = bch2_extent_update(&trans, inum, &iter, sk.k, ret = bch2_extent_update(trans, inum, &iter, sk.k,
&op->res, &op->res,
op->new_i_size, &op->i_sectors_delta, op->new_i_size, &op->i_sectors_delta,
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 (bch2_err_matches(ret, BCH_ERR_transaction_restart)) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
continue; continue;
@ -369,7 +368,7 @@ static int bch2_write_index_default(struct bch_write_op *op)
bch2_cut_front(iter.pos, k); bch2_cut_front(iter.pos, k);
} while (!bch2_keylist_empty(keys)); } while (!bch2_keylist_empty(keys));
bch2_trans_exit(&trans); bch2_trans_put(trans);
bch2_bkey_buf_exit(&sk, c); bch2_bkey_buf_exit(&sk, c);
return ret; return ret;
@ -1163,20 +1162,18 @@ static int bch2_nocow_write_convert_one_unwritten(struct btree_trans *trans,
static void bch2_nocow_write_convert_unwritten(struct bch_write_op *op) static void bch2_nocow_write_convert_unwritten(struct bch_write_op *op)
{ {
struct bch_fs *c = op->c; struct bch_fs *c = op->c;
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_i *orig; struct bkey_i *orig;
struct bkey_s_c k; struct bkey_s_c k;
int ret; int ret;
bch2_trans_init(&trans, c, 0, 0);
for_each_keylist_key(&op->insert_keys, orig) { for_each_keylist_key(&op->insert_keys, orig) {
ret = for_each_btree_key_upto_commit(&trans, iter, BTREE_ID_extents, ret = for_each_btree_key_upto_commit(trans, iter, BTREE_ID_extents,
bkey_start_pos(&orig->k), orig->k.p, bkey_start_pos(&orig->k), orig->k.p,
BTREE_ITER_INTENT, k, BTREE_ITER_INTENT, k,
NULL, NULL, BTREE_INSERT_NOFAIL, ({ NULL, NULL, BTREE_INSERT_NOFAIL, ({
bch2_nocow_write_convert_one_unwritten(&trans, &iter, orig, k, op->new_i_size); bch2_nocow_write_convert_one_unwritten(trans, &iter, orig, k, op->new_i_size);
})); }));
if (ret && !bch2_err_matches(ret, EROFS)) { if (ret && !bch2_err_matches(ret, EROFS)) {
@ -1194,7 +1191,7 @@ static void bch2_nocow_write_convert_unwritten(struct bch_write_op *op)
} }
} }
bch2_trans_exit(&trans); bch2_trans_put(trans);
} }
static void __bch2_nocow_write_done(struct bch_write_op *op) static void __bch2_nocow_write_done(struct bch_write_op *op)
@ -1218,7 +1215,7 @@ static void bch2_nocow_write_done(struct closure *cl)
static void bch2_nocow_write(struct bch_write_op *op) static void bch2_nocow_write(struct bch_write_op *op)
{ {
struct bch_fs *c = op->c; struct bch_fs *c = op->c;
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bkey_ptrs_c ptrs; struct bkey_ptrs_c ptrs;
@ -1235,15 +1232,15 @@ static void bch2_nocow_write(struct bch_write_op *op)
if (op->flags & BCH_WRITE_MOVE) if (op->flags & BCH_WRITE_MOVE)
return; return;
bch2_trans_init(&trans, c, 0, 0); trans = bch2_trans_get(c);
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
ret = bch2_subvolume_get_snapshot(&trans, op->subvol, &snapshot); ret = bch2_subvolume_get_snapshot(trans, op->subvol, &snapshot);
if (unlikely(ret)) if (unlikely(ret))
goto err; goto err;
bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents, bch2_trans_iter_init(trans, &iter, BTREE_ID_extents,
SPOS(op->pos.inode, op->pos.offset, snapshot), SPOS(op->pos.inode, op->pos.offset, snapshot),
BTREE_ITER_SLOTS); BTREE_ITER_SLOTS);
while (1) { while (1) {
@ -1289,7 +1286,7 @@ retry:
/* Unlock before taking nocow locks, doing IO: */ /* Unlock before taking nocow locks, doing IO: */
bkey_reassemble(op->insert_keys.top, k); bkey_reassemble(op->insert_keys.top, k);
bch2_trans_unlock(&trans); bch2_trans_unlock(trans);
bch2_cut_front(op->pos, op->insert_keys.top); bch2_cut_front(op->pos, op->insert_keys.top);
if (op->flags & BCH_WRITE_CONVERT_UNWRITTEN) if (op->flags & BCH_WRITE_CONVERT_UNWRITTEN)
@ -1338,7 +1335,7 @@ retry:
bch2_btree_iter_advance(&iter); bch2_btree_iter_advance(&iter);
} }
out: out:
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
err: err:
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
@ -1353,7 +1350,7 @@ err:
op->flags |= BCH_WRITE_DONE; op->flags |= BCH_WRITE_DONE;
} }
bch2_trans_exit(&trans); bch2_trans_put(trans);
/* fallback to cow write path? */ /* fallback to cow write path? */
if (!(op->flags & BCH_WRITE_DONE)) { if (!(op->flags & BCH_WRITE_DONE)) {
@ -1431,7 +1428,7 @@ again:
* allocations for specific disks may hang arbitrarily long: * allocations for specific disks may hang arbitrarily long:
*/ */
ret = bch2_trans_do(c, NULL, NULL, 0, ret = bch2_trans_do(c, NULL, NULL, 0,
bch2_alloc_sectors_start_trans(&trans, bch2_alloc_sectors_start_trans(trans,
op->target, op->target,
op->opts.erasure_code && !(op->flags & BCH_WRITE_CACHED), op->opts.erasure_code && !(op->flags & BCH_WRITE_CACHED),
op->write_point, op->write_point,

View File

@ -834,7 +834,7 @@ static int __bch2_set_nr_journal_buckets(struct bch_dev *ca, unsigned nr,
break; break;
ret = bch2_trans_run(c, ret = bch2_trans_run(c,
bch2_trans_mark_metadata_bucket(&trans, ca, bch2_trans_mark_metadata_bucket(trans, ca,
ob[nr_got]->bucket, BCH_DATA_journal, ob[nr_got]->bucket, BCH_DATA_journal,
ca->mi.bucket_size)); ca->mi.bucket_size));
if (ret) { if (ret) {
@ -915,7 +915,7 @@ err_unblock:
if (ret && !new_fs) if (ret && !new_fs)
for (i = 0; i < nr_got; i++) for (i = 0; i < nr_got; i++)
bch2_trans_run(c, bch2_trans_run(c,
bch2_trans_mark_metadata_bucket(&trans, ca, bch2_trans_mark_metadata_bucket(trans, ca,
bu[i], BCH_DATA_free, 0)); bu[i], BCH_DATA_free, 0));
err_free: err_free:
if (!new_fs) if (!new_fs)

View File

@ -250,20 +250,18 @@ void bch2_blacklist_entries_gc(struct work_struct *work)
struct journal_seq_blacklist_table *t; struct journal_seq_blacklist_table *t;
struct bch_sb_field_journal_seq_blacklist *bl; struct bch_sb_field_journal_seq_blacklist *bl;
struct journal_seq_blacklist_entry *src, *dst; struct journal_seq_blacklist_entry *src, *dst;
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
unsigned i, nr, new_nr; unsigned i, nr, new_nr;
int ret; int ret;
bch2_trans_init(&trans, c, 0, 0);
for (i = 0; i < BTREE_ID_NR; i++) { for (i = 0; i < BTREE_ID_NR; i++) {
struct btree_iter iter; struct btree_iter iter;
struct btree *b; struct btree *b;
bch2_trans_node_iter_init(&trans, &iter, i, POS_MIN, bch2_trans_node_iter_init(trans, &iter, i, POS_MIN,
0, 0, BTREE_ITER_PREFETCH); 0, 0, BTREE_ITER_PREFETCH);
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
b = bch2_btree_iter_peek_node(&iter); b = bch2_btree_iter_peek_node(&iter);
@ -275,10 +273,10 @@ retry:
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) 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);
} }
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (ret) if (ret)
return; return;

View File

@ -59,9 +59,9 @@ int bch2_resume_logged_ops(struct bch_fs *c)
int ret; int ret;
ret = bch2_trans_run(c, ret = bch2_trans_run(c,
for_each_btree_key2(&trans, iter, for_each_btree_key2(trans, iter,
BTREE_ID_logged_ops, POS_MIN, BTREE_ITER_PREFETCH, k, BTREE_ID_logged_ops, POS_MIN, BTREE_ITER_PREFETCH, k,
resume_logged_op(&trans, &iter, k))); resume_logged_op(trans, &iter, k)));
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
return ret; return ret;

View File

@ -151,10 +151,10 @@ int bch2_check_lrus(struct bch_fs *c)
int ret = 0; int ret = 0;
ret = bch2_trans_run(c, ret = bch2_trans_run(c,
for_each_btree_key_commit(&trans, iter, for_each_btree_key_commit(trans, iter,
BTREE_ID_lru, POS_MIN, BTREE_ITER_PREFETCH, k, BTREE_ID_lru, POS_MIN, BTREE_ITER_PREFETCH, k,
NULL, NULL, BTREE_INSERT_NOFAIL|BTREE_INSERT_LAZY_RW, NULL, NULL, BTREE_INSERT_NOFAIL|BTREE_INSERT_LAZY_RW,
bch2_check_lru_key(&trans, &iter, k, &last_flushed_pos))); bch2_check_lru_key(trans, &iter, k, &last_flushed_pos)));
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
return ret; return ret;

View File

@ -78,34 +78,32 @@ static int bch2_dev_usrdata_drop_key(struct btree_trans *trans,
static int bch2_dev_usrdata_drop(struct bch_fs *c, unsigned dev_idx, int flags) static int bch2_dev_usrdata_drop(struct bch_fs *c, unsigned dev_idx, int flags)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
enum btree_id id; enum btree_id id;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0);
for (id = 0; id < BTREE_ID_NR; id++) { for (id = 0; id < BTREE_ID_NR; id++) {
if (!btree_type_has_ptrs(id)) if (!btree_type_has_ptrs(id))
continue; continue;
ret = for_each_btree_key_commit(&trans, iter, id, POS_MIN, ret = for_each_btree_key_commit(trans, iter, id, POS_MIN,
BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k, BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k,
NULL, NULL, BTREE_INSERT_NOFAIL, NULL, NULL, BTREE_INSERT_NOFAIL,
bch2_dev_usrdata_drop_key(&trans, &iter, k, dev_idx, flags)); bch2_dev_usrdata_drop_key(trans, &iter, k, dev_idx, flags));
if (ret) if (ret)
break; break;
} }
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags) static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags)
{ {
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter iter; struct btree_iter iter;
struct closure cl; struct closure cl;
struct btree *b; struct btree *b;
@ -117,16 +115,16 @@ static int bch2_dev_metadata_drop(struct bch_fs *c, unsigned dev_idx, int flags)
if (flags & BCH_FORCE_IF_METADATA_LOST) if (flags & BCH_FORCE_IF_METADATA_LOST)
return -EINVAL; return -EINVAL;
trans = bch2_trans_get(c);
bch2_bkey_buf_init(&k); bch2_bkey_buf_init(&k);
bch2_trans_init(&trans, c, 0, 0);
closure_init_stack(&cl); closure_init_stack(&cl);
for (id = 0; id < BTREE_ID_NR; id++) { for (id = 0; id < BTREE_ID_NR; id++) {
bch2_trans_node_iter_init(&trans, &iter, id, POS_MIN, 0, 0, bch2_trans_node_iter_init(trans, &iter, id, POS_MIN, 0, 0,
BTREE_ITER_PREFETCH); BTREE_ITER_PREFETCH);
retry: retry:
ret = 0; ret = 0;
while (bch2_trans_begin(&trans), while (bch2_trans_begin(trans),
(b = bch2_btree_iter_peek_node(&iter)) && (b = bch2_btree_iter_peek_node(&iter)) &&
!(ret = PTR_ERR_OR_ZERO(b))) { !(ret = PTR_ERR_OR_ZERO(b))) {
if (!bch2_bkey_has_device_c(bkey_i_to_s_c(&b->key), dev_idx)) if (!bch2_bkey_has_device_c(bkey_i_to_s_c(&b->key), dev_idx))
@ -141,7 +139,7 @@ retry:
break; break;
} }
ret = bch2_btree_node_update_key(&trans, &iter, b, k.k, 0, false); ret = bch2_btree_node_update_key(trans, &iter, b, k.k, 0, false);
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) { if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) {
ret = 0; ret = 0;
continue; continue;
@ -157,7 +155,7 @@ next:
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) 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);
if (ret) if (ret)
goto err; goto err;
@ -166,8 +164,8 @@ next:
bch2_btree_interior_updates_flush(c); bch2_btree_interior_updates_flush(c);
ret = 0; ret = 0;
err: err:
bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&k, c); bch2_bkey_buf_exit(&k, c);
bch2_trans_put(trans);
BUG_ON(bch2_err_matches(ret, BCH_ERR_transaction_restart)); BUG_ON(bch2_err_matches(ret, BCH_ERR_transaction_restart));

View File

@ -525,7 +525,7 @@ static int __bch2_move_data(struct moving_context *ctxt,
struct bch_fs *c = ctxt->c; struct bch_fs *c = ctxt->c;
struct bch_io_opts io_opts = bch2_opts_to_inode_opts(c->opts); struct bch_io_opts io_opts = bch2_opts_to_inode_opts(c->opts);
struct bkey_buf sk; struct bkey_buf sk;
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct data_update_opts data_opts; struct data_update_opts data_opts;
@ -533,7 +533,6 @@ static int __bch2_move_data(struct moving_context *ctxt,
int ret = 0, ret2; int ret = 0, ret2;
bch2_bkey_buf_init(&sk); bch2_bkey_buf_init(&sk);
bch2_trans_init(&trans, c, 0, 0);
if (ctxt->stats) { if (ctxt->stats) {
ctxt->stats->data_type = BCH_DATA_user; ctxt->stats->data_type = BCH_DATA_user;
@ -541,15 +540,15 @@ static int __bch2_move_data(struct moving_context *ctxt,
ctxt->stats->pos = start; ctxt->stats->pos = start;
} }
bch2_trans_iter_init(&trans, &iter, btree_id, start, bch2_trans_iter_init(trans, &iter, btree_id, start,
BTREE_ITER_PREFETCH| BTREE_ITER_PREFETCH|
BTREE_ITER_ALL_SNAPSHOTS); BTREE_ITER_ALL_SNAPSHOTS);
if (ctxt->rate) if (ctxt->rate)
bch2_ratelimit_reset(ctxt->rate); bch2_ratelimit_reset(ctxt->rate);
while (!move_ratelimit(&trans, ctxt)) { while (!move_ratelimit(trans, ctxt)) {
bch2_trans_begin(&trans); bch2_trans_begin(trans);
k = bch2_btree_iter_peek(&iter); k = bch2_btree_iter_peek(&iter);
if (!k.k) if (!k.k)
@ -570,7 +569,7 @@ static int __bch2_move_data(struct moving_context *ctxt,
if (!bkey_extent_is_direct_data(k.k)) if (!bkey_extent_is_direct_data(k.k))
goto next_nondata; goto next_nondata;
ret = move_get_io_opts(&trans, &io_opts, k, &cur_inum); ret = move_get_io_opts(trans, &io_opts, k, &cur_inum);
if (ret) if (ret)
continue; continue;
@ -585,7 +584,7 @@ static int __bch2_move_data(struct moving_context *ctxt,
bch2_bkey_buf_reassemble(&sk, c, k); bch2_bkey_buf_reassemble(&sk, c, k);
k = bkey_i_to_s_c(sk.k); k = bkey_i_to_s_c(sk.k);
ret2 = bch2_move_extent(&trans, &iter, ctxt, NULL, ret2 = bch2_move_extent(trans, &iter, ctxt, NULL,
io_opts, btree_id, k, data_opts); io_opts, btree_id, k, data_opts);
if (ret2) { if (ret2) {
if (bch2_err_matches(ret2, BCH_ERR_transaction_restart)) if (bch2_err_matches(ret2, BCH_ERR_transaction_restart))
@ -593,7 +592,7 @@ static int __bch2_move_data(struct moving_context *ctxt,
if (ret2 == -ENOMEM) { if (ret2 == -ENOMEM) {
/* memory allocation failure, wait for some IO to finish */ /* memory allocation failure, wait for some IO to finish */
bch2_move_ctxt_wait_for_io(ctxt, &trans); bch2_move_ctxt_wait_for_io(ctxt, trans);
continue; continue;
} }
@ -610,8 +609,8 @@ next_nondata:
bch2_btree_iter_advance(&iter); bch2_btree_iter_advance(&iter);
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans); bch2_trans_put(trans);
bch2_bkey_buf_exit(&sk, c); bch2_bkey_buf_exit(&sk, c);
return ret; return ret;
@ -826,15 +825,14 @@ int bch2_evacuate_bucket(struct bch_fs *c,
struct write_point_specifier wp, struct write_point_specifier wp,
bool wait_on_copygc) bool wait_on_copygc)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct moving_context ctxt; struct moving_context ctxt;
int ret; int ret;
bch2_trans_init(&trans, c, 0, 0);
bch2_moving_ctxt_init(&ctxt, c, rate, stats, wp, wait_on_copygc); bch2_moving_ctxt_init(&ctxt, c, rate, stats, wp, wait_on_copygc);
ret = __bch2_evacuate_bucket(&trans, &ctxt, NULL, bucket, gen, data_opts); ret = __bch2_evacuate_bucket(trans, &ctxt, NULL, bucket, gen, data_opts);
bch2_moving_ctxt_exit(&ctxt); bch2_moving_ctxt_exit(&ctxt);
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
@ -851,14 +849,13 @@ static int bch2_move_btree(struct bch_fs *c,
{ {
bool kthread = (current->flags & PF_KTHREAD) != 0; bool kthread = (current->flags & PF_KTHREAD) != 0;
struct bch_io_opts io_opts = bch2_opts_to_inode_opts(c->opts); struct bch_io_opts io_opts = bch2_opts_to_inode_opts(c->opts);
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct btree *b; struct btree *b;
enum btree_id id; enum btree_id id;
struct data_update_opts data_opts; struct data_update_opts data_opts;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c, 0, 0);
progress_list_add(c, stats); progress_list_add(c, stats);
stats->data_type = BCH_DATA_btree; stats->data_type = BCH_DATA_btree;
@ -871,11 +868,11 @@ static int bch2_move_btree(struct bch_fs *c,
if (!bch2_btree_id_root(c, id)->b) if (!bch2_btree_id_root(c, id)->b)
continue; continue;
bch2_trans_node_iter_init(&trans, &iter, id, POS_MIN, 0, 0, bch2_trans_node_iter_init(trans, &iter, id, POS_MIN, 0, 0,
BTREE_ITER_PREFETCH); BTREE_ITER_PREFETCH);
retry: retry:
ret = 0; ret = 0;
while (bch2_trans_begin(&trans), while (bch2_trans_begin(trans),
(b = bch2_btree_iter_peek_node(&iter)) && (b = bch2_btree_iter_peek_node(&iter)) &&
!(ret = PTR_ERR_OR_ZERO(b))) { !(ret = PTR_ERR_OR_ZERO(b))) {
if (kthread && kthread_should_stop()) if (kthread && kthread_should_stop())
@ -890,7 +887,7 @@ retry:
if (!pred(c, arg, b, &io_opts, &data_opts)) if (!pred(c, arg, b, &io_opts, &data_opts))
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 (bch2_err_matches(ret, BCH_ERR_transaction_restart)) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
continue; continue;
if (ret) if (ret)
@ -901,13 +898,13 @@ next:
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) 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);
if (kthread && kthread_should_stop()) if (kthread && kthread_should_stop())
break; break;
} }
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);

View File

@ -300,7 +300,7 @@ void bch2_copygc_wait_to_text(struct printbuf *out, struct bch_fs *c)
static int bch2_copygc_thread(void *arg) static int bch2_copygc_thread(void *arg)
{ {
struct bch_fs *c = arg; struct bch_fs *c = arg;
struct btree_trans trans; struct btree_trans *trans;
struct moving_context ctxt; struct moving_context ctxt;
struct bch_move_stats move_stats; struct bch_move_stats move_stats;
struct io_clock *clock = &c->io_clock[WRITE]; struct io_clock *clock = &c->io_clock[WRITE];
@ -317,7 +317,7 @@ static int bch2_copygc_thread(void *arg)
} }
set_freezable(); set_freezable();
bch2_trans_init(&trans, c, 0, 0); trans = bch2_trans_get(c);
bch2_move_stats_init(&move_stats, "copygc"); bch2_move_stats_init(&move_stats, "copygc");
bch2_moving_ctxt_init(&ctxt, c, NULL, &move_stats, bch2_moving_ctxt_init(&ctxt, c, NULL, &move_stats,
@ -325,16 +325,16 @@ static int bch2_copygc_thread(void *arg)
false); false);
while (!ret && !kthread_should_stop()) { while (!ret && !kthread_should_stop()) {
bch2_trans_unlock(&trans); bch2_trans_unlock(trans);
cond_resched(); cond_resched();
if (!c->copy_gc_enabled) { if (!c->copy_gc_enabled) {
move_buckets_wait(&trans, &ctxt, &buckets, true); move_buckets_wait(trans, &ctxt, &buckets, true);
kthread_wait_freezable(c->copy_gc_enabled); kthread_wait_freezable(c->copy_gc_enabled);
} }
if (unlikely(freezing(current))) { if (unlikely(freezing(current))) {
move_buckets_wait(&trans, &ctxt, &buckets, true); move_buckets_wait(trans, &ctxt, &buckets, true);
__refrigerator(false); __refrigerator(false);
continue; continue;
} }
@ -345,7 +345,7 @@ static int bch2_copygc_thread(void *arg)
if (wait > clock->max_slop) { if (wait > clock->max_slop) {
c->copygc_wait_at = last; c->copygc_wait_at = last;
c->copygc_wait = last + wait; c->copygc_wait = last + wait;
move_buckets_wait(&trans, &ctxt, &buckets, true); move_buckets_wait(trans, &ctxt, &buckets, true);
trace_and_count(c, copygc_wait, c, wait, last + wait); trace_and_count(c, copygc_wait, c, wait, last + wait);
bch2_kthread_io_clock_wait(clock, last + wait, bch2_kthread_io_clock_wait(clock, last + wait,
MAX_SCHEDULE_TIMEOUT); MAX_SCHEDULE_TIMEOUT);
@ -355,15 +355,15 @@ static int bch2_copygc_thread(void *arg)
c->copygc_wait = 0; c->copygc_wait = 0;
c->copygc_running = true; c->copygc_running = true;
ret = bch2_copygc(&trans, &ctxt, &buckets); ret = bch2_copygc(trans, &ctxt, &buckets);
c->copygc_running = false; c->copygc_running = false;
wake_up(&c->copygc_running_wq); wake_up(&c->copygc_running_wq);
} }
move_buckets_wait(&trans, &ctxt, &buckets, true); move_buckets_wait(trans, &ctxt, &buckets, true);
rhashtable_destroy(&buckets.table); rhashtable_destroy(&buckets.table);
bch2_trans_exit(&trans); bch2_trans_put(trans);
bch2_moving_ctxt_exit(&ctxt); bch2_moving_ctxt_exit(&ctxt);
return 0; return 0;

View File

@ -599,7 +599,7 @@ advance:
int bch2_fs_quota_read(struct bch_fs *c) int bch2_fs_quota_read(struct bch_fs *c)
{ {
struct bch_sb_field_quota *sb_quota; struct bch_sb_field_quota *sb_quota;
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
int ret; int ret;
@ -614,16 +614,16 @@ int bch2_fs_quota_read(struct bch_fs *c)
bch2_sb_quota_read(c); bch2_sb_quota_read(c);
mutex_unlock(&c->sb_lock); mutex_unlock(&c->sb_lock);
bch2_trans_init(&trans, c, 0, 0); trans = bch2_trans_get(c);
ret = for_each_btree_key2(&trans, iter, BTREE_ID_quotas, ret = for_each_btree_key2(trans, iter, BTREE_ID_quotas,
POS_MIN, BTREE_ITER_PREFETCH, k, POS_MIN, BTREE_ITER_PREFETCH, k,
__bch2_quota_set(c, k, NULL)) ?: __bch2_quota_set(c, k, NULL)) ?:
for_each_btree_key2(&trans, iter, BTREE_ID_inodes, for_each_btree_key2(trans, iter, BTREE_ID_inodes,
POS_MIN, BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k, POS_MIN, BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k,
bch2_fs_quota_read_inode(&trans, &iter, k)); bch2_fs_quota_read_inode(trans, &iter, k));
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
@ -956,7 +956,7 @@ static int bch2_set_quota(struct super_block *sb, struct kqid qid,
new_quota.k.p = POS(qid.type, from_kqid(&init_user_ns, qid)); new_quota.k.p = POS(qid.type, from_kqid(&init_user_ns, qid));
ret = bch2_trans_do(c, NULL, NULL, 0, ret = bch2_trans_do(c, NULL, NULL, 0,
bch2_set_quota_trans(&trans, &new_quota, qdq)) ?: bch2_set_quota_trans(trans, &new_quota, qdq)) ?:
__bch2_quota_set(c, bkey_i_to_s_c(&new_quota.k_i), qdq); __bch2_quota_set(c, bkey_i_to_s_c(&new_quota.k_i), qdq);
return bch2_err_class(ret); return bch2_err_class(ret);

View File

@ -165,7 +165,7 @@ static int bch2_journal_replay(struct bch_fs *c)
(!k->allocated (!k->allocated
? BTREE_INSERT_JOURNAL_REPLAY|BCH_WATERMARK_reclaim ? BTREE_INSERT_JOURNAL_REPLAY|BCH_WATERMARK_reclaim
: 0), : 0),
bch2_journal_replay_key(&trans, k)); bch2_journal_replay_key(trans, k));
if (ret) { if (ret) {
bch_err(c, "journal replay: error while replaying key at btree %s level %u: %s", bch_err(c, "journal replay: error while replaying key at btree %s level %u: %s",
bch2_btree_ids[k->btree_id], k->level, bch2_err_str(ret)); bch2_btree_ids[k->btree_id], k->level, bch2_err_str(ret));
@ -466,7 +466,7 @@ noinline_for_stack
static int bch2_fs_upgrade_for_subvolumes(struct bch_fs *c) static int bch2_fs_upgrade_for_subvolumes(struct bch_fs *c)
{ {
int ret = bch2_trans_do(c, NULL, NULL, BTREE_INSERT_LAZY_RW, int ret = bch2_trans_do(c, NULL, NULL, BTREE_INSERT_LAZY_RW,
__bch2_fs_upgrade_for_subvolumes(&trans)); __bch2_fs_upgrade_for_subvolumes(trans));
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
return ret; return ret;
@ -1013,7 +1013,7 @@ int bch2_fs_initialize(struct bch_fs *c)
bch2_inode_init_early(c, &lostfound_inode); bch2_inode_init_early(c, &lostfound_inode);
ret = bch2_trans_do(c, NULL, NULL, 0, ret = bch2_trans_do(c, NULL, NULL, 0,
bch2_create_trans(&trans, bch2_create_trans(trans,
BCACHEFS_ROOT_SUBVOL_INUM, BCACHEFS_ROOT_SUBVOL_INUM,
&root_inode, &lostfound_inode, &root_inode, &lostfound_inode,
&lostfound, &lostfound,

View File

@ -253,7 +253,7 @@ s64 bch2_remap_range(struct bch_fs *c,
u64 remap_sectors, u64 remap_sectors,
u64 new_i_size, s64 *i_sectors_delta) u64 new_i_size, s64 *i_sectors_delta)
{ {
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter dst_iter, src_iter; struct btree_iter dst_iter, src_iter;
struct bkey_s_c src_k; struct bkey_s_c src_k;
struct bkey_buf new_dst, new_src; struct bkey_buf new_dst, new_src;
@ -275,11 +275,11 @@ s64 bch2_remap_range(struct bch_fs *c,
bch2_bkey_buf_init(&new_dst); bch2_bkey_buf_init(&new_dst);
bch2_bkey_buf_init(&new_src); bch2_bkey_buf_init(&new_src);
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 4096); trans = bch2_trans_get(c);
bch2_trans_iter_init(&trans, &src_iter, BTREE_ID_extents, src_start, bch2_trans_iter_init(trans, &src_iter, BTREE_ID_extents, src_start,
BTREE_ITER_INTENT); BTREE_ITER_INTENT);
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 || while ((ret == 0 ||
@ -287,21 +287,21 @@ s64 bch2_remap_range(struct bch_fs *c,
bkey_lt(dst_iter.pos, dst_end)) { bkey_lt(dst_iter.pos, dst_end)) {
struct disk_reservation disk_res = { 0 }; struct disk_reservation disk_res = { 0 };
bch2_trans_begin(&trans); bch2_trans_begin(trans);
if (fatal_signal_pending(current)) { if (fatal_signal_pending(current)) {
ret = -EINTR; ret = -EINTR;
break; break;
} }
ret = bch2_subvolume_get_snapshot(&trans, src_inum.subvol, ret = bch2_subvolume_get_snapshot(trans, src_inum.subvol,
&src_snapshot); &src_snapshot);
if (ret) if (ret)
continue; continue;
bch2_btree_iter_set_snapshot(&src_iter, src_snapshot); bch2_btree_iter_set_snapshot(&src_iter, src_snapshot);
ret = bch2_subvolume_get_snapshot(&trans, dst_inum.subvol, ret = bch2_subvolume_get_snapshot(trans, dst_inum.subvol,
&dst_snapshot); &dst_snapshot);
if (ret) if (ret)
continue; continue;
@ -318,7 +318,7 @@ s64 bch2_remap_range(struct bch_fs *c,
continue; continue;
if (bkey_lt(src_want, src_iter.pos)) { if (bkey_lt(src_want, src_iter.pos)) {
ret = bch2_fpunch_at(&trans, &dst_iter, dst_inum, ret = bch2_fpunch_at(trans, &dst_iter, dst_inum,
min(dst_end.offset, min(dst_end.offset,
dst_iter.pos.offset + dst_iter.pos.offset +
src_iter.pos.offset - src_want.offset), src_iter.pos.offset - src_want.offset),
@ -332,7 +332,7 @@ s64 bch2_remap_range(struct bch_fs *c,
bch2_bkey_buf_reassemble(&new_src, c, src_k); bch2_bkey_buf_reassemble(&new_src, c, src_k);
src_k = bkey_i_to_s_c(new_src.k); src_k = bkey_i_to_s_c(new_src.k);
ret = bch2_make_extent_indirect(&trans, &src_iter, ret = bch2_make_extent_indirect(trans, &src_iter,
new_src.k); new_src.k);
if (ret) if (ret)
continue; continue;
@ -360,14 +360,14 @@ s64 bch2_remap_range(struct bch_fs *c,
min(src_k.k->p.offset - src_want.offset, min(src_k.k->p.offset - src_want.offset,
dst_end.offset - dst_iter.pos.offset)); dst_end.offset - dst_iter.pos.offset));
ret = bch2_extent_update(&trans, dst_inum, &dst_iter, ret = bch2_extent_update(trans, dst_inum, &dst_iter,
new_dst.k, &disk_res, new_dst.k, &disk_res,
new_i_size, i_sectors_delta, new_i_size, i_sectors_delta,
true); true);
bch2_disk_reservation_put(c, &disk_res); bch2_disk_reservation_put(c, &disk_res);
} }
bch2_trans_iter_exit(&trans, &dst_iter); bch2_trans_iter_exit(trans, &dst_iter);
bch2_trans_iter_exit(&trans, &src_iter); bch2_trans_iter_exit(trans, &src_iter);
BUG_ON(!ret && !bkey_eq(dst_iter.pos, dst_end)); BUG_ON(!ret && !bkey_eq(dst_iter.pos, dst_end));
BUG_ON(bkey_gt(dst_iter.pos, dst_end)); BUG_ON(bkey_gt(dst_iter.pos, dst_end));
@ -379,23 +379,23 @@ s64 bch2_remap_range(struct bch_fs *c,
struct bch_inode_unpacked inode_u; struct bch_inode_unpacked inode_u;
struct btree_iter inode_iter = { NULL }; struct btree_iter inode_iter = { NULL };
bch2_trans_begin(&trans); bch2_trans_begin(trans);
ret2 = bch2_inode_peek(&trans, &inode_iter, &inode_u, ret2 = bch2_inode_peek(trans, &inode_iter, &inode_u,
dst_inum, BTREE_ITER_INTENT); dst_inum, BTREE_ITER_INTENT);
if (!ret2 && if (!ret2 &&
inode_u.bi_size < new_i_size) { inode_u.bi_size < new_i_size) {
inode_u.bi_size = new_i_size; inode_u.bi_size = new_i_size;
ret2 = bch2_inode_write(&trans, &inode_iter, &inode_u) ?: ret2 = bch2_inode_write(trans, &inode_iter, &inode_u) ?:
bch2_trans_commit(&trans, NULL, NULL, bch2_trans_commit(trans, NULL, NULL,
BTREE_INSERT_NOFAIL); BTREE_INSERT_NOFAIL);
} }
bch2_trans_iter_exit(&trans, &inode_iter); bch2_trans_iter_exit(trans, &inode_iter);
} while (bch2_err_matches(ret2, BCH_ERR_transaction_restart)); } while (bch2_err_matches(ret2, BCH_ERR_transaction_restart));
bch2_trans_exit(&trans); bch2_trans_put(trans);
bch2_bkey_buf_exit(&new_src, c); bch2_bkey_buf_exit(&new_src, c);
bch2_bkey_buf_exit(&new_dst, c); bch2_bkey_buf_exit(&new_dst, c);

View File

@ -610,11 +610,11 @@ int bch2_check_snapshot_trees(struct bch_fs *c)
int ret; int ret;
ret = bch2_trans_run(c, ret = bch2_trans_run(c,
for_each_btree_key_commit(&trans, iter, for_each_btree_key_commit(trans, iter,
BTREE_ID_snapshot_trees, POS_MIN, BTREE_ID_snapshot_trees, POS_MIN,
BTREE_ITER_PREFETCH, k, BTREE_ITER_PREFETCH, k,
NULL, NULL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL, NULL, NULL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL,
check_snapshot_tree(&trans, &iter, k))); check_snapshot_tree(trans, &iter, k)));
if (ret) if (ret)
bch_err(c, "error %i checking snapshot trees", ret); bch_err(c, "error %i checking snapshot trees", ret);
@ -883,11 +883,11 @@ int bch2_check_snapshots(struct bch_fs *c)
* the parent's depth already be correct: * the parent's depth already be correct:
*/ */
ret = bch2_trans_run(c, ret = bch2_trans_run(c,
for_each_btree_key_reverse_commit(&trans, iter, for_each_btree_key_reverse_commit(trans, iter,
BTREE_ID_snapshots, POS_MAX, BTREE_ID_snapshots, POS_MAX,
BTREE_ITER_PREFETCH, k, BTREE_ITER_PREFETCH, k,
NULL, NULL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL, NULL, NULL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL,
check_snapshot(&trans, &iter, k))); check_snapshot(trans, &iter, k)));
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
return ret; return ret;
@ -1373,7 +1373,7 @@ static int bch2_fix_child_of_deleted_snapshot(struct btree_trans *trans,
int bch2_delete_dead_snapshots(struct bch_fs *c) int bch2_delete_dead_snapshots(struct bch_fs *c)
{ {
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bkey_s_c_snapshot snap; struct bkey_s_c_snapshot snap;
@ -1390,30 +1390,30 @@ int bch2_delete_dead_snapshots(struct bch_fs *c)
} }
} }
bch2_trans_init(&trans, c, 0, 0); trans = bch2_trans_get(c);
/* /*
* For every snapshot node: If we have no live children and it's not * For every snapshot node: If we have no live children and it's not
* pointed to by a subvolume, delete it: * pointed to by a subvolume, delete it:
*/ */
ret = for_each_btree_key_commit(&trans, iter, BTREE_ID_snapshots, ret = for_each_btree_key_commit(trans, iter, BTREE_ID_snapshots,
POS_MIN, 0, k, POS_MIN, 0, k,
NULL, NULL, 0, NULL, NULL, 0,
bch2_delete_redundant_snapshot(&trans, &iter, k)); bch2_delete_redundant_snapshot(trans, &iter, k));
if (ret) { if (ret) {
bch_err_msg(c, ret, "deleting redundant snapshots"); bch_err_msg(c, ret, "deleting redundant snapshots");
goto err; goto err;
} }
for_each_btree_key2(&trans, iter, BTREE_ID_snapshots, for_each_btree_key2(trans, iter, BTREE_ID_snapshots,
POS_MIN, 0, k, POS_MIN, 0, k,
bch2_snapshot_set_equiv(&trans, k)); bch2_snapshot_set_equiv(trans, k));
if (ret) { if (ret) {
bch_err_msg(c, ret, "in bch2_snapshots_set_equiv"); bch_err_msg(c, ret, "in bch2_snapshots_set_equiv");
goto err; goto err;
} }
for_each_btree_key(&trans, iter, BTREE_ID_snapshots, for_each_btree_key(trans, iter, BTREE_ID_snapshots,
POS_MIN, 0, k, ret) { POS_MIN, 0, k, ret) {
if (k.k->type != KEY_TYPE_snapshot) if (k.k->type != KEY_TYPE_snapshot)
continue; continue;
@ -1425,7 +1425,7 @@ int bch2_delete_dead_snapshots(struct bch_fs *c)
break; break;
} }
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
if (ret) { if (ret) {
bch_err_msg(c, ret, "walking snapshots"); bch_err_msg(c, ret, "walking snapshots");
@ -1440,16 +1440,16 @@ int bch2_delete_dead_snapshots(struct bch_fs *c)
if (!btree_type_has_snapshots(id)) if (!btree_type_has_snapshots(id))
continue; continue;
ret = for_each_btree_key_commit(&trans, iter, ret = for_each_btree_key_commit(trans, iter,
id, POS_MIN, id, POS_MIN,
BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k, BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k,
&res, NULL, BTREE_INSERT_NOFAIL, &res, NULL, BTREE_INSERT_NOFAIL,
snapshot_delete_key(&trans, &iter, k, &deleted, &equiv_seen, &last_pos)) ?: snapshot_delete_key(trans, &iter, k, &deleted, &equiv_seen, &last_pos)) ?:
for_each_btree_key_commit(&trans, iter, for_each_btree_key_commit(trans, iter,
id, POS_MIN, id, POS_MIN,
BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k, BTREE_ITER_PREFETCH|BTREE_ITER_ALL_SNAPSHOTS, k,
&res, NULL, BTREE_INSERT_NOFAIL, &res, NULL, BTREE_INSERT_NOFAIL,
move_key_to_correct_snapshot(&trans, &iter, k)); move_key_to_correct_snapshot(trans, &iter, k));
bch2_disk_reservation_put(c, &res); bch2_disk_reservation_put(c, &res);
darray_exit(&equiv_seen); darray_exit(&equiv_seen);
@ -1460,7 +1460,7 @@ int bch2_delete_dead_snapshots(struct bch_fs *c)
} }
} }
for_each_btree_key(&trans, iter, BTREE_ID_snapshots, for_each_btree_key(trans, iter, BTREE_ID_snapshots,
POS_MIN, 0, k, ret) { POS_MIN, 0, k, ret) {
u32 snapshot = k.k->p.offset; u32 snapshot = k.k->p.offset;
u32 equiv = bch2_snapshot_equiv(c, snapshot); u32 equiv = bch2_snapshot_equiv(c, snapshot);
@ -1468,23 +1468,23 @@ int bch2_delete_dead_snapshots(struct bch_fs *c)
if (equiv != snapshot) if (equiv != snapshot)
snapshot_list_add(c, &deleted_interior, snapshot); snapshot_list_add(c, &deleted_interior, snapshot);
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
/* /*
* Fixing children of deleted snapshots can't be done completely * Fixing children of deleted snapshots can't be done completely
* atomically, if we crash between here and when we delete the interior * atomically, if we crash between here and when we delete the interior
* nodes some depth fields will be off: * nodes some depth fields will be off:
*/ */
ret = for_each_btree_key_commit(&trans, iter, BTREE_ID_snapshots, POS_MIN, ret = for_each_btree_key_commit(trans, iter, BTREE_ID_snapshots, POS_MIN,
BTREE_ITER_INTENT, k, BTREE_ITER_INTENT, k,
NULL, NULL, BTREE_INSERT_NOFAIL, NULL, NULL, BTREE_INSERT_NOFAIL,
bch2_fix_child_of_deleted_snapshot(&trans, &iter, k, &deleted_interior)); bch2_fix_child_of_deleted_snapshot(trans, &iter, k, &deleted_interior));
if (ret) if (ret)
goto err; goto err;
darray_for_each(deleted, i) { darray_for_each(deleted, i) {
ret = commit_do(&trans, NULL, NULL, 0, ret = commit_do(trans, NULL, NULL, 0,
bch2_snapshot_node_delete(&trans, *i)); bch2_snapshot_node_delete(trans, *i));
if (ret) { if (ret) {
bch_err_msg(c, ret, "deleting snapshot %u", *i); bch_err_msg(c, ret, "deleting snapshot %u", *i);
goto err; goto err;
@ -1492,8 +1492,8 @@ int bch2_delete_dead_snapshots(struct bch_fs *c)
} }
darray_for_each(deleted_interior, i) { darray_for_each(deleted_interior, i) {
ret = commit_do(&trans, NULL, NULL, 0, ret = commit_do(trans, NULL, NULL, 0,
bch2_snapshot_node_delete(&trans, *i)); bch2_snapshot_node_delete(trans, *i));
if (ret) { if (ret) {
bch_err_msg(c, ret, "deleting snapshot %u", *i); bch_err_msg(c, ret, "deleting snapshot %u", *i);
goto err; goto err;
@ -1504,7 +1504,7 @@ int bch2_delete_dead_snapshots(struct bch_fs *c)
err: err:
darray_exit(&deleted_interior); darray_exit(&deleted_interior);
darray_exit(&deleted); darray_exit(&deleted);
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
return ret; return ret;
@ -1671,11 +1671,11 @@ int bch2_snapshots_read(struct bch_fs *c)
int ret = 0; int ret = 0;
ret = bch2_trans_run(c, ret = bch2_trans_run(c,
for_each_btree_key2(&trans, iter, BTREE_ID_snapshots, for_each_btree_key2(trans, iter, BTREE_ID_snapshots,
POS_MIN, 0, k, POS_MIN, 0, k,
bch2_mark_snapshot(&trans, BTREE_ID_snapshots, 0, bkey_s_c_null, k, 0) ?: bch2_mark_snapshot(trans, BTREE_ID_snapshots, 0, bkey_s_c_null, k, 0) ?:
bch2_snapshot_set_equiv(&trans, k)) ?: bch2_snapshot_set_equiv(trans, k)) ?:
for_each_btree_key2(&trans, iter, BTREE_ID_snapshots, for_each_btree_key2(trans, iter, BTREE_ID_snapshots,
POS_MIN, 0, k, POS_MIN, 0, k,
(set_is_ancestor_bitmap(c, k.k->p.offset), 0))); (set_is_ancestor_bitmap(c, k.k->p.offset), 0)));
if (ret) if (ret)

View File

@ -86,10 +86,10 @@ int bch2_check_subvols(struct bch_fs *c)
int ret; int ret;
ret = bch2_trans_run(c, ret = bch2_trans_run(c,
for_each_btree_key_commit(&trans, iter, for_each_btree_key_commit(trans, iter,
BTREE_ID_subvolumes, POS_MIN, BTREE_ITER_PREFETCH, k, BTREE_ID_subvolumes, POS_MIN, BTREE_ITER_PREFETCH, k,
NULL, NULL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL, NULL, NULL, BTREE_INSERT_LAZY_RW|BTREE_INSERT_NOFAIL,
check_subvol(&trans, &iter, k))); check_subvol(trans, &iter, k)));
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
return ret; return ret;
@ -293,7 +293,7 @@ static void bch2_subvolume_wait_for_pagecache_and_delete(struct work_struct *wor
bch2_evict_subvolume_inodes(c, &s); bch2_evict_subvolume_inodes(c, &s);
for (id = s.data; id < s.data + s.nr; id++) { for (id = s.data; id < s.data + s.nr; id++) {
ret = bch2_trans_run(c, bch2_subvolume_delete(&trans, *id)); ret = bch2_trans_run(c, bch2_subvolume_delete(trans, *id));
if (ret) { if (ret) {
bch_err_msg(c, ret, "deleting subvolume %u", *id); bch_err_msg(c, ret, "deleting subvolume %u", *id);
break; break;

View File

@ -470,7 +470,6 @@ int bch2_fs_read_write_early(struct bch_fs *c)
static void __bch2_fs_free(struct bch_fs *c) static void __bch2_fs_free(struct bch_fs *c)
{ {
unsigned i; unsigned i;
int cpu;
for (i = 0; i < BCH_TIME_STAT_NR; i++) for (i = 0; i < BCH_TIME_STAT_NR; i++)
bch2_time_stats_exit(&c->times[i]); bch2_time_stats_exit(&c->times[i]);
@ -502,12 +501,7 @@ static void __bch2_fs_free(struct bch_fs *c)
percpu_free_rwsem(&c->mark_lock); percpu_free_rwsem(&c->mark_lock);
free_percpu(c->online_reserved); free_percpu(c->online_reserved);
if (c->btree_paths_bufs)
for_each_possible_cpu(cpu)
kfree(per_cpu_ptr(c->btree_paths_bufs, cpu)->path);
darray_exit(&c->btree_roots_extra); darray_exit(&c->btree_roots_extra);
free_percpu(c->btree_paths_bufs);
free_percpu(c->pcpu); free_percpu(c->pcpu);
mempool_exit(&c->large_bkey_pool); mempool_exit(&c->large_bkey_pool);
mempool_exit(&c->btree_bounce_pool); mempool_exit(&c->btree_bounce_pool);
@ -829,7 +823,6 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
BIOSET_NEED_BVECS) || BIOSET_NEED_BVECS) ||
!(c->pcpu = alloc_percpu(struct bch_fs_pcpu)) || !(c->pcpu = alloc_percpu(struct bch_fs_pcpu)) ||
!(c->online_reserved = alloc_percpu(u64)) || !(c->online_reserved = alloc_percpu(u64)) ||
!(c->btree_paths_bufs = alloc_percpu(struct btree_path_buf)) ||
mempool_init_kvpmalloc_pool(&c->btree_bounce_pool, 1, mempool_init_kvpmalloc_pool(&c->btree_bounce_pool, 1,
btree_bytes(c)) || btree_bytes(c)) ||
mempool_init_kmalloc_pool(&c->large_bkey_pool, 1, 2048) || mempool_init_kmalloc_pool(&c->large_bkey_pool, 1, 2048) ||

View File

@ -252,7 +252,7 @@ static size_t bch2_btree_cache_size(struct bch_fs *c)
static int bch2_compression_stats_to_text(struct printbuf *out, struct bch_fs *c) static int bch2_compression_stats_to_text(struct printbuf *out, struct bch_fs *c)
{ {
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
enum btree_id id; enum btree_id id;
@ -268,13 +268,13 @@ static int bch2_compression_stats_to_text(struct printbuf *out, struct bch_fs *c
if (!test_bit(BCH_FS_STARTED, &c->flags)) if (!test_bit(BCH_FS_STARTED, &c->flags))
return -EPERM; return -EPERM;
bch2_trans_init(&trans, c, 0, 0); trans = bch2_trans_get(c);
for (id = 0; id < BTREE_ID_NR; id++) { for (id = 0; id < BTREE_ID_NR; id++) {
if (!btree_type_has_ptrs(id)) if (!btree_type_has_ptrs(id))
continue; continue;
for_each_btree_key(&trans, iter, id, POS_MIN, for_each_btree_key(trans, iter, id, POS_MIN,
BTREE_ITER_ALL_SNAPSHOTS, k, ret) { BTREE_ITER_ALL_SNAPSHOTS, k, ret) {
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k); struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
const union bch_extent_entry *entry; const union bch_extent_entry *entry;
@ -308,10 +308,10 @@ static int bch2_compression_stats_to_text(struct printbuf *out, struct bch_fs *c
else if (compressed) else if (compressed)
nr_compressed_extents++; nr_compressed_extents++;
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
} }
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (ret) if (ret)
return ret; return ret;

View File

@ -31,7 +31,7 @@ static void delete_test_keys(struct bch_fs *c)
static int test_delete(struct bch_fs *c, u64 nr) static int test_delete(struct bch_fs *c, u64 nr)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_i_cookie k; struct bkey_i_cookie k;
int ret; int ret;
@ -39,44 +39,43 @@ static int test_delete(struct bch_fs *c, u64 nr)
bkey_cookie_init(&k.k_i); bkey_cookie_init(&k.k_i);
k.k.p.snapshot = U32_MAX; k.k.p.snapshot = U32_MAX;
bch2_trans_init(&trans, c, 0, 0); bch2_trans_iter_init(trans, &iter, BTREE_ID_xattrs, k.k.p,
bch2_trans_iter_init(&trans, &iter, BTREE_ID_xattrs, k.k.p,
BTREE_ITER_INTENT); BTREE_ITER_INTENT);
ret = commit_do(&trans, NULL, NULL, 0, ret = commit_do(trans, NULL, NULL, 0,
bch2_btree_iter_traverse(&iter) ?: bch2_btree_iter_traverse(&iter) ?:
bch2_trans_update(&trans, &iter, &k.k_i, 0)); bch2_trans_update(trans, &iter, &k.k_i, 0));
if (ret) { if (ret) {
bch_err_msg(c, ret, "update error"); bch_err_msg(c, ret, "update error");
goto err; goto err;
} }
pr_info("deleting once"); pr_info("deleting once");
ret = commit_do(&trans, NULL, NULL, 0, ret = commit_do(trans, NULL, NULL, 0,
bch2_btree_iter_traverse(&iter) ?: bch2_btree_iter_traverse(&iter) ?:
bch2_btree_delete_at(&trans, &iter, 0)); bch2_btree_delete_at(trans, &iter, 0));
if (ret) { if (ret) {
bch_err_msg(c, ret, "delete error (first)"); bch_err_msg(c, ret, "delete error (first)");
goto err; goto err;
} }
pr_info("deleting twice"); pr_info("deleting twice");
ret = commit_do(&trans, NULL, NULL, 0, ret = commit_do(trans, NULL, NULL, 0,
bch2_btree_iter_traverse(&iter) ?: bch2_btree_iter_traverse(&iter) ?:
bch2_btree_delete_at(&trans, &iter, 0)); bch2_btree_delete_at(trans, &iter, 0));
if (ret) { if (ret) {
bch_err_msg(c, ret, "delete error (second)"); bch_err_msg(c, ret, "delete error (second)");
goto err; goto err;
} }
err: err:
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
static int test_delete_written(struct bch_fs *c, u64 nr) static int test_delete_written(struct bch_fs *c, u64 nr)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_i_cookie k; struct bkey_i_cookie k;
int ret; int ret;
@ -84,45 +83,41 @@ static int test_delete_written(struct bch_fs *c, u64 nr)
bkey_cookie_init(&k.k_i); bkey_cookie_init(&k.k_i);
k.k.p.snapshot = U32_MAX; k.k.p.snapshot = U32_MAX;
bch2_trans_init(&trans, c, 0, 0); bch2_trans_iter_init(trans, &iter, BTREE_ID_xattrs, k.k.p,
bch2_trans_iter_init(&trans, &iter, BTREE_ID_xattrs, k.k.p,
BTREE_ITER_INTENT); BTREE_ITER_INTENT);
ret = commit_do(&trans, NULL, NULL, 0, ret = commit_do(trans, NULL, NULL, 0,
bch2_btree_iter_traverse(&iter) ?: bch2_btree_iter_traverse(&iter) ?:
bch2_trans_update(&trans, &iter, &k.k_i, 0)); bch2_trans_update(trans, &iter, &k.k_i, 0));
if (ret) { if (ret) {
bch_err_msg(c, ret, "update error"); bch_err_msg(c, ret, "update error");
goto err; goto err;
} }
bch2_trans_unlock(&trans); bch2_trans_unlock(trans);
bch2_journal_flush_all_pins(&c->journal); bch2_journal_flush_all_pins(&c->journal);
ret = commit_do(&trans, NULL, NULL, 0, ret = commit_do(trans, NULL, NULL, 0,
bch2_btree_iter_traverse(&iter) ?: bch2_btree_iter_traverse(&iter) ?:
bch2_btree_delete_at(&trans, &iter, 0)); bch2_btree_delete_at(trans, &iter, 0));
if (ret) { if (ret) {
bch_err_msg(c, ret, "delete error"); bch_err_msg(c, ret, "delete error");
goto err; goto err;
} }
err: err:
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
static int test_iterate(struct bch_fs *c, u64 nr) static int test_iterate(struct bch_fs *c, u64 nr)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter = { NULL }; struct btree_iter iter = { NULL };
struct bkey_s_c k; struct bkey_s_c k;
u64 i; u64 i;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c, 0, 0);
delete_test_keys(c); delete_test_keys(c);
pr_info("inserting test keys"); pr_info("inserting test keys");
@ -145,7 +140,7 @@ static int test_iterate(struct bch_fs *c, u64 nr)
i = 0; i = 0;
ret = for_each_btree_key2_upto(&trans, iter, BTREE_ID_xattrs, ret = for_each_btree_key2_upto(trans, iter, BTREE_ID_xattrs,
SPOS(0, 0, U32_MAX), POS(0, U64_MAX), SPOS(0, 0, U32_MAX), POS(0, U64_MAX),
0, k, ({ 0, k, ({
BUG_ON(k.k->p.offset != i++); BUG_ON(k.k->p.offset != i++);
@ -160,7 +155,7 @@ static int test_iterate(struct bch_fs *c, u64 nr)
pr_info("iterating backwards"); pr_info("iterating backwards");
ret = for_each_btree_key_reverse(&trans, iter, BTREE_ID_xattrs, ret = for_each_btree_key_reverse(trans, iter, BTREE_ID_xattrs,
SPOS(0, U64_MAX, U32_MAX), 0, k, SPOS(0, U64_MAX, U32_MAX), 0, k,
({ ({
BUG_ON(k.k->p.offset != --i); BUG_ON(k.k->p.offset != --i);
@ -173,21 +168,19 @@ static int test_iterate(struct bch_fs *c, u64 nr)
BUG_ON(i); BUG_ON(i);
err: err:
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
static int test_iterate_extents(struct bch_fs *c, u64 nr) static int test_iterate_extents(struct bch_fs *c, u64 nr)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter = { NULL }; struct btree_iter iter = { NULL };
struct bkey_s_c k; struct bkey_s_c k;
u64 i; u64 i;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c, 0, 0);
delete_test_keys(c); delete_test_keys(c);
pr_info("inserting test extents"); pr_info("inserting test extents");
@ -211,7 +204,7 @@ static int test_iterate_extents(struct bch_fs *c, u64 nr)
i = 0; i = 0;
ret = for_each_btree_key2_upto(&trans, iter, BTREE_ID_extents, ret = for_each_btree_key2_upto(trans, iter, BTREE_ID_extents,
SPOS(0, 0, U32_MAX), POS(0, U64_MAX), SPOS(0, 0, U32_MAX), POS(0, U64_MAX),
0, k, ({ 0, k, ({
BUG_ON(bkey_start_offset(k.k) != i); BUG_ON(bkey_start_offset(k.k) != i);
@ -227,7 +220,7 @@ static int test_iterate_extents(struct bch_fs *c, u64 nr)
pr_info("iterating backwards"); pr_info("iterating backwards");
ret = for_each_btree_key_reverse(&trans, iter, BTREE_ID_extents, ret = for_each_btree_key_reverse(trans, iter, BTREE_ID_extents,
SPOS(0, U64_MAX, U32_MAX), 0, k, SPOS(0, U64_MAX, U32_MAX), 0, k,
({ ({
BUG_ON(k.k->p.offset != i); BUG_ON(k.k->p.offset != i);
@ -241,21 +234,19 @@ static int test_iterate_extents(struct bch_fs *c, u64 nr)
BUG_ON(i); BUG_ON(i);
err: err:
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
static int test_iterate_slots(struct bch_fs *c, u64 nr) static int test_iterate_slots(struct bch_fs *c, u64 nr)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter = { NULL }; struct btree_iter iter = { NULL };
struct bkey_s_c k; struct bkey_s_c k;
u64 i; u64 i;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c, 0, 0);
delete_test_keys(c); delete_test_keys(c);
pr_info("inserting test keys"); pr_info("inserting test keys");
@ -278,7 +269,7 @@ static int test_iterate_slots(struct bch_fs *c, u64 nr)
i = 0; i = 0;
ret = for_each_btree_key2_upto(&trans, iter, BTREE_ID_xattrs, ret = for_each_btree_key2_upto(trans, iter, BTREE_ID_xattrs,
SPOS(0, 0, U32_MAX), POS(0, U64_MAX), SPOS(0, 0, U32_MAX), POS(0, U64_MAX),
0, k, ({ 0, k, ({
BUG_ON(k.k->p.offset != i); BUG_ON(k.k->p.offset != i);
@ -296,7 +287,7 @@ static int test_iterate_slots(struct bch_fs *c, u64 nr)
i = 0; i = 0;
ret = for_each_btree_key2_upto(&trans, iter, BTREE_ID_xattrs, ret = for_each_btree_key2_upto(trans, iter, BTREE_ID_xattrs,
SPOS(0, 0, U32_MAX), POS(0, U64_MAX), SPOS(0, 0, U32_MAX), POS(0, U64_MAX),
BTREE_ITER_SLOTS, k, ({ BTREE_ITER_SLOTS, k, ({
if (i >= nr * 2) if (i >= nr * 2)
@ -314,20 +305,18 @@ static int test_iterate_slots(struct bch_fs *c, u64 nr)
} }
ret = 0; ret = 0;
err: err:
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
static int test_iterate_slots_extents(struct bch_fs *c, u64 nr) static int test_iterate_slots_extents(struct bch_fs *c, u64 nr)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter = { NULL }; struct btree_iter iter = { NULL };
struct bkey_s_c k; struct bkey_s_c k;
u64 i; u64 i;
int ret = 0; int ret = 0;
bch2_trans_init(&trans, c, 0, 0);
delete_test_keys(c); delete_test_keys(c);
pr_info("inserting test keys"); pr_info("inserting test keys");
@ -351,7 +340,7 @@ static int test_iterate_slots_extents(struct bch_fs *c, u64 nr)
i = 0; i = 0;
ret = for_each_btree_key2_upto(&trans, iter, BTREE_ID_extents, ret = for_each_btree_key2_upto(trans, iter, BTREE_ID_extents,
SPOS(0, 0, U32_MAX), POS(0, U64_MAX), SPOS(0, 0, U32_MAX), POS(0, U64_MAX),
0, k, ({ 0, k, ({
BUG_ON(bkey_start_offset(k.k) != i + 8); BUG_ON(bkey_start_offset(k.k) != i + 8);
@ -370,7 +359,7 @@ static int test_iterate_slots_extents(struct bch_fs *c, u64 nr)
i = 0; i = 0;
ret = for_each_btree_key2_upto(&trans, iter, BTREE_ID_extents, ret = for_each_btree_key2_upto(trans, iter, BTREE_ID_extents,
SPOS(0, 0, U32_MAX), POS(0, U64_MAX), SPOS(0, 0, U32_MAX), POS(0, U64_MAX),
BTREE_ITER_SLOTS, k, ({ BTREE_ITER_SLOTS, k, ({
if (i == nr) if (i == nr)
@ -388,7 +377,7 @@ static int test_iterate_slots_extents(struct bch_fs *c, u64 nr)
} }
ret = 0; ret = 0;
err: err:
bch2_trans_exit(&trans); bch2_trans_put(trans);
return 0; return 0;
} }
@ -398,43 +387,41 @@ err:
*/ */
static int test_peek_end(struct bch_fs *c, u64 nr) static int test_peek_end(struct bch_fs *c, u64 nr)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
bch2_trans_init(&trans, c, 0, 0); bch2_trans_iter_init(trans, &iter, BTREE_ID_xattrs,
bch2_trans_iter_init(&trans, &iter, BTREE_ID_xattrs,
SPOS(0, 0, U32_MAX), 0); SPOS(0, 0, U32_MAX), 0);
lockrestart_do(&trans, bkey_err(k = bch2_btree_iter_peek_upto(&iter, POS(0, U64_MAX)))); lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek_upto(&iter, POS(0, U64_MAX))));
BUG_ON(k.k); BUG_ON(k.k);
lockrestart_do(&trans, bkey_err(k = bch2_btree_iter_peek_upto(&iter, POS(0, U64_MAX)))); lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek_upto(&iter, POS(0, U64_MAX))));
BUG_ON(k.k); BUG_ON(k.k);
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans); bch2_trans_put(trans);
return 0; return 0;
} }
static int test_peek_end_extents(struct bch_fs *c, u64 nr) static int test_peek_end_extents(struct bch_fs *c, u64 nr)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
bch2_trans_init(&trans, c, 0, 0); bch2_trans_iter_init(trans, &iter, BTREE_ID_extents,
bch2_trans_iter_init(&trans, &iter, BTREE_ID_extents,
SPOS(0, 0, U32_MAX), 0); SPOS(0, 0, U32_MAX), 0);
lockrestart_do(&trans, bkey_err(k = bch2_btree_iter_peek_upto(&iter, POS(0, U64_MAX)))); lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek_upto(&iter, POS(0, U64_MAX))));
BUG_ON(k.k); BUG_ON(k.k);
lockrestart_do(&trans, bkey_err(k = bch2_btree_iter_peek_upto(&iter, POS(0, U64_MAX)))); lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek_upto(&iter, POS(0, U64_MAX))));
BUG_ON(k.k); BUG_ON(k.k);
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans); bch2_trans_put(trans);
return 0; return 0;
} }
@ -510,7 +497,7 @@ static int insert_test_overlapping_extent(struct bch_fs *c, u64 inum, u64 start,
k.k_i.k.size = len; k.k_i.k.size = len;
ret = bch2_trans_do(c, NULL, NULL, 0, ret = bch2_trans_do(c, NULL, NULL, 0,
bch2_btree_insert_nonextent(&trans, BTREE_ID_extents, &k.k_i, bch2_btree_insert_nonextent(trans, BTREE_ID_extents, &k.k_i,
BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE)); BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE));
if (ret) if (ret)
bch_err_fn(c, ret); bch_err_fn(c, ret);
@ -533,7 +520,7 @@ static int test_extent_create_overlapping(struct bch_fs *c, u64 inum)
/* Test skipping over keys in unrelated snapshots: */ /* Test skipping over keys in unrelated snapshots: */
static int test_snapshot_filter(struct bch_fs *c, u32 snapid_lo, u32 snapid_hi) static int test_snapshot_filter(struct bch_fs *c, u32 snapid_lo, u32 snapid_hi)
{ {
struct btree_trans trans; struct btree_trans *trans;
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bkey_i_cookie cookie; struct bkey_i_cookie cookie;
@ -545,15 +532,15 @@ static int test_snapshot_filter(struct bch_fs *c, u32 snapid_lo, u32 snapid_hi)
if (ret) if (ret)
return ret; return ret;
bch2_trans_init(&trans, c, 0, 0); trans = bch2_trans_get(c);
bch2_trans_iter_init(&trans, &iter, BTREE_ID_xattrs, bch2_trans_iter_init(trans, &iter, BTREE_ID_xattrs,
SPOS(0, 0, snapid_lo), 0); SPOS(0, 0, snapid_lo), 0);
lockrestart_do(&trans, bkey_err(k = bch2_btree_iter_peek_upto(&iter, POS(0, U64_MAX)))); lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek_upto(&iter, POS(0, U64_MAX))));
BUG_ON(k.k->p.snapshot != U32_MAX); BUG_ON(k.k->p.snapshot != U32_MAX);
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
@ -571,7 +558,7 @@ static int test_snapshots(struct bch_fs *c, u64 nr)
return ret; return ret;
ret = bch2_trans_do(c, NULL, NULL, 0, ret = bch2_trans_do(c, NULL, NULL, 0,
bch2_snapshot_node_create(&trans, U32_MAX, bch2_snapshot_node_create(trans, U32_MAX,
snapids, snapids,
snapid_subvols, snapid_subvols,
2)); 2));
@ -602,38 +589,34 @@ static u64 test_rand(void)
static int rand_insert(struct bch_fs *c, u64 nr) static int rand_insert(struct bch_fs *c, u64 nr)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct bkey_i_cookie k; struct bkey_i_cookie k;
int ret = 0; int ret = 0;
u64 i; u64 i;
bch2_trans_init(&trans, c, 0, 0);
for (i = 0; i < nr; i++) { for (i = 0; i < nr; i++) {
bkey_cookie_init(&k.k_i); bkey_cookie_init(&k.k_i);
k.k.p.offset = test_rand(); k.k.p.offset = test_rand();
k.k.p.snapshot = U32_MAX; k.k.p.snapshot = U32_MAX;
ret = commit_do(&trans, NULL, NULL, 0, ret = commit_do(trans, NULL, NULL, 0,
bch2_btree_insert_trans(&trans, BTREE_ID_xattrs, &k.k_i, 0)); bch2_btree_insert_trans(trans, BTREE_ID_xattrs, &k.k_i, 0));
if (ret) if (ret)
break; break;
} }
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
static int rand_insert_multi(struct bch_fs *c, u64 nr) static int rand_insert_multi(struct bch_fs *c, u64 nr)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct bkey_i_cookie k[8]; struct bkey_i_cookie k[8];
int ret = 0; int ret = 0;
unsigned j; unsigned j;
u64 i; u64 i;
bch2_trans_init(&trans, c, 0, 0);
for (i = 0; i < nr; i += ARRAY_SIZE(k)) { for (i = 0; i < nr; i += ARRAY_SIZE(k)) {
for (j = 0; j < ARRAY_SIZE(k); j++) { for (j = 0; j < ARRAY_SIZE(k); j++) {
bkey_cookie_init(&k[j].k_i); bkey_cookie_init(&k[j].k_i);
@ -641,46 +624,45 @@ static int rand_insert_multi(struct bch_fs *c, u64 nr)
k[j].k.p.snapshot = U32_MAX; k[j].k.p.snapshot = U32_MAX;
} }
ret = commit_do(&trans, NULL, NULL, 0, ret = commit_do(trans, NULL, NULL, 0,
bch2_btree_insert_trans(&trans, BTREE_ID_xattrs, &k[0].k_i, 0) ?: bch2_btree_insert_trans(trans, BTREE_ID_xattrs, &k[0].k_i, 0) ?:
bch2_btree_insert_trans(&trans, BTREE_ID_xattrs, &k[1].k_i, 0) ?: bch2_btree_insert_trans(trans, BTREE_ID_xattrs, &k[1].k_i, 0) ?:
bch2_btree_insert_trans(&trans, BTREE_ID_xattrs, &k[2].k_i, 0) ?: bch2_btree_insert_trans(trans, BTREE_ID_xattrs, &k[2].k_i, 0) ?:
bch2_btree_insert_trans(&trans, BTREE_ID_xattrs, &k[3].k_i, 0) ?: bch2_btree_insert_trans(trans, BTREE_ID_xattrs, &k[3].k_i, 0) ?:
bch2_btree_insert_trans(&trans, BTREE_ID_xattrs, &k[4].k_i, 0) ?: bch2_btree_insert_trans(trans, BTREE_ID_xattrs, &k[4].k_i, 0) ?:
bch2_btree_insert_trans(&trans, BTREE_ID_xattrs, &k[5].k_i, 0) ?: bch2_btree_insert_trans(trans, BTREE_ID_xattrs, &k[5].k_i, 0) ?:
bch2_btree_insert_trans(&trans, BTREE_ID_xattrs, &k[6].k_i, 0) ?: bch2_btree_insert_trans(trans, BTREE_ID_xattrs, &k[6].k_i, 0) ?:
bch2_btree_insert_trans(&trans, BTREE_ID_xattrs, &k[7].k_i, 0)); bch2_btree_insert_trans(trans, BTREE_ID_xattrs, &k[7].k_i, 0));
if (ret) if (ret)
break; break;
} }
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
static int rand_lookup(struct bch_fs *c, u64 nr) static int rand_lookup(struct bch_fs *c, u64 nr)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
int ret = 0; int ret = 0;
u64 i; u64 i;
bch2_trans_init(&trans, c, 0, 0); bch2_trans_iter_init(trans, &iter, BTREE_ID_xattrs,
bch2_trans_iter_init(&trans, &iter, BTREE_ID_xattrs,
SPOS(0, 0, U32_MAX), 0); SPOS(0, 0, U32_MAX), 0);
for (i = 0; i < nr; i++) { for (i = 0; i < nr; i++) {
bch2_btree_iter_set_pos(&iter, SPOS(0, test_rand(), U32_MAX)); bch2_btree_iter_set_pos(&iter, SPOS(0, test_rand(), U32_MAX));
lockrestart_do(&trans, bkey_err(k = bch2_btree_iter_peek(&iter))); lockrestart_do(trans, bkey_err(k = bch2_btree_iter_peek(&iter)));
ret = bkey_err(k); ret = bkey_err(k);
if (ret) if (ret)
break; break;
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
@ -712,26 +694,25 @@ static int rand_mixed_trans(struct btree_trans *trans,
static int rand_mixed(struct bch_fs *c, u64 nr) static int rand_mixed(struct bch_fs *c, u64 nr)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_i_cookie cookie; struct bkey_i_cookie cookie;
int ret = 0; int ret = 0;
u64 i, rand; u64 i, rand;
bch2_trans_init(&trans, c, 0, 0); bch2_trans_iter_init(trans, &iter, BTREE_ID_xattrs,
bch2_trans_iter_init(&trans, &iter, BTREE_ID_xattrs,
SPOS(0, 0, U32_MAX), 0); SPOS(0, 0, U32_MAX), 0);
for (i = 0; i < nr; i++) { for (i = 0; i < nr; i++) {
rand = test_rand(); rand = test_rand();
ret = commit_do(&trans, NULL, NULL, 0, ret = commit_do(trans, NULL, NULL, 0,
rand_mixed_trans(&trans, &iter, &cookie, i, rand)); rand_mixed_trans(trans, &iter, &cookie, i, rand));
if (ret) if (ret)
break; break;
} }
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
@ -759,22 +740,20 @@ err:
static int rand_delete(struct bch_fs *c, u64 nr) static int rand_delete(struct bch_fs *c, u64 nr)
{ {
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
int ret = 0; int ret = 0;
u64 i; u64 i;
bch2_trans_init(&trans, c, 0, 0);
for (i = 0; i < nr; i++) { for (i = 0; i < nr; i++) {
struct bpos pos = SPOS(0, test_rand(), U32_MAX); struct bpos pos = SPOS(0, test_rand(), U32_MAX);
ret = commit_do(&trans, NULL, NULL, 0, ret = commit_do(trans, NULL, NULL, 0,
__do_delete(&trans, pos)); __do_delete(trans, pos));
if (ret) if (ret)
break; break;
} }
bch2_trans_exit(&trans); bch2_trans_put(trans);
return ret; return ret;
} }
@ -787,14 +766,14 @@ static int seq_insert(struct bch_fs *c, u64 nr)
bkey_cookie_init(&insert.k_i); bkey_cookie_init(&insert.k_i);
return bch2_trans_run(c, return bch2_trans_run(c,
for_each_btree_key_commit(&trans, iter, BTREE_ID_xattrs, for_each_btree_key_commit(trans, iter, BTREE_ID_xattrs,
SPOS(0, 0, U32_MAX), SPOS(0, 0, U32_MAX),
BTREE_ITER_SLOTS|BTREE_ITER_INTENT, k, BTREE_ITER_SLOTS|BTREE_ITER_INTENT, k,
NULL, NULL, 0, ({ NULL, NULL, 0, ({
if (iter.pos.offset >= nr) if (iter.pos.offset >= nr)
break; break;
insert.k.p = iter.pos; insert.k.p = iter.pos;
bch2_trans_update(&trans, &iter, &insert.k_i, 0); bch2_trans_update(trans, &iter, &insert.k_i, 0);
}))); })));
} }
@ -804,7 +783,7 @@ static int seq_lookup(struct bch_fs *c, u64 nr)
struct bkey_s_c k; struct bkey_s_c k;
return bch2_trans_run(c, return bch2_trans_run(c,
for_each_btree_key2_upto(&trans, iter, BTREE_ID_xattrs, for_each_btree_key2_upto(trans, iter, BTREE_ID_xattrs,
SPOS(0, 0, U32_MAX), POS(0, U64_MAX), SPOS(0, 0, U32_MAX), POS(0, U64_MAX),
0, k, 0, k,
0)); 0));
@ -816,14 +795,14 @@ static int seq_overwrite(struct bch_fs *c, u64 nr)
struct bkey_s_c k; struct bkey_s_c k;
return bch2_trans_run(c, return bch2_trans_run(c,
for_each_btree_key_commit(&trans, iter, BTREE_ID_xattrs, for_each_btree_key_commit(trans, iter, BTREE_ID_xattrs,
SPOS(0, 0, U32_MAX), SPOS(0, 0, U32_MAX),
BTREE_ITER_INTENT, k, BTREE_ITER_INTENT, k,
NULL, NULL, 0, ({ NULL, NULL, 0, ({
struct bkey_i_cookie u; struct bkey_i_cookie u;
bkey_reassemble(&u.k_i, k); bkey_reassemble(&u.k_i, k);
bch2_trans_update(&trans, &iter, &u.k_i, 0); bch2_trans_update(trans, &iter, &u.k_i, 0);
}))); })));
} }

View File

@ -307,24 +307,22 @@ ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
{ {
struct bch_fs *c = dentry->d_sb->s_fs_info; struct bch_fs *c = dentry->d_sb->s_fs_info;
struct bch_inode_info *inode = to_bch_ei(dentry->d_inode); struct bch_inode_info *inode = to_bch_ei(dentry->d_inode);
struct btree_trans trans; struct btree_trans *trans = bch2_trans_get(c);
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct xattr_buf buf = { .buf = buffer, .len = buffer_size }; struct xattr_buf buf = { .buf = buffer, .len = buffer_size };
u64 offset = 0, inum = inode->ei_inode.bi_inum; u64 offset = 0, inum = inode->ei_inode.bi_inum;
u32 snapshot; u32 snapshot;
int ret; int ret;
bch2_trans_init(&trans, c, 0, 0);
retry: retry:
bch2_trans_begin(&trans); bch2_trans_begin(trans);
iter = (struct btree_iter) { NULL }; iter = (struct btree_iter) { NULL };
ret = bch2_subvolume_get_snapshot(&trans, inode->ei_subvol, &snapshot); ret = bch2_subvolume_get_snapshot(trans, inode->ei_subvol, &snapshot);
if (ret) if (ret)
goto err; goto err;
for_each_btree_key_upto_norestart(&trans, iter, BTREE_ID_xattrs, for_each_btree_key_upto_norestart(trans, iter, BTREE_ID_xattrs,
SPOS(inum, offset, snapshot), SPOS(inum, offset, snapshot),
POS(inum, U64_MAX), 0, k, ret) { POS(inum, U64_MAX), 0, k, ret) {
if (k.k->type != KEY_TYPE_xattr) if (k.k->type != KEY_TYPE_xattr)
@ -336,12 +334,12 @@ retry:
} }
offset = iter.pos.offset; offset = iter.pos.offset;
bch2_trans_iter_exit(&trans, &iter); bch2_trans_iter_exit(trans, &iter);
err: err:
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry; goto retry;
bch2_trans_exit(&trans); bch2_trans_put(trans);
if (ret) if (ret)
goto out; goto out;
@ -366,7 +364,7 @@ static int bch2_xattr_get_handler(const struct xattr_handler *handler,
struct bch_inode_info *inode = to_bch_ei(vinode); struct bch_inode_info *inode = to_bch_ei(vinode);
struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_fs *c = inode->v.i_sb->s_fs_info;
int ret = bch2_trans_do(c, NULL, NULL, 0, int ret = bch2_trans_do(c, NULL, NULL, 0,
bch2_xattr_get_trans(&trans, inode, name, buffer, size, handler->flags)); bch2_xattr_get_trans(trans, inode, name, buffer, size, handler->flags));
return bch2_err_class(ret); return bch2_err_class(ret);
} }
@ -381,18 +379,14 @@ static int bch2_xattr_set_handler(const struct xattr_handler *handler,
struct bch_fs *c = inode->v.i_sb->s_fs_info; struct bch_fs *c = inode->v.i_sb->s_fs_info;
struct bch_hash_info hash = bch2_hash_info_init(c, &inode->ei_inode); struct bch_hash_info hash = bch2_hash_info_init(c, &inode->ei_inode);
struct bch_inode_unpacked inode_u; struct bch_inode_unpacked inode_u;
struct btree_trans trans;
int ret; int ret;
bch2_trans_init(&trans, c, 0, 0); ret = bch2_trans_run(c,
commit_do(trans, NULL, NULL, 0,
ret = commit_do(&trans, NULL, NULL, 0, bch2_xattr_set(trans, inode_inum(inode), &inode_u,
bch2_xattr_set(&trans, inode_inum(inode), &inode_u,
&hash, name, value, size, &hash, name, value, size,
handler->flags, flags)); handler->flags, flags)) ?:
if (!ret) (bch2_inode_update_after_write(trans, inode, &inode_u, ATTR_CTIME), 0));
bch2_inode_update_after_write(&trans, inode, &inode_u, ATTR_CTIME);
bch2_trans_exit(&trans);
return bch2_err_class(ret); return bch2_err_class(ret);
} }