]> git.proxmox.com Git - mirror_zfs.git/blame - module/os/linux/zfs/zpl_ctldir.c
Linux 6.5 compat: blkdev changes
[mirror_zfs.git] / module / os / linux / zfs / zpl_ctldir.c
CommitLineData
ebe7e575
BB
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1d3ba0bf 9 * or https://opensource.org/licenses/CDDL-1.0.
ebe7e575
BB
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright (C) 2011 Lawrence Livermore National Security, LLC.
23 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
24 * LLNL-CODE-403049.
25 * Rewritten for Linux by:
26 * Rohan Puri <rohan.puri15@gmail.com>
27 * Brian Behlendorf <behlendorf1@llnl.gov>
28 */
29
657ce253 30#include <sys/zfs_znode.h>
ebe7e575
BB
31#include <sys/zfs_vfsops.h>
32#include <sys/zfs_vnops.h>
ebe7e575
BB
33#include <sys/zfs_ctldir.h>
34#include <sys/zpl.h>
f6097399
AW
35#include <sys/dmu.h>
36#include <sys/dsl_dataset.h>
37#include <sys/zap.h>
ebe7e575
BB
38
39/*
40 * Common open routine. Disallow any write access.
41 */
ebe7e575
BB
42static int
43zpl_common_open(struct inode *ip, struct file *filp)
44{
43e8f6e3 45 if (blk_mode_is_open_write(filp->f_mode))
ebe7e575
BB
46 return (-EACCES);
47
d1d7e268 48 return (generic_file_open(ip, filp));
ebe7e575
BB
49}
50
ebe7e575
BB
51/*
52 * Get root directory contents.
53 */
54static int
9464b959 55zpl_root_iterate(struct file *filp, zpl_dir_context_t *ctx)
ebe7e575 56{
0037b49e 57 zfsvfs_t *zfsvfs = ITOZSB(file_inode(filp));
ebe7e575
BB
58 int error = 0;
59
768eaced
CC
60 if ((error = zpl_enter(zfsvfs, FTAG)) != 0)
61 return (error);
ebe7e575 62
9464b959 63 if (!zpl_dir_emit_dots(filp, ctx))
0f37d0c8 64 goto out;
ebe7e575 65
0f37d0c8 66 if (ctx->pos == 2) {
9464b959
BB
67 if (!zpl_dir_emit(ctx, ZFS_SNAPDIR_NAME,
68 strlen(ZFS_SNAPDIR_NAME), ZFSCTL_INO_SNAPDIR, DT_DIR))
ebe7e575
BB
69 goto out;
70
0f37d0c8
RY
71 ctx->pos++;
72 }
ebe7e575 73
0f37d0c8 74 if (ctx->pos == 3) {
9464b959
BB
75 if (!zpl_dir_emit(ctx, ZFS_SHAREDIR_NAME,
76 strlen(ZFS_SHAREDIR_NAME), ZFSCTL_INO_SHARES, DT_DIR))
ebe7e575
BB
77 goto out;
78
0f37d0c8 79 ctx->pos++;
ebe7e575
BB
80 }
81out:
768eaced 82 zpl_exit(zfsvfs, FTAG);
ebe7e575
BB
83
84 return (error);
85}
86
9baaa7de 87#if !defined(HAVE_VFS_ITERATE) && !defined(HAVE_VFS_ITERATE_SHARED)
0f37d0c8
RY
88static int
89zpl_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
90{
9464b959
BB
91 zpl_dir_context_t ctx =
92 ZPL_DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos);
0f37d0c8
RY
93 int error;
94
95 error = zpl_root_iterate(filp, &ctx);
96 filp->f_pos = ctx.pos;
97
98 return (error);
99}
9464b959 100#endif /* !HAVE_VFS_ITERATE && !HAVE_VFS_ITERATE_SHARED */
0f37d0c8 101
ebe7e575
BB
102/*
103 * Get root directory attributes.
104 */
ebe7e575 105static int
d4dc53da
YY
106#ifdef HAVE_IDMAP_IOPS_GETATTR
107zpl_root_getattr_impl(struct mnt_idmap *user_ns,
108 const struct path *path, struct kstat *stat, u32 request_mask,
109 unsigned int query_flags)
110#elif defined(HAVE_USERNS_IOPS_GETATTR)
e2a82961
CK
111zpl_root_getattr_impl(struct user_namespace *user_ns,
112 const struct path *path, struct kstat *stat, u32 request_mask,
113 unsigned int query_flags)
114#else
a3478c07
OF
115zpl_root_getattr_impl(const struct path *path, struct kstat *stat,
116 u32 request_mask, unsigned int query_flags)
e2a82961 117#endif
ebe7e575 118{
ef70eff1 119 (void) request_mask, (void) query_flags;
2946a1a1
BB
120 struct inode *ip = path->dentry->d_inode;
121
d4dc53da 122#if (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR))
ef70eff1 123#ifdef HAVE_GENERIC_FILLATTR_USERNS
e2a82961 124 generic_fillattr(user_ns, ip, stat);
d4dc53da
YY
125#elif defined(HAVE_GENERIC_FILLATTR_IDMAP)
126 generic_fillattr(user_ns, ip, stat);
ef70eff1
AZ
127#else
128 (void) user_ns;
129#endif
e2a82961 130#else
2946a1a1 131 generic_fillattr(ip, stat);
e2a82961 132#endif
2946a1a1 133 stat->atime = current_time(ip);
ebe7e575 134
a3478c07 135 return (0);
ebe7e575 136}
a3478c07 137ZPL_GETATTR_WRAPPER(zpl_root_getattr);
ebe7e575
BB
138
139static struct dentry *
8f195a90 140zpl_root_lookup(struct inode *dip, struct dentry *dentry, unsigned int flags)
ebe7e575
BB
141{
142 cred_t *cr = CRED();
143 struct inode *ip;
144 int error;
145
146 crhold(cr);
147 error = -zfsctl_root_lookup(dip, dname(dentry), &ip, 0, cr, NULL, NULL);
148 ASSERT3S(error, <=, 0);
149 crfree(cr);
150
151 if (error) {
152 if (error == -ENOENT)
d1d7e268 153 return (d_splice_alias(NULL, dentry));
ebe7e575 154 else
d1d7e268 155 return (ERR_PTR(error));
ebe7e575
BB
156 }
157
d1d7e268 158 return (d_splice_alias(ip, dentry));
ebe7e575
BB
159}
160
161/*
162 * The '.zfs' control directory file and inode operations.
163 */
164const struct file_operations zpl_fops_root = {
165 .open = zpl_common_open,
166 .llseek = generic_file_llseek,
167 .read = generic_read_dir,
9baaa7de
CC
168#ifdef HAVE_VFS_ITERATE_SHARED
169 .iterate_shared = zpl_root_iterate,
170#elif defined(HAVE_VFS_ITERATE)
0f37d0c8
RY
171 .iterate = zpl_root_iterate,
172#else
ebe7e575 173 .readdir = zpl_root_readdir,
0f37d0c8 174#endif
ebe7e575
BB
175};
176
177const struct inode_operations zpl_ops_root = {
178 .lookup = zpl_root_lookup,
179 .getattr = zpl_root_getattr,
180};
181
f1a05fa1
NB
182static struct vfsmount *
183zpl_snapdir_automount(struct path *path)
184{
f1a05fa1
NB
185 int error;
186
278bee93 187 error = -zfsctl_snapshot_mount(path, 0);
f1a05fa1 188 if (error)
d1d7e268 189 return (ERR_PTR(error));
f1a05fa1
NB
190
191 /*
192 * Rather than returning the new vfsmount for the snapshot we must
193 * return NULL to indicate a mount collision. This is done because
194 * the user space mount calls do_add_mount() which adds the vfsmount
195 * to the name space. If we returned the new mount here it would be
196 * added again to the vfsmount list resulting in list corruption.
197 */
198 return (NULL);
199}
f1a05fa1
NB
200
201/*
278bee93
BB
202 * Negative dentries must always be revalidated so newly created snapshots
203 * can be detected and automounted. Normal dentries should be kept because
204 * as of the 3.18 kernel revaliding the mountpoint dentry will result in
205 * the snapshot being immediately unmounted.
f1a05fa1
NB
206 */
207static int
208#ifdef HAVE_D_REVALIDATE_NAMEIDATA
209zpl_snapdir_revalidate(struct dentry *dentry, struct nameidata *i)
210#else
211zpl_snapdir_revalidate(struct dentry *dentry, unsigned int flags)
212#endif
213{
278bee93 214 return (!!dentry->d_inode);
f1a05fa1
NB
215}
216
a2d5643f 217static dentry_operations_t zpl_dops_snapdirs = {
f1a05fa1
NB
218/*
219 * Auto mounting of snapshots is only supported for 2.6.37 and
220 * newer kernels. Prior to this kernel the ops->follow_link()
221 * callback was used as a hack to trigger the mount. The
222 * resulting vfsmount was then explicitly grafted in to the
223 * name space. While it might be possible to add compatibility
224 * code to accomplish this it would require considerable care.
225 */
f1a05fa1 226 .d_automount = zpl_snapdir_automount,
f1a05fa1
NB
227 .d_revalidate = zpl_snapdir_revalidate,
228};
229
ebe7e575 230static struct dentry *
8f195a90
YS
231zpl_snapdir_lookup(struct inode *dip, struct dentry *dentry,
232 unsigned int flags)
ebe7e575 233{
7fad6290 234 fstrans_cookie_t cookie;
ebe7e575 235 cred_t *cr = CRED();
f1a05fa1 236 struct inode *ip = NULL;
ebe7e575
BB
237 int error;
238
239 crhold(cr);
7fad6290 240 cookie = spl_fstrans_mark();
ebe7e575
BB
241 error = -zfsctl_snapdir_lookup(dip, dname(dentry), &ip,
242 0, cr, NULL, NULL);
243 ASSERT3S(error, <=, 0);
7fad6290 244 spl_fstrans_unmark(cookie);
ebe7e575
BB
245 crfree(cr);
246
f1a05fa1 247 if (error && error != -ENOENT)
d1d7e268 248 return (ERR_PTR(error));
ebe7e575 249
f1a05fa1 250 ASSERT(error == 0 || ip == NULL);
bf01b5e6 251 d_clear_d_op(dentry);
f1a05fa1 252 d_set_d_op(dentry, &zpl_dops_snapdirs);
278bee93 253 dentry->d_flags |= DCACHE_NEED_AUTOMOUNT;
ebe7e575 254
d1d7e268 255 return (d_splice_alias(ip, dentry));
ebe7e575
BB
256}
257
ebe7e575 258static int
9464b959 259zpl_snapdir_iterate(struct file *filp, zpl_dir_context_t *ctx)
ebe7e575 260{
0037b49e 261 zfsvfs_t *zfsvfs = ITOZSB(file_inode(filp));
7fad6290 262 fstrans_cookie_t cookie;
ebe7e575 263 char snapname[MAXNAMELEN];
ebe7e575 264 boolean_t case_conflict;
7fad6290 265 uint64_t id, pos;
ebe7e575
BB
266 int error = 0;
267
768eaced
CC
268 if ((error = zpl_enter(zfsvfs, FTAG)) != 0)
269 return (error);
7fad6290 270 cookie = spl_fstrans_mark();
ebe7e575 271
9464b959 272 if (!zpl_dir_emit_dots(filp, ctx))
0f37d0c8 273 goto out;
ebe7e575 274
9bd14b87
TP
275 /* Start the position at 0 if it already emitted . and .. */
276 pos = (ctx->pos == 2 ? 0 : ctx->pos);
0f37d0c8 277 while (error == 0) {
0037b49e
BB
278 dsl_pool_config_enter(dmu_objset_pool(zfsvfs->z_os), FTAG);
279 error = -dmu_snapshot_list_next(zfsvfs->z_os, MAXNAMELEN,
7fad6290 280 snapname, &id, &pos, &case_conflict);
0037b49e 281 dsl_pool_config_exit(dmu_objset_pool(zfsvfs->z_os), FTAG);
ebe7e575
BB
282 if (error)
283 goto out;
284
9464b959 285 if (!zpl_dir_emit(ctx, snapname, strlen(snapname),
0f37d0c8
RY
286 ZFSCTL_INO_SHARES - id, DT_DIR))
287 goto out;
5f15fa22 288
7fad6290 289 ctx->pos = pos;
ebe7e575
BB
290 }
291out:
7fad6290 292 spl_fstrans_unmark(cookie);
768eaced 293 zpl_exit(zfsvfs, FTAG);
ebe7e575
BB
294
295 if (error == -ENOENT)
296 return (0);
297
298 return (error);
299}
300
9baaa7de 301#if !defined(HAVE_VFS_ITERATE) && !defined(HAVE_VFS_ITERATE_SHARED)
0f37d0c8
RY
302static int
303zpl_snapdir_readdir(struct file *filp, void *dirent, filldir_t filldir)
304{
9464b959
BB
305 zpl_dir_context_t ctx =
306 ZPL_DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos);
0f37d0c8
RY
307 int error;
308
309 error = zpl_snapdir_iterate(filp, &ctx);
310 filp->f_pos = ctx.pos;
311
312 return (error);
313}
9464b959 314#endif /* !HAVE_VFS_ITERATE && !HAVE_VFS_ITERATE_SHARED */
0f37d0c8 315
b8d9e264 316static int
e2a82961
CK
317#ifdef HAVE_IOPS_RENAME_USERNS
318zpl_snapdir_rename2(struct user_namespace *user_ns, struct inode *sdip,
319 struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry,
320 unsigned int flags)
d4dc53da
YY
321#elif defined(HAVE_IOPS_RENAME_IDMAP)
322zpl_snapdir_rename2(struct mnt_idmap *user_ns, struct inode *sdip,
323 struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry,
324 unsigned int flags)
e2a82961 325#else
b8d9e264
CC
326zpl_snapdir_rename2(struct inode *sdip, struct dentry *sdentry,
327 struct inode *tdip, struct dentry *tdentry, unsigned int flags)
e2a82961 328#endif
ebe7e575
BB
329{
330 cred_t *cr = CRED();
331 int error;
332
b8d9e264
CC
333 /* We probably don't want to support renameat2(2) in ctldir */
334 if (flags)
335 return (-EINVAL);
336
ebe7e575
BB
337 crhold(cr);
338 error = -zfsctl_snapdir_rename(sdip, dname(sdentry),
339 tdip, dname(tdentry), cr, 0);
340 ASSERT3S(error, <=, 0);
341 crfree(cr);
342
343 return (error);
344}
345
d4dc53da
YY
346#if (!defined(HAVE_RENAME_WANTS_FLAGS) && \
347 !defined(HAVE_IOPS_RENAME_USERNS) && \
348 !defined(HAVE_IOPS_RENAME_IDMAP))
b8d9e264
CC
349static int
350zpl_snapdir_rename(struct inode *sdip, struct dentry *sdentry,
351 struct inode *tdip, struct dentry *tdentry)
352{
353 return (zpl_snapdir_rename2(sdip, sdentry, tdip, tdentry, 0));
354}
355#endif
356
ebe7e575
BB
357static int
358zpl_snapdir_rmdir(struct inode *dip, struct dentry *dentry)
359{
360 cred_t *cr = CRED();
361 int error;
362
363 crhold(cr);
364 error = -zfsctl_snapdir_remove(dip, dname(dentry), cr, 0);
365 ASSERT3S(error, <=, 0);
366 crfree(cr);
367
368 return (error);
369}
370
371static int
e2a82961
CK
372#ifdef HAVE_IOPS_MKDIR_USERNS
373zpl_snapdir_mkdir(struct user_namespace *user_ns, struct inode *dip,
374 struct dentry *dentry, umode_t mode)
d4dc53da
YY
375#elif defined(HAVE_IOPS_MKDIR_IDMAP)
376zpl_snapdir_mkdir(struct mnt_idmap *user_ns, struct inode *dip,
377 struct dentry *dentry, umode_t mode)
e2a82961 378#else
066e8252 379zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode)
e2a82961 380#endif
ebe7e575
BB
381{
382 cred_t *cr = CRED();
383 vattr_t *vap;
384 struct inode *ip;
385 int error;
386
387 crhold(cr);
d1d7e268 388 vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP);
d4dc53da 389#if (defined(HAVE_IOPS_MKDIR_USERNS) || defined(HAVE_IOPS_MKDIR_IDMAP))
2a068a13
YY
390 zpl_vap_init(vap, dip, mode | S_IFDIR, cr, user_ns);
391#else
d4dc53da 392 zpl_vap_init(vap, dip, mode | S_IFDIR, cr, zfs_init_idmap);
2a068a13 393#endif
ebe7e575
BB
394
395 error = -zfsctl_snapdir_mkdir(dip, dname(dentry), vap, &ip, cr, 0);
396 if (error == 0) {
bf01b5e6 397 d_clear_d_op(dentry);
f1a05fa1 398 d_set_d_op(dentry, &zpl_dops_snapdirs);
ebe7e575
BB
399 d_instantiate(dentry, ip);
400 }
401
d1d7e268 402 kmem_free(vap, sizeof (vattr_t));
ebe7e575
BB
403 ASSERT3S(error, <=, 0);
404 crfree(cr);
405
406 return (error);
407}
408
ebe7e575
BB
409/*
410 * Get snapshot directory attributes.
411 */
ebe7e575 412static int
d4dc53da
YY
413#ifdef HAVE_IDMAP_IOPS_GETATTR
414zpl_snapdir_getattr_impl(struct mnt_idmap *user_ns,
415 const struct path *path, struct kstat *stat, u32 request_mask,
416 unsigned int query_flags)
417#elif defined(HAVE_USERNS_IOPS_GETATTR)
e2a82961
CK
418zpl_snapdir_getattr_impl(struct user_namespace *user_ns,
419 const struct path *path, struct kstat *stat, u32 request_mask,
420 unsigned int query_flags)
421#else
a3478c07
OF
422zpl_snapdir_getattr_impl(const struct path *path, struct kstat *stat,
423 u32 request_mask, unsigned int query_flags)
e2a82961 424#endif
ebe7e575 425{
ef70eff1 426 (void) request_mask, (void) query_flags;
2946a1a1
BB
427 struct inode *ip = path->dentry->d_inode;
428 zfsvfs_t *zfsvfs = ITOZSB(ip);
768eaced 429 int error;
ebe7e575 430
768eaced
CC
431 if ((error = zpl_enter(zfsvfs, FTAG)) != 0)
432 return (error);
d4dc53da 433#if (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR))
ef70eff1 434#ifdef HAVE_GENERIC_FILLATTR_USERNS
e2a82961 435 generic_fillattr(user_ns, ip, stat);
d4dc53da
YY
436#elif defined(HAVE_GENERIC_FILLATTR_IDMAP)
437 generic_fillattr(user_ns, ip, stat);
ef70eff1
AZ
438#else
439 (void) user_ns;
440#endif
e2a82961 441#else
2946a1a1 442 generic_fillattr(ip, stat);
e2a82961 443#endif
a3478c07 444
278bee93 445 stat->nlink = stat->size = 2;
f6097399
AW
446
447 dsl_dataset_t *ds = dmu_objset_ds(zfsvfs->z_os);
448 if (dsl_dataset_phys(ds)->ds_snapnames_zapobj != 0) {
449 uint64_t snap_count;
450 int err = zap_count(
451 dmu_objset_pool(ds->ds_objset)->dp_meta_objset,
452 dsl_dataset_phys(ds)->ds_snapnames_zapobj, &snap_count);
453 if (err != 0) {
768eaced 454 zpl_exit(zfsvfs, FTAG);
f6097399
AW
455 return (-err);
456 }
457 stat->nlink += snap_count;
458 }
459
0037b49e 460 stat->ctime = stat->mtime = dmu_objset_snap_cmtime(zfsvfs->z_os);
2946a1a1 461 stat->atime = current_time(ip);
768eaced 462 zpl_exit(zfsvfs, FTAG);
ebe7e575 463
a3478c07 464 return (0);
ebe7e575 465}
a3478c07 466ZPL_GETATTR_WRAPPER(zpl_snapdir_getattr);
ebe7e575
BB
467
468/*
469 * The '.zfs/snapshot' directory file operations. These mainly control
470 * generating the list of available snapshots when doing an 'ls' in the
471 * directory. See zpl_snapdir_readdir().
472 */
473const struct file_operations zpl_fops_snapdir = {
474 .open = zpl_common_open,
475 .llseek = generic_file_llseek,
476 .read = generic_read_dir,
9baaa7de
CC
477#ifdef HAVE_VFS_ITERATE_SHARED
478 .iterate_shared = zpl_snapdir_iterate,
479#elif defined(HAVE_VFS_ITERATE)
0f37d0c8
RY
480 .iterate = zpl_snapdir_iterate,
481#else
ebe7e575 482 .readdir = zpl_snapdir_readdir,
0f37d0c8
RY
483#endif
484
ebe7e575
BB
485};
486
487/*
488 * The '.zfs/snapshot' directory inode operations. These mainly control
489 * creating an inode for a snapshot directory and initializing the needed
490 * infrastructure to automount the snapshot. See zpl_snapdir_lookup().
491 */
492const struct inode_operations zpl_ops_snapdir = {
493 .lookup = zpl_snapdir_lookup,
494 .getattr = zpl_snapdir_getattr,
d4dc53da
YY
495#if (defined(HAVE_RENAME_WANTS_FLAGS) || \
496 defined(HAVE_IOPS_RENAME_USERNS) || \
497 defined(HAVE_IOPS_RENAME_IDMAP))
b8d9e264
CC
498 .rename = zpl_snapdir_rename2,
499#else
ebe7e575 500 .rename = zpl_snapdir_rename,
b8d9e264 501#endif
ebe7e575
BB
502 .rmdir = zpl_snapdir_rmdir,
503 .mkdir = zpl_snapdir_mkdir,
504};
505
ebe7e575 506static struct dentry *
8f195a90
YS
507zpl_shares_lookup(struct inode *dip, struct dentry *dentry,
508 unsigned int flags)
ebe7e575 509{
7fad6290 510 fstrans_cookie_t cookie;
ebe7e575
BB
511 cred_t *cr = CRED();
512 struct inode *ip = NULL;
513 int error;
514
515 crhold(cr);
7fad6290 516 cookie = spl_fstrans_mark();
ebe7e575
BB
517 error = -zfsctl_shares_lookup(dip, dname(dentry), &ip,
518 0, cr, NULL, NULL);
519 ASSERT3S(error, <=, 0);
7fad6290 520 spl_fstrans_unmark(cookie);
ebe7e575
BB
521 crfree(cr);
522
523 if (error) {
524 if (error == -ENOENT)
d1d7e268 525 return (d_splice_alias(NULL, dentry));
ebe7e575 526 else
d1d7e268 527 return (ERR_PTR(error));
ebe7e575
BB
528 }
529
d1d7e268 530 return (d_splice_alias(ip, dentry));
ebe7e575
BB
531}
532
ebe7e575 533static int
9464b959 534zpl_shares_iterate(struct file *filp, zpl_dir_context_t *ctx)
ebe7e575 535{
7fad6290 536 fstrans_cookie_t cookie;
ebe7e575 537 cred_t *cr = CRED();
0037b49e 538 zfsvfs_t *zfsvfs = ITOZSB(file_inode(filp));
ebe7e575 539 znode_t *dzp;
0f37d0c8 540 int error = 0;
ebe7e575 541
768eaced
CC
542 if ((error = zpl_enter(zfsvfs, FTAG)) != 0)
543 return (error);
7fad6290 544 cookie = spl_fstrans_mark();
ebe7e575 545
0037b49e 546 if (zfsvfs->z_shares_dir == 0) {
9464b959 547 zpl_dir_emit_dots(filp, ctx);
0f37d0c8 548 goto out;
ebe7e575
BB
549 }
550
0037b49e 551 error = -zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp);
0f37d0c8
RY
552 if (error)
553 goto out;
ebe7e575
BB
554
555 crhold(cr);
0f37d0c8 556 error = -zfs_readdir(ZTOI(dzp), ctx, cr);
ebe7e575
BB
557 crfree(cr);
558
559 iput(ZTOI(dzp));
0f37d0c8 560out:
7fad6290 561 spl_fstrans_unmark(cookie);
768eaced 562 zpl_exit(zfsvfs, FTAG);
ebe7e575
BB
563 ASSERT3S(error, <=, 0);
564
565 return (error);
566}
567
9baaa7de 568#if !defined(HAVE_VFS_ITERATE) && !defined(HAVE_VFS_ITERATE_SHARED)
0f37d0c8
RY
569static int
570zpl_shares_readdir(struct file *filp, void *dirent, filldir_t filldir)
571{
9464b959
BB
572 zpl_dir_context_t ctx =
573 ZPL_DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos);
0f37d0c8
RY
574 int error;
575
576 error = zpl_shares_iterate(filp, &ctx);
577 filp->f_pos = ctx.pos;
578
579 return (error);
580}
9464b959 581#endif /* !HAVE_VFS_ITERATE && !HAVE_VFS_ITERATE_SHARED */
0f37d0c8 582
ebe7e575 583static int
e2a82961
CK
584#ifdef HAVE_USERNS_IOPS_GETATTR
585zpl_shares_getattr_impl(struct user_namespace *user_ns,
586 const struct path *path, struct kstat *stat, u32 request_mask,
587 unsigned int query_flags)
d4dc53da
YY
588#elif defined(HAVE_IDMAP_IOPS_GETATTR)
589zpl_shares_getattr_impl(struct mnt_idmap *user_ns,
590 const struct path *path, struct kstat *stat, u32 request_mask,
591 unsigned int query_flags)
e2a82961 592#else
a3478c07
OF
593zpl_shares_getattr_impl(const struct path *path, struct kstat *stat,
594 u32 request_mask, unsigned int query_flags)
e2a82961 595#endif
ebe7e575 596{
ef70eff1 597 (void) request_mask, (void) query_flags;
a3478c07 598 struct inode *ip = path->dentry->d_inode;
0037b49e 599 zfsvfs_t *zfsvfs = ITOZSB(ip);
ebe7e575
BB
600 znode_t *dzp;
601 int error;
602
768eaced
CC
603 if ((error = zpl_enter(zfsvfs, FTAG)) != 0)
604 return (error);
ebe7e575 605
0037b49e 606 if (zfsvfs->z_shares_dir == 0) {
d4dc53da 607#if (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR))
ef70eff1 608#ifdef HAVE_GENERIC_FILLATTR_USERNS
e2a82961 609 generic_fillattr(user_ns, path->dentry->d_inode, stat);
d4dc53da
YY
610#elif defined(HAVE_GENERIC_FILLATTR_IDMAP)
611 generic_fillattr(user_ns, path->dentry->d_inode, stat);
ef70eff1
AZ
612#else
613 (void) user_ns;
614#endif
e2a82961 615#else
a3478c07 616 generic_fillattr(path->dentry->d_inode, stat);
e2a82961 617#endif
ebe7e575 618 stat->nlink = stat->size = 2;
2946a1a1 619 stat->atime = current_time(ip);
768eaced 620 zpl_exit(zfsvfs, FTAG);
a3478c07 621 return (0);
ebe7e575
BB
622 }
623
0037b49e 624 error = -zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp);
90ee9ed3 625 if (error == 0) {
d4dc53da 626#if (defined(HAVE_USERNS_IOPS_GETATTR) || defined(HAVE_IDMAP_IOPS_GETATTR))
e2a82961
CK
627 error = -zfs_getattr_fast(user_ns, ZTOI(dzp), stat);
628#else
629 error = -zfs_getattr_fast(kcred->user_ns, ZTOI(dzp), stat);
630#endif
90ee9ed3
BB
631 iput(ZTOI(dzp));
632 }
ebe7e575 633
768eaced 634 zpl_exit(zfsvfs, FTAG);
ebe7e575
BB
635 ASSERT3S(error, <=, 0);
636
637 return (error);
638}
a3478c07 639ZPL_GETATTR_WRAPPER(zpl_shares_getattr);
ebe7e575
BB
640
641/*
642 * The '.zfs/shares' directory file operations.
643 */
644const struct file_operations zpl_fops_shares = {
645 .open = zpl_common_open,
646 .llseek = generic_file_llseek,
647 .read = generic_read_dir,
9baaa7de
CC
648#ifdef HAVE_VFS_ITERATE_SHARED
649 .iterate_shared = zpl_shares_iterate,
650#elif defined(HAVE_VFS_ITERATE)
0f37d0c8
RY
651 .iterate = zpl_shares_iterate,
652#else
ebe7e575 653 .readdir = zpl_shares_readdir,
0f37d0c8
RY
654#endif
655
ebe7e575
BB
656};
657
658/*
659 * The '.zfs/shares' directory inode operations.
660 */
661const struct inode_operations zpl_ops_shares = {
662 .lookup = zpl_shares_lookup,
663 .getattr = zpl_shares_getattr,
664};