summaryrefslogtreecommitdiff
path: root/fs/bcachefs/reflink.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-10-14 16:54:47 +0300
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-23 00:09:14 +0300
commit6d76aefea1902a11c47e20fec5495d30a39891f3 (patch)
tree3492b62e7853384faad5e0b97a4c5f7c60f7d945 /fs/bcachefs/reflink.c
parentbfe88863cf3063204fc49a04307fa6635554d6e3 (diff)
downloadlinux-6d76aefea1902a11c47e20fec5495d30a39891f3.tar.xz
bcachefs: Fix for leaking of reflinked extents
When a reflink pointer points to only part of an indirect extent, and then that indirect extent is fragmented (e.g. by copygc), if the reflink pointer only points to one of the fragments we leak a reference. Fix this by storing front/back pad values in reflink pointers - when inserting reflink pointesr, we initialize them to cover the full range of the indirect extents we reference. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Diffstat (limited to 'fs/bcachefs/reflink.c')
-rw-r--r--fs/bcachefs/reflink.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/fs/bcachefs/reflink.c b/fs/bcachefs/reflink.c
index 9bcf4216a286..2827d0ef1019 100644
--- a/fs/bcachefs/reflink.c
+++ b/fs/bcachefs/reflink.c
@@ -32,6 +32,10 @@ const char *bch2_reflink_p_invalid(const struct bch_fs *c, struct bkey_s_c k)
if (bkey_val_bytes(p.k) != sizeof(*p.v))
return "incorrect value size";
+ if (c->sb.version >= bcachefs_metadata_version_reflink_p_fix &&
+ le64_to_cpu(p.v->idx) < le32_to_cpu(p.v->front_pad))
+ return "idx < front_pad";
+
return NULL;
}