]>
Commit | Line | Data |
---|---|---|
0b2b52b7 JR |
1 | From e2a8296131e94ad785f5564156ed2db1fdb2e080 Mon Sep 17 00:00:00 2001 |
2 | From: Coleman Kane <ckane@colemankane.org> | |
3 | Date: Sat, 20 Mar 2021 00:00:59 -0400 | |
4 | Subject: [PATCH] Linux 5.12 compat: idmapped mounts | |
5 | ||
6 | In Linux 5.12, the filesystem API was modified to support ipmapped | |
7 | mounts by adding a "struct user_namespace *" parameter to a number | |
8 | functions and VFS handlers. This change adds the needed autoconf | |
9 | macros to detect the new interfaces and updates the code appropriately. | |
10 | This change does not add support for idmapped mounts, instead it | |
11 | preserves the existing behavior by passing the initial user namespace | |
12 | where needed. A subsequent commit will be required to add support | |
13 | for idmapped mounted. | |
14 | ||
15 | Reviewed-by: Tony Hutter <hutter2@llnl.gov> | |
16 | Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> | |
17 | Co-authored-by: Brian Behlendorf <behlendorf1@llnl.gov> | |
18 | Signed-off-by: Coleman Kane <ckane@colemankane.org> | |
19 | Closes #11712 | |
20 | --- | |
21 | config/kernel-generic_fillattr.m4 | 28 +++++++ | |
22 | config/kernel-inode-create.m4 | 43 +++++++++-- | |
23 | config/kernel-inode-getattr.m4 | 63 +++++++++++++--- | |
24 | config/kernel-is_owner_or_cap.m4 | 23 +++++- | |
25 | config/kernel-mkdir-umode-t.m4 | 32 -------- | |
26 | config/kernel-mkdir.m4 | 65 ++++++++++++++++ | |
27 | config/kernel-mknod.m4 | 30 ++++++++ | |
28 | config/kernel-rename.m4 | 50 ++++++++++--- | |
29 | config/kernel-setattr-prepare.m4 | 45 ++++++++--- | |
30 | config/kernel-symlink.m4 | 30 ++++++++ | |
31 | config/kernel-xattr-handler.m4 | 78 +++++++++++++------- | |
32 | config/kernel.m4 | 18 +++-- | |
33 | include/os/linux/kernel/linux/vfs_compat.h | 24 +++++- | |
34 | include/os/linux/kernel/linux/xattr_compat.h | 17 ++++- | |
35 | include/os/linux/zfs/sys/zfs_vnops_os.h | 3 +- | |
36 | include/os/linux/zfs/sys/zpl.h | 18 +++++ | |
37 | module/os/linux/zfs/policy.c | 2 +- | |
38 | module/os/linux/zfs/zfs_vnops_os.c | 5 +- | |
39 | module/os/linux/zfs/zpl_ctldir.c | 51 ++++++++++++- | |
40 | module/os/linux/zfs/zpl_file.c | 2 +- | |
41 | module/os/linux/zfs/zpl_inode.c | 49 +++++++++++- | |
42 | module/os/linux/zfs/zpl_xattr.c | 4 +- | |
43 | 22 files changed, 557 insertions(+), 123 deletions(-) | |
44 | create mode 100644 config/kernel-generic_fillattr.m4 | |
45 | delete mode 100644 config/kernel-mkdir-umode-t.m4 | |
46 | create mode 100644 config/kernel-mkdir.m4 | |
47 | create mode 100644 config/kernel-mknod.m4 | |
48 | create mode 100644 config/kernel-symlink.m4 | |
49 | ||
50 | diff --git a/config/kernel-generic_fillattr.m4 b/config/kernel-generic_fillattr.m4 | |
51 | new file mode 100644 | |
52 | index 00000000000..50c8031305b | |
53 | --- /dev/null | |
54 | +++ b/config/kernel-generic_fillattr.m4 | |
55 | @@ -0,0 +1,28 @@ | |
56 | +dnl # | |
57 | +dnl # 5.12 API | |
58 | +dnl # | |
59 | +dnl # generic_fillattr in linux/fs.h now requires a struct user_namespace* | |
60 | +dnl # as the first arg, to support idmapped mounts. | |
61 | +dnl # | |
62 | +AC_DEFUN([ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR_USERNS], [ | |
63 | + ZFS_LINUX_TEST_SRC([generic_fillattr_userns], [ | |
64 | + #include <linux/fs.h> | |
65 | + ],[ | |
66 | + struct user_namespace *userns = NULL; | |
67 | + struct inode *in = NULL; | |
68 | + struct kstat *k = NULL; | |
69 | + generic_fillattr(userns, in, k); | |
70 | + ]) | |
71 | +]) | |
72 | + | |
73 | +AC_DEFUN([ZFS_AC_KERNEL_GENERIC_FILLATTR_USERNS], [ | |
74 | + AC_MSG_CHECKING([whether generic_fillattr requres struct user_namespace*]) | |
75 | + ZFS_LINUX_TEST_RESULT([generic_fillattr_userns], [ | |
76 | + AC_MSG_RESULT([yes]) | |
77 | + AC_DEFINE(HAVE_GENERIC_FILLATTR_USERNS, 1, | |
78 | + [generic_fillattr requires struct user_namespace*]) | |
79 | + ],[ | |
80 | + AC_MSG_RESULT([no]) | |
81 | + ]) | |
82 | +]) | |
83 | + | |
84 | diff --git a/config/kernel-inode-create.m4 b/config/kernel-inode-create.m4 | |
85 | index 9f28bcbd4f7..a6ea11fb61b 100644 | |
86 | --- a/config/kernel-inode-create.m4 | |
87 | +++ b/config/kernel-inode-create.m4 | |
88 | @@ -1,7 +1,25 @@ | |
89 | -dnl # | |
90 | -dnl # 3.6 API change | |
91 | -dnl # | |
92 | -AC_DEFUN([ZFS_AC_KERNEL_SRC_CREATE_FLAGS], [ | |
93 | +AC_DEFUN([ZFS_AC_KERNEL_SRC_CREATE], [ | |
94 | + dnl # | |
95 | + dnl # 5.12 API change that added the struct user_namespace* arg | |
96 | + dnl # to the front of this function type's arg list. | |
97 | + dnl # | |
98 | + ZFS_LINUX_TEST_SRC([create_userns], [ | |
99 | + #include <linux/fs.h> | |
100 | + #include <linux/sched.h> | |
101 | + | |
102 | + int inode_create(struct user_namespace *userns, | |
103 | + struct inode *inode ,struct dentry *dentry, | |
104 | + umode_t umode, bool flag) { return 0; } | |
105 | + | |
106 | + static const struct inode_operations | |
107 | + iops __attribute__ ((unused)) = { | |
108 | + .create = inode_create, | |
109 | + }; | |
110 | + ],[]) | |
111 | + | |
112 | + dnl # | |
113 | + dnl # 3.6 API change | |
114 | + dnl # | |
115 | ZFS_LINUX_TEST_SRC([create_flags], [ | |
116 | #include <linux/fs.h> | |
117 | #include <linux/sched.h> | |
118 | @@ -16,11 +34,20 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_CREATE_FLAGS], [ | |
119 | ],[]) | |
120 | ]) | |
121 | ||
122 | -AC_DEFUN([ZFS_AC_KERNEL_CREATE_FLAGS], [ | |
123 | - AC_MSG_CHECKING([whether iops->create() passes flags]) | |
124 | - ZFS_LINUX_TEST_RESULT([create_flags], [ | |
125 | +AC_DEFUN([ZFS_AC_KERNEL_CREATE], [ | |
126 | + AC_MSG_CHECKING([whether iops->create() takes struct user_namespace*]) | |
127 | + ZFS_LINUX_TEST_RESULT([create_userns], [ | |
128 | AC_MSG_RESULT(yes) | |
129 | + AC_DEFINE(HAVE_IOPS_CREATE_USERNS, 1, | |
130 | + [iops->create() takes struct user_namespace*]) | |
131 | ],[ | |
132 | - ZFS_LINUX_TEST_ERROR([iops->create()]) | |
133 | + AC_MSG_RESULT(no) | |
134 | + | |
135 | + AC_MSG_CHECKING([whether iops->create() passes flags]) | |
136 | + ZFS_LINUX_TEST_RESULT([create_flags], [ | |
137 | + AC_MSG_RESULT(yes) | |
138 | + ],[ | |
139 | + ZFS_LINUX_TEST_ERROR([iops->create()]) | |
140 | + ]) | |
141 | ]) | |
142 | ]) | |
143 | diff --git a/config/kernel-inode-getattr.m4 b/config/kernel-inode-getattr.m4 | |
144 | index 48391d66f8b..f62e82f5230 100644 | |
145 | --- a/config/kernel-inode-getattr.m4 | |
146 | +++ b/config/kernel-inode-getattr.m4 | |
147 | @@ -1,8 +1,29 @@ | |
148 | -dnl # | |
149 | -dnl # Linux 4.11 API | |
150 | -dnl # See torvalds/linux@a528d35 | |
151 | -dnl # | |
152 | AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GETATTR], [ | |
153 | + dnl # | |
154 | + dnl # Linux 5.12 API | |
155 | + dnl # The getattr I/O operations handler type was extended to require | |
156 | + dnl # a struct user_namespace* as its first arg, to support idmapped | |
157 | + dnl # mounts. | |
158 | + dnl # | |
159 | + ZFS_LINUX_TEST_SRC([inode_operations_getattr_userns], [ | |
160 | + #include <linux/fs.h> | |
161 | + | |
162 | + int test_getattr( | |
163 | + struct user_namespace *userns, | |
164 | + const struct path *p, struct kstat *k, | |
165 | + u32 request_mask, unsigned int query_flags) | |
166 | + { return 0; } | |
167 | + | |
168 | + static const struct inode_operations | |
169 | + iops __attribute__ ((unused)) = { | |
170 | + .getattr = test_getattr, | |
171 | + }; | |
172 | + ],[]) | |
173 | + | |
174 | + dnl # | |
175 | + dnl # Linux 4.11 API | |
176 | + dnl # See torvalds/linux@a528d35 | |
177 | + dnl # | |
178 | ZFS_LINUX_TEST_SRC([inode_operations_getattr_path], [ | |
179 | #include <linux/fs.h> | |
180 | ||
181 | @@ -33,21 +54,39 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GETATTR], [ | |
182 | ]) | |
183 | ||
184 | AC_DEFUN([ZFS_AC_KERNEL_INODE_GETATTR], [ | |
185 | - AC_MSG_CHECKING([whether iops->getattr() takes a path]) | |
186 | - ZFS_LINUX_TEST_RESULT([inode_operations_getattr_path], [ | |
187 | + dnl # | |
188 | + dnl # Kernel 5.12 test | |
189 | + dnl # | |
190 | + AC_MSG_CHECKING([whether iops->getattr() takes user_namespace]) | |
191 | + ZFS_LINUX_TEST_RESULT([inode_operations_getattr_userns], [ | |
192 | AC_MSG_RESULT(yes) | |
193 | - AC_DEFINE(HAVE_PATH_IOPS_GETATTR, 1, | |
194 | - [iops->getattr() takes a path]) | |
195 | + AC_DEFINE(HAVE_USERNS_IOPS_GETATTR, 1, | |
196 | + [iops->getattr() takes struct user_namespace*]) | |
197 | ],[ | |
198 | AC_MSG_RESULT(no) | |
199 | ||
200 | - AC_MSG_CHECKING([whether iops->getattr() takes a vfsmount]) | |
201 | - ZFS_LINUX_TEST_RESULT([inode_operations_getattr_vfsmount], [ | |
202 | + dnl # | |
203 | + dnl # Kernel 4.11 test | |
204 | + dnl # | |
205 | + AC_MSG_CHECKING([whether iops->getattr() takes a path]) | |
206 | + ZFS_LINUX_TEST_RESULT([inode_operations_getattr_path], [ | |
207 | AC_MSG_RESULT(yes) | |
208 | - AC_DEFINE(HAVE_VFSMOUNT_IOPS_GETATTR, 1, | |
209 | - [iops->getattr() takes a vfsmount]) | |
210 | + AC_DEFINE(HAVE_PATH_IOPS_GETATTR, 1, | |
211 | + [iops->getattr() takes a path]) | |
212 | ],[ | |
213 | AC_MSG_RESULT(no) | |
214 | + | |
215 | + dnl # | |
216 | + dnl # Kernel < 4.11 test | |
217 | + dnl # | |
218 | + AC_MSG_CHECKING([whether iops->getattr() takes a vfsmount]) | |
219 | + ZFS_LINUX_TEST_RESULT([inode_operations_getattr_vfsmount], [ | |
220 | + AC_MSG_RESULT(yes) | |
221 | + AC_DEFINE(HAVE_VFSMOUNT_IOPS_GETATTR, 1, | |
222 | + [iops->getattr() takes a vfsmount]) | |
223 | + ],[ | |
224 | + AC_MSG_RESULT(no) | |
225 | + ]) | |
226 | ]) | |
227 | ]) | |
228 | ]) | |
229 | diff --git a/config/kernel-is_owner_or_cap.m4 b/config/kernel-is_owner_or_cap.m4 | |
230 | index 3df6163da27..3c3c6ad2240 100644 | |
231 | --- a/config/kernel-is_owner_or_cap.m4 | |
232 | +++ b/config/kernel-is_owner_or_cap.m4 | |
233 | @@ -11,13 +11,32 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_OWNER_OR_CAPABLE], [ | |
234 | struct inode *ip = NULL; | |
235 | (void) inode_owner_or_capable(ip); | |
236 | ]) | |
237 | + | |
238 | + ZFS_LINUX_TEST_SRC([inode_owner_or_capable_idmapped], [ | |
239 | + #include <linux/fs.h> | |
240 | + ],[ | |
241 | + struct inode *ip = NULL; | |
242 | + (void) inode_owner_or_capable(&init_user_ns, ip); | |
243 | + ]) | |
244 | ]) | |
245 | ||
246 | AC_DEFUN([ZFS_AC_KERNEL_INODE_OWNER_OR_CAPABLE], [ | |
247 | AC_MSG_CHECKING([whether inode_owner_or_capable() exists]) | |
248 | ZFS_LINUX_TEST_RESULT([inode_owner_or_capable], [ | |
249 | AC_MSG_RESULT(yes) | |
250 | - ],[ | |
251 | - ZFS_LINUX_TEST_ERROR([capability]) | |
252 | + AC_DEFINE(HAVE_INODE_OWNER_OR_CAPABLE, 1, | |
253 | + [inode_owner_or_capable() exists]) | |
254 | + ], [ | |
255 | + AC_MSG_RESULT(no) | |
256 | + | |
257 | + AC_MSG_CHECKING( | |
258 | + [whether inode_owner_or_capable() takes user_ns]) | |
259 | + ZFS_LINUX_TEST_RESULT([inode_owner_or_capable_idmapped], [ | |
260 | + AC_MSG_RESULT(yes) | |
261 | + AC_DEFINE(HAVE_INODE_OWNER_OR_CAPABLE_IDMAPPED, 1, | |
262 | + [inode_owner_or_capable() takes user_ns]) | |
263 | + ],[ | |
264 | + ZFS_LINUX_TEST_ERROR([capability]) | |
265 | + ]) | |
266 | ]) | |
267 | ]) | |
268 | diff --git a/config/kernel-mkdir-umode-t.m4 b/config/kernel-mkdir-umode-t.m4 | |
269 | deleted file mode 100644 | |
270 | index 19599670df3..00000000000 | |
271 | --- a/config/kernel-mkdir-umode-t.m4 | |
272 | +++ /dev/null | |
273 | @@ -1,32 +0,0 @@ | |
274 | -dnl # | |
275 | -dnl # 3.3 API change | |
276 | -dnl # The VFS .create, .mkdir and .mknod callbacks were updated to take a | |
277 | -dnl # umode_t type rather than an int. The expectation is that any backport | |
278 | -dnl # would also change all three prototypes. However, if it turns out that | |
279 | -dnl # some distribution doesn't backport the whole thing this could be | |
280 | -dnl # broken apart into three separate checks. | |
281 | -dnl # | |
282 | -AC_DEFUN([ZFS_AC_KERNEL_SRC_MKDIR_UMODE_T], [ | |
283 | - ZFS_LINUX_TEST_SRC([inode_operations_mkdir], [ | |
284 | - #include <linux/fs.h> | |
285 | - | |
286 | - int mkdir(struct inode *inode, struct dentry *dentry, | |
287 | - umode_t umode) { return 0; } | |
288 | - | |
289 | - static const struct inode_operations | |
290 | - iops __attribute__ ((unused)) = { | |
291 | - .mkdir = mkdir, | |
292 | - }; | |
293 | - ],[]) | |
294 | -]) | |
295 | - | |
296 | -AC_DEFUN([ZFS_AC_KERNEL_MKDIR_UMODE_T], [ | |
297 | - AC_MSG_CHECKING([whether iops->create()/mkdir()/mknod() take umode_t]) | |
298 | - ZFS_LINUX_TEST_RESULT([inode_operations_mkdir], [ | |
299 | - AC_MSG_RESULT(yes) | |
300 | - AC_DEFINE(HAVE_MKDIR_UMODE_T, 1, | |
301 | - [iops->create()/mkdir()/mknod() take umode_t]) | |
302 | - ],[ | |
303 | - ZFS_LINUX_TEST_ERROR([mkdir()]) | |
304 | - ]) | |
305 | -]) | |
306 | diff --git a/config/kernel-mkdir.m4 b/config/kernel-mkdir.m4 | |
307 | new file mode 100644 | |
308 | index 00000000000..a162bcd880f | |
309 | --- /dev/null | |
310 | +++ b/config/kernel-mkdir.m4 | |
311 | @@ -0,0 +1,65 @@ | |
312 | +dnl # | |
313 | +dnl # Supported mkdir() interfaces checked newest to oldest. | |
314 | +dnl # | |
315 | +AC_DEFUN([ZFS_AC_KERNEL_SRC_MKDIR], [ | |
316 | + dnl # | |
317 | + dnl # 5.12 API change | |
318 | + dnl # The struct user_namespace arg was added as the first argument to | |
319 | + dnl # mkdir() | |
320 | + dnl # | |
321 | + ZFS_LINUX_TEST_SRC([mkdir_user_namespace], [ | |
322 | + #include <linux/fs.h> | |
323 | + | |
324 | + int mkdir(struct user_namespace *userns, | |
325 | + struct inode *inode, struct dentry *dentry, | |
326 | + umode_t umode) { return 0; } | |
327 | + | |
328 | + static const struct inode_operations | |
329 | + iops __attribute__ ((unused)) = { | |
330 | + .mkdir = mkdir, | |
331 | + }; | |
332 | + ],[]) | |
333 | + | |
334 | + dnl # | |
335 | + dnl # 3.3 API change | |
336 | + dnl # The VFS .create, .mkdir and .mknod callbacks were updated to take a | |
337 | + dnl # umode_t type rather than an int. The expectation is that any backport | |
338 | + dnl # would also change all three prototypes. However, if it turns out that | |
339 | + dnl # some distribution doesn't backport the whole thing this could be | |
340 | + dnl # broken apart into three separate checks. | |
341 | + dnl # | |
342 | + ZFS_LINUX_TEST_SRC([inode_operations_mkdir], [ | |
343 | + #include <linux/fs.h> | |
344 | + | |
345 | + int mkdir(struct inode *inode, struct dentry *dentry, | |
346 | + umode_t umode) { return 0; } | |
347 | + | |
348 | + static const struct inode_operations | |
349 | + iops __attribute__ ((unused)) = { | |
350 | + .mkdir = mkdir, | |
351 | + }; | |
352 | + ],[]) | |
353 | +]) | |
354 | + | |
355 | +AC_DEFUN([ZFS_AC_KERNEL_MKDIR], [ | |
356 | + dnl # | |
357 | + dnl # 5.12 API change | |
358 | + dnl # The struct user_namespace arg was added as the first argument to | |
359 | + dnl # mkdir() of the iops structure. | |
360 | + dnl # | |
361 | + AC_MSG_CHECKING([whether iops->mkdir() takes struct user_namespace*]) | |
362 | + ZFS_LINUX_TEST_RESULT([mkdir_user_namespace], [ | |
363 | + AC_MSG_RESULT(yes) | |
364 | + AC_DEFINE(HAVE_IOPS_MKDIR_USERNS, 1, | |
365 | + [iops->mkdir() takes struct user_namespace*]) | |
366 | + ],[ | |
367 | + AC_MSG_CHECKING([whether iops->mkdir() takes umode_t]) | |
368 | + ZFS_LINUX_TEST_RESULT([inode_operations_mkdir], [ | |
369 | + AC_MSG_RESULT(yes) | |
370 | + AC_DEFINE(HAVE_MKDIR_UMODE_T, 1, | |
371 | + [iops->mkdir() takes umode_t]) | |
372 | + ],[ | |
373 | + ZFS_LINUX_TEST_ERROR([mkdir()]) | |
374 | + ]) | |
375 | + ]) | |
376 | +]) | |
377 | diff --git a/config/kernel-mknod.m4 b/config/kernel-mknod.m4 | |
378 | new file mode 100644 | |
379 | index 00000000000..ffe45106003 | |
380 | --- /dev/null | |
381 | +++ b/config/kernel-mknod.m4 | |
382 | @@ -0,0 +1,30 @@ | |
383 | +AC_DEFUN([ZFS_AC_KERNEL_SRC_MKNOD], [ | |
384 | + dnl # | |
385 | + dnl # 5.12 API change that added the struct user_namespace* arg | |
386 | + dnl # to the front of this function type's arg list. | |
387 | + dnl # | |
388 | + ZFS_LINUX_TEST_SRC([mknod_userns], [ | |
389 | + #include <linux/fs.h> | |
390 | + #include <linux/sched.h> | |
391 | + | |
392 | + int tmp_mknod(struct user_namespace *userns, | |
393 | + struct inode *inode ,struct dentry *dentry, | |
394 | + umode_t u, dev_t d) { return 0; } | |
395 | + | |
396 | + static const struct inode_operations | |
397 | + iops __attribute__ ((unused)) = { | |
398 | + .mknod = tmp_mknod, | |
399 | + }; | |
400 | + ],[]) | |
401 | +]) | |
402 | + | |
403 | +AC_DEFUN([ZFS_AC_KERNEL_MKNOD], [ | |
404 | + AC_MSG_CHECKING([whether iops->mknod() takes struct user_namespace*]) | |
405 | + ZFS_LINUX_TEST_RESULT([mknod_userns], [ | |
406 | + AC_MSG_RESULT(yes) | |
407 | + AC_DEFINE(HAVE_IOPS_MKNOD_USERNS, 1, | |
408 | + [iops->mknod() takes struct user_namespace*]) | |
409 | + ],[ | |
410 | + AC_MSG_RESULT(no) | |
411 | + ]) | |
412 | +]) | |
413 | diff --git a/config/kernel-rename.m4 b/config/kernel-rename.m4 | |
414 | index f707391539d..31d199f33bb 100644 | |
415 | --- a/config/kernel-rename.m4 | |
416 | +++ b/config/kernel-rename.m4 | |
417 | @@ -1,10 +1,10 @@ | |
418 | -dnl # | |
419 | -dnl # 4.9 API change, | |
420 | -dnl # iops->rename2() merged into iops->rename(), and iops->rename() now wants | |
421 | -dnl # flags. | |
422 | -dnl # | |
423 | -AC_DEFUN([ZFS_AC_KERNEL_SRC_RENAME_WANTS_FLAGS], [ | |
424 | - ZFS_LINUX_TEST_SRC([inode_operations_rename], [ | |
425 | +AC_DEFUN([ZFS_AC_KERNEL_SRC_RENAME], [ | |
426 | + dnl # | |
427 | + dnl # 4.9 API change, | |
428 | + dnl # iops->rename2() merged into iops->rename(), and iops->rename() now wants | |
429 | + dnl # flags. | |
430 | + dnl # | |
431 | + ZFS_LINUX_TEST_SRC([inode_operations_rename_flags], [ | |
432 | #include <linux/fs.h> | |
433 | int rename_fn(struct inode *sip, struct dentry *sdp, | |
434 | struct inode *tip, struct dentry *tdp, | |
435 | @@ -15,15 +15,41 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_RENAME_WANTS_FLAGS], [ | |
436 | .rename = rename_fn, | |
437 | }; | |
438 | ],[]) | |
439 | + | |
440 | + dnl # | |
441 | + dnl # 5.12 API change, | |
442 | + dnl # | |
443 | + dnl # Linux 5.12 introduced passing struct user_namespace* as the first argument | |
444 | + dnl # of the rename() and other inode_operations members. | |
445 | + dnl # | |
446 | + ZFS_LINUX_TEST_SRC([inode_operations_rename_userns], [ | |
447 | + #include <linux/fs.h> | |
448 | + int rename_fn(struct user_namespace *user_ns, struct inode *sip, | |
449 | + struct dentry *sdp, struct inode *tip, struct dentry *tdp, | |
450 | + unsigned int flags) { return 0; } | |
451 | + | |
452 | + static const struct inode_operations | |
453 | + iops __attribute__ ((unused)) = { | |
454 | + .rename = rename_fn, | |
455 | + }; | |
456 | + ],[]) | |
457 | ]) | |
458 | ||
459 | -AC_DEFUN([ZFS_AC_KERNEL_RENAME_WANTS_FLAGS], [ | |
460 | - AC_MSG_CHECKING([whether iops->rename() wants flags]) | |
461 | - ZFS_LINUX_TEST_RESULT([inode_operations_rename], [ | |
462 | +AC_DEFUN([ZFS_AC_KERNEL_RENAME], [ | |
463 | + AC_MSG_CHECKING([whether iops->rename() takes struct user_namespace*]) | |
464 | + ZFS_LINUX_TEST_RESULT([inode_operations_rename_userns], [ | |
465 | AC_MSG_RESULT(yes) | |
466 | - AC_DEFINE(HAVE_RENAME_WANTS_FLAGS, 1, | |
467 | - [iops->rename() wants flags]) | |
468 | + AC_DEFINE(HAVE_IOPS_RENAME_USERNS, 1, | |
469 | + [iops->rename() takes struct user_namespace*]) | |
470 | ],[ | |
471 | AC_MSG_RESULT(no) | |
472 | + | |
473 | + ZFS_LINUX_TEST_RESULT([inode_operations_rename_flags], [ | |
474 | + AC_MSG_RESULT(yes) | |
475 | + AC_DEFINE(HAVE_RENAME_WANTS_FLAGS, 1, | |
476 | + [iops->rename() wants flags]) | |
477 | + ],[ | |
478 | + AC_MSG_RESULT(no) | |
479 | + ]) | |
480 | ]) | |
481 | ]) | |
482 | diff --git a/config/kernel-setattr-prepare.m4 b/config/kernel-setattr-prepare.m4 | |
483 | index 45408c45c69..24245aa5344 100644 | |
484 | --- a/config/kernel-setattr-prepare.m4 | |
485 | +++ b/config/kernel-setattr-prepare.m4 | |
486 | @@ -1,27 +1,52 @@ | |
487 | -dnl # | |
488 | -dnl # 4.9 API change | |
489 | -dnl # The inode_change_ok() function has been renamed setattr_prepare() | |
490 | -dnl # and updated to take a dentry rather than an inode. | |
491 | -dnl # | |
492 | AC_DEFUN([ZFS_AC_KERNEL_SRC_SETATTR_PREPARE], [ | |
493 | + dnl # | |
494 | + dnl # 4.9 API change | |
495 | + dnl # The inode_change_ok() function has been renamed setattr_prepare() | |
496 | + dnl # and updated to take a dentry rather than an inode. | |
497 | + dnl # | |
498 | ZFS_LINUX_TEST_SRC([setattr_prepare], [ | |
499 | #include <linux/fs.h> | |
500 | ], [ | |
501 | struct dentry *dentry = NULL; | |
502 | struct iattr *attr = NULL; | |
503 | int error __attribute__ ((unused)) = | |
504 | - setattr_prepare(dentry, attr); | |
505 | + setattr_prepare(dentry, attr); | |
506 | + ]) | |
507 | + | |
508 | + dnl # | |
509 | + dnl # 5.12 API change | |
510 | + dnl # The setattr_prepare() function has been changed to accept a new argument | |
511 | + dnl # for struct user_namespace* | |
512 | + dnl # | |
513 | + ZFS_LINUX_TEST_SRC([setattr_prepare_userns], [ | |
514 | + #include <linux/fs.h> | |
515 | + ], [ | |
516 | + struct dentry *dentry = NULL; | |
517 | + struct iattr *attr = NULL; | |
518 | + struct user_namespace *userns = NULL; | |
519 | + int error __attribute__ ((unused)) = | |
520 | + setattr_prepare(userns, dentry, attr); | |
521 | ]) | |
522 | ]) | |
523 | ||
524 | AC_DEFUN([ZFS_AC_KERNEL_SETATTR_PREPARE], [ | |
525 | - AC_MSG_CHECKING([whether setattr_prepare() is available]) | |
526 | - ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare], | |
527 | + AC_MSG_CHECKING([whether setattr_prepare() is available and accepts struct user_namespace*]) | |
528 | + ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare_userns], | |
529 | [setattr_prepare], [fs/attr.c], [ | |
530 | AC_MSG_RESULT(yes) | |
531 | - AC_DEFINE(HAVE_SETATTR_PREPARE, 1, | |
532 | - [setattr_prepare() is available]) | |
533 | + AC_DEFINE(HAVE_SETATTR_PREPARE_USERNS, 1, | |
534 | + [setattr_prepare() accepts user_namespace]) | |
535 | ], [ | |
536 | AC_MSG_RESULT(no) | |
537 | + | |
538 | + AC_MSG_CHECKING([whether setattr_prepare() is available, doesn't accept user_namespace]) | |
539 | + ZFS_LINUX_TEST_RESULT_SYMBOL([setattr_prepare], | |
540 | + [setattr_prepare], [fs/attr.c], [ | |
541 | + AC_MSG_RESULT(yes) | |
542 | + AC_DEFINE(HAVE_SETATTR_PREPARE_NO_USERNS, 1, | |
543 | + [setattr_prepare() is available, doesn't accept user_namespace]) | |
544 | + ], [ | |
545 | + AC_MSG_RESULT(no) | |
546 | + ]) | |
547 | ]) | |
548 | ]) | |
549 | diff --git a/config/kernel-symlink.m4 b/config/kernel-symlink.m4 | |
550 | new file mode 100644 | |
551 | index 00000000000..d90366d04b7 | |
552 | --- /dev/null | |
553 | +++ b/config/kernel-symlink.m4 | |
554 | @@ -0,0 +1,30 @@ | |
555 | +AC_DEFUN([ZFS_AC_KERNEL_SRC_SYMLINK], [ | |
556 | + dnl # | |
557 | + dnl # 5.12 API change that added the struct user_namespace* arg | |
558 | + dnl # to the front of this function type's arg list. | |
559 | + dnl # | |
560 | + ZFS_LINUX_TEST_SRC([symlink_userns], [ | |
561 | + #include <linux/fs.h> | |
562 | + #include <linux/sched.h> | |
563 | + | |
564 | + int tmp_symlink(struct user_namespace *userns, | |
565 | + struct inode *inode ,struct dentry *dentry, | |
566 | + const char *path) { return 0; } | |
567 | + | |
568 | + static const struct inode_operations | |
569 | + iops __attribute__ ((unused)) = { | |
570 | + .symlink = tmp_symlink, | |
571 | + }; | |
572 | + ],[]) | |
573 | +]) | |
574 | + | |
575 | +AC_DEFUN([ZFS_AC_KERNEL_SYMLINK], [ | |
576 | + AC_MSG_CHECKING([whether iops->symlink() takes struct user_namespace*]) | |
577 | + ZFS_LINUX_TEST_RESULT([symlink_userns], [ | |
578 | + AC_MSG_RESULT(yes) | |
579 | + AC_DEFINE(HAVE_IOPS_SYMLINK_USERNS, 1, | |
580 | + [iops->symlink() takes struct user_namespace*]) | |
581 | + ],[ | |
582 | + AC_MSG_RESULT(no) | |
583 | + ]) | |
584 | +]) | |
585 | diff --git a/config/kernel-xattr-handler.m4 b/config/kernel-xattr-handler.m4 | |
586 | index 137bf4a8aff..00b1e74a9cc 100644 | |
587 | --- a/config/kernel-xattr-handler.m4 | |
588 | +++ b/config/kernel-xattr-handler.m4 | |
589 | @@ -152,6 +152,21 @@ dnl # | |
590 | dnl # Supported xattr handler set() interfaces checked newest to oldest. | |
591 | dnl # | |
592 | AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_SET], [ | |
593 | + ZFS_LINUX_TEST_SRC([xattr_handler_set_userns], [ | |
594 | + #include <linux/xattr.h> | |
595 | + | |
596 | + int set(const struct xattr_handler *handler, | |
597 | + struct user_namespace *mnt_userns, | |
598 | + struct dentry *dentry, struct inode *inode, | |
599 | + const char *name, const void *buffer, | |
600 | + size_t size, int flags) | |
601 | + { return 0; } | |
602 | + static const struct xattr_handler | |
603 | + xops __attribute__ ((unused)) = { | |
604 | + .set = set, | |
605 | + }; | |
606 | + ],[]) | |
607 | + | |
608 | ZFS_LINUX_TEST_SRC([xattr_handler_set_dentry_inode], [ | |
609 | #include <linux/xattr.h> | |
610 | ||
611 | @@ -194,45 +209,58 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_XATTR_HANDLER_SET], [ | |
612 | ||
613 | AC_DEFUN([ZFS_AC_KERNEL_XATTR_HANDLER_SET], [ | |
614 | dnl # | |
615 | - dnl # 4.7 API change, | |
616 | - dnl # The xattr_handler->set() callback was changed to take both | |
617 | - dnl # dentry and inode. | |
618 | + dnl # 5.12 API change, | |
619 | + dnl # The xattr_handler->set() callback was changed to 8 arguments, and | |
620 | + dnl # struct user_namespace* was inserted as arg #2 | |
621 | dnl # | |
622 | - AC_MSG_CHECKING([whether xattr_handler->set() wants dentry and inode]) | |
623 | - ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry_inode], [ | |
624 | + AC_MSG_CHECKING([whether xattr_handler->set() wants dentry, inode, and user_namespace]) | |
625 | + ZFS_LINUX_TEST_RESULT([xattr_handler_set_userns], [ | |
626 | AC_MSG_RESULT(yes) | |
627 | - AC_DEFINE(HAVE_XATTR_SET_DENTRY_INODE, 1, | |
628 | - [xattr_handler->set() wants both dentry and inode]) | |
629 | + AC_DEFINE(HAVE_XATTR_SET_USERNS, 1, | |
630 | + [xattr_handler->set() takes user_namespace]) | |
631 | ],[ | |
632 | dnl # | |
633 | - dnl # 4.4 API change, | |
634 | - dnl # The xattr_handler->set() callback was changed to take a | |
635 | - dnl # xattr_handler, and handler_flags argument was removed and | |
636 | - dnl # should be accessed by handler->flags. | |
637 | + dnl # 4.7 API change, | |
638 | + dnl # The xattr_handler->set() callback was changed to take both | |
639 | + dnl # dentry and inode. | |
640 | dnl # | |
641 | AC_MSG_RESULT(no) | |
642 | - AC_MSG_CHECKING( | |
643 | - [whether xattr_handler->set() wants xattr_handler]) | |
644 | - ZFS_LINUX_TEST_RESULT([xattr_handler_set_xattr_handler], [ | |
645 | + AC_MSG_CHECKING([whether xattr_handler->set() wants dentry and inode]) | |
646 | + ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry_inode], [ | |
647 | AC_MSG_RESULT(yes) | |
648 | - AC_DEFINE(HAVE_XATTR_SET_HANDLER, 1, | |
649 | - [xattr_handler->set() wants xattr_handler]) | |
650 | + AC_DEFINE(HAVE_XATTR_SET_DENTRY_INODE, 1, | |
651 | + [xattr_handler->set() wants both dentry and inode]) | |
652 | ],[ | |
653 | dnl # | |
654 | - dnl # 2.6.33 API change, | |
655 | - dnl # The xattr_handler->set() callback was changed | |
656 | - dnl # to take a dentry instead of an inode, and a | |
657 | - dnl # handler_flags argument was added. | |
658 | + dnl # 4.4 API change, | |
659 | + dnl # The xattr_handler->set() callback was changed to take a | |
660 | + dnl # xattr_handler, and handler_flags argument was removed and | |
661 | + dnl # should be accessed by handler->flags. | |
662 | dnl # | |
663 | AC_MSG_RESULT(no) | |
664 | AC_MSG_CHECKING( | |
665 | - [whether xattr_handler->set() wants dentry]) | |
666 | - ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry], [ | |
667 | + [whether xattr_handler->set() wants xattr_handler]) | |
668 | + ZFS_LINUX_TEST_RESULT([xattr_handler_set_xattr_handler], [ | |
669 | AC_MSG_RESULT(yes) | |
670 | - AC_DEFINE(HAVE_XATTR_SET_DENTRY, 1, | |
671 | - [xattr_handler->set() wants dentry]) | |
672 | + AC_DEFINE(HAVE_XATTR_SET_HANDLER, 1, | |
673 | + [xattr_handler->set() wants xattr_handler]) | |
674 | ],[ | |
675 | - ZFS_LINUX_TEST_ERROR([xattr set()]) | |
676 | + dnl # | |
677 | + dnl # 2.6.33 API change, | |
678 | + dnl # The xattr_handler->set() callback was changed | |
679 | + dnl # to take a dentry instead of an inode, and a | |
680 | + dnl # handler_flags argument was added. | |
681 | + dnl # | |
682 | + AC_MSG_RESULT(no) | |
683 | + AC_MSG_CHECKING( | |
684 | + [whether xattr_handler->set() wants dentry]) | |
685 | + ZFS_LINUX_TEST_RESULT([xattr_handler_set_dentry], [ | |
686 | + AC_MSG_RESULT(yes) | |
687 | + AC_DEFINE(HAVE_XATTR_SET_DENTRY, 1, | |
688 | + [xattr_handler->set() wants dentry]) | |
689 | + ],[ | |
690 | + ZFS_LINUX_TEST_ERROR([xattr set()]) | |
691 | + ]) | |
692 | ]) | |
693 | ]) | |
694 | ]) | |
695 | diff --git a/config/kernel.m4 b/config/kernel.m4 | |
696 | index f31be845f5d..24db38f09f4 100644 | |
697 | --- a/config/kernel.m4 | |
698 | +++ b/config/kernel.m4 | |
699 | @@ -79,9 +79,9 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ | |
700 | ZFS_AC_KERNEL_SRC_EVICT_INODE | |
701 | ZFS_AC_KERNEL_SRC_DIRTY_INODE | |
702 | ZFS_AC_KERNEL_SRC_SHRINKER | |
703 | - ZFS_AC_KERNEL_SRC_MKDIR_UMODE_T | |
704 | + ZFS_AC_KERNEL_SRC_MKDIR | |
705 | ZFS_AC_KERNEL_SRC_LOOKUP_FLAGS | |
706 | - ZFS_AC_KERNEL_SRC_CREATE_FLAGS | |
707 | + ZFS_AC_KERNEL_SRC_CREATE | |
708 | ZFS_AC_KERNEL_SRC_GET_LINK | |
709 | ZFS_AC_KERNEL_SRC_PUT_LINK | |
710 | ZFS_AC_KERNEL_SRC_TMPFILE | |
711 | @@ -115,7 +115,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ | |
712 | ZFS_AC_KERNEL_SRC_KUIDGID_T | |
713 | ZFS_AC_KERNEL_SRC_KUID_HELPERS | |
714 | ZFS_AC_KERNEL_SRC_MODULE_PARAM_CALL_CONST | |
715 | - ZFS_AC_KERNEL_SRC_RENAME_WANTS_FLAGS | |
716 | + ZFS_AC_KERNEL_SRC_RENAME | |
717 | ZFS_AC_KERNEL_SRC_CURRENT_TIME | |
718 | ZFS_AC_KERNEL_SRC_USERNS_CAPABILITIES | |
719 | ZFS_AC_KERNEL_SRC_IN_COMPAT_SYSCALL | |
720 | @@ -125,6 +125,9 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ | |
721 | ZFS_AC_KERNEL_SRC_TOTALHIGH_PAGES | |
722 | ZFS_AC_KERNEL_SRC_KSTRTOUL | |
723 | ZFS_AC_KERNEL_SRC_PERCPU | |
724 | + ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR_USERNS | |
725 | + ZFS_AC_KERNEL_SRC_MKNOD | |
726 | + ZFS_AC_KERNEL_SRC_SYMLINK | |
727 | ||
728 | AC_MSG_CHECKING([for available kernel interfaces]) | |
729 | ZFS_LINUX_TEST_COMPILE_ALL([kabi]) | |
730 | @@ -177,9 +180,9 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ | |
731 | ZFS_AC_KERNEL_EVICT_INODE | |
732 | ZFS_AC_KERNEL_DIRTY_INODE | |
733 | ZFS_AC_KERNEL_SHRINKER | |
734 | - ZFS_AC_KERNEL_MKDIR_UMODE_T | |
735 | + ZFS_AC_KERNEL_MKDIR | |
736 | ZFS_AC_KERNEL_LOOKUP_FLAGS | |
737 | - ZFS_AC_KERNEL_CREATE_FLAGS | |
738 | + ZFS_AC_KERNEL_CREATE | |
739 | ZFS_AC_KERNEL_GET_LINK | |
740 | ZFS_AC_KERNEL_PUT_LINK | |
741 | ZFS_AC_KERNEL_TMPFILE | |
742 | @@ -213,7 +216,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ | |
743 | ZFS_AC_KERNEL_KUIDGID_T | |
744 | ZFS_AC_KERNEL_KUID_HELPERS | |
745 | ZFS_AC_KERNEL_MODULE_PARAM_CALL_CONST | |
746 | - ZFS_AC_KERNEL_RENAME_WANTS_FLAGS | |
747 | + ZFS_AC_KERNEL_RENAME | |
748 | ZFS_AC_KERNEL_CURRENT_TIME | |
749 | ZFS_AC_KERNEL_USERNS_CAPABILITIES | |
750 | ZFS_AC_KERNEL_IN_COMPAT_SYSCALL | |
751 | @@ -223,6 +226,9 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ | |
752 | ZFS_AC_KERNEL_TOTALHIGH_PAGES | |
753 | ZFS_AC_KERNEL_KSTRTOUL | |
754 | ZFS_AC_KERNEL_PERCPU | |
755 | + ZFS_AC_KERNEL_GENERIC_FILLATTR_USERNS | |
756 | + ZFS_AC_KERNEL_MKNOD | |
757 | + ZFS_AC_KERNEL_SYMLINK | |
758 | ]) | |
759 | ||
760 | dnl # | |
761 | diff --git a/include/os/linux/kernel/linux/vfs_compat.h b/include/os/linux/kernel/linux/vfs_compat.h | |
762 | index c35e80d31cd..91e908598fb 100644 | |
763 | --- a/include/os/linux/kernel/linux/vfs_compat.h | |
764 | +++ b/include/os/linux/kernel/linux/vfs_compat.h | |
765 | @@ -343,7 +343,8 @@ static inline void zfs_gid_write(struct inode *ip, gid_t gid) | |
766 | /* | |
767 | * 4.9 API change | |
768 | */ | |
769 | -#ifndef HAVE_SETATTR_PREPARE | |
770 | +#if !(defined(HAVE_SETATTR_PREPARE_NO_USERNS) || \ | |
771 | + defined(HAVE_SETATTR_PREPARE_USERNS)) | |
772 | static inline int | |
773 | setattr_prepare(struct dentry *dentry, struct iattr *ia) | |
774 | { | |
775 | @@ -389,6 +390,15 @@ func(const struct path *path, struct kstat *stat, u32 request_mask, \ | |
776 | { \ | |
777 | return (func##_impl(path, stat, request_mask, query_flags)); \ | |
778 | } | |
779 | +#elif defined(HAVE_USERNS_IOPS_GETATTR) | |
780 | +#define ZPL_GETATTR_WRAPPER(func) \ | |
781 | +static int \ | |
782 | +func(struct user_namespace *user_ns, const struct path *path, \ | |
783 | + struct kstat *stat, u32 request_mask, unsigned int query_flags) \ | |
784 | +{ \ | |
785 | + return (func##_impl(user_ns, path, stat, request_mask, \ | |
786 | + query_flags)); \ | |
787 | +} | |
788 | #else | |
789 | #error | |
790 | #endif | |
791 | @@ -436,4 +446,16 @@ zpl_is_32bit_api(void) | |
792 | #endif | |
793 | } | |
794 | ||
795 | +/* | |
796 | + * 5.12 API change | |
797 | + * To support id-mapped mounts, generic_fillattr() was modified to | |
798 | + * accept a new struct user_namespace* as its first arg. | |
799 | + */ | |
800 | +#ifdef HAVE_GENERIC_FILLATTR_USERNS | |
801 | +#define zpl_generic_fillattr(user_ns, ip, sp) \ | |
802 | + generic_fillattr(user_ns, ip, sp) | |
803 | +#else | |
804 | +#define zpl_generic_fillattr(user_ns, ip, sp) generic_fillattr(ip, sp) | |
805 | +#endif | |
806 | + | |
807 | #endif /* _ZFS_VFS_H */ | |
808 | diff --git a/include/os/linux/kernel/linux/xattr_compat.h b/include/os/linux/kernel/linux/xattr_compat.h | |
809 | index 8348e99198a..54690727eab 100644 | |
810 | --- a/include/os/linux/kernel/linux/xattr_compat.h | |
811 | +++ b/include/os/linux/kernel/linux/xattr_compat.h | |
812 | @@ -119,12 +119,27 @@ fn(struct dentry *dentry, const char *name, void *buffer, size_t size, \ | |
813 | #error "Unsupported kernel" | |
814 | #endif | |
815 | ||
816 | +/* | |
817 | + * 5.12 API change, | |
818 | + * The xattr_handler->set() callback was changed to take the | |
819 | + * struct user_namespace* as the first arg, to support idmapped | |
820 | + * mounts. | |
821 | + */ | |
822 | +#if defined(HAVE_XATTR_SET_USERNS) | |
823 | +#define ZPL_XATTR_SET_WRAPPER(fn) \ | |
824 | +static int \ | |
825 | +fn(const struct xattr_handler *handler, struct user_namespace *user_ns, \ | |
826 | + struct dentry *dentry, struct inode *inode, const char *name, \ | |
827 | + const void *buffer, size_t size, int flags) \ | |
828 | +{ \ | |
829 | + return (__ ## fn(inode, name, buffer, size, flags)); \ | |
830 | +} | |
831 | /* | |
832 | * 4.7 API change, | |
833 | * The xattr_handler->set() callback was changed to take a both dentry and | |
834 | * inode, because the dentry might not be attached to an inode yet. | |
835 | */ | |
836 | -#if defined(HAVE_XATTR_SET_DENTRY_INODE) | |
837 | +#elif defined(HAVE_XATTR_SET_DENTRY_INODE) | |
838 | #define ZPL_XATTR_SET_WRAPPER(fn) \ | |
839 | static int \ | |
840 | fn(const struct xattr_handler *handler, struct dentry *dentry, \ | |
841 | diff --git a/include/os/linux/zfs/sys/zfs_vnops_os.h b/include/os/linux/zfs/sys/zfs_vnops_os.h | |
842 | index ef76de3e298..47f91e4a6cf 100644 | |
843 | --- a/include/os/linux/zfs/sys/zfs_vnops_os.h | |
844 | +++ b/include/os/linux/zfs/sys/zfs_vnops_os.h | |
845 | @@ -54,7 +54,8 @@ extern int zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap, | |
846 | extern int zfs_rmdir(znode_t *dzp, char *name, znode_t *cwd, | |
847 | cred_t *cr, int flags); | |
848 | extern int zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr); | |
849 | -extern int zfs_getattr_fast(struct inode *ip, struct kstat *sp); | |
850 | +extern int zfs_getattr_fast(struct user_namespace *, struct inode *ip, | |
851 | + struct kstat *sp); | |
852 | extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr); | |
853 | extern int zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, | |
854 | char *tnm, cred_t *cr, int flags); | |
855 | diff --git a/include/os/linux/zfs/sys/zpl.h b/include/os/linux/zfs/sys/zpl.h | |
856 | index b0bb9c29c0b..21825d1f378 100644 | |
857 | --- a/include/os/linux/zfs/sys/zpl.h | |
858 | +++ b/include/os/linux/zfs/sys/zpl.h | |
859 | @@ -171,4 +171,22 @@ zpl_dir_emit_dots(struct file *file, zpl_dir_context_t *ctx) | |
860 | timespec_trunc(ts, (ip)->i_sb->s_time_gran) | |
861 | #endif | |
862 | ||
863 | +#if defined(HAVE_INODE_OWNER_OR_CAPABLE) | |
864 | +#define zpl_inode_owner_or_capable(ns, ip) inode_owner_or_capable(ip) | |
865 | +#elif defined(HAVE_INODE_OWNER_OR_CAPABLE_IDMAPPED) | |
866 | +#define zpl_inode_owner_or_capable(ns, ip) inode_owner_or_capable(ns, ip) | |
867 | +#else | |
868 | +#error "Unsupported kernel" | |
869 | +#endif | |
870 | + | |
871 | +#ifdef HAVE_SETATTR_PREPARE_USERNS | |
872 | +#define zpl_setattr_prepare(ns, dentry, ia) setattr_prepare(ns, dentry, ia) | |
873 | +#else | |
874 | +/* | |
875 | + * Use kernel-provided version, or our own from | |
876 | + * linux/vfs_compat.h | |
877 | + */ | |
878 | +#define zpl_setattr_prepare(ns, dentry, ia) setattr_prepare(dentry, ia) | |
879 | +#endif | |
880 | + | |
881 | #endif /* _SYS_ZPL_H */ | |
882 | diff --git a/module/os/linux/zfs/policy.c b/module/os/linux/zfs/policy.c | |
883 | index 8780d7f6c70..bbccb2e572d 100644 | |
884 | --- a/module/os/linux/zfs/policy.c | |
885 | +++ b/module/os/linux/zfs/policy.c | |
886 | @@ -124,7 +124,7 @@ secpolicy_vnode_any_access(const cred_t *cr, struct inode *ip, uid_t owner) | |
887 | if (crgetfsuid(cr) == owner) | |
888 | return (0); | |
889 | ||
890 | - if (inode_owner_or_capable(ip)) | |
891 | + if (zpl_inode_owner_or_capable(kcred->user_ns, ip)) | |
892 | return (0); | |
893 | ||
894 | #if defined(CONFIG_USER_NS) | |
895 | diff --git a/module/os/linux/zfs/zfs_vnops_os.c b/module/os/linux/zfs/zfs_vnops_os.c | |
896 | index 84c33b541ea..8aeed6f568c 100644 | |
897 | --- a/module/os/linux/zfs/zfs_vnops_os.c | |
898 | +++ b/module/os/linux/zfs/zfs_vnops_os.c | |
899 | @@ -1656,7 +1656,8 @@ zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr) | |
900 | */ | |
901 | /* ARGSUSED */ | |
902 | int | |
903 | -zfs_getattr_fast(struct inode *ip, struct kstat *sp) | |
904 | +zfs_getattr_fast(struct user_namespace *user_ns, struct inode *ip, | |
905 | + struct kstat *sp) | |
906 | { | |
907 | znode_t *zp = ITOZ(ip); | |
908 | zfsvfs_t *zfsvfs = ITOZSB(ip); | |
909 | @@ -1668,7 +1669,7 @@ zfs_getattr_fast(struct inode *ip, struct kstat *sp) | |
910 | ||
911 | mutex_enter(&zp->z_lock); | |
912 | ||
913 | - generic_fillattr(ip, sp); | |
914 | + zpl_generic_fillattr(user_ns, ip, sp); | |
915 | /* | |
916 | * +1 link count for root inode with visible '.zfs' directory. | |
917 | */ | |
918 | diff --git a/module/os/linux/zfs/zpl_ctldir.c b/module/os/linux/zfs/zpl_ctldir.c | |
919 | index e6420f19ed8..9b526afd000 100644 | |
920 | --- a/module/os/linux/zfs/zpl_ctldir.c | |
921 | +++ b/module/os/linux/zfs/zpl_ctldir.c | |
922 | @@ -101,12 +101,22 @@ zpl_root_readdir(struct file *filp, void *dirent, filldir_t filldir) | |
923 | */ | |
924 | /* ARGSUSED */ | |
925 | static int | |
926 | +#ifdef HAVE_USERNS_IOPS_GETATTR | |
927 | +zpl_root_getattr_impl(struct user_namespace *user_ns, | |
928 | + const struct path *path, struct kstat *stat, u32 request_mask, | |
929 | + unsigned int query_flags) | |
930 | +#else | |
931 | zpl_root_getattr_impl(const struct path *path, struct kstat *stat, | |
932 | u32 request_mask, unsigned int query_flags) | |
933 | +#endif | |
934 | { | |
935 | struct inode *ip = path->dentry->d_inode; | |
936 | ||
937 | +#if defined(HAVE_GENERIC_FILLATTR_USERNS) && defined(HAVE_USERNS_IOPS_GETATTR) | |
938 | + generic_fillattr(user_ns, ip, stat); | |
939 | +#else | |
940 | generic_fillattr(ip, stat); | |
941 | +#endif | |
942 | stat->atime = current_time(ip); | |
943 | ||
944 | return (0); | |
945 | @@ -290,8 +300,14 @@ zpl_snapdir_readdir(struct file *filp, void *dirent, filldir_t filldir) | |
946 | #endif /* !HAVE_VFS_ITERATE && !HAVE_VFS_ITERATE_SHARED */ | |
947 | ||
948 | static int | |
949 | +#ifdef HAVE_IOPS_RENAME_USERNS | |
950 | +zpl_snapdir_rename2(struct user_namespace *user_ns, struct inode *sdip, | |
951 | + struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry, | |
952 | + unsigned int flags) | |
953 | +#else | |
954 | zpl_snapdir_rename2(struct inode *sdip, struct dentry *sdentry, | |
955 | struct inode *tdip, struct dentry *tdentry, unsigned int flags) | |
956 | +#endif | |
957 | { | |
958 | cred_t *cr = CRED(); | |
959 | int error; | |
960 | @@ -309,7 +325,7 @@ zpl_snapdir_rename2(struct inode *sdip, struct dentry *sdentry, | |
961 | return (error); | |
962 | } | |
963 | ||
964 | -#ifndef HAVE_RENAME_WANTS_FLAGS | |
965 | +#if !defined(HAVE_RENAME_WANTS_FLAGS) && !defined(HAVE_IOPS_RENAME_USERNS) | |
966 | static int | |
967 | zpl_snapdir_rename(struct inode *sdip, struct dentry *sdentry, | |
968 | struct inode *tdip, struct dentry *tdentry) | |
969 | @@ -333,7 +349,12 @@ zpl_snapdir_rmdir(struct inode *dip, struct dentry *dentry) | |
970 | } | |
971 | ||
972 | static int | |
973 | +#ifdef HAVE_IOPS_MKDIR_USERNS | |
974 | +zpl_snapdir_mkdir(struct user_namespace *user_ns, struct inode *dip, | |
975 | + struct dentry *dentry, umode_t mode) | |
976 | +#else | |
977 | zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode) | |
978 | +#endif | |
979 | { | |
980 | cred_t *cr = CRED(); | |
981 | vattr_t *vap; | |
982 | @@ -363,14 +384,24 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode) | |
983 | */ | |
984 | /* ARGSUSED */ | |
985 | static int | |
986 | +#ifdef HAVE_USERNS_IOPS_GETATTR | |
987 | +zpl_snapdir_getattr_impl(struct user_namespace *user_ns, | |
988 | + const struct path *path, struct kstat *stat, u32 request_mask, | |
989 | + unsigned int query_flags) | |
990 | +#else | |
991 | zpl_snapdir_getattr_impl(const struct path *path, struct kstat *stat, | |
992 | u32 request_mask, unsigned int query_flags) | |
993 | +#endif | |
994 | { | |
995 | struct inode *ip = path->dentry->d_inode; | |
996 | zfsvfs_t *zfsvfs = ITOZSB(ip); | |
997 | ||
998 | ZPL_ENTER(zfsvfs); | |
999 | +#if defined(HAVE_GENERIC_FILLATTR_USERNS) && defined(HAVE_USERNS_IOPS_GETATTR) | |
1000 | + generic_fillattr(user_ns, ip, stat); | |
1001 | +#else | |
1002 | generic_fillattr(ip, stat); | |
1003 | +#endif | |
1004 | ||
1005 | stat->nlink = stat->size = 2; | |
1006 | stat->ctime = stat->mtime = dmu_objset_snap_cmtime(zfsvfs->z_os); | |
1007 | @@ -408,7 +439,7 @@ const struct file_operations zpl_fops_snapdir = { | |
1008 | const struct inode_operations zpl_ops_snapdir = { | |
1009 | .lookup = zpl_snapdir_lookup, | |
1010 | .getattr = zpl_snapdir_getattr, | |
1011 | -#ifdef HAVE_RENAME_WANTS_FLAGS | |
1012 | +#if defined(HAVE_RENAME_WANTS_FLAGS) || defined(HAVE_IOPS_RENAME_USERNS) | |
1013 | .rename = zpl_snapdir_rename2, | |
1014 | #else | |
1015 | .rename = zpl_snapdir_rename, | |
1016 | @@ -495,8 +526,14 @@ zpl_shares_readdir(struct file *filp, void *dirent, filldir_t filldir) | |
1017 | ||
1018 | /* ARGSUSED */ | |
1019 | static int | |
1020 | +#ifdef HAVE_USERNS_IOPS_GETATTR | |
1021 | +zpl_shares_getattr_impl(struct user_namespace *user_ns, | |
1022 | + const struct path *path, struct kstat *stat, u32 request_mask, | |
1023 | + unsigned int query_flags) | |
1024 | +#else | |
1025 | zpl_shares_getattr_impl(const struct path *path, struct kstat *stat, | |
1026 | u32 request_mask, unsigned int query_flags) | |
1027 | +#endif | |
1028 | { | |
1029 | struct inode *ip = path->dentry->d_inode; | |
1030 | zfsvfs_t *zfsvfs = ITOZSB(ip); | |
1031 | @@ -506,7 +543,11 @@ zpl_shares_getattr_impl(const struct path *path, struct kstat *stat, | |
1032 | ZPL_ENTER(zfsvfs); | |
1033 | ||
1034 | if (zfsvfs->z_shares_dir == 0) { | |
1035 | +#if defined(HAVE_GENERIC_FILLATTR_USERNS) && defined(HAVE_USERNS_IOPS_GETATTR) | |
1036 | + generic_fillattr(user_ns, path->dentry->d_inode, stat); | |
1037 | +#else | |
1038 | generic_fillattr(path->dentry->d_inode, stat); | |
1039 | +#endif | |
1040 | stat->nlink = stat->size = 2; | |
1041 | stat->atime = current_time(ip); | |
1042 | ZPL_EXIT(zfsvfs); | |
1043 | @@ -515,7 +556,11 @@ zpl_shares_getattr_impl(const struct path *path, struct kstat *stat, | |
1044 | ||
1045 | error = -zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp); | |
1046 | if (error == 0) { | |
1047 | - error = -zfs_getattr_fast(ZTOI(dzp), stat); | |
1048 | +#if defined(HAVE_GENERIC_FILLATTR_USERNS) && defined(HAVE_USERNS_IOPS_GETATTR) | |
1049 | + error = -zfs_getattr_fast(user_ns, ZTOI(dzp), stat); | |
1050 | +#else | |
1051 | + error = -zfs_getattr_fast(kcred->user_ns, ZTOI(dzp), stat); | |
1052 | +#endif | |
1053 | iput(ZTOI(dzp)); | |
1054 | } | |
1055 | ||
1056 | diff --git a/module/os/linux/zfs/zpl_file.c b/module/os/linux/zfs/zpl_file.c | |
1057 | index 970db4a8b73..ea6993ffa4b 100644 | |
1058 | --- a/module/os/linux/zfs/zpl_file.c | |
1059 | +++ b/module/os/linux/zfs/zpl_file.c | |
1060 | @@ -869,7 +869,7 @@ __zpl_ioctl_setflags(struct inode *ip, uint32_t ioctl_flags, xvattr_t *xva) | |
1061 | !capable(CAP_LINUX_IMMUTABLE)) | |
1062 | return (-EACCES); | |
1063 | ||
1064 | - if (!inode_owner_or_capable(ip)) | |
1065 | + if (!zpl_inode_owner_or_capable(kcred->user_ns, ip)) | |
1066 | return (-EACCES); | |
1067 | ||
1068 | xva_init(xva); | |
1069 | diff --git a/module/os/linux/zfs/zpl_inode.c b/module/os/linux/zfs/zpl_inode.c | |
1070 | index 117963f44af..cf0eab3e8c9 100644 | |
1071 | --- a/module/os/linux/zfs/zpl_inode.c | |
1072 | +++ b/module/os/linux/zfs/zpl_inode.c | |
1073 | @@ -128,7 +128,12 @@ zpl_vap_init(vattr_t *vap, struct inode *dir, umode_t mode, cred_t *cr) | |
1074 | } | |
1075 | ||
1076 | static int | |
1077 | +#ifdef HAVE_IOPS_CREATE_USERNS | |
1078 | +zpl_create(struct user_namespace *user_ns, struct inode *dir, | |
1079 | + struct dentry *dentry, umode_t mode, bool flag) | |
1080 | +#else | |
1081 | zpl_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool flag) | |
1082 | +#endif | |
1083 | { | |
1084 | cred_t *cr = CRED(); | |
1085 | znode_t *zp; | |
1086 | @@ -163,7 +168,12 @@ zpl_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool flag) | |
1087 | } | |
1088 | ||
1089 | static int | |
1090 | +#ifdef HAVE_IOPS_MKNOD_USERNS | |
1091 | +zpl_mknod(struct user_namespace *user_ns, struct inode *dir, | |
1092 | + struct dentry *dentry, umode_t mode, | |
1093 | +#else | |
1094 | zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, | |
1095 | +#endif | |
1096 | dev_t rdev) | |
1097 | { | |
1098 | cred_t *cr = CRED(); | |
1099 | @@ -278,7 +288,12 @@ zpl_unlink(struct inode *dir, struct dentry *dentry) | |
1100 | } | |
1101 | ||
1102 | static int | |
1103 | +#ifdef HAVE_IOPS_MKDIR_USERNS | |
1104 | +zpl_mkdir(struct user_namespace *user_ns, struct inode *dir, | |
1105 | + struct dentry *dentry, umode_t mode) | |
1106 | +#else | |
1107 | zpl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |
1108 | +#endif | |
1109 | { | |
1110 | cred_t *cr = CRED(); | |
1111 | vattr_t *vap; | |
1112 | @@ -338,8 +353,14 @@ zpl_rmdir(struct inode *dir, struct dentry *dentry) | |
1113 | } | |
1114 | ||
1115 | static int | |
1116 | +#ifdef HAVE_USERNS_IOPS_GETATTR | |
1117 | +zpl_getattr_impl(struct user_namespace *user_ns, | |
1118 | + const struct path *path, struct kstat *stat, u32 request_mask, | |
1119 | + unsigned int query_flags) | |
1120 | +#else | |
1121 | zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask, | |
1122 | unsigned int query_flags) | |
1123 | +#endif | |
1124 | { | |
1125 | int error; | |
1126 | fstrans_cookie_t cookie; | |
1127 | @@ -350,7 +371,11 @@ zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask, | |
1128 | * XXX request_mask and query_flags currently ignored. | |
1129 | */ | |
1130 | ||
1131 | - error = -zfs_getattr_fast(path->dentry->d_inode, stat); | |
1132 | +#ifdef HAVE_USERNS_IOPS_GETATTR | |
1133 | + error = -zfs_getattr_fast(user_ns, path->dentry->d_inode, stat); | |
1134 | +#else | |
1135 | + error = -zfs_getattr_fast(kcred->user_ns, path->dentry->d_inode, stat); | |
1136 | +#endif | |
1137 | spl_fstrans_unmark(cookie); | |
1138 | ASSERT3S(error, <=, 0); | |
1139 | ||
1140 | @@ -359,7 +384,12 @@ zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask, | |
1141 | ZPL_GETATTR_WRAPPER(zpl_getattr); | |
1142 | ||
1143 | static int | |
1144 | +#ifdef HAVE_SETATTR_PREPARE_USERNS | |
1145 | +zpl_setattr(struct user_namespace *user_ns, struct dentry *dentry, | |
1146 | + struct iattr *ia) | |
1147 | +#else | |
1148 | zpl_setattr(struct dentry *dentry, struct iattr *ia) | |
1149 | +#endif | |
1150 | { | |
1151 | struct inode *ip = dentry->d_inode; | |
1152 | cred_t *cr = CRED(); | |
1153 | @@ -367,7 +397,7 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia) | |
1154 | int error; | |
1155 | fstrans_cookie_t cookie; | |
1156 | ||
1157 | - error = setattr_prepare(dentry, ia); | |
1158 | + error = zpl_setattr_prepare(kcred->user_ns, dentry, ia); | |
1159 | if (error) | |
1160 | return (error); | |
1161 | ||
1162 | @@ -399,8 +429,14 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia) | |
1163 | } | |
1164 | ||
1165 | static int | |
1166 | +#ifdef HAVE_IOPS_RENAME_USERNS | |
1167 | +zpl_rename2(struct user_namespace *user_ns, struct inode *sdip, | |
1168 | + struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry, | |
1169 | + unsigned int flags) | |
1170 | +#else | |
1171 | zpl_rename2(struct inode *sdip, struct dentry *sdentry, | |
1172 | struct inode *tdip, struct dentry *tdentry, unsigned int flags) | |
1173 | +#endif | |
1174 | { | |
1175 | cred_t *cr = CRED(); | |
1176 | int error; | |
1177 | @@ -421,7 +457,7 @@ zpl_rename2(struct inode *sdip, struct dentry *sdentry, | |
1178 | return (error); | |
1179 | } | |
1180 | ||
1181 | -#ifndef HAVE_RENAME_WANTS_FLAGS | |
1182 | +#if !defined(HAVE_RENAME_WANTS_FLAGS) && !defined(HAVE_IOPS_RENAME_USERNS) | |
1183 | static int | |
1184 | zpl_rename(struct inode *sdip, struct dentry *sdentry, | |
1185 | struct inode *tdip, struct dentry *tdentry) | |
1186 | @@ -431,7 +467,12 @@ zpl_rename(struct inode *sdip, struct dentry *sdentry, | |
1187 | #endif | |
1188 | ||
1189 | static int | |
1190 | +#ifdef HAVE_IOPS_SYMLINK_USERNS | |
1191 | +zpl_symlink(struct user_namespace *user_ns, struct inode *dir, | |
1192 | + struct dentry *dentry, const char *name) | |
1193 | +#else | |
1194 | zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name) | |
1195 | +#endif | |
1196 | { | |
1197 | cred_t *cr = CRED(); | |
1198 | vattr_t *vap; | |
1199 | @@ -678,7 +719,7 @@ const struct inode_operations zpl_dir_inode_operations = { | |
1200 | .mkdir = zpl_mkdir, | |
1201 | .rmdir = zpl_rmdir, | |
1202 | .mknod = zpl_mknod, | |
1203 | -#ifdef HAVE_RENAME_WANTS_FLAGS | |
1204 | +#if defined(HAVE_RENAME_WANTS_FLAGS) || defined(HAVE_IOPS_RENAME_USERNS) | |
1205 | .rename = zpl_rename2, | |
1206 | #else | |
1207 | .rename = zpl_rename, | |
1208 | diff --git a/module/os/linux/zfs/zpl_xattr.c b/module/os/linux/zfs/zpl_xattr.c | |
1209 | index 83812f2dcba..971cd6ad031 100644 | |
1210 | --- a/module/os/linux/zfs/zpl_xattr.c | |
1211 | +++ b/module/os/linux/zfs/zpl_xattr.c | |
1212 | @@ -1233,7 +1233,7 @@ __zpl_xattr_acl_set_access(struct inode *ip, const char *name, | |
1213 | if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) | |
1214 | return (-EOPNOTSUPP); | |
1215 | ||
1216 | - if (!inode_owner_or_capable(ip)) | |
1217 | + if (!zpl_inode_owner_or_capable(kcred->user_ns, ip)) | |
1218 | return (-EPERM); | |
1219 | ||
1220 | if (value) { | |
1221 | @@ -1273,7 +1273,7 @@ __zpl_xattr_acl_set_default(struct inode *ip, const char *name, | |
1222 | if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) | |
1223 | return (-EOPNOTSUPP); | |
1224 | ||
1225 | - if (!inode_owner_or_capable(ip)) | |
1226 | + if (!zpl_inode_owner_or_capable(kcred->user_ns, ip)) | |
1227 | return (-EPERM); | |
1228 | ||
1229 | if (value) { | |
1230 | From ffd6978ef59cfe2773e984bf03de2f0b93b03f5c Mon Sep 17 00:00:00 2001 | |
1231 | From: Coleman Kane <ckane@colemankane.org> | |
1232 | Date: Sat, 20 Mar 2021 01:33:42 -0400 | |
1233 | Subject: [PATCH] Linux 5.12 update: bio_max_segs() replaces BIO_MAX_PAGES | |
1234 | ||
1235 | The BIO_MAX_PAGES macro is being retired in favor of a bio_max_segs() | |
1236 | function that implements the typical MIN(x,y) logic used throughout the | |
1237 | kernel for bounding the allocation, and also the new implementation is | |
1238 | intended to be signed-safe (which the former was not). | |
1239 | ||
1240 | Reviewed-by: Tony Hutter <hutter2@llnl.gov> | |
1241 | Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> | |
1242 | Signed-off-by: Coleman Kane <ckane@colemankane.org> | |
1243 | Closes #11765 | |
1244 | --- | |
1245 | config/kernel-bio_max_segs.m4 | 23 +++++++++++++++++++++++ | |
1246 | config/kernel.m4 | 2 ++ | |
1247 | module/os/linux/zfs/vdev_disk.c | 5 +++++ | |
1248 | 3 files changed, 30 insertions(+) | |
1249 | create mode 100644 config/kernel-bio_max_segs.m4 | |
1250 | ||
1251 | diff --git a/config/kernel-bio_max_segs.m4 b/config/kernel-bio_max_segs.m4 | |
1252 | new file mode 100644 | |
1253 | index 00000000000..a90d75455c1 | |
1254 | --- /dev/null | |
1255 | +++ b/config/kernel-bio_max_segs.m4 | |
1256 | @@ -0,0 +1,23 @@ | |
1257 | +dnl # | |
1258 | +dnl # 5.12 API change removes BIO_MAX_PAGES in favor of bio_max_segs() | |
1259 | +dnl # which will handle the logic of setting the upper-bound to a | |
1260 | +dnl # BIO_MAX_PAGES, internally. | |
1261 | +dnl # | |
1262 | +AC_DEFUN([ZFS_AC_KERNEL_SRC_BIO_MAX_SEGS], [ | |
1263 | + ZFS_LINUX_TEST_SRC([bio_max_segs], [ | |
1264 | + #include <linux/bio.h> | |
1265 | + ],[ | |
1266 | + bio_max_segs(1); | |
1267 | + ]) | |
1268 | +]) | |
1269 | + | |
1270 | +AC_DEFUN([ZFS_AC_KERNEL_BIO_MAX_SEGS], [ | |
1271 | + AC_MSG_CHECKING([whether bio_max_segs() exists]) | |
1272 | + ZFS_LINUX_TEST_RESULT([bio_max_segs], [ | |
1273 | + AC_MSG_RESULT(yes) | |
1274 | + | |
1275 | + AC_DEFINE([HAVE_BIO_MAX_SEGS], 1, [bio_max_segs() is implemented]) | |
1276 | + ],[ | |
1277 | + AC_MSG_RESULT(no) | |
1278 | + ]) | |
1279 | +]) | |
1280 | diff --git a/config/kernel.m4 b/config/kernel.m4 | |
1281 | index 24db38f09f4..dfb6165d879 100644 | |
1282 | --- a/config/kernel.m4 | |
1283 | +++ b/config/kernel.m4 | |
1284 | @@ -128,6 +128,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ | |
1285 | ZFS_AC_KERNEL_SRC_GENERIC_FILLATTR_USERNS | |
1286 | ZFS_AC_KERNEL_SRC_MKNOD | |
1287 | ZFS_AC_KERNEL_SRC_SYMLINK | |
1288 | + ZFS_AC_KERNEL_SRC_BIO_MAX_SEGS | |
1289 | ||
1290 | AC_MSG_CHECKING([for available kernel interfaces]) | |
1291 | ZFS_LINUX_TEST_COMPILE_ALL([kabi]) | |
1292 | @@ -229,6 +230,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ | |
1293 | ZFS_AC_KERNEL_GENERIC_FILLATTR_USERNS | |
1294 | ZFS_AC_KERNEL_MKNOD | |
1295 | ZFS_AC_KERNEL_SYMLINK | |
1296 | + ZFS_AC_KERNEL_BIO_MAX_SEGS | |
1297 | ]) | |
1298 | ||
1299 | dnl # | |
1300 | diff --git a/module/os/linux/zfs/vdev_disk.c b/module/os/linux/zfs/vdev_disk.c | |
1301 | index ff71ef4cd06..c56fd3a6ff2 100644 | |
1302 | --- a/module/os/linux/zfs/vdev_disk.c | |
1303 | +++ b/module/os/linux/zfs/vdev_disk.c | |
1304 | @@ -589,9 +589,14 @@ __vdev_disk_physio(struct block_device *bdev, zio_t *zio, | |
1305 | } | |
1306 | ||
1307 | /* bio_alloc() with __GFP_WAIT never returns NULL */ | |
1308 | +#ifdef HAVE_BIO_MAX_SEGS | |
1309 | + dr->dr_bio[i] = bio_alloc(GFP_NOIO, bio_max_segs( | |
1310 | + abd_nr_pages_off(zio->io_abd, bio_size, abd_offset))); | |
1311 | +#else | |
1312 | dr->dr_bio[i] = bio_alloc(GFP_NOIO, | |
1313 | MIN(abd_nr_pages_off(zio->io_abd, bio_size, abd_offset), | |
1314 | BIO_MAX_PAGES)); | |
1315 | +#endif | |
1316 | if (unlikely(dr->dr_bio[i] == NULL)) { | |
1317 | vdev_disk_dio_free(dr); | |
1318 | return (SET_ERROR(ENOMEM)); |