summary refs log tree commit diff
path: root/pkgs/os-specific/linux/util-linux/bcachefs-patch-set.patch
blob: 068744d4f32d0d277c609c3819daff6cb1b3495f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
commit 68564ebb50f8afab5a9527c534417e247cca0b27
Author: Filipe Manana <fdmanana@kernel.org>
Date:   Thu Aug 17 10:20:13 2023 +0100

    libmount: Fix regression when mounting with atime
    
    A regression was introduced in v2.39 that causes mounting with the atime
    option to fail:
    
      $ mkfs.ext4 -F /dev/sdi
      $ mount -o atime /dev/sdi /mnt/sdi
      mount: /mnt/sdi: not mount point or bad option.
             dmesg(1) may have more information after failed mount system call.
    
    The failure comes from the mount_setattr(2) call returning -EINVAL. This
    is because we pass an invalid value for the attr_clr argument. From a
    strace capture we have:
    
      mount_setattr(4, "", AT_EMPTY_PATH, {attr_set=0, attr_clr=MOUNT_ATTR_NOATIME, propagation=0 /* MS_??? */, userns_fd=0}, 32) = -1 EINVAL (Invalid argument)
    
    We can't pass MOUNT_ATTR_NOATIME to mount_setattr(2) through the attr_clr
    argument because all atime options are exclusive, so in order to set atime
    one has to pass MOUNT_ATTR__ATIME to attr_clr and leave attr_set as
    MOUNT_ATTR_RELATIME (which is defined as a value of 0).
    
    This can be read from the man page for mount_setattr(2) and also from the
    kernel source:
    
      $ cat fs/namespace.c
      static int build_mount_kattr(const struct mount_attr *attr, size_t usize,
                                   struct mount_kattr *kattr, unsigned int flags)
      {
          (...)
          /*
           * Since the MOUNT_ATTR_<atime> values are an enum, not a bitmap,
           * users wanting to transition to a different atime setting cannot
           * simply specify the atime setting in @attr_set, but must also
           * specify MOUNT_ATTR__ATIME in the @attr_clr field.
           * So ensure that MOUNT_ATTR__ATIME can't be partially set in
           * @attr_clr and that @attr_set can't have any atime bits set if
           * MOUNT_ATTR__ATIME isn't set in @attr_clr.
           */
          if (attr->attr_clr & MOUNT_ATTR__ATIME) {
              if ((attr->attr_clr & MOUNT_ATTR__ATIME) != MOUNT_ATTR__ATIME)
                  return -EINVAL;
    
                  /*
                   * Clear all previous time settings as they are mutually
                   * exclusive.
                   */
                  kattr->attr_clr |= MNT_RELATIME | MNT_NOATIME;
                  switch (attr->attr_set & MOUNT_ATTR__ATIME) {
                  case MOUNT_ATTR_RELATIME:
                      kattr->attr_set |= MNT_RELATIME;
                      break;
                  case MOUNT_ATTR_NOATIME:
                      kattr->attr_set |= MNT_NOATIME;
                      break;
                  case MOUNT_ATTR_STRICTATIME:
                      break;
                  default:
                      return -EINVAL;
                  }
        (...)
    
    So fix this by setting attr_clr MOUNT_ATTR__ATIME if we want to clear any
    atime related option.
    
    Signed-off-by: Filipe Manana <fdmanana@kernel.org>

diff --git a/libmount/src/optlist.c b/libmount/src/optlist.c
index 1e962ec6d..0702adae7 100644
--- a/libmount/src/optlist.c
+++ b/libmount/src/optlist.c
@@ -875,7 +875,18 @@ int mnt_optlist_get_attrs(struct libmnt_optlist *ls, uint64_t *set, uint64_t *cl
 
 		if (opt->ent->mask & MNT_INVERT) {
 			DBG(OPTLIST, ul_debugobj(ls, " clr: %s", opt->ent->name));
-			*clr |= x;
+			/*
+			 * All atime settings are mutually exclusive so *clr must
+			 * have MOUNT_ATTR__ATIME set.
+			 *
+			 * See the function fs/namespace.c:build_mount_kattr()
+			 * in the linux kernel source.
+			 */
+			if (x == MOUNT_ATTR_RELATIME || x == MOUNT_ATTR_NOATIME ||
+			    x == MOUNT_ATTR_STRICTATIME)
+				*clr |= MOUNT_ATTR__ATIME;
+			else
+				*clr |= x;
 		} else {
 			DBG(OPTLIST, ul_debugobj(ls, " set: %s", opt->ent->name));
 			*set |= x;
diff --git a/tests/expected/libmount/context-mount-flags b/tests/expected/libmount/context-mount-flags
index 960641863..eb71323dd 100644
--- a/tests/expected/libmount/context-mount-flags
+++ b/tests/expected/libmount/context-mount-flags
@@ -3,3 +3,6 @@ ro,nosuid,noexec
 successfully mounted
 rw,nosuid,noexec
 successfully umounted
+successfully mounted
+rw,relatime
+successfully umounted
diff --git a/tests/ts/libmount/context b/tests/ts/libmount/context
index f5b47185e..a5d2e81a3 100755
--- a/tests/ts/libmount/context
+++ b/tests/ts/libmount/context
@@ -116,8 +116,15 @@ $TS_CMD_FINDMNT --kernel --mountpoint $MOUNTPOINT -o VFS-OPTIONS -n >> $TS_OUTPU
 
 ts_run $TESTPROG --umount $MOUNTPOINT >> $TS_OUTPUT 2>> $TS_ERRLOG
 is_mounted $DEVICE && echo "$DEVICE still mounted" >> $TS_OUTPUT 2>> $TS_ERRLOG
-ts_finalize_subtest
 
+# Test that the atime option works after the migration to use the new kernel mount APIs.
+ts_run $TESTPROG --mount -o atime $DEVICE $MOUNTPOINT >> $TS_OUTPUT 2>> $TS_ERRLOG
+$TS_CMD_FINDMNT --kernel --mountpoint $MOUNTPOINT -o VFS-OPTIONS -n >> $TS_OUTPUT 2>> $TS_ERRLOG
+is_mounted $DEVICE || echo "$DEVICE not mounted" >> $TS_OUTPUT 2>> $TS_ERRLOG
+ts_run $TESTPROG --umount $MOUNTPOINT >> $TS_OUTPUT 2>> $TS_ERRLOG
+is_mounted $DEVICE && echo "$DEVICE still mounted" >> $TS_OUTPUT 2>> $TS_ERRLOG
+
+ts_finalize_subtest
 
 ts_init_subtest "mount-loopdev"
 mkdir -p $MOUNTPOINT &> /dev/null

commit 1ec71634aa4ef5ddca23d65c8a296f3614231e8a
Author: Colin Gillespie <colin@cgillespie.xyz>
Date:   Wed Aug 9 18:28:07 2023 +1000

    libblkid: (bcachefs) fix not detecting large superblocks
    
    Probing does not detect bcachefs filesystems with a superblock larger
    than 4KiB. Bcachefs superblocks grow in size and can become much larger
    than this.
    
    Increase the superblock maximum size limit to 1MiB.
    
    Validate the superblock isn't larger than the maximum size defined in
    the superblocks layout section.
    
    (cherry picked from commit 48d573797797650d96456979797c0155d58f61cb)

diff --git a/libblkid/src/superblocks/bcache.c b/libblkid/src/superblocks/bcache.c
index 40e702d75..236877042 100644
--- a/libblkid/src/superblocks/bcache.c
+++ b/libblkid/src/superblocks/bcache.c
@@ -102,6 +102,15 @@ union bcachefs_sb_csum {
 	uint8_t raw[16];
 } __attribute__((packed));
 
+struct bcachefs_sb_layout {
+	uint8_t		magic[16];
+	uint8_t		layout_type;
+	uint8_t		sb_max_size_bits;
+	uint8_t		nr_superblocks;
+	uint8_t		pad[5];
+	uint64_t	sb_offset[61];
+} __attribute__((packed));
+
 struct bcachefs_super_block {
 	union bcachefs_sb_csum	csum;
 	uint16_t	version;
@@ -123,7 +132,7 @@ struct bcachefs_super_block {
 	uint64_t	flags[8];
 	uint64_t	features[2];
 	uint64_t	compat[2];
-	uint8_t		layout[512];
+	struct bcachefs_sb_layout layout;
 	struct bcachefs_sb_field _start[];
 }  __attribute__((packed));
 
@@ -143,7 +152,7 @@ struct bcachefs_super_block {
 /* granularity of offset and length fields within superblock */
 #define BCACHEFS_SECTOR_SIZE   512
 /* maximum superblock size */
-#define BCACHEFS_SB_MAX_SIZE   4096
+#define BCACHEFS_SB_MAX_SIZE   0x100000
 /* fields offset within super block */
 #define BCACHEFS_SB_FIELDS_OFF offsetof(struct bcachefs_super_block, _start)
 /* tag value for members field */
@@ -302,6 +311,9 @@ static int probe_bcachefs(blkid_probe pr, const struct blkid_idmag *mag)
 		return BLKID_PROBE_NONE;
 
 	sb_size = BCACHEFS_SB_FIELDS_OFF + BYTES(bcs);
+	if (sb_size > BCACHEFS_SECTOR_SIZE << bcs->layout.sb_max_size_bits)
+		return BLKID_PROBE_NONE;
+
 	if (sb_size > BCACHEFS_SB_MAX_SIZE)
 		return BLKID_PROBE_NONE;
 

commit acbf17ae8f8ee0f941fe98ed12f115f2b349bba8
Author: Karel Zak <kzak@redhat.com>
Date:   Wed Aug 23 11:53:45 2023 +0200

    libblkid: (bcachefs) fix compiler warning [-Werror=sign-compare]
    
    Addresses: https://github.com/util-linux/util-linux/pull/2427
    Signed-off-by: Karel Zak <kzak@redhat.com>
    (cherry picked from commit 17873d38fc97913c0a31d4bd08cfbfe45c4de5be)

diff --git a/libblkid/src/superblocks/bcache.c b/libblkid/src/superblocks/bcache.c
index 236877042..6ab3fe9d4 100644
--- a/libblkid/src/superblocks/bcache.c
+++ b/libblkid/src/superblocks/bcache.c
@@ -311,7 +311,7 @@ static int probe_bcachefs(blkid_probe pr, const struct blkid_idmag *mag)
 		return BLKID_PROBE_NONE;
 
 	sb_size = BCACHEFS_SB_FIELDS_OFF + BYTES(bcs);
-	if (sb_size > BCACHEFS_SECTOR_SIZE << bcs->layout.sb_max_size_bits)
+	if (sb_size > ((uint64_t) BCACHEFS_SECTOR_SIZE << bcs->layout.sb_max_size_bits))
 		return BLKID_PROBE_NONE;
 
 	if (sb_size > BCACHEFS_SB_MAX_SIZE)

commit 6b9fda87c4e5d0c6f945d7565197f157b9fa3d5f
Author: Thomas Weißschuh <thomas@t-8ch.de>
Date:   Wed Aug 23 11:58:33 2023 +0200

    libblkid: (bcachefs) fix size validation
    
    Avoid signed shift out-of-bounds.
    
    Also mark the constants explitly as unsigned instead of casting.
    
    Signed-off-by: Thomas Weißschuh <thomas@t-8ch.de>
    (cherry picked from commit befe455f59de8c7bc66b85ed52aae8cbc95325fa)

diff --git a/libblkid/src/superblocks/bcache.c b/libblkid/src/superblocks/bcache.c
index 6ab3fe9d4..28ac4b52b 100644
--- a/libblkid/src/superblocks/bcache.c
+++ b/libblkid/src/superblocks/bcache.c
@@ -142,17 +142,19 @@ struct bcachefs_super_block {
 /* magic string len */
 #define BCACHE_SB_MAGIC_LEN (sizeof(BCACHE_SB_MAGIC) - 1)
 /* super block offset */
-#define BCACHE_SB_OFF       0x1000
+#define BCACHE_SB_OFF       0x1000U
 /* supper block offset in kB */
 #define BCACHE_SB_KBOFF     (BCACHE_SB_OFF >> 10)
 /* magic string offset within super block */
 #define BCACHE_SB_MAGIC_OFF offsetof(struct bcache_super_block, magic)
 /* start of checksummed data within superblock */
-#define BCACHE_SB_CSUMMED_START 8
+#define BCACHE_SB_CSUMMED_START 8U
 /* granularity of offset and length fields within superblock */
-#define BCACHEFS_SECTOR_SIZE   512
+#define BCACHEFS_SECTOR_SIZE   512U
+/* maximum superblock size shift */
+#define BCACHEFS_SB_MAX_SIZE_SHIFT   0x10U
 /* maximum superblock size */
-#define BCACHEFS_SB_MAX_SIZE   0x100000
+#define BCACHEFS_SB_MAX_SIZE   (1U << BCACHEFS_SB_MAX_SIZE_SHIFT)
 /* fields offset within super block */
 #define BCACHEFS_SB_FIELDS_OFF offsetof(struct bcachefs_super_block, _start)
 /* tag value for members field */
@@ -311,12 +313,16 @@ static int probe_bcachefs(blkid_probe pr, const struct blkid_idmag *mag)
 		return BLKID_PROBE_NONE;
 
 	sb_size = BCACHEFS_SB_FIELDS_OFF + BYTES(bcs);
-	if (sb_size > ((uint64_t) BCACHEFS_SECTOR_SIZE << bcs->layout.sb_max_size_bits))
-		return BLKID_PROBE_NONE;
 
 	if (sb_size > BCACHEFS_SB_MAX_SIZE)
 		return BLKID_PROBE_NONE;
 
+	if (bcs->layout.sb_max_size_bits > BCACHEFS_SB_MAX_SIZE_SHIFT)
+		return BLKID_PROBE_NONE;
+
+	if (sb_size > (BCACHEFS_SECTOR_SIZE << bcs->layout.sb_max_size_bits))
+		return BLKID_PROBE_NONE;
+
 	sb = blkid_probe_get_sb_buffer(pr, mag, sb_size);
 	if (!sb)
 		return BLKID_PROBE_NONE;