diff options
Diffstat (limited to 'fs/bcachefs/inode.c')
-rw-r--r-- | fs/bcachefs/inode.c | 190 |
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; } |