}
xattr = bkey_s_c_to_xattr(bch2_btree_iter_peek_slot(iter));
-
acl = bch2_acl_from_disk(xattr_val(xattr.v),
le16_to_cpu(xattr.v->x_val_len));
if (!IS_ERR(acl))
set_cached_acl(&inode->v, type, acl);
+ bch2_trans_iter_put(&trans, iter);
out:
bch2_trans_exit(&trans);
return acl;
if (type == ACL_TYPE_ACCESS) {
ret = posix_acl_update_mode(idmap, &inode->v, &mode, &acl);
if (ret)
- goto err;
+ goto btree_err;
}
hash_info = bch2_hash_info_init(c, &inode_u);
&inode->ei_journal_seq,
BTREE_INSERT_NOUNLOCK);
btree_err:
+ bch2_trans_iter_put(&trans, inode_iter);
+
if (ret == -EINTR)
goto retry;
if (unlikely(ret))
struct bkey_s_c_xattr xattr;
struct bkey_i_xattr *new;
struct posix_acl *acl;
- int ret = 0;
+ int ret;
iter = bch2_hash_lookup(trans, bch2_xattr_hash_desc,
&hash_info, inode->bi_inum,
&X_SEARCH(KEY_TYPE_XATTR_INDEX_POSIX_ACL_ACCESS, "", 0),
BTREE_ITER_INTENT);
- if (IS_ERR(iter))
- return PTR_ERR(iter) != -ENOENT ? PTR_ERR(iter) : 0;
+ ret = PTR_ERR_OR_ZERO(iter);
+ if (ret)
+ return ret == -ENOENT ? 0 : ret;
xattr = bkey_s_c_to_xattr(bch2_btree_iter_peek_slot(iter));
-
acl = bch2_acl_from_disk(xattr_val(xattr.v),
le16_to_cpu(xattr.v->x_val_len));
- if (IS_ERR_OR_NULL(acl))
- return PTR_ERR(acl);
+ ret = PTR_ERR_OR_ZERO(acl);
+ if (ret || !acl)
+ goto err;
ret = __posix_acl_chmod(&acl, GFP_KERNEL, mode);
if (ret)
*new_acl = acl;
acl = NULL;
err:
+ bch2_trans_iter_put(trans, iter);
kfree(acl);
return ret;
}
int ret = 0;
bch2_trans_init(&trans, c, BTREE_ITER_MAX, 0);
-
iter = bch2_trans_get_iter(&trans, BTREE_ID_alloc, POS_MIN,
BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
}
}
err:
+ bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
return ret;
}
int ret = 0;
bch2_trans_init(&trans, c, 0, 0);
-
iter = bch2_trans_get_iter(&trans, BTREE_ID_alloc,
POS(ca->dev_idx, 0),
BTREE_ITER_CACHED|
(!fifo_empty(&ca->free_inc)
? BTREE_INSERT_NOWAIT : 0));
+ bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
/* If we used NOWAIT, don't return the error: */
bch2_trans_cond_resched(&trans);
}
+ bch2_trans_iter_put(&trans, iter);
+
ret = bch2_trans_exit(&trans) ?: ret;
if (ret)
return ret;
bch2_btree_iter_next(iter);
}
+ bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&sk, c);
struct btree *b;
bool kthread = (current->flags & PF_KTHREAD) != 0;
unsigned i;
+ int ret = 0;
/* Sliding window of adjacent btree nodes */
struct btree *merge[GC_MERGE_NODES];
lock_seq[0] = merge[0]->c.lock.state.seq;
if (kthread && kthread_should_stop()) {
- bch2_trans_exit(&trans);
- return -ESHUTDOWN;
+ ret = -ESHUTDOWN;
+ break;
}
bch2_trans_cond_resched(&trans);
memset(merge + 1, 0,
(GC_MERGE_NODES - 1) * sizeof(merge[0]));
}
- return bch2_trans_exit(&trans);
+ bch2_trans_iter_put(&trans, iter);
+
+ return bch2_trans_exit(&trans) ?: ret;
}
/**
if (ret)
goto err;
out:
+ bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&k, c);
bio_put(&wbio->wbio.bio);
#include "btree_locking.h"
#include "btree_update.h"
#include "debug.h"
+#include "error.h"
#include "extents.h"
#include "journal.h"
#include "trace.h"
for (i = 0; i < ARRAY_SIZE(iter->l); i++)
iter->l[i].b = NULL;
iter->l[iter->level].b = BTREE_ITER_NO_NODE_INIT;
+ iter->ip_allocated = _RET_IP_;
return iter;
}
(void *) &trans->fs_usage_deltas->memset_start);
}
+ bch2_trans_cond_resched(trans);
+
if (!(flags & TRANS_RESET_NOTRAVERSE))
bch2_btree_iter_traverse_all(trans);
}
bch2_trans_unlock(trans);
#ifdef CONFIG_BCACHEFS_DEBUG
+ if (trans->iters_live) {
+ struct btree_iter *iter;
+
+ bch_err(c, "btree iterators leaked!");
+ trans_for_each_iter(trans, iter)
+ if (btree_iter_live(trans, iter))
+ printk(KERN_ERR " btree %s allocated at %pS\n",
+ bch2_btree_ids[iter->btree_id],
+ (void *) iter->ip_allocated);
+ /* Be noisy about this: */
+ bch2_fatal_error(c);
+ }
+
mutex_lock(&trans->c->btree_trans_lock);
list_del(&trans->list);
mutex_unlock(&trans->c->btree_trans_lock);
if (!i->size)
break;
}
+ bch2_trans_iter_put(&trans, iter);
+
bch2_trans_exit(&trans);
return err < 0 ? err : i->ret;
if (!i->size)
break;
}
+ bch2_trans_iter_put(&trans, iter);
+
bch2_trans_exit(&trans);
return err < 0 ? err : i->ret;
k = bch2_btree_iter_peek_slot(iter);
inum = le64_to_cpu(bkey_s_c_to_dirent(k).v->d_inum);
+ bch2_trans_iter_put(&trans, iter);
out:
bch2_trans_exit(&trans);
return inum;
break;
ctx->pos = dirent.k->p.offset + 1;
}
+ bch2_trans_iter_put(&trans, iter);
+
ret = bch2_trans_exit(&trans) ?: ret;
return ret;
if (ret)
break;
}
+ bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&sk, c);
int ret = 0;
bch2_trans_init(&trans, c, 0, 0);
-
iter = bch2_trans_get_iter(&trans, BTREE_ID_stripes, POS(0, U64_MAX), 0);
k = bch2_btree_iter_prev(iter);
if (!IS_ERR_OR_NULL(k.k))
idx = k.k->p.offset + 1;
+
+ bch2_trans_iter_put(&trans, iter);
ret = bch2_trans_exit(&trans);
if (ret)
return ret;
break;
}
}
+ bch2_trans_iter_put(&trans, iter);
+
bch2_trans_exit(&trans);
return ret;
BUG_ON(ret);
bch2_trans_init(&trans, c, 0, 0);
-
iter = bch2_trans_get_iter(&trans, BTREE_ID_extents, POS_MIN,
BTREE_ITER_SLOTS);
bch2_pagecache_add_put(&inode->ei_pagecache_lock);
+ bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
kfree(readpages_iter.pages);
}
bchfs_read(&trans, iter, rbio, inum, NULL);
+ bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
}
break;
}
}
+ bch2_trans_iter_put(&trans, iter);
return bch2_trans_exit(&trans) ?: ret;
}
bch2_trans_init(&trans, c, 0, 0);
iter = bch2_inode_peek(&trans, &inode_u, inode->v.i_ino, 0);
ret = PTR_ERR_OR_ZERO(iter);
+ bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
if (ret)
struct btree_iter *src, *dst, *del;
loff_t shift, new_size;
u64 src_start;
- int ret;
+ int ret = 0;
if ((offset | len) & (block_bytes(c) - 1))
return -EINVAL;
- bch2_bkey_buf_init(©);
- bch2_trans_init(&trans, c, BTREE_ITER_MAX, 256);
-
/*
* We need i_mutex to keep the page cache consistent with the extents
* btree, and the btree consistent with i_size - we don't need outside
goto err;
}
+ bch2_bkey_buf_init(©);
+ bch2_trans_init(&trans, c, BTREE_ITER_MAX, 256);
src = bch2_trans_get_iter(&trans, BTREE_ID_extents,
POS(inode->v.i_ino, src_start >> 9),
BTREE_ITER_INTENT);
dst = bch2_trans_copy_iter(&trans, src);
del = bch2_trans_copy_iter(&trans, src);
- while (1) {
+ while (ret == 0 || ret == -EINTR) {
struct disk_reservation disk_res =
bch2_disk_reservation_init(c, 0);
struct bkey_i delete;
? bch2_btree_iter_peek_prev(src)
: bch2_btree_iter_peek(src);
if ((ret = bkey_err(k)))
- goto bkey_err;
+ continue;
if (!k.k || k.k->p.inode != inode->v.i_ino)
break;
ret = bch2_extent_atomic_end(dst, copy.k, &atomic_end);
if (ret)
- goto bkey_err;
+ continue;
if (bkey_cmp(atomic_end, copy.k->k.p)) {
if (insert) {
&inode->ei_journal_seq,
BTREE_INSERT_NOFAIL);
bch2_disk_reservation_put(c, &disk_res);
-bkey_err:
+
if (!ret)
bch2_btree_iter_set_pos(src, next_pos);
-
- if (ret == -EINTR)
- ret = 0;
- if (ret)
- goto err;
-
- bch2_trans_cond_resched(&trans);
}
- bch2_trans_unlock(&trans);
+ bch2_trans_iter_put(&trans, del);
+ bch2_trans_iter_put(&trans, dst);
+ bch2_trans_iter_put(&trans, src);
+ bch2_trans_exit(&trans);
+ bch2_bkey_buf_exit(©, c);
+
+ if (ret)
+ goto err;
if (!insert) {
i_size_write(&inode->v, new_size);
mutex_unlock(&inode->ei_update_lock);
}
err:
- bch2_trans_exit(&trans);
- bch2_bkey_buf_exit(©, c);
bch2_pagecache_block_put(&inode->ei_pagecache_lock);
inode_unlock(&inode->v);
return ret;
BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
end_pos = POS(inode->v.i_ino, block_end >> 9);
- while (bkey_cmp(iter->pos, end_pos) < 0) {
+ while (!ret && bkey_cmp(iter->pos, end_pos) < 0) {
s64 i_sectors_delta = 0;
struct disk_reservation disk_res = { 0 };
struct quota_res quota_res = { 0 };
bch2_disk_reservation_put(c, &disk_res);
if (ret == -EINTR)
ret = 0;
- if (ret)
- goto err;
}
+ bch2_trans_iter_put(&trans, iter);
+
+ if (ret)
+ goto err;
/*
* Do we need to extend the file?
ret = PTR_ERR_OR_ZERO(inode_iter);
} while (ret == -EINTR);
+ bch2_trans_iter_put(&trans, inode_iter);
bch2_trans_unlock(&trans);
if (ret)
} else if (k.k->p.offset >> 9 > isize)
break;
}
+ bch2_trans_iter_put(&trans, iter);
ret = bch2_trans_exit(&trans) ?: ret;
if (ret)
offset = max(offset, bkey_start_offset(k.k) << 9);
}
}
+ bch2_trans_iter_put(&trans, iter);
ret = bch2_trans_exit(&trans) ?: ret;
if (ret)
BTREE_INSERT_NOUNLOCK|
BTREE_INSERT_NOFAIL);
btree_err:
+ bch2_trans_iter_put(&trans, inode_iter);
+
if (ret == -EINTR)
goto retry;
if (unlikely(ret))
ret = bch2_fill_extent(c, info, bkey_i_to_s_c(prev.k),
FIEMAP_EXTENT_LAST);
+ bch2_trans_iter_put(&trans, iter);
ret = bch2_trans_exit(&trans) ?: ret;
bch2_bkey_buf_exit(&cur, c);
bch2_bkey_buf_exit(&prev, c);
BCH_INODE_I_SECTORS_DIRTY|
BCH_INODE_UNLINKED)) {
ret = check_inode(&trans, NULL, iter, inode, NULL);
- BUG_ON(ret == -EINTR);
if (ret)
break;
}
}
+ bch2_trans_iter_put(&trans, iter);
+
BUG_ON(ret == -EINTR);
return bch2_trans_exit(&trans) ?: ret;
ret = bch2_trans_commit(&trans, NULL, NULL,
BTREE_INSERT_NOFAIL);
+ bch2_trans_iter_put(&trans, iter);
err:
if (ret == -EINTR)
goto retry;
ret = bch2_fpunch_at(&trans, iter, POS(inum, end),
journal_seq, i_sectors_delta);
+
+ bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
if (ret == -EINTR)
bch2_keylist_pop_front(keys);
} while (!bch2_keylist_empty(keys));
+ bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&sk, c);
goto err;
out:
bch2_rbio_done(rbio);
+ bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&sk, c);
return;
k = bch2_btree_iter_peek_slot(iter);
ret = bkey_err(k);
if (ret)
- goto err;
+ break;
offset_into_extent = iter->pos.offset -
bkey_start_offset(k.k);
ret = bch2_read_indirect_extent(&trans, &data_btree,
&offset_into_extent, &sk);
if (ret)
- goto err;
+ break;
k = bkey_i_to_s_c(sk.k);
ret = __bch2_read_extent(&trans, rbio, bvec_iter, iter->pos,
data_btree, k,
offset_into_extent, failed, flags);
- switch (ret) {
- case READ_RETRY:
- goto retry;
- case READ_ERR:
- goto err;
- };
+ if (ret)
+ break;
if (flags & BCH_READ_LAST_FRAGMENT)
break;
swap(bvec_iter.bi_size, bytes);
bio_advance_iter(&rbio->bio, &bvec_iter, bytes);
}
-out:
- bch2_trans_exit(&trans);
- bch2_bkey_buf_exit(&sk, c);
- return;
-err:
- if (ret == -EINTR)
+ bch2_trans_iter_put(&trans, iter);
+
+ if (ret == -EINTR || ret == READ_RETRY || ret == READ_RETRY_AVOID)
goto retry;
- bch_err_inum_ratelimited(c, inode,
- "read error %i from btree lookup", ret);
- rbio->bio.bi_status = BLK_STS_IOERR;
- bch2_rbio_done(rbio);
- goto out;
+ if (ret) {
+ bch_err_inum_ratelimited(c, inode,
+ "read error %i from btree lookup", ret);
+ rbio->bio.bi_status = BLK_STS_IOERR;
+ bch2_rbio_done(rbio);
+ }
+ bch2_trans_exit(&trans);
+ bch2_bkey_buf_exit(&sk, c);
}
void bch2_fs_io_exit(struct bch_fs *c)
if (ret)
break;
}
+ bch2_trans_iter_put(&trans, iter);
ret = bch2_trans_exit(&trans) ?: ret;
bch2_bkey_buf_exit(&sk, c);
dev_idx, flags, true);
if (ret) {
bch_err(c, "Cannot drop device without losing data");
- goto err;
+ break;
}
ret = bch2_btree_node_update_key(c, iter, b, k.k);
if (ret == -EINTR) {
b = bch2_btree_iter_peek_node(iter);
+ ret = 0;
goto retry;
}
if (ret) {
bch_err(c, "Error updating btree node key: %i", ret);
- goto err;
+ break;
}
}
bch2_trans_iter_free(&trans, iter);
+
+ if (ret)
+ goto err;
}
/* flush relevant btree updates */
goto next;
}
out:
+ bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
bch2_bkey_buf_exit(&_insert, c);
bch2_bkey_buf_exit(&_new, c);
bch2_trans_cond_resched(&trans);
}
out:
+
+ bch2_trans_iter_put(&trans, iter);
ret = bch2_trans_exit(&trans) ?: ret;
bch2_bkey_buf_exit(&sk, c);
if (ret)
break;
}
+ bch2_trans_iter_put(&trans, iter);
return bch2_trans_exit(&trans) ?: ret;
}
KEY_TYPE_QUOTA_NOCHECK);
}
}
+ bch2_trans_iter_put(&trans, iter);
+
return bch2_trans_exit(&trans) ?: ret;
}
if (qdq->d_fieldmask & QC_INO_HARD)
new_quota->v.c[Q_INO].hardlimit = cpu_to_le64(qdq->d_ino_hardlimit);
- return bch2_trans_update(trans, iter, &new_quota->k_i, 0);
+ ret = bch2_trans_update(trans, iter, &new_quota->k_i, 0);
+ bch2_trans_iter_put(trans, iter);
+ return ret;
}
static int bch2_set_quota(struct super_block *sb, struct kqid qid,
dst_iter = bch2_trans_get_iter(&trans, BTREE_ID_extents, dst_start,
BTREE_ITER_INTENT);
- while (1) {
+ while (ret == 0 || ret == -EINTR) {
bch2_trans_begin(&trans);
- trans.mem_top = 0;
-
if (fatal_signal_pending(current)) {
ret = -EINTR;
- goto err;
+ break;
}
src_k = get_next_src(src_iter, src_end);
ret = bkey_err(src_k);
if (ret)
- goto btree_err;
+ continue;
src_done = bpos_min(src_iter->pos, src_end).offset -
src_start.offset;
if (bkey_cmp(dst_iter->pos, dst_want) < 0) {
ret = bch2_fpunch_at(&trans, dst_iter, dst_want,
journal_seq, i_sectors_delta);
- if (ret)
- goto btree_err;
continue;
}
ret = bch2_make_extent_indirect(&trans, src_iter,
new_src.k);
if (ret)
- goto btree_err;
+ continue;
BUG_ON(src_k.k->type != KEY_TYPE_reflink_p);
}
NULL, journal_seq,
new_i_size, i_sectors_delta);
if (ret)
- goto btree_err;
+ continue;
dst_done = dst_iter->pos.offset - dst_start.offset;
src_want = POS(src_start.inode, src_start.offset + dst_done);
bch2_btree_iter_set_pos(src_iter, src_want);
-btree_err:
- if (ret == -EINTR)
- ret = 0;
- if (ret)
- goto err;
}
+ bch2_trans_iter_put(&trans, dst_iter);
+ bch2_trans_iter_put(&trans, src_iter);
- BUG_ON(bkey_cmp(dst_iter->pos, dst_end));
-err:
+ BUG_ON(!ret && bkey_cmp(dst_iter->pos, dst_end));
BUG_ON(bkey_cmp(dst_iter->pos, dst_end) > 0);
dst_done = dst_iter->pos.offset - dst_start.offset;
ret2 = bch2_inode_write(&trans, inode_iter, &inode_u) ?:
bch2_trans_commit(&trans, NULL, journal_seq, 0);
}
+
+ bch2_trans_iter_put(&trans, inode_iter);
} while (ret2 == -EINTR);
ret = bch2_trans_exit(&trans) ?: ret;
goto err;
}
err:
+ bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
return ret;
}
goto err;
}
err:
+ bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
return ret;
}
static int test_iterate(struct bch_fs *c, u64 nr)
{
struct btree_trans trans;
- struct btree_iter *iter;
+ struct btree_iter *iter = NULL;
struct bkey_s_c k;
u64 i;
int ret = 0;
BUG_ON(i);
err:
+ bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
return ret;
}
static int test_iterate_extents(struct bch_fs *c, u64 nr)
{
struct btree_trans trans;
- struct btree_iter *iter;
+ struct btree_iter *iter = NULL;
struct bkey_s_c k;
u64 i;
int ret = 0;
BUG_ON(i);
err:
+ bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
return ret;
}
BUG_ON(k.k->p.offset != i);
i += 2;
}
- bch2_trans_iter_free(&trans, iter);
+ bch2_trans_iter_put(&trans, iter);
BUG_ON(i != nr * 2);
if (i == nr * 2)
break;
}
+ bch2_trans_iter_put(&trans, iter);
err:
bch2_trans_exit(&trans);
return ret;
BUG_ON(k.k->size != 8);
i += 16;
}
- bch2_trans_iter_free(&trans, iter);
+ bch2_trans_iter_put(&trans, iter);
BUG_ON(i != nr);
if (i == nr)
break;
}
+ bch2_trans_iter_put(&trans, iter);
err:
bch2_trans_exit(&trans);
return 0;
k = bch2_btree_iter_peek(iter);
BUG_ON(k.k);
+ bch2_trans_iter_put(&trans, iter);
+
bch2_trans_exit(&trans);
return 0;
}
k = bch2_btree_iter_peek(iter);
BUG_ON(k.k);
+ bch2_trans_iter_put(&trans, iter);
+
bch2_trans_exit(&trans);
return 0;
}
}
}
- bch2_trans_iter_free(&trans, iter);
+ bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
return ret;
}
}
}
- bch2_trans_iter_free(&trans, iter);
+ bch2_trans_iter_put(&trans, iter);
bch2_trans_exit(&trans);
return ret;
}
if (++i == nr)
break;
}
+ bch2_trans_iter_put(&trans, iter);
+
bch2_trans_exit(&trans);
return ret;
}
for_each_btree_key(&trans, iter, BTREE_ID_xattrs, POS_MIN, 0, k, ret)
;
+ bch2_trans_iter_put(&trans, iter);
+
bch2_trans_exit(&trans);
return ret;
}
break;
}
}
+ bch2_trans_iter_put(&trans, iter);
+
bch2_trans_exit(&trans);
return ret;
}
inode->v.i_ino,
&X_SEARCH(type, name, strlen(name)),
0);
- if (IS_ERR(iter)) {
- bch2_trans_exit(&trans);
- BUG_ON(PTR_ERR(iter) == -EINTR);
-
- return PTR_ERR(iter) == -ENOENT ? -ENODATA : PTR_ERR(iter);
- }
+ ret = PTR_ERR_OR_ZERO(iter);
+ if (ret)
+ goto err;
xattr = bkey_s_c_to_xattr(bch2_btree_iter_peek_slot(iter));
ret = le16_to_cpu(xattr.v->x_val_len);
else
memcpy(buffer, xattr_val(xattr.v), ret);
}
-
+ bch2_trans_iter_put(&trans, iter);
+err:
bch2_trans_exit(&trans);
- return ret;
+
+ BUG_ON(ret == -EINTR);
+ return ret == -ENOENT ? -ENODATA : ret;
}
int bch2_xattr_set(struct btree_trans *trans, u64 inum,
if (ret)
break;
}
+ bch2_trans_iter_put(&trans, iter);
+
ret = bch2_trans_exit(&trans) ?: ret;
if (ret)