summaryrefslogtreecommitdiff
path: root/libbcachefs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbcachefs/inode.c')
-rw-r--r--libbcachefs/inode.c111
1 files changed, 57 insertions, 54 deletions
diff --git a/libbcachefs/inode.c b/libbcachefs/inode.c
index 3ae5ac97..d4139faa 100644
--- a/libbcachefs/inode.c
+++ b/libbcachefs/inode.c
@@ -203,6 +203,10 @@ const char *bch2_inode_invalid(const struct bch_fs *c, struct bkey_s_c k)
if (unpacked.bi_compression >= BCH_COMPRESSION_OPT_NR + 1)
return "invalid data checksum type";
+ if ((unpacked.bi_flags & BCH_INODE_UNLINKED) &&
+ unpacked.bi_nlink != 0)
+ return "flagged as unlinked but bi_nlink != 0";
+
return NULL;
}
case BCH_INODE_BLOCKDEV:
@@ -276,12 +280,27 @@ void bch2_inode_init(struct bch_fs *c, struct bch_inode_unpacked *inode_u,
}
}
-int bch2_inode_create(struct bch_fs *c, struct bch_inode_unpacked *inode_u,
- u64 min, u64 max, u64 *hint)
+static inline u32 bkey_generation(struct bkey_s_c k)
{
- struct bkey_inode_buf inode_p;
- struct btree_iter iter;
- bool searched_from_start = false;
+ switch (k.k->type) {
+ case BCH_INODE_BLOCKDEV:
+ case BCH_INODE_FS:
+ BUG();
+ case BCH_INODE_GENERATION:
+ return le32_to_cpu(bkey_s_c_to_inode_generation(k).v->bi_generation);
+ default:
+ return 0;
+ }
+}
+
+int __bch2_inode_create(struct btree_trans *trans,
+ struct bch_inode_unpacked *inode_u,
+ u64 min, u64 max, u64 *hint)
+{
+ struct bch_fs *c = trans->c;
+ struct bkey_inode_buf *inode_p;
+ struct btree_iter *iter;
+ u64 start;
int ret;
if (!max)
@@ -290,82 +309,66 @@ int bch2_inode_create(struct bch_fs *c, struct bch_inode_unpacked *inode_u,
if (c->opts.inodes_32bit)
max = min_t(u64, max, U32_MAX);
- if (*hint >= max || *hint < min)
- *hint = min;
+ start = READ_ONCE(*hint);
- if (*hint == min)
- searched_from_start = true;
-again:
- bch2_btree_iter_init(&iter, c, BTREE_ID_INODES, POS(*hint, 0),
- BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
+ if (start >= max || start < min)
+ start = min;
+ inode_p = bch2_trans_kmalloc(trans, sizeof(*inode_p));
+ if (IS_ERR(inode_p))
+ return PTR_ERR(inode_p);
+
+ iter = bch2_trans_get_iter(trans,
+ BTREE_ID_INODES, POS(start, 0),
+ BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
+ if (IS_ERR(iter))
+ return PTR_ERR(iter);
+again:
while (1) {
- struct bkey_s_c k = bch2_btree_iter_peek_slot(&iter);
- u32 bi_generation = 0;
+ struct bkey_s_c k = bch2_btree_iter_peek_slot(iter);
ret = btree_iter_err(k);
- if (ret) {
- bch2_btree_iter_unlock(&iter);
+ if (ret)
return ret;
- }
switch (k.k->type) {
case BCH_INODE_BLOCKDEV:
case BCH_INODE_FS:
/* slot used */
- if (iter.pos.inode == max)
+ if (iter->pos.inode >= max)
goto out;
- bch2_btree_iter_next_slot(&iter);
+ bch2_btree_iter_next_slot(iter);
break;
- case BCH_INODE_GENERATION: {
- struct bkey_s_c_inode_generation g =
- bkey_s_c_to_inode_generation(k);
- bi_generation = le32_to_cpu(g.v->bi_generation);
- /* fallthrough: */
- }
default:
- inode_u->bi_generation = bi_generation;
-
- 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_p.inode.k_i));
-
- if (ret != -EINTR) {
- bch2_btree_iter_unlock(&iter);
-
- if (!ret) {
- inode_u->bi_inum =
- inode_p.inode.k.p.inode;
- *hint = inode_p.inode.k.p.inode + 1;
- }
-
- return ret;
- }
-
- if (ret == -EINTR)
- continue;
+ *hint = k.k->p.inode;
+ inode_u->bi_inum = k.k->p.inode;
+ inode_u->bi_generation = bkey_generation(k);
+ bch2_inode_pack(inode_p, inode_u);
+ bch2_trans_update(trans, iter, &inode_p->inode.k_i, 0);
+ return 0;
}
}
out:
- bch2_btree_iter_unlock(&iter);
-
- if (!searched_from_start) {
+ if (start != min) {
/* Retry from start */
- *hint = min;
- searched_from_start = true;
+ start = min;
+ bch2_btree_iter_set_pos(iter, POS(start, 0));
goto again;
}
return -ENOSPC;
}
+int bch2_inode_create(struct bch_fs *c, struct bch_inode_unpacked *inode_u,
+ u64 min, u64 max, u64 *hint)
+{
+ return bch2_trans_do(c, NULL, BTREE_INSERT_ATOMIC,
+ __bch2_inode_create(&trans, inode_u, min, max, hint));
+}
+
int bch2_inode_truncate(struct bch_fs *c, u64 inode_nr, u64 new_size,
struct extent_insert_hook *hook, u64 *journal_seq)
{