mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 13:11:40 +00:00
bcachefs: Don't use commit_do() unnecessarily
Using commit_do() to call alloc_sectors_start_trans() breaks when we're randomly injecting transaction restarts - the restart in the commit causes us to leak the lock that alloc_sectorS_start_trans() takes. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
6bee2a04c5
commit
a0d11feefb
@ -1977,7 +1977,7 @@ static void bch2_do_discards_fast_work(struct work_struct *work)
|
||||
ca->mi.bucket_size,
|
||||
GFP_KERNEL);
|
||||
|
||||
int ret = bch2_trans_do(c, NULL, NULL,
|
||||
int ret = bch2_trans_commit_do(c, NULL, NULL,
|
||||
BCH_WATERMARK_btree|
|
||||
BCH_TRANS_COMMIT_no_enospc,
|
||||
bch2_clear_bucket_needs_discard(trans, POS(ca->dev_idx, bucket)));
|
||||
|
@ -684,7 +684,7 @@ struct open_bucket *bch2_bucket_alloc(struct bch_fs *c, struct bch_dev *ca,
|
||||
struct bch_dev_usage usage;
|
||||
struct open_bucket *ob;
|
||||
|
||||
bch2_trans_do(c, NULL, NULL, 0,
|
||||
bch2_trans_do(c,
|
||||
PTR_ERR_OR_ZERO(ob = bch2_bucket_alloc_trans(trans, ca, watermark,
|
||||
data_type, cl, false, &usage)));
|
||||
return ob;
|
||||
|
@ -1871,7 +1871,7 @@ static void btree_node_write_work(struct work_struct *work)
|
||||
|
||||
}
|
||||
} else {
|
||||
ret = bch2_trans_do(c, NULL, NULL, 0,
|
||||
ret = bch2_trans_do(c,
|
||||
bch2_btree_node_update_key_get_iter(trans, b, &wbio->key,
|
||||
BCH_WATERMARK_interior_updates|
|
||||
BCH_TRANS_COMMIT_journal_reclaim|
|
||||
|
@ -912,6 +912,8 @@ struct bkey_s_c bch2_btree_iter_peek_and_restart_outlined(struct btree_iter *);
|
||||
_ret; \
|
||||
})
|
||||
|
||||
#define bch2_trans_do(_c, _do) bch2_trans_run(_c, lockrestart_do(trans, _do))
|
||||
|
||||
struct btree_trans *__bch2_trans_get(struct bch_fs *, unsigned);
|
||||
void bch2_trans_put(struct btree_trans *);
|
||||
|
||||
|
@ -668,7 +668,7 @@ int bch2_btree_insert(struct bch_fs *c, enum btree_id id, struct bkey_i *k,
|
||||
struct disk_reservation *disk_res, int flags,
|
||||
enum btree_iter_update_trigger_flags iter_flags)
|
||||
{
|
||||
return bch2_trans_do(c, disk_res, NULL, flags,
|
||||
return bch2_trans_commit_do(c, disk_res, NULL, flags,
|
||||
bch2_btree_insert_trans(trans, id, k, iter_flags));
|
||||
}
|
||||
|
||||
@ -865,7 +865,7 @@ __bch2_fs_log_msg(struct bch_fs *c, unsigned commit_flags, const char *fmt,
|
||||
memcpy(l->d, buf.buf, buf.pos);
|
||||
c->journal.early_journal_entries.nr += jset_u64s(u64s);
|
||||
} else {
|
||||
ret = bch2_trans_do(c, NULL, NULL,
|
||||
ret = bch2_trans_commit_do(c, NULL, NULL,
|
||||
BCH_TRANS_COMMIT_lazy_rw|commit_flags,
|
||||
__bch2_trans_log_msg(trans, &buf, u64s));
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ static inline int bch2_trans_commit(struct btree_trans *trans,
|
||||
nested_lockrestart_do(_trans, _do ?: bch2_trans_commit(_trans, (_disk_res),\
|
||||
(_journal_seq), (_flags)))
|
||||
|
||||
#define bch2_trans_do(_c, _disk_res, _journal_seq, _flags, _do) \
|
||||
#define bch2_trans_commit_do(_c, _disk_res, _journal_seq, _flags, _do) \
|
||||
bch2_trans_run(_c, commit_do(trans, _disk_res, _journal_seq, _flags, _do))
|
||||
|
||||
#define trans_for_each_update(_trans, _i) \
|
||||
|
@ -2239,10 +2239,8 @@ static void async_btree_node_rewrite_work(struct work_struct *work)
|
||||
struct async_btree_rewrite *a =
|
||||
container_of(work, struct async_btree_rewrite, work);
|
||||
struct bch_fs *c = a->c;
|
||||
int ret;
|
||||
|
||||
ret = bch2_trans_do(c, NULL, NULL, 0,
|
||||
async_btree_node_rewrite_trans(trans, a));
|
||||
int ret = bch2_trans_do(c, async_btree_node_rewrite_trans(trans, a));
|
||||
bch_err_fn_ratelimited(c, ret);
|
||||
bch2_write_ref_put(c, BCH_WRITE_REF_node_rewrite);
|
||||
kfree(a);
|
||||
|
@ -856,8 +856,10 @@ int bch2_dev_usage_init(struct bch_dev *ca, bool gc)
|
||||
};
|
||||
u64 v[3] = { ca->mi.nbuckets - ca->mi.first_bucket, 0, 0 };
|
||||
|
||||
int ret = bch2_trans_do(c, NULL, NULL, 0,
|
||||
bch2_disk_accounting_mod(trans, &acc, v, ARRAY_SIZE(v), gc));
|
||||
int ret = bch2_trans_do(c, ({
|
||||
bch2_disk_accounting_mod(trans, &acc, v, ARRAY_SIZE(v), gc) ?:
|
||||
(!gc ? bch2_trans_commit(trans, NULL, NULL, 0) : 0);
|
||||
}));
|
||||
bch_err_fn(c, ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1186,7 +1186,7 @@ static void ec_stripe_delete_work(struct work_struct *work)
|
||||
if (!idx)
|
||||
break;
|
||||
|
||||
int ret = bch2_trans_do(c, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
|
||||
int ret = bch2_trans_commit_do(c, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
|
||||
ec_stripe_delete(trans, idx));
|
||||
bch_err_fn(c, ret);
|
||||
if (ret)
|
||||
@ -1519,14 +1519,14 @@ static void ec_stripe_create(struct ec_stripe_new *s)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = bch2_trans_do(c, &s->res, NULL,
|
||||
BCH_TRANS_COMMIT_no_check_rw|
|
||||
BCH_TRANS_COMMIT_no_enospc,
|
||||
ec_stripe_key_update(trans,
|
||||
s->have_existing_stripe
|
||||
? bkey_i_to_stripe(&s->existing_stripe.key)
|
||||
: NULL,
|
||||
bkey_i_to_stripe(&s->new_stripe.key)));
|
||||
ret = bch2_trans_commit_do(c, &s->res, NULL,
|
||||
BCH_TRANS_COMMIT_no_check_rw|
|
||||
BCH_TRANS_COMMIT_no_enospc,
|
||||
ec_stripe_key_update(trans,
|
||||
s->have_existing_stripe
|
||||
? bkey_i_to_stripe(&s->existing_stripe.key)
|
||||
: NULL,
|
||||
bkey_i_to_stripe(&s->new_stripe.key)));
|
||||
bch_err_msg(c, ret, "creating stripe key");
|
||||
if (ret) {
|
||||
goto err;
|
||||
|
@ -658,7 +658,7 @@ static struct dentry *bch2_lookup(struct inode *vdir, struct dentry *dentry,
|
||||
struct bch_hash_info hash = bch2_hash_info_init(c, &dir->ei_inode);
|
||||
|
||||
struct bch_inode_info *inode;
|
||||
bch2_trans_do(c, NULL, NULL, 0,
|
||||
bch2_trans_do(c,
|
||||
PTR_ERR_OR_ZERO(inode = bch2_lookup_trans(trans, inode_inum(dir),
|
||||
&hash, &dentry->d_name)));
|
||||
if (IS_ERR(inode))
|
||||
|
@ -2509,7 +2509,7 @@ fsck_err:
|
||||
/* Get root directory, create if it doesn't exist: */
|
||||
int bch2_check_root(struct bch_fs *c)
|
||||
{
|
||||
int ret = bch2_trans_do(c, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
|
||||
int ret = bch2_trans_commit_do(c, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
|
||||
check_root_trans(trans));
|
||||
bch_err_fn(c, ret);
|
||||
return ret;
|
||||
|
@ -1087,8 +1087,7 @@ int bch2_inode_find_by_inum_trans(struct btree_trans *trans,
|
||||
int bch2_inode_find_by_inum(struct bch_fs *c, subvol_inum inum,
|
||||
struct bch_inode_unpacked *inode)
|
||||
{
|
||||
return bch2_trans_do(c, NULL, NULL, 0,
|
||||
bch2_inode_find_by_inum_trans(trans, inum, inode));
|
||||
return bch2_trans_do(c, bch2_inode_find_by_inum_trans(trans, inum, inode));
|
||||
}
|
||||
|
||||
int bch2_inode_nlink_inc(struct bch_inode_unpacked *bi)
|
||||
|
@ -557,8 +557,8 @@ out:
|
||||
|
||||
static noinline void bch2_rbio_narrow_crcs(struct bch_read_bio *rbio)
|
||||
{
|
||||
bch2_trans_do(rbio->c, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
|
||||
__bch2_rbio_narrow_crcs(trans, rbio));
|
||||
bch2_trans_commit_do(rbio->c, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
|
||||
__bch2_rbio_narrow_crcs(trans, rbio));
|
||||
}
|
||||
|
||||
/* Inner part that may run in process context */
|
||||
|
@ -1437,7 +1437,7 @@ again:
|
||||
* freeing up space on specific disks, which means that
|
||||
* allocations for specific disks may hang arbitrarily long:
|
||||
*/
|
||||
ret = bch2_trans_do(c, NULL, NULL, 0,
|
||||
ret = bch2_trans_run(c, lockrestart_do(trans,
|
||||
bch2_alloc_sectors_start_trans(trans,
|
||||
op->target,
|
||||
op->opts.erasure_code && !(op->flags & BCH_WRITE_CACHED),
|
||||
@ -1447,7 +1447,7 @@ again:
|
||||
op->nr_replicas_required,
|
||||
op->watermark,
|
||||
op->flags,
|
||||
&op->cl, &wp));
|
||||
&op->cl, &wp)));
|
||||
if (unlikely(ret)) {
|
||||
if (bch2_err_matches(ret, BCH_ERR_operation_blocked))
|
||||
break;
|
||||
|
@ -869,7 +869,7 @@ static int bch2_set_quota(struct super_block *sb, struct kqid qid,
|
||||
bkey_quota_init(&new_quota.k_i);
|
||||
new_quota.k.p = POS(qid.type, from_kqid(&init_user_ns, qid));
|
||||
|
||||
ret = bch2_trans_do(c, NULL, NULL, 0,
|
||||
ret = bch2_trans_commit_do(c, NULL, NULL, 0,
|
||||
bch2_set_quota_trans(trans, &new_quota, qdq)) ?:
|
||||
__bch2_quota_set(c, bkey_i_to_s_c(&new_quota.k_i), qdq);
|
||||
|
||||
|
@ -70,7 +70,9 @@ err:
|
||||
|
||||
int bch2_set_rebalance_needs_scan(struct bch_fs *c, u64 inum)
|
||||
{
|
||||
int ret = bch2_trans_do(c, NULL, NULL, BCH_TRANS_COMMIT_no_enospc|BCH_TRANS_COMMIT_lazy_rw,
|
||||
int ret = bch2_trans_commit_do(c, NULL, NULL,
|
||||
BCH_TRANS_COMMIT_no_enospc|
|
||||
BCH_TRANS_COMMIT_lazy_rw,
|
||||
__bch2_set_rebalance_needs_scan(trans, inum));
|
||||
rebalance_wakeup(c);
|
||||
return ret;
|
||||
|
@ -1091,7 +1091,7 @@ int bch2_fs_initialize(struct bch_fs *c)
|
||||
|
||||
bch2_inode_init_early(c, &lostfound_inode);
|
||||
|
||||
ret = bch2_trans_do(c, NULL, NULL, 0,
|
||||
ret = bch2_trans_commit_do(c, NULL, NULL, 0,
|
||||
bch2_create_trans(trans,
|
||||
BCACHEFS_ROOT_SUBVOL_INUM,
|
||||
&root_inode, &lostfound_inode,
|
||||
|
@ -319,8 +319,7 @@ int bch2_subvol_is_ro_trans(struct btree_trans *trans, u32 subvol)
|
||||
|
||||
int bch2_subvol_is_ro(struct bch_fs *c, u32 subvol)
|
||||
{
|
||||
return bch2_trans_do(c, NULL, NULL, 0,
|
||||
bch2_subvol_is_ro_trans(trans, subvol));
|
||||
return bch2_trans_do(c, bch2_subvol_is_ro_trans(trans, subvol));
|
||||
}
|
||||
|
||||
int bch2_snapshot_get_subvol(struct btree_trans *trans, u32 snapshot,
|
||||
@ -676,8 +675,8 @@ err:
|
||||
/* set bi_subvol on root inode */
|
||||
int bch2_fs_upgrade_for_subvolumes(struct bch_fs *c)
|
||||
{
|
||||
int ret = bch2_trans_do(c, NULL, NULL, BCH_TRANS_COMMIT_lazy_rw,
|
||||
__bch2_fs_upgrade_for_subvolumes(trans));
|
||||
int ret = bch2_trans_commit_do(c, NULL, NULL, BCH_TRANS_COMMIT_lazy_rw,
|
||||
__bch2_fs_upgrade_for_subvolumes(trans));
|
||||
bch_err_fn(c, ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1972,7 +1972,7 @@ int bch2_dev_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
|
||||
};
|
||||
u64 v[3] = { nbuckets - old_nbuckets, 0, 0 };
|
||||
|
||||
ret = bch2_trans_do(ca->fs, NULL, NULL, 0,
|
||||
ret = bch2_trans_commit_do(ca->fs, NULL, NULL, 0,
|
||||
bch2_disk_accounting_mod(trans, &acc, v, ARRAY_SIZE(v), false)) ?:
|
||||
bch2_dev_freespace_init(c, ca, old_nbuckets, nbuckets);
|
||||
if (ret)
|
||||
|
@ -450,7 +450,7 @@ static int insert_test_overlapping_extent(struct bch_fs *c, u64 inum, u64 start,
|
||||
k.k_i.k.p.snapshot = snapid;
|
||||
k.k_i.k.size = len;
|
||||
|
||||
ret = bch2_trans_do(c, NULL, NULL, 0,
|
||||
ret = bch2_trans_commit_do(c, NULL, NULL, 0,
|
||||
bch2_btree_insert_nonextent(trans, BTREE_ID_extents, &k.k_i,
|
||||
BTREE_UPDATE_internal_snapshot_node));
|
||||
bch_err_fn(c, ret);
|
||||
@ -510,7 +510,7 @@ static int test_snapshots(struct bch_fs *c, u64 nr)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = bch2_trans_do(c, NULL, NULL, 0,
|
||||
ret = bch2_trans_commit_do(c, NULL, NULL, 0,
|
||||
bch2_snapshot_node_create(trans, U32_MAX,
|
||||
snapids,
|
||||
snapid_subvols,
|
||||
|
@ -330,7 +330,7 @@ static int bch2_xattr_get_handler(const struct xattr_handler *handler,
|
||||
{
|
||||
struct bch_inode_info *inode = to_bch_ei(vinode);
|
||||
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,
|
||||
bch2_xattr_get_trans(trans, inode, name, buffer, size, handler->flags));
|
||||
|
||||
if (ret < 0 && bch2_err_matches(ret, ENOENT))
|
||||
|
Loading…
Reference in New Issue
Block a user