summaryrefslogtreecommitdiff
path: root/fs/bcachefs/bcachefs_format.h
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-10-14 09:54:47 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:09:14 -0400
commit6d76aefea1902a11c47e20fec5495d30a39891f3 (patch)
tree3492b62e7853384faad5e0b97a4c5f7c60f7d945 /fs/bcachefs/bcachefs_format.h
parentbfe88863cf3063204fc49a04307fa6635554d6e3 (diff)
downloadlwn-6d76aefea1902a11c47e20fec5495d30a39891f3.tar.gz
lwn-6d76aefea1902a11c47e20fec5495d30a39891f3.zip
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/bcachefs_format.h')
-rw-r--r--fs/bcachefs/bcachefs_format.h15
1 files changed, 12 insertions, 3 deletions
diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h
index 579acb69115d..4b2bf8f7b28a 100644
--- a/fs/bcachefs/bcachefs_format.h
+++ b/fs/bcachefs/bcachefs_format.h
@@ -917,15 +917,24 @@ struct bch_stripe {
struct bch_reflink_p {
struct bch_val v;
__le64 idx;
- __le64 v2;
-};
+ /*
+ * A reflink pointer might point to an indirect extent which is then
+ * later split (by copygc or rebalance). If we only pointed to part of
+ * the original indirect extent, and then one of the fragments is
+ * outside the range we point to, we'd leak a refcount: so when creating
+ * reflink pointers, we need to store pad values to remember the full
+ * range we were taking a reference on.
+ */
+ __le32 front_pad;
+ __le32 back_pad;
+} __attribute__((packed, aligned(8)));
struct bch_reflink_v {
struct bch_val v;
__le64 refcount;
union bch_extent_entry start[0];
__u64 _data[0];
-};
+} __attribute__((packed, aligned(8)));
struct bch_indirect_inline_data {
struct bch_val v;