summaryrefslogtreecommitdiff
path: root/fs/bcachefs/inode.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-03-16 07:28:17 +0300
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-23 00:09:12 +0300
commit6fed42bb7750e217b0d1169ccfccc7639a3e1d3f (patch)
tree88e8f85e58cd7c68b86c6e804c99a2aebcbb74d0 /fs/bcachefs/inode.c
parentc075ff700ff397671636bf45f6ef6ef330258d3e (diff)
downloadlinux-6fed42bb7750e217b0d1169ccfccc7639a3e1d3f.tar.xz
bcachefs: Plumb through subvolume id
To implement snapshots, we need every filesystem btree operation (every btree operation without a subvolume) to start by looking up the subvolume and getting the current snapshot ID, with bch2_subvolume_get_snapshot() - then, that snapshot ID is used for doing btree lookups in BTREE_ITER_FILTER_SNAPSHOTS mode. This patch adds those bch2_subvolume_get_snapshot() calls, and also switches to passing around a subvol_inum instead of just an inode number. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Diffstat (limited to 'fs/bcachefs/inode.c')
-rw-r--r--fs/bcachefs/inode.c109
1 files changed, 90 insertions, 19 deletions
diff --git a/fs/bcachefs/inode.c b/fs/bcachefs/inode.c
index 3b19dc6b9ddc..7fccf842a46b 100644
--- a/fs/bcachefs/inode.c
+++ b/fs/bcachefs/inode.c
@@ -6,6 +6,7 @@
#include "btree_update.h"
#include "error.h"
#include "extents.h"
+#include "extent_update.h"
#include "inode.h"
#include "str_hash.h"
#include "subvolume.h"
@@ -296,15 +297,21 @@ int bch2_inode_unpack(struct bkey_s_c_inode inode,
int bch2_inode_peek(struct btree_trans *trans,
struct btree_iter *iter,
struct bch_inode_unpacked *inode,
- u64 inum, unsigned flags)
+ subvol_inum inum, unsigned flags)
{
struct bkey_s_c k;
+ u32 snapshot;
int ret;
if (trans->c->opts.inodes_use_key_cache)
flags |= BTREE_ITER_CACHED;
- bch2_trans_iter_init(trans, iter, BTREE_ID_inodes, POS(0, inum), flags);
+ ret = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot);
+ if (ret)
+ return ret;
+
+ bch2_trans_iter_init(trans, iter, BTREE_ID_inodes,
+ SPOS(0, inum.inum, snapshot), flags);
k = bch2_btree_iter_peek_slot(iter);
ret = bkey_err(k);
if (ret)
@@ -486,6 +493,9 @@ static inline u32 bkey_generation(struct bkey_s_c k)
}
}
+/*
+ * This just finds an empty slot:
+ */
int bch2_inode_create(struct btree_trans *trans,
struct btree_iter *iter,
struct bch_inode_unpacked *inode_u,
@@ -585,16 +595,74 @@ found_slot:
return 0;
}
-int bch2_inode_rm(struct bch_fs *c, u64 inode_nr, bool cached)
+static int bch2_inode_delete_keys(struct btree_trans *trans,
+ subvol_inum inum, enum btree_id id)
+{
+ u64 offset = 0;
+ int ret = 0;
+
+ while (!ret || ret == -EINTR) {
+ struct btree_iter iter;
+ struct bkey_s_c k;
+ struct bkey_i delete;
+ u32 snapshot;
+
+ bch2_trans_begin(trans);
+
+ ret = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot);
+ if (ret)
+ continue;
+
+ bch2_trans_iter_init(trans, &iter, id,
+ SPOS(inum.inum, offset, snapshot),
+ BTREE_ITER_INTENT);
+ k = bch2_btree_iter_peek(&iter);
+
+ if (!k.k || iter.pos.inode != inum.inum) {
+ bch2_trans_iter_exit(trans, &iter);
+ break;
+ }
+
+ ret = bkey_err(k);
+ if (ret)
+ goto err;
+
+ bkey_init(&delete.k);
+ delete.k.p = iter.pos;
+
+ if (btree_node_type_is_extents(iter.btree_id)) {
+ unsigned max_sectors =
+ min_t(u64, U64_MAX - iter.pos.offset,
+ KEY_SIZE_MAX & (~0 << trans->c->block_bits));
+
+ /* create the biggest key we can */
+ bch2_key_resize(&delete.k, max_sectors);
+
+ ret = bch2_extent_trim_atomic(trans, &iter, &delete);
+ if (ret)
+ goto err;
+ }
+
+ ret = bch2_trans_update(trans, &iter, &delete, 0) ?:
+ bch2_trans_commit(trans, NULL, NULL,
+ BTREE_INSERT_NOFAIL);
+err:
+ offset = iter.pos.offset;
+ bch2_trans_iter_exit(trans, &iter);
+ }
+
+ return ret;
+}
+
+int bch2_inode_rm(struct bch_fs *c, subvol_inum inum, bool cached)
{
struct btree_trans trans;
struct btree_iter iter = { NULL };
struct bkey_i_inode_generation delete;
- struct bpos start = POS(inode_nr, 0);
- struct bpos end = POS(inode_nr + 1, 0);
struct bch_inode_unpacked inode_u;
struct bkey_s_c k;
unsigned iter_flags = BTREE_ITER_INTENT;
+ u32 snapshot;
int ret;
if (cached && c->opts.inodes_use_key_cache)
@@ -610,19 +678,20 @@ int bch2_inode_rm(struct bch_fs *c, u64 inode_nr, bool cached)
* XXX: the dirent could ideally would delete whiteouts when they're no
* longer needed
*/
- ret = bch2_btree_delete_range_trans(&trans, BTREE_ID_extents,
- start, end, NULL) ?:
- bch2_btree_delete_range_trans(&trans, BTREE_ID_xattrs,
- start, end, NULL) ?:
- bch2_btree_delete_range_trans(&trans, BTREE_ID_dirents,
- start, end, NULL);
+ 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_dirents);
if (ret)
goto err;
retry:
bch2_trans_begin(&trans);
+ ret = bch2_subvolume_get_snapshot(&trans, inum.subvol, &snapshot);
+ if (ret)
+ goto err;
+
bch2_trans_iter_init(&trans, &iter, BTREE_ID_inodes,
- POS(0, inode_nr), iter_flags);
+ SPOS(0, inum.inum, snapshot), iter_flags);
k = bch2_btree_iter_peek_slot(&iter);
ret = bkey_err(k);
@@ -632,7 +701,7 @@ retry:
if (k.k->type != KEY_TYPE_inode) {
bch2_fs_inconsistent(trans.c,
"inode %llu not found when deleting",
- inode_nr);
+ inum.inum);
ret = -EIO;
goto err;
}
@@ -662,20 +731,22 @@ err:
return ret;
}
-static int bch2_inode_find_by_inum_trans(struct btree_trans *trans, u64 inode_nr,
+static int bch2_inode_find_by_inum_trans(struct btree_trans *trans,
+ subvol_inum inum,
struct bch_inode_unpacked *inode)
{
- struct btree_iter iter = { NULL };
+ struct btree_iter iter;
int ret;
- ret = bch2_inode_peek(trans, &iter, inode, inode_nr, 0);
- bch2_trans_iter_exit(trans, &iter);
+ ret = bch2_inode_peek(trans, &iter, inode, inum, 0);
+ if (!ret)
+ bch2_trans_iter_exit(trans, &iter);
return ret;
}
-int bch2_inode_find_by_inum(struct bch_fs *c, u64 inode_nr,
+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, inode_nr, inode));
+ bch2_inode_find_by_inum_trans(&trans, inum, inode));
}