summaryrefslogtreecommitdiff
path: root/fs/bcachefs/buckets.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2020-10-24 19:51:34 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:08:45 -0400
commit801a3de6427924d87ecc7e218a99ad3245ee8290 (patch)
tree9fb234d536b6e5d8dbc990ea89ae80a8ca7aa35f /fs/bcachefs/buckets.c
parent13dcd4abcd8d4e177f4f75ea3f5c8838a8a8c3c3 (diff)
downloadlwn-801a3de6427924d87ecc7e218a99ad3245ee8290.tar.gz
lwn-801a3de6427924d87ecc7e218a99ad3245ee8290.zip
bcachefs: Indirect inline data extents
When inline data extents were added, reflink was forgotten about - we need indirect inline data extents for reflink + inline data to work correctly. This patch adds them, and a new feature bit that's flipped when they're used. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/buckets.c')
-rw-r--r--fs/bcachefs/buckets.c49
1 files changed, 31 insertions, 18 deletions
diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c
index aacc20f71729..0dc01386d1cd 100644
--- a/fs/bcachefs/buckets.c
+++ b/fs/bcachefs/buckets.c
@@ -1811,6 +1811,18 @@ put_iter:
return ret;
}
+static __le64 *bkey_refcount(struct bkey_i *k)
+{
+ switch (k->k.type) {
+ case KEY_TYPE_reflink_v:
+ return &bkey_i_to_reflink_v(k)->v.refcount;
+ case KEY_TYPE_indirect_inline_data:
+ return &bkey_i_to_indirect_inline_data(k)->v.refcount;
+ default:
+ return NULL;
+ }
+}
+
static int __bch2_trans_mark_reflink_p(struct btree_trans *trans,
struct bkey_s_c_reflink_p p,
u64 idx, unsigned sectors,
@@ -1819,7 +1831,8 @@ static int __bch2_trans_mark_reflink_p(struct btree_trans *trans,
struct bch_fs *c = trans->c;
struct btree_iter *iter;
struct bkey_s_c k;
- struct bkey_i_reflink_v *r_v;
+ struct bkey_i *n;
+ __le64 *refcount;
s64 ret;
ret = trans_get_key(trans, BTREE_ID_REFLINK,
@@ -1827,14 +1840,6 @@ static int __bch2_trans_mark_reflink_p(struct btree_trans *trans,
if (ret < 0)
return ret;
- if (k.k->type != KEY_TYPE_reflink_v) {
- bch2_fs_inconsistent(c,
- "%llu:%llu len %u points to nonexistent indirect extent %llu",
- p.k->p.inode, p.k->p.offset, p.k->size, idx);
- ret = -EIO;
- goto err;
- }
-
if ((flags & BTREE_TRIGGER_OVERWRITE) &&
(bkey_start_offset(k.k) < idx ||
k.k->p.offset > idx + sectors))
@@ -1842,25 +1847,33 @@ static int __bch2_trans_mark_reflink_p(struct btree_trans *trans,
sectors = k.k->p.offset - idx;
- r_v = bch2_trans_kmalloc(trans, bkey_bytes(k.k));
- ret = PTR_ERR_OR_ZERO(r_v);
+ n = bch2_trans_kmalloc(trans, bkey_bytes(k.k));
+ ret = PTR_ERR_OR_ZERO(n);
if (ret)
goto err;
- bkey_reassemble(&r_v->k_i, k);
+ bkey_reassemble(n, k);
+
+ refcount = bkey_refcount(n);
+ if (!refcount) {
+ bch2_fs_inconsistent(c,
+ "%llu:%llu len %u points to nonexistent indirect extent %llu",
+ p.k->p.inode, p.k->p.offset, p.k->size, idx);
+ ret = -EIO;
+ goto err;
+ }
- le64_add_cpu(&r_v->v.refcount,
- !(flags & BTREE_TRIGGER_OVERWRITE) ? 1 : -1);
+ le64_add_cpu(refcount, !(flags & BTREE_TRIGGER_OVERWRITE) ? 1 : -1);
- if (!r_v->v.refcount) {
- r_v->k.type = KEY_TYPE_deleted;
- set_bkey_val_u64s(&r_v->k, 0);
+ if (!*refcount) {
+ n->k.type = KEY_TYPE_deleted;
+ set_bkey_val_u64s(&n->k, 0);
}
bch2_btree_iter_set_pos(iter, bkey_start_pos(k.k));
BUG_ON(iter->uptodate > BTREE_ITER_NEED_PEEK);
- bch2_trans_update(trans, iter, &r_v->k_i, 0);
+ bch2_trans_update(trans, iter, n, 0);
out:
ret = sectors;
err: