summaryrefslogtreecommitdiff
path: root/libbcachefs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbcachefs/inode.c')
-rw-r--r--libbcachefs/inode.c110
1 files changed, 89 insertions, 21 deletions
diff --git a/libbcachefs/inode.c b/libbcachefs/inode.c
index 18bc182a..1422cc24 100644
--- a/libbcachefs/inode.c
+++ b/libbcachefs/inode.c
@@ -207,6 +207,11 @@ static const char *bch2_inode_invalid(const struct bch_fs *c,
return "blockdev inode in fs range";
return NULL;
+ case BCH_INODE_GENERATION:
+ if (bkey_val_bytes(k.k) != sizeof(struct bch_inode_generation))
+ return "incorrect value size";
+
+ return NULL;
default:
return "invalid type";
}
@@ -257,9 +262,10 @@ void bch2_inode_init(struct bch_fs *c, struct bch_inode_unpacked *inode_u,
inode_u->i_otime = now;
}
-int bch2_inode_create(struct bch_fs *c, struct bkey_i *inode,
+int bch2_inode_create(struct bch_fs *c, struct bch_inode_unpacked *inode_u,
u64 min, u64 max, u64 *hint)
{
+ struct bkey_inode_buf inode_p;
struct btree_iter iter;
bool searched_from_start = false;
int ret;
@@ -281,6 +287,7 @@ again:
while (1) {
struct bkey_s_c k = bch2_btree_iter_peek_with_holes(&iter);
+ u32 i_generation = 0;
ret = btree_iter_err(k);
if (ret) {
@@ -288,31 +295,51 @@ again:
return ret;
}
- if (k.k->type < BCH_INODE_FS) {
- inode->k.p = k.k->p;
+ switch (k.k->type) {
+ case BCH_INODE_BLOCKDEV:
+ case BCH_INODE_FS:
+ /* slot used */
+ if (iter.pos.inode == max)
+ goto out;
+
+ bch2_btree_iter_advance_pos(&iter);
+ break;
+
+ case BCH_INODE_GENERATION: {
+ struct bkey_s_c_inode_generation g =
+ bkey_s_c_to_inode_generation(k);
+ i_generation = le32_to_cpu(g.v->i_generation);
+ /* fallthrough: */
+ }
+ default:
+ inode_u->i_generation = i_generation;
- pr_debug("inserting inode %llu (size %u)",
- inode->k.p.inode, inode->k.u64s);
+ bch2_inode_pack(&inode_p, inode_u);
+ inode_p.inode.k.p = k.k->p;
ret = bch2_btree_insert_at(c, NULL, NULL, NULL,
BTREE_INSERT_ATOMIC,
- BTREE_INSERT_ENTRY(&iter, inode));
+ BTREE_INSERT_ENTRY(&iter,
+ &inode_p.inode.k_i));
+
+ if (ret != -EINTR) {
+ bch2_btree_iter_unlock(&iter);
+
+ if (!ret) {
+ inode_u->inum =
+ inode_p.inode.k.p.inode;
+ *hint = inode_p.inode.k.p.inode + 1;
+ }
+
+ return ret;
+ }
if (ret == -EINTR)
continue;
- bch2_btree_iter_unlock(&iter);
- if (!ret)
- *hint = k.k->p.inode + 1;
-
- return ret;
- } else {
- if (iter.pos.inode == max)
- break;
- /* slot used */
- bch2_btree_iter_advance_pos(&iter);
}
}
+out:
bch2_btree_iter_unlock(&iter);
if (!searched_from_start) {
@@ -337,7 +364,8 @@ int bch2_inode_truncate(struct bch_fs *c, u64 inode_nr, u64 new_size,
int bch2_inode_rm(struct bch_fs *c, u64 inode_nr)
{
- struct bkey_i delete;
+ struct btree_iter iter;
+ struct bkey_i_inode_generation delete;
int ret;
ret = bch2_inode_truncate(c, inode_nr, 0, NULL, NULL);
@@ -366,11 +394,51 @@ int bch2_inode_rm(struct bch_fs *c, u64 inode_nr)
if (ret < 0)
return ret;
- bkey_init(&delete.k);
- delete.k.p.inode = inode_nr;
+ bch2_btree_iter_init(&iter, c, BTREE_ID_INODES, POS(inode_nr, 0),
+ BTREE_ITER_INTENT);
+ do {
+ struct bkey_s_c k = bch2_btree_iter_peek_with_holes(&iter);
+ u32 i_generation = 0;
+
+ ret = btree_iter_err(k);
+ if (ret) {
+ bch2_btree_iter_unlock(&iter);
+ return ret;
+ }
+
+ switch (k.k->type) {
+ case BCH_INODE_FS: {
+ struct bch_inode_unpacked inode_u;
- return bch2_btree_insert(c, BTREE_ID_INODES, &delete, NULL,
- NULL, NULL, BTREE_INSERT_NOFAIL);
+ if (!bch2_inode_unpack(bkey_s_c_to_inode(k), &inode_u))
+ i_generation = cpu_to_le32(inode_u.i_generation) + 1;
+ break;
+ }
+ case BCH_INODE_GENERATION: {
+ struct bkey_s_c_inode_generation g =
+ bkey_s_c_to_inode_generation(k);
+ i_generation = le32_to_cpu(g.v->i_generation);
+ break;
+ }
+ }
+
+ if (!i_generation) {
+ bkey_init(&delete.k);
+ delete.k.p.inode = inode_nr;
+ } else {
+ bkey_inode_generation_init(&delete.k_i);
+ delete.k.p.inode = inode_nr;
+ delete.v.i_generation = cpu_to_le32(i_generation);
+ }
+
+ ret = bch2_btree_insert_at(c, NULL, NULL, NULL,
+ BTREE_INSERT_ATOMIC|
+ BTREE_INSERT_NOFAIL,
+ BTREE_INSERT_ENTRY(&iter, &delete.k_i));
+ } while (ret == -EINTR);
+
+ bch2_btree_iter_unlock(&iter);
+ return ret;
}
int bch2_inode_find_by_inum(struct bch_fs *c, u64 inode_nr,