]>
Commit | Line | Data |
---|---|---|
0994e9e8 JR |
1 | From 4859fe796c5b03687a7b2ab3735b882c4f5cad66 Mon Sep 17 00:00:00 2001 |
2 | From: Olaf Faaland <faaland1@llnl.gov> | |
3 | Date: Tue, 28 Feb 2017 16:10:18 -0800 | |
4 | Subject: [PATCH] Linux 4.11 compat: avoid refcount_t name conflict | |
5 | ||
6 | Linux 4.11 introduces a new type, refcount_t, which conflicts with the | |
7 | type of the same name defined within ZFS. | |
8 | ||
9 | Rename the ZFS type zfs_refcount_t. Within the ZFS code, use a macro to | |
10 | cause references to refcount_t to be changed to zfs_refcount_t at | |
11 | compile time. This reduces conflicts when later landing OpenZFS | |
12 | patches. | |
13 | ||
14 | Reviewed-by: George Melikov <mail@gmelikov.ru> | |
15 | Reviewed-by: Giuseppe Di Natale <dinatale2@llnl.gov> | |
16 | Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> | |
17 | Signed-off-by: Olaf Faaland <faaland1@llnl.gov> | |
18 | Closes #5823 | |
19 | Closes #5842 | |
20 | --- | |
21 | include/sys/refcount.h | 17 ++++++++++++++--- | |
22 | module/zfs/refcount.c | 2 +- | |
23 | 2 files changed, 15 insertions(+), 4 deletions(-) | |
24 | ||
25 | diff --git a/include/sys/refcount.h b/include/sys/refcount.h | |
26 | index 3f50cdd..a96220b 100644 | |
27 | --- a/include/sys/refcount.h | |
28 | +++ b/include/sys/refcount.h | |
29 | @@ -41,6 +41,17 @@ extern "C" { | |
30 | */ | |
31 | #define FTAG ((char *)__func__) | |
32 | ||
33 | +/* | |
34 | + * Starting with 4.11, torvalds/linux@f405df5, the linux kernel defines a | |
35 | + * refcount_t type of its own. The macro below effectively changes references | |
36 | + * in the ZFS code from refcount_t to zfs_refcount_t at compile time, so that | |
37 | + * existing code need not be altered, reducing conflicts when landing openZFS | |
38 | + * patches. | |
39 | + */ | |
40 | + | |
41 | +#define refcount_t zfs_refcount_t | |
42 | +#define refcount_add zfs_refcount_add | |
43 | + | |
44 | #ifdef ZFS_DEBUG | |
45 | typedef struct reference { | |
46 | list_node_t ref_link; | |
47 | @@ -56,7 +67,7 @@ typedef struct refcount { | |
48 | list_t rc_removed; | |
49 | int64_t rc_count; | |
50 | int64_t rc_removed_count; | |
51 | -} refcount_t; | |
52 | +} zfs_refcount_t; | |
53 | ||
54 | /* Note: refcount_t must be initialized with refcount_create[_untracked]() */ | |
55 | ||
56 | @@ -67,7 +78,7 @@ void refcount_destroy(refcount_t *rc); | |
57 | void refcount_destroy_many(refcount_t *rc, uint64_t number); | |
58 | int refcount_is_zero(refcount_t *rc); | |
59 | int64_t refcount_count(refcount_t *rc); | |
60 | -int64_t refcount_add(refcount_t *rc, void *holder_tag); | |
61 | +int64_t zfs_refcount_add(refcount_t *rc, void *holder_tag); | |
62 | int64_t refcount_remove(refcount_t *rc, void *holder_tag); | |
63 | int64_t refcount_add_many(refcount_t *rc, uint64_t number, void *holder_tag); | |
64 | int64_t refcount_remove_many(refcount_t *rc, uint64_t number, void *holder_tag); | |
65 | @@ -92,7 +103,7 @@ typedef struct refcount { | |
66 | #define refcount_destroy_many(rc, number) ((rc)->rc_count = 0) | |
67 | #define refcount_is_zero(rc) ((rc)->rc_count == 0) | |
68 | #define refcount_count(rc) ((rc)->rc_count) | |
69 | -#define refcount_add(rc, holder) atomic_add_64_nv(&(rc)->rc_count, 1) | |
70 | +#define zfs_refcount_add(rc, holder) atomic_add_64_nv(&(rc)->rc_count, 1) | |
71 | #define refcount_remove(rc, holder) atomic_add_64_nv(&(rc)->rc_count, -1) | |
72 | #define refcount_add_many(rc, number, holder) \ | |
73 | atomic_add_64_nv(&(rc)->rc_count, number) | |
74 | diff --git a/module/zfs/refcount.c b/module/zfs/refcount.c | |
75 | index b338747..a151ace 100644 | |
76 | --- a/module/zfs/refcount.c | |
77 | +++ b/module/zfs/refcount.c | |
78 | @@ -143,7 +143,7 @@ refcount_add_many(refcount_t *rc, uint64_t number, void *holder) | |
79 | } | |
80 | ||
81 | int64_t | |
82 | -refcount_add(refcount_t *rc, void *holder) | |
83 | +zfs_refcount_add(refcount_t *rc, void *holder) | |
84 | { | |
85 | return (refcount_add_many(rc, 1, holder)); | |
86 | } | |
87 | From a3478c074752610814f894375c3d947ece4938fe Mon Sep 17 00:00:00 2001 | |
88 | From: Olaf Faaland <faaland1@llnl.gov> | |
89 | Date: Mon, 20 Mar 2017 17:51:16 -0700 | |
90 | Subject: [PATCH] Linux 4.11 compat: iops.getattr and friends | |
91 | ||
92 | In torvalds/linux@a528d35, there are changes to the getattr family of functions, | |
93 | struct kstat, and the interface of inode_operations .getattr. | |
94 | ||
95 | The inode_operations .getattr and simple_getattr() interface changed to: | |
96 | ||
97 | int (*getattr) (const struct path *, struct dentry *, struct kstat *, | |
98 | u32 request_mask, unsigned int query_flags) | |
99 | ||
100 | The request_mask argument indicates which field(s) the caller intends to use. | |
101 | Fields the caller has not specified via request_mask may be set in the returned | |
102 | struct anyway, but their values may be approximate. | |
103 | ||
104 | The query_flags argument indicates whether the filesystem must update | |
105 | the attributes from the backing store. | |
106 | ||
107 | Currently both fields are ignored. It is possible that getattr-related | |
108 | functions within zfs could be optimized based on the request_mask. | |
109 | ||
110 | struct kstat includes new fields: | |
111 | u32 result_mask; /* What fields the user got */ | |
112 | u64 attributes; /* See STATX_ATTR_* flags */ | |
113 | struct timespec btime; /* File creation time */ | |
114 | ||
115 | Fields attribute and btime are cleared; the result_mask reflects this. These | |
116 | appear to be optional based on simple_getattr() and vfs_getattr() within the | |
117 | kernel, which take the same approach. | |
118 | ||
119 | Reviewed-by: Chunwei Chen <david.chen@osnexus.com> | |
120 | Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> | |
121 | Signed-off-by: Olaf Faaland <faaland1@llnl.gov> | |
122 | Closes #5875 | |
123 | --- | |
124 | config/kernel-inode-getattr.m4 | 67 ++++++++++++++++++++++++++++++++++++++++++ | |
125 | config/kernel.m4 | 1 + | |
126 | include/linux/vfs_compat.h | 43 +++++++++++++++++++++++++++ | |
127 | module/zfs/zpl_ctldir.c | 35 +++++++++++----------- | |
128 | module/zfs/zpl_inode.c | 11 +++++-- | |
129 | 5 files changed, 138 insertions(+), 19 deletions(-) | |
130 | create mode 100644 config/kernel-inode-getattr.m4 | |
131 | ||
132 | diff --git a/config/kernel-inode-getattr.m4 b/config/kernel-inode-getattr.m4 | |
133 | new file mode 100644 | |
134 | index 0000000..f10e0b2 | |
135 | --- /dev/null | |
136 | +++ b/config/kernel-inode-getattr.m4 | |
137 | @@ -0,0 +1,67 @@ | |
138 | +dnl # | |
139 | +dnl # Linux 4.11 API | |
140 | +dnl # See torvalds/linux@a528d35 | |
141 | +dnl # | |
142 | +AC_DEFUN([ZFS_AC_PATH_KERNEL_IOPS_GETATTR], [ | |
143 | + AC_MSG_CHECKING([whether iops->getattr() takes a path]) | |
144 | + ZFS_LINUX_TRY_COMPILE([ | |
145 | + #include <linux/fs.h> | |
146 | + | |
147 | + int test_getattr( | |
148 | + const struct path *p, struct kstat *k, | |
149 | + u32 request_mask, unsigned int query_flags) | |
150 | + { return 0; } | |
151 | + | |
152 | + static const struct inode_operations | |
153 | + iops __attribute__ ((unused)) = { | |
154 | + .getattr = test_getattr, | |
155 | + }; | |
156 | + ],[ | |
157 | + ],[ | |
158 | + AC_MSG_RESULT(yes) | |
159 | + AC_DEFINE(HAVE_PATH_IOPS_GETATTR, 1, | |
160 | + [iops->getattr() takes a path]) | |
161 | + ],[ | |
162 | + AC_MSG_RESULT(no) | |
163 | + ]) | |
164 | +]) | |
165 | + | |
166 | + | |
167 | + | |
168 | +dnl # | |
169 | +dnl # Linux 3.9 - 4.10 API | |
170 | +dnl # | |
171 | +AC_DEFUN([ZFS_AC_VFSMOUNT_KERNEL_IOPS_GETATTR], [ | |
172 | + AC_MSG_CHECKING([whether iops->getattr() takes a vfsmount]) | |
173 | + ZFS_LINUX_TRY_COMPILE([ | |
174 | + #include <linux/fs.h> | |
175 | + | |
176 | + int test_getattr( | |
177 | + struct vfsmount *mnt, struct dentry *d, | |
178 | + struct kstat *k) | |
179 | + { return 0; } | |
180 | + | |
181 | + static const struct inode_operations | |
182 | + iops __attribute__ ((unused)) = { | |
183 | + .getattr = test_getattr, | |
184 | + }; | |
185 | + ],[ | |
186 | + ],[ | |
187 | + AC_MSG_RESULT(yes) | |
188 | + AC_DEFINE(HAVE_VFSMOUNT_IOPS_GETATTR, 1, | |
189 | + [iops->getattr() takes a vfsmount]) | |
190 | + ],[ | |
191 | + AC_MSG_RESULT(no) | |
192 | + ]) | |
193 | +]) | |
194 | + | |
195 | + | |
196 | +dnl # | |
197 | +dnl # The interface of the getattr callback from the inode_operations | |
198 | +dnl # structure changed. Also, the interface of the simple_getattr() | |
199 | +dnl # function provided by the kernel changed. | |
200 | +dnl # | |
201 | +AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GETATTR], [ | |
202 | + ZFS_AC_PATH_KERNEL_IOPS_GETATTR | |
203 | + ZFS_AC_VFSMOUNT_KERNEL_IOPS_GETATTR | |
204 | +]) | |
205 | diff --git a/config/kernel.m4 b/config/kernel.m4 | |
206 | index 0b50a54..25271ce 100644 | |
207 | --- a/config/kernel.m4 | |
208 | +++ b/config/kernel.m4 | |
209 | @@ -59,6 +59,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [ | |
210 | ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS | |
211 | ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL | |
212 | ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL | |
213 | + ZFS_AC_KERNEL_INODE_OPERATIONS_GETATTR | |
214 | ZFS_AC_KERNEL_GET_ACL_HANDLE_CACHE | |
215 | ZFS_AC_KERNEL_SHOW_OPTIONS | |
216 | ZFS_AC_KERNEL_FILE_INODE | |
217 | diff --git a/include/linux/vfs_compat.h b/include/linux/vfs_compat.h | |
218 | index baa2980..cd22b52 100644 | |
219 | --- a/include/linux/vfs_compat.h | |
220 | +++ b/include/linux/vfs_compat.h | |
221 | @@ -454,4 +454,47 @@ setattr_prepare(struct dentry *dentry, struct iattr *ia) | |
222 | } | |
223 | #endif | |
224 | ||
225 | +/* | |
226 | + * 4.11 API change | |
227 | + * These macros are defined by kernel 4.11. We define them so that the same | |
228 | + * code builds under kernels < 4.11 and >= 4.11. The macros are set to 0 so | |
229 | + * that it will create obvious failures if they are accidentally used when built | |
230 | + * against a kernel >= 4.11. | |
231 | + */ | |
232 | + | |
233 | +#ifndef STATX_BASIC_STATS | |
234 | +#define STATX_BASIC_STATS 0 | |
235 | +#endif | |
236 | + | |
237 | +#ifndef AT_STATX_SYNC_AS_STAT | |
238 | +#define AT_STATX_SYNC_AS_STAT 0 | |
239 | +#endif | |
240 | + | |
241 | +/* | |
242 | + * 4.11 API change | |
243 | + * 4.11 takes struct path *, < 4.11 takes vfsmount * | |
244 | + */ | |
245 | + | |
246 | +#ifdef HAVE_VFSMOUNT_IOPS_GETATTR | |
247 | +#define ZPL_GETATTR_WRAPPER(func) \ | |
248 | +static int \ | |
249 | +func(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) \ | |
250 | +{ \ | |
251 | + struct path path = { .mnt = mnt, .dentry = dentry }; \ | |
252 | + return func##_impl(&path, stat, STATX_BASIC_STATS, \ | |
253 | + AT_STATX_SYNC_AS_STAT); \ | |
254 | +} | |
255 | +#elif defined(HAVE_PATH_IOPS_GETATTR) | |
256 | +#define ZPL_GETATTR_WRAPPER(func) \ | |
257 | +static int \ | |
258 | +func(const struct path *path, struct kstat *stat, u32 request_mask, \ | |
259 | + unsigned int query_flags) \ | |
260 | +{ \ | |
261 | + return (func##_impl(path, stat, request_mask, query_flags)); \ | |
262 | +} | |
263 | +#else | |
264 | +#error | |
265 | +#endif | |
266 | + | |
267 | + | |
268 | #endif /* _ZFS_VFS_H */ | |
269 | diff --git a/module/zfs/zpl_ctldir.c b/module/zfs/zpl_ctldir.c | |
270 | index b6a3b66..bd8af39 100644 | |
271 | --- a/module/zfs/zpl_ctldir.c | |
272 | +++ b/module/zfs/zpl_ctldir.c | |
273 | @@ -100,16 +100,15 @@ zpl_root_readdir(struct file *filp, void *dirent, filldir_t filldir) | |
274 | */ | |
275 | /* ARGSUSED */ | |
276 | static int | |
277 | -zpl_root_getattr(struct vfsmount *mnt, struct dentry *dentry, | |
278 | - struct kstat *stat) | |
279 | +zpl_root_getattr_impl(const struct path *path, struct kstat *stat, | |
280 | + u32 request_mask, unsigned int query_flags) | |
281 | { | |
282 | - int error; | |
283 | - | |
284 | - error = simple_getattr(mnt, dentry, stat); | |
285 | + generic_fillattr(path->dentry->d_inode, stat); | |
286 | stat->atime = CURRENT_TIME; | |
287 | ||
288 | - return (error); | |
289 | + return (0); | |
290 | } | |
291 | +ZPL_GETATTR_WRAPPER(zpl_root_getattr); | |
292 | ||
293 | static struct dentry * | |
294 | #ifdef HAVE_LOOKUP_NAMEIDATA | |
295 | @@ -375,21 +374,22 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, zpl_umode_t mode) | |
296 | */ | |
297 | /* ARGSUSED */ | |
298 | static int | |
299 | -zpl_snapdir_getattr(struct vfsmount *mnt, struct dentry *dentry, | |
300 | - struct kstat *stat) | |
301 | +zpl_snapdir_getattr_impl(const struct path *path, struct kstat *stat, | |
302 | + u32 request_mask, unsigned int query_flags) | |
303 | { | |
304 | - zfs_sb_t *zsb = ITOZSB(dentry->d_inode); | |
305 | - int error; | |
306 | + zfs_sb_t *zsb = ITOZSB(path->dentry->d_inode); | |
307 | ||
308 | ZFS_ENTER(zsb); | |
309 | - error = simple_getattr(mnt, dentry, stat); | |
310 | + generic_fillattr(path->dentry->d_inode, stat); | |
311 | + | |
312 | stat->nlink = stat->size = 2; | |
313 | stat->ctime = stat->mtime = dmu_objset_snap_cmtime(zsb->z_os); | |
314 | stat->atime = CURRENT_TIME; | |
315 | ZFS_EXIT(zsb); | |
316 | ||
317 | - return (error); | |
318 | + return (0); | |
319 | } | |
320 | +ZPL_GETATTR_WRAPPER(zpl_snapdir_getattr); | |
321 | ||
322 | /* | |
323 | * The '.zfs/snapshot' directory file operations. These mainly control | |
324 | @@ -509,10 +509,10 @@ zpl_shares_readdir(struct file *filp, void *dirent, filldir_t filldir) | |
325 | ||
326 | /* ARGSUSED */ | |
327 | static int | |
328 | -zpl_shares_getattr(struct vfsmount *mnt, struct dentry *dentry, | |
329 | - struct kstat *stat) | |
330 | +zpl_shares_getattr_impl(const struct path *path, struct kstat *stat, | |
331 | + u32 request_mask, unsigned int query_flags) | |
332 | { | |
333 | - struct inode *ip = dentry->d_inode; | |
334 | + struct inode *ip = path->dentry->d_inode; | |
335 | zfs_sb_t *zsb = ITOZSB(ip); | |
336 | znode_t *dzp; | |
337 | int error; | |
338 | @@ -520,11 +520,11 @@ zpl_shares_getattr(struct vfsmount *mnt, struct dentry *dentry, | |
339 | ZFS_ENTER(zsb); | |
340 | ||
341 | if (zsb->z_shares_dir == 0) { | |
342 | - error = simple_getattr(mnt, dentry, stat); | |
343 | + generic_fillattr(path->dentry->d_inode, stat); | |
344 | stat->nlink = stat->size = 2; | |
345 | stat->atime = CURRENT_TIME; | |
346 | ZFS_EXIT(zsb); | |
347 | - return (error); | |
348 | + return (0); | |
349 | } | |
350 | ||
351 | error = -zfs_zget(zsb, zsb->z_shares_dir, &dzp); | |
352 | @@ -538,6 +538,7 @@ zpl_shares_getattr(struct vfsmount *mnt, struct dentry *dentry, | |
353 | ||
354 | return (error); | |
355 | } | |
356 | +ZPL_GETATTR_WRAPPER(zpl_shares_getattr); | |
357 | ||
358 | /* | |
359 | * The '.zfs/shares' directory file operations. | |
360 | diff --git a/module/zfs/zpl_inode.c b/module/zfs/zpl_inode.c | |
361 | index 2e438ea..8351ab5 100644 | |
362 | --- a/module/zfs/zpl_inode.c | |
363 | +++ b/module/zfs/zpl_inode.c | |
364 | @@ -340,18 +340,25 @@ zpl_rmdir(struct inode *dir, struct dentry *dentry) | |
365 | } | |
366 | ||
367 | static int | |
368 | -zpl_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |
369 | +zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask, | |
370 | + unsigned int query_flags) | |
371 | { | |
372 | int error; | |
373 | fstrans_cookie_t cookie; | |
374 | ||
375 | cookie = spl_fstrans_mark(); | |
376 | - error = -zfs_getattr_fast(dentry->d_inode, stat); | |
377 | + | |
378 | + /* | |
379 | + * XXX request_mask and query_flags currently ignored. | |
380 | + */ | |
381 | + | |
382 | + error = -zfs_getattr_fast(path->dentry->d_inode, stat); | |
383 | spl_fstrans_unmark(cookie); | |
384 | ASSERT3S(error, <=, 0); | |
385 | ||
386 | return (error); | |
387 | } | |
388 | +ZPL_GETATTR_WRAPPER(zpl_getattr); | |
389 | ||
390 | static int | |
391 | zpl_setattr(struct dentry *dentry, struct iattr *ia) |