summaryrefslogtreecommitdiff
path: root/fs/bcachefs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/bcachefs/inode.c')
-rw-r--r--fs/bcachefs/inode.c190
1 files changed, 77 insertions, 113 deletions
diff --git a/fs/bcachefs/inode.c b/fs/bcachefs/inode.c
index 307fb0c95656..d5e5190f0663 100644
--- a/fs/bcachefs/inode.c
+++ b/fs/bcachefs/inode.c
@@ -345,12 +345,12 @@ int __bch2_inode_peek(struct btree_trans *trans,
if (ret)
return ret;
- struct bkey_s_c k = bch2_bkey_get_iter(trans, iter, BTREE_ID_inodes,
- SPOS(0, inum.inum, snapshot),
- flags|BTREE_ITER_cached);
+ bch2_trans_iter_init(trans, iter, BTREE_ID_inodes, SPOS(0, inum.inum, snapshot),
+ flags|BTREE_ITER_cached);
+ struct bkey_s_c k = bch2_btree_iter_peek_slot(iter);
ret = bkey_err(k);
if (ret)
- return ret;
+ goto err;
ret = bkey_is_inode(k.k) ? 0 : -BCH_ERR_ENOENT_inode;
if (ret)
@@ -364,7 +364,7 @@ int __bch2_inode_peek(struct btree_trans *trans,
err:
if (warn)
bch_err_msg(trans->c, ret, "looking up inum %llu:%llu:", inum.subvol, inum.inum);
- bch2_trans_iter_exit(trans, iter);
+ bch2_trans_iter_exit(iter);
return ret;
}
@@ -373,19 +373,15 @@ int bch2_inode_find_by_inum_snapshot(struct btree_trans *trans,
struct bch_inode_unpacked *inode,
unsigned flags)
{
- struct btree_iter iter;
- struct bkey_s_c k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_inodes,
- SPOS(0, inode_nr, snapshot), flags);
+ CLASS(btree_iter, iter)(trans, BTREE_ID_inodes, SPOS(0, inode_nr, snapshot), flags);
+ struct bkey_s_c k = bch2_btree_iter_peek_slot(&iter);
int ret = bkey_err(k);
if (ret)
- goto err;
+ return ret;
- ret = bkey_is_inode(k.k)
+ return bkey_is_inode(k.k)
? bch2_inode_unpack(k, inode)
: -BCH_ERR_ENOENT_inode;
-err:
- bch2_trans_iter_exit(trans, &iter);
- return ret;
}
int bch2_inode_find_by_inum_nowarn_trans(struct btree_trans *trans,
@@ -397,7 +393,7 @@ int bch2_inode_find_by_inum_nowarn_trans(struct btree_trans *trans,
ret = bch2_inode_peek_nowarn(trans, &iter, inode, inum, 0);
if (!ret)
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
return ret;
}
@@ -410,20 +406,20 @@ int bch2_inode_find_by_inum_trans(struct btree_trans *trans,
ret = bch2_inode_peek(trans, &iter, inode, inum, 0);
if (!ret)
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
return ret;
}
int bch2_inode_find_by_inum(struct bch_fs *c, subvol_inum inum,
struct bch_inode_unpacked *inode)
{
- return bch2_trans_do(c, bch2_inode_find_by_inum_trans(trans, inum, inode));
+ CLASS(btree_trans, trans)(c);
+ return lockrestart_do(trans, bch2_inode_find_by_inum_trans(trans, inum, inode));
}
int bch2_inode_find_snapshot_root(struct btree_trans *trans, u64 inum,
struct bch_inode_unpacked *root)
{
- struct btree_iter iter;
struct bkey_s_c k;
int ret = 0;
@@ -432,15 +428,11 @@ int bch2_inode_find_snapshot_root(struct btree_trans *trans, u64 inum,
BTREE_ITER_all_snapshots, k, ret) {
if (k.k->p.offset != inum)
break;
- if (bkey_is_inode(k.k)) {
- ret = bch2_inode_unpack(k, root);
- goto out;
- }
+ if (bkey_is_inode(k.k))
+ return bch2_inode_unpack(k, root);
}
/* We're only called when we know we have an inode for @inum */
BUG_ON(!ret);
-out:
- bch2_trans_iter_exit(trans, &iter);
return ret;
}
@@ -471,9 +463,10 @@ int __bch2_fsck_write_inode(struct btree_trans *trans, struct bch_inode_unpacked
bch2_inode_pack(inode_p, inode);
inode_p->inode.k.p.snapshot = inode->bi_snapshot;
- return bch2_btree_insert_nonextent(trans, BTREE_ID_inodes,
- &inode_p->inode.k_i,
- BTREE_UPDATE_internal_snapshot_node);
+ return bch2_btree_insert_trans(trans, BTREE_ID_inodes,
+ &inode_p->inode.k_i,
+ BTREE_ITER_cached|
+ BTREE_UPDATE_internal_snapshot_node);
}
int bch2_fsck_write_inode(struct btree_trans *trans, struct bch_inode_unpacked *inode)
@@ -695,14 +688,15 @@ bch2_bkey_get_iter_snapshot_parent(struct btree_trans *trans, struct btree_iter
struct bkey_s_c k;
int ret = 0;
- for_each_btree_key_max_norestart(trans, *iter, btree,
- bpos_successor(pos),
- SPOS(pos.inode, pos.offset, U32_MAX),
- flags|BTREE_ITER_all_snapshots, k, ret)
+ bch2_trans_iter_init(trans, iter, btree, bpos_successor(pos),
+ flags|BTREE_ITER_all_snapshots);
+
+ for_each_btree_key_max_continue_norestart(*iter, SPOS(pos.inode, pos.offset, U32_MAX),
+ flags|BTREE_ITER_all_snapshots, k, ret)
if (bch2_snapshot_is_ancestor(c, pos.snapshot, k.k->p.snapshot))
return k;
- bch2_trans_iter_exit(trans, iter);
+ bch2_trans_iter_exit(iter);
return ret ? bkey_s_c_err(ret) : bkey_s_c_null;
}
@@ -718,7 +712,7 @@ again:
bkey_is_inode(k.k))
return k;
- bch2_trans_iter_exit(trans, iter);
+ bch2_trans_iter_exit(iter);
pos = k.k->p;
goto again;
}
@@ -726,7 +720,6 @@ again:
int __bch2_inode_has_child_snapshots(struct btree_trans *trans, struct bpos pos)
{
struct bch_fs *c = trans->c;
- struct btree_iter iter;
struct bkey_s_c k;
int ret = 0;
@@ -739,7 +732,6 @@ int __bch2_inode_has_child_snapshots(struct btree_trans *trans, struct bpos pos)
ret = 1;
break;
}
- bch2_trans_iter_exit(trans, &iter);
return ret;
}
@@ -791,7 +783,7 @@ static int update_parent_inode_has_children(struct btree_trans *trans, struct bp
bkey_inode_flags_set(bkey_i_to_s(update), f ^ BCH_INODE_has_child_snapshot);
}
err:
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
return ret;
}
@@ -960,11 +952,10 @@ bch2_inode_alloc_cursor_get(struct btree_trans *trans, u64 cpu, u64 *min, u64 *m
cursor_idx &= ~(~0ULL << c->opts.shard_inode_numbers_bits);
- struct btree_iter iter;
- struct bkey_s_c k = bch2_bkey_get_iter(trans, &iter,
- BTREE_ID_logged_ops,
- POS(LOGGED_OPS_INUM_inode_cursors, cursor_idx),
- BTREE_ITER_cached);
+ CLASS(btree_iter, iter)(trans, BTREE_ID_logged_ops,
+ POS(LOGGED_OPS_INUM_inode_cursors, cursor_idx),
+ BTREE_ITER_cached);
+ struct bkey_s_c k = bch2_btree_iter_peek_slot(&iter);
int ret = bkey_err(k);
if (ret)
return ERR_PTR(ret);
@@ -973,9 +964,8 @@ bch2_inode_alloc_cursor_get(struct btree_trans *trans, u64 cpu, u64 *min, u64 *m
k.k->type == KEY_TYPE_inode_alloc_cursor
? bch2_bkey_make_mut_typed(trans, &iter, &k, 0, inode_alloc_cursor)
: bch2_bkey_alloc(trans, &iter, 0, inode_alloc_cursor);
- ret = PTR_ERR_OR_ZERO(cursor);
- if (ret)
- goto err;
+ if (IS_ERR(cursor))
+ return cursor;
if (c->opts.inodes_32bit) {
*min = BLOCKDEV_INODE_MAX;
@@ -996,9 +986,8 @@ bch2_inode_alloc_cursor_get(struct btree_trans *trans, u64 cpu, u64 *min, u64 *m
cursor->v.idx = cpu_to_le64(*min);
le32_add_cpu(&cursor->v.gen, 1);
}
-err:
- bch2_trans_iter_exit(trans, &iter);
- return ret ? ERR_PTR(ret) : cursor;
+
+ return cursor;
}
/*
@@ -1025,7 +1014,7 @@ int bch2_inode_create(struct btree_trans *trans,
BTREE_ITER_intent);
struct bkey_s_c k;
again:
- while ((k = bch2_btree_iter_peek(trans, iter)).k &&
+ while ((k = bch2_btree_iter_peek(iter)).k &&
!(ret = bkey_err(k)) &&
bkey_lt(k.k->p, POS(0, max))) {
if (pos < iter->pos.offset)
@@ -1042,7 +1031,7 @@ again:
* we've found just one:
*/
pos = iter->pos.offset + 1;
- bch2_btree_iter_set_pos(trans, iter, POS(0, pos));
+ bch2_btree_iter_set_pos(iter, POS(0, pos));
}
if (!ret && pos < max)
@@ -1052,21 +1041,21 @@ again:
ret = bch_err_throw(trans->c, ENOSPC_inode_create);
if (ret) {
- bch2_trans_iter_exit(trans, iter);
+ bch2_trans_iter_exit(iter);
return ret;
}
/* Retry from start */
pos = start = min;
- bch2_btree_iter_set_pos(trans, iter, POS(0, pos));
+ bch2_btree_iter_set_pos(iter, POS(0, pos));
le32_add_cpu(&cursor->v.gen, 1);
goto again;
found_slot:
- bch2_btree_iter_set_pos(trans, iter, SPOS(0, pos, snapshot));
- k = bch2_btree_iter_peek_slot(trans, iter);
+ bch2_btree_iter_set_pos(iter, SPOS(0, pos, snapshot));
+ k = bch2_btree_iter_peek_slot(iter);
ret = bkey_err(k);
if (ret) {
- bch2_trans_iter_exit(trans, iter);
+ bch2_trans_iter_exit(iter);
return ret;
}
@@ -1079,7 +1068,6 @@ found_slot:
static int bch2_inode_delete_keys(struct btree_trans *trans,
subvol_inum inum, enum btree_id id)
{
- struct btree_iter iter;
struct bkey_s_c k;
struct bkey_i delete;
struct bpos end = POS(inum.inum, U64_MAX);
@@ -1090,8 +1078,7 @@ static int bch2_inode_delete_keys(struct btree_trans *trans,
* We're never going to be deleting partial extents, no need to use an
* extent iterator:
*/
- bch2_trans_iter_init(trans, &iter, id, POS(inum.inum, 0),
- BTREE_ITER_intent);
+ CLASS(btree_iter, iter)(trans, id, POS(inum.inum, 0), BTREE_ITER_intent);
while (1) {
bch2_trans_begin(trans);
@@ -1100,9 +1087,9 @@ static int bch2_inode_delete_keys(struct btree_trans *trans,
if (ret)
goto err;
- bch2_btree_iter_set_snapshot(trans, &iter, snapshot);
+ bch2_btree_iter_set_snapshot(&iter, snapshot);
- k = bch2_btree_iter_peek_max(trans, &iter, end);
+ k = bch2_btree_iter_peek_max(&iter, end);
ret = bkey_err(k);
if (ret)
goto err;
@@ -1126,13 +1113,12 @@ err:
break;
}
- bch2_trans_iter_exit(trans, &iter);
return ret;
}
int bch2_inode_rm(struct bch_fs *c, subvol_inum inum)
{
- struct btree_trans *trans = bch2_trans_get(c);
+ CLASS(btree_trans, trans)(c);
struct btree_iter iter = {};
struct bkey_s_c k;
struct bch_inode_unpacked inode;
@@ -1141,7 +1127,7 @@ int bch2_inode_rm(struct bch_fs *c, subvol_inum inum)
ret = lockrestart_do(trans, may_delete_deleted_inum(trans, inum, &inode));
if (ret)
- goto err2;
+ return ret;
/*
* If this was a directory, there shouldn't be any real dirents left -
@@ -1156,7 +1142,7 @@ int bch2_inode_rm(struct bch_fs *c, subvol_inum inum)
: bch2_inode_delete_keys(trans, inum, BTREE_ID_dirents)) ?:
bch2_inode_delete_keys(trans, inum, BTREE_ID_xattrs);
if (ret)
- goto err2;
+ return ret;
retry:
bch2_trans_begin(trans);
@@ -1183,17 +1169,14 @@ retry:
bch2_trans_commit(trans, NULL, NULL,
BCH_TRANS_COMMIT_no_enospc);
err:
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry;
if (ret)
- goto err2;
+ return ret;
- ret = delete_ancestor_snapshot_inodes(trans, SPOS(0, inum.inum, snapshot));
-err2:
- bch2_trans_put(trans);
- return ret;
+ return delete_ancestor_snapshot_inodes(trans, SPOS(0, inum.inum, snapshot));
}
int bch2_inode_nlink_inc(struct bch_inode_unpacked *bi)
@@ -1307,10 +1290,7 @@ int bch2_inode_set_casefold(struct btree_trans *trans, subvol_inum inum,
static noinline int __bch2_inode_rm_snapshot(struct btree_trans *trans, u64 inum, u32 snapshot)
{
struct bch_fs *c = trans->c;
- struct btree_iter iter = {};
- struct bkey_i_inode_generation delete;
- struct bch_inode_unpacked inode_u;
- struct bkey_s_c k;
+ struct btree_iter iter = { NULL };
int ret;
do {
@@ -1332,8 +1312,8 @@ static noinline int __bch2_inode_rm_snapshot(struct btree_trans *trans, u64 inum
retry:
bch2_trans_begin(trans);
- k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_inodes,
- SPOS(0, inum, snapshot), BTREE_ITER_intent);
+ struct bkey_s_c k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_inodes,
+ SPOS(0, inum, snapshot), BTREE_ITER_intent);
ret = bkey_err(k);
if (ret)
goto err;
@@ -1346,12 +1326,14 @@ retry:
goto err;
}
+ struct bch_inode_unpacked inode_u;
bch2_inode_unpack(k, &inode_u);
/* Subvolume root? */
if (inode_u.bi_subvol)
bch_warn(c, "deleting inode %llu marked as unlinked, but also a subvolume root!?", inode_u.bi_inum);
+ struct bkey_i_inode_generation delete;
bkey_inode_generation_init(&delete.k_i);
delete.k.p = iter.pos;
delete.v.bi_generation = cpu_to_le32(inode_u.bi_generation + 1);
@@ -1360,7 +1342,7 @@ retry:
bch2_trans_commit(trans, NULL, NULL,
BCH_TRANS_COMMIT_no_enospc);
err:
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
goto retry;
@@ -1385,7 +1367,7 @@ next_parent:
bool unlinked = bkey_is_unlinked_inode(k);
pos = k.k->p;
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
if (!unlinked)
return 0;
@@ -1411,12 +1393,11 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos,
bool from_deleted_inodes)
{
struct bch_fs *c = trans->c;
- struct btree_iter inode_iter;
- struct bkey_s_c k;
- struct printbuf buf = PRINTBUF;
+ CLASS(printbuf, buf)();
int ret;
- k = bch2_bkey_get_iter(trans, &inode_iter, BTREE_ID_inodes, pos, BTREE_ITER_cached);
+ CLASS(btree_iter, inode_iter)(trans, BTREE_ID_inodes, pos, BTREE_ITER_cached);
+ struct bkey_s_c k = bch2_btree_iter_peek_slot(&inode_iter);
ret = bkey_err(k);
if (ret)
return ret;
@@ -1428,11 +1409,11 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos,
pos.offset, pos.snapshot))
goto delete;
if (ret)
- goto out;
+ return ret;
ret = bch2_inode_unpack(k, inode);
if (ret)
- goto out;
+ return ret;
if (S_ISDIR(inode->bi_mode)) {
ret = bch2_empty_dir_snapshot(trans, pos.offset, 0, pos.snapshot);
@@ -1443,7 +1424,7 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos,
pos.offset, pos.snapshot))
goto delete;
if (ret)
- goto out;
+ return ret;
}
ret = inode->bi_flags & BCH_INODE_unlinked ? 0 : bch_err_throw(c, inode_not_unlinked);
@@ -1453,7 +1434,7 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos,
pos.offset, pos.snapshot))
goto delete;
if (ret)
- goto out;
+ return ret;
ret = !(inode->bi_flags & BCH_INODE_has_child_snapshot)
? 0 : bch_err_throw(c, inode_has_child_snapshot);
@@ -1464,11 +1445,11 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos,
pos.offset, pos.snapshot))
goto delete;
if (ret)
- goto out;
+ return ret;
ret = bch2_inode_has_child_snapshots(trans, k.k->p);
if (ret < 0)
- goto out;
+ return ret;
if (ret) {
if (fsck_err(trans, inode_has_child_snapshots_wrong,
@@ -1479,13 +1460,12 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos,
inode->bi_flags |= BCH_INODE_has_child_snapshot;
ret = __bch2_fsck_write_inode(trans, inode);
if (ret)
- goto out;
+ return ret;
}
if (!from_deleted_inodes) {
- ret = bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc) ?:
+ return bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc) ?:
bch_err_throw(c, inode_has_child_snapshot);
- goto out;
}
goto delete;
@@ -1496,21 +1476,15 @@ static int may_delete_deleted_inode(struct btree_trans *trans, struct bpos pos,
if (test_bit(BCH_FS_clean_recovery, &c->flags) &&
!fsck_err(trans, deleted_inode_but_clean,
"filesystem marked as clean but have deleted inode %llu:%u",
- pos.offset, pos.snapshot)) {
- ret = 0;
- goto out;
- }
+ pos.offset, pos.snapshot))
+ return 0;
ret = 1;
}
-out:
fsck_err:
- bch2_trans_iter_exit(trans, &inode_iter);
- printbuf_exit(&buf);
return ret;
delete:
- ret = bch2_btree_bit_mod_buffered(trans, BTREE_ID_deleted_inodes, pos, false);
- goto out;
+ return bch2_btree_bit_mod_buffered(trans, BTREE_ID_deleted_inodes, pos, false);
}
static int may_delete_deleted_inum(struct btree_trans *trans, subvol_inum inum,
@@ -1524,29 +1498,23 @@ static int may_delete_deleted_inum(struct btree_trans *trans, subvol_inum inum,
int bch2_delete_dead_inodes(struct bch_fs *c)
{
- struct btree_trans *trans = bch2_trans_get(c);
- int ret;
-
+ CLASS(btree_trans, trans)(c);
/*
* if we ran check_inodes() unlinked inodes will have already been
* cleaned up but the write buffer will be out of sync; therefore we
* alway need a write buffer flush
- */
- ret = bch2_btree_write_buffer_flush_sync(trans);
- if (ret)
- goto err;
-
- /*
+ *
* Weird transaction restart handling here because on successful delete,
* bch2_inode_rm_snapshot() will return a nested transaction restart,
* but we can't retry because the btree write buffer won't have been
* flushed and we'd spin:
*/
- ret = for_each_btree_key_commit(trans, iter, BTREE_ID_deleted_inodes, POS_MIN,
+ return bch2_btree_write_buffer_flush_sync(trans) ?:
+ for_each_btree_key_commit(trans, iter, BTREE_ID_deleted_inodes, POS_MIN,
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
struct bch_inode_unpacked inode;
- ret = may_delete_deleted_inode(trans, k.k->p, &inode, true);
+ int ret = may_delete_deleted_inode(trans, k.k->p, &inode, true);
if (ret > 0) {
bch_verbose_ratelimited(c, "deleting unlinked inode %llu:%u",
k.k->p.offset, k.k->p.snapshot);
@@ -1567,8 +1535,4 @@ int bch2_delete_dead_inodes(struct bch_fs *c)
ret;
}));
-err:
- bch2_trans_put(trans);
- bch_err_fn(c, ret);
- return ret;
}