2 * Copyright (c) 2015 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/kernel.h>
32 #include <sys/vnode_internal.h>
34 #include <sys/kauth.h>
35 #include <sys/mount_internal.h>
36 #include <sys/fcntl.h>
37 #include <sys/unistd.h>
38 #include <sys/malloc.h>
39 #include <vfs/vfs_support.h>
41 #include <libkern/OSAtomic.h>
44 #include <security/mac_framework.h>
49 static int routefs_init(__unused
struct vfsconf
*vfsp
);
50 static int routefs_mount(struct mount
*mp
, __unused vnode_t devvp
, __unused user_addr_t data
, vfs_context_t ctx
);
51 static int routefs_start(__unused
struct mount
*mp
, __unused
int flags
, __unused vfs_context_t ctx
);
52 static int routefs_unmount( struct mount
*mp
, int mntflags
, __unused vfs_context_t ctx
);
53 static int routefs_root(struct mount
*mp
, struct vnode
**vpp
, __unused vfs_context_t ctx
);
54 static int routefs_statfs( struct mount
*mp
, struct vfsstatfs
*sbp
, __unused vfs_context_t ctx
);
55 static int routefs_vfs_getattr(__unused mount_t mp
, struct vfs_attr
*fsap
, __unused vfs_context_t ctx
);
56 static int routefs_sync(__unused
struct mount
*mp
, __unused
int waitfor
, __unused vfs_context_t ctx
);
57 static int routefs_vget(__unused
struct mount
*mp
, __unused ino64_t ino
, __unused
struct vnode
**vpp
, __unused vfs_context_t ctx
);
58 static int routefs_fhtovp (__unused
struct mount
*mp
, __unused
int fhlen
, __unused
unsigned char *fhp
, __unused
struct vnode
**vpp
, __unused vfs_context_t ctx
);
59 static int routefs_vptofh (__unused
struct vnode
*vp
, __unused
int *fhlenp
, __unused
unsigned char *fhp
, __unused vfs_context_t ctx
);
60 static int routefs_sysctl(__unused
int *name
, __unused u_int namelen
, __unused user_addr_t oldp
,
61 __unused
size_t *oldlenp
, __unused user_addr_t newp
,
62 __unused
size_t newlen
, __unused vfs_context_t ctx
);
63 static int routefserr_lookup(__unused
struct vnop_lookup_args
* args
);
65 static int routefserr_setlabel(__unused
struct vnop_setlabel_args
* args
);
68 lck_grp_t
* routefs_lck_grp
;
69 lck_grp_attr_t
* routefs_lck_grp_attr
;
70 lck_attr_t
* routefs_lck_attr
;
71 lck_mtx_t routefs_mutex
;
73 #define ROUTEFS_LOCK() lck_mtx_lock(&routefs_mutex)
74 #define ROUTEFS_UNLOCK() lck_mtx_unlock(&routefs_mutex)
75 static int _lock_inited
= 0;
76 static boolean_t _fs_alreadyMounted
= FALSE
; /* atleast a mount of this filesystem is present */
79 routefs_init(__unused
struct vfsconf
*vfsp
)
81 routefs_lck_grp_attr
= lck_grp_attr_alloc_init();
82 routefs_lck_grp
= lck_grp_alloc_init("routefs_lock", routefs_lck_grp_attr
);
83 routefs_lck_attr
= lck_attr_alloc_init();
84 lck_mtx_init(&routefs_mutex
, routefs_lck_grp
, routefs_lck_attr
);
91 routefs_mount(struct mount
*mp
, __unused vnode_t devvp
, user_addr_t data
, vfs_context_t ctx
)
93 struct routefs_mount
*routefs_mp_p
= NULL
; /* routefs specific mount info */
95 struct routefs_args
* rargs
= (struct routefs_args
*)data
;
98 * If they just want to update, we don't need to do anything.
100 if (mp
->mnt_flag
& MNT_UPDATE
)
106 /* check for root mount only */
107 if ((error
= proc_suser(current_proc()))!= 0) {
111 if (vfs_iskernelmount(mp
) == FALSE
) {
116 if (_fs_alreadyMounted
== TRUE
) {
117 /* if a filesystem is mounted, it needs to be unmounted prior to mount again */
122 /* Advisory locking should be handled at the VFS layer */
123 vfs_setlocklocal(mp
);
126 * Well, it's not an update, it's a real mount request.
128 * HERE we should check to see if we are already mounted here.
131 MALLOC(routefs_mp_p
, struct routefs_mount
*, sizeof(struct routefs_mount
),
133 if (routefs_mp_p
== NULL
)
135 bzero(routefs_mp_p
, sizeof(*routefs_mp_p
));
137 routefs_mp_p
->route_mount
= mp
;
139 if (rargs
->route_rvp
== NULLVP
) {
144 strlcpy(routefs_mp_p
->route_path
,rargs
->route_path
, MAXPATHLEN
);
145 routefs_mp_p
->route_rvp
= rargs
->route_rvp
;
146 routefs_mp_p
->route_vpvid
= vnode_vid(rargs
->route_rvp
);
148 if (vnode_ref(routefs_mp_p
->route_rvp
) != 0) {
154 * Fill out some fields
156 __IGNORE_WCASTALIGN(mp
->mnt_data
= (qaddr_t
)routefs_mp_p
);
157 mp
->mnt_vfsstat
.f_fsid
.val
[0] = (int32_t)(uintptr_t)routefs_mp_p
;
158 mp
->mnt_vfsstat
.f_fsid
.val
[1] = vfs_typenum(mp
);
159 mp
->mnt_flag
|= MNT_LOCAL
;
162 * Copy in the name of the directory the filesystem
163 * is to be mounted on.
164 * And we clear the remainder of the character strings
168 bzero(mp
->mnt_vfsstat
.f_mntfromname
, MAXPATHLEN
);
169 bcopy("routefs",mp
->mnt_vfsstat
.f_mntfromname
, 5);
170 (void)routefs_statfs(mp
, &mp
->mnt_vfsstat
, ctx
);
171 _fs_alreadyMounted
= TRUE
; /* yep, fs is in play now */
175 if (routefs_mp_p
!= NULL
)
176 FREE((caddr_t
)routefs_mp_p
, M_TEMP
);
183 routefs_start(__unused
struct mount
*mp
, __unused
int flags
, __unused vfs_context_t ctx
)
189 * Unmount the filesystem described by mp.
192 routefs_unmount( struct mount
*mp
, int mntflags
, __unused vfs_context_t ctx
)
194 struct routefs_mount
*routefs_mp_p
= (struct routefs_mount
*)mp
->mnt_data
;
199 /* check for root unmount only */
200 if ((error
= proc_suser(current_proc()))!= 0) {
204 if (mntflags
& MNT_FORCE
) {
208 /* giveup the ioref of vnode, no longer need it */
209 if (routefs_mp_p
->route_rvp
!= NULLVP
) {
210 if (vnode_getwithref(routefs_mp_p
->route_rvp
) == 0) {
211 vnode_rele(routefs_mp_p
->route_rvp
);
212 vnode_put(routefs_mp_p
->route_rvp
);
213 routefs_mp_p
->route_rvp
= NULLVP
;
216 /* no vnodes, ignore any errors */
217 (void)vflush(mp
, NULLVP
, flags
);
218 FREE((caddr_t
)routefs_mp_p
, M_TEMP
);
219 mp
->mnt_data
= (qaddr_t
)0;
220 mp
->mnt_flag
&= ~MNT_LOCAL
;
221 _fs_alreadyMounted
= FALSE
; /* unmounted the fs, only one allowed at a time */
225 /* return the address of the root vnode in *vpp */
227 routefs_root(struct mount
*mp
, struct vnode
**vpp
, __unused vfs_context_t ctx
)
229 struct routefs_mount
*routefs_mp_p
= (struct routefs_mount
*)(mp
->mnt_data
);
232 /* check for nullvp incase its being rolled */
233 if (routefs_mp_p
->route_rvp
== NULLVP
) {
235 if (routefs_mp_p
->route_rvp
== NULLVP
) {
242 if (vnode_getwithvid(routefs_mp_p
->route_rvp
, routefs_mp_p
->route_vpvid
) != 0) {
243 /* only one in the path., since no vnodes with this, you can hold across this call */
245 if (vnode_getwithref(routefs_mp_p
->route_rvp
) == 0) {
246 vnode_rele(routefs_mp_p
->route_rvp
);
247 vnode_put(routefs_mp_p
->route_rvp
);
248 routefs_mp_p
->route_rvp
= NULLVP
;
249 routefs_mp_p
->route_vpvid
= -1;
250 error
= vnode_lookup(routefs_mp_p
->route_path
, FREAD
|O_DIRECTORY
, &routefs_mp_p
->route_rvp
, ctx
);
252 routefs_mp_p
->route_vpvid
= vnode_vid(routefs_mp_p
->route_rvp
);
261 *vpp
= routefs_mp_p
->route_rvp
;
267 routefs_statfs( struct mount
*mp
, struct vfsstatfs
*sbp
, __unused vfs_context_t ctx
)
269 struct routefs_mount
*routefs_mp_p
= (struct routefs_mount
*)mp
->mnt_data
;
272 * Fill in the stat block.
274 //sbp->f_type = mp->mnt_vfsstat.f_type;
275 sbp
->f_flags
= 0; /* XXX */
278 sbp
->f_blocks
= (sizeof(struct routefs_mount
)+ sbp
->f_bsize
) / sbp
->f_bsize
;
283 sbp
->f_fsid
.val
[0] = (int32_t)(uintptr_t)routefs_mp_p
;
284 sbp
->f_fsid
.val
[1] = vfs_typenum(mp
);
290 routefs_vfs_getattr(__unused mount_t mp
, struct vfs_attr
*fsap
, __unused vfs_context_t ctx
)
292 VFSATTR_RETURN(fsap
, f_objcount
, 1);
293 VFSATTR_RETURN(fsap
, f_maxobjcount
, 1);
294 VFSATTR_RETURN(fsap
, f_bsize
, 512);
295 VFSATTR_RETURN(fsap
, f_iosize
, 512);
296 if (VFSATTR_IS_ACTIVE(fsap
, f_blocks
) || VFSATTR_IS_ACTIVE(fsap
, f_bused
)) {
297 fsap
->f_blocks
= (sizeof(struct routefs_mount
)+ fsap
->f_bsize
) / fsap
->f_bsize
;
298 fsap
->f_bused
= fsap
->f_blocks
;
299 VFSATTR_SET_SUPPORTED(fsap
, f_blocks
);
300 VFSATTR_SET_SUPPORTED(fsap
, f_bused
);
302 VFSATTR_RETURN(fsap
, f_bfree
, 0);
303 VFSATTR_RETURN(fsap
, f_bavail
, 0);
304 VFSATTR_RETURN(fsap
, f_files
, 0);
305 VFSATTR_RETURN(fsap
, f_ffree
, 0);
306 VFSATTR_RETURN(fsap
, f_fssubtype
, 0);
308 if (VFSATTR_IS_ACTIVE(fsap
, f_capabilities
)) {
309 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_FORMAT
] =
310 VOL_CAP_FMT_SYMBOLICLINKS
|
311 VOL_CAP_FMT_HARDLINKS
|
312 VOL_CAP_FMT_NO_ROOT_TIMES
|
313 VOL_CAP_FMT_CASE_SENSITIVE
|
314 VOL_CAP_FMT_CASE_PRESERVING
|
315 VOL_CAP_FMT_FAST_STATFS
|
316 VOL_CAP_FMT_2TB_FILESIZE
|
317 VOL_CAP_FMT_HIDDEN_FILES
;
318 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_INTERFACES
] =
319 VOL_CAP_INT_ATTRLIST
;
320 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_RESERVED1
] = 0;
321 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_RESERVED2
] = 0;
323 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_FORMAT
] =
324 VOL_CAP_FMT_PERSISTENTOBJECTIDS
|
325 VOL_CAP_FMT_SYMBOLICLINKS
|
326 VOL_CAP_FMT_HARDLINKS
|
327 VOL_CAP_FMT_JOURNAL
|
328 VOL_CAP_FMT_JOURNAL_ACTIVE
|
329 VOL_CAP_FMT_NO_ROOT_TIMES
|
330 VOL_CAP_FMT_SPARSE_FILES
|
331 VOL_CAP_FMT_ZERO_RUNS
|
332 VOL_CAP_FMT_CASE_SENSITIVE
|
333 VOL_CAP_FMT_CASE_PRESERVING
|
334 VOL_CAP_FMT_FAST_STATFS
|
335 VOL_CAP_FMT_2TB_FILESIZE
|
336 VOL_CAP_FMT_OPENDENYMODES
|
337 VOL_CAP_FMT_HIDDEN_FILES
|
338 VOL_CAP_FMT_PATH_FROM_ID
|
339 VOL_CAP_FMT_NO_VOLUME_SIZES
;
340 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_INTERFACES
] =
341 VOL_CAP_INT_SEARCHFS
|
342 VOL_CAP_INT_ATTRLIST
|
343 VOL_CAP_INT_NFSEXPORT
|
344 VOL_CAP_INT_READDIRATTR
|
345 VOL_CAP_INT_EXCHANGEDATA
|
346 VOL_CAP_INT_COPYFILE
|
347 VOL_CAP_INT_ALLOCATE
|
348 VOL_CAP_INT_VOL_RENAME
|
349 VOL_CAP_INT_ADVLOCK
|
351 VOL_CAP_INT_EXTENDED_SECURITY
|
352 VOL_CAP_INT_USERACCESS
|
353 VOL_CAP_INT_MANLOCK
|
354 VOL_CAP_INT_EXTENDED_ATTR
|
355 VOL_CAP_INT_NAMEDSTREAMS
;
356 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_RESERVED1
] = 0;
357 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_RESERVED2
] = 0;
359 VFSATTR_SET_SUPPORTED(fsap
, f_capabilities
);
362 if (VFSATTR_IS_ACTIVE(fsap
, f_attributes
)) {
363 fsap
->f_attributes
.validattr
.commonattr
=
364 ATTR_CMN_NAME
| ATTR_CMN_DEVID
| ATTR_CMN_FSID
|
365 ATTR_CMN_OBJTYPE
| ATTR_CMN_OBJTAG
| ATTR_CMN_OBJID
|
367 ATTR_CMN_MODTIME
| ATTR_CMN_CHGTIME
| ATTR_CMN_ACCTIME
|
368 ATTR_CMN_OWNERID
| ATTR_CMN_GRPID
| ATTR_CMN_ACCESSMASK
|
369 ATTR_CMN_FLAGS
| ATTR_CMN_USERACCESS
| ATTR_CMN_FILEID
;
370 fsap
->f_attributes
.validattr
.volattr
=
371 ATTR_VOL_FSTYPE
| ATTR_VOL_SIZE
| ATTR_VOL_SPACEFREE
|
372 ATTR_VOL_SPACEAVAIL
| ATTR_VOL_MINALLOCATION
|
373 ATTR_VOL_OBJCOUNT
| ATTR_VOL_MAXOBJCOUNT
|
374 ATTR_VOL_MOUNTPOINT
| ATTR_VOL_MOUNTFLAGS
|
375 ATTR_VOL_MOUNTEDDEVICE
| ATTR_VOL_CAPABILITIES
|
377 fsap
->f_attributes
.validattr
.dirattr
=
378 ATTR_DIR_LINKCOUNT
| ATTR_DIR_MOUNTSTATUS
;
379 fsap
->f_attributes
.validattr
.fileattr
=
380 ATTR_FILE_LINKCOUNT
| ATTR_FILE_TOTALSIZE
|
381 ATTR_FILE_IOBLOCKSIZE
| ATTR_FILE_DEVTYPE
|
382 ATTR_FILE_DATALENGTH
;
383 fsap
->f_attributes
.validattr
.forkattr
= 0;
385 fsap
->f_attributes
.nativeattr
.commonattr
=
386 ATTR_CMN_NAME
| ATTR_CMN_DEVID
| ATTR_CMN_FSID
|
387 ATTR_CMN_OBJTYPE
| ATTR_CMN_OBJTAG
| ATTR_CMN_OBJID
|
389 ATTR_CMN_MODTIME
| ATTR_CMN_CHGTIME
| ATTR_CMN_ACCTIME
|
390 ATTR_CMN_OWNERID
| ATTR_CMN_GRPID
| ATTR_CMN_ACCESSMASK
|
391 ATTR_CMN_FLAGS
| ATTR_CMN_USERACCESS
| ATTR_CMN_FILEID
;
392 fsap
->f_attributes
.nativeattr
.volattr
=
393 ATTR_VOL_FSTYPE
| ATTR_VOL_SIZE
| ATTR_VOL_SPACEFREE
|
394 ATTR_VOL_SPACEAVAIL
| ATTR_VOL_MINALLOCATION
|
395 ATTR_VOL_OBJCOUNT
| ATTR_VOL_MAXOBJCOUNT
|
396 ATTR_VOL_MOUNTPOINT
| ATTR_VOL_MOUNTFLAGS
|
397 ATTR_VOL_MOUNTEDDEVICE
| ATTR_VOL_CAPABILITIES
|
399 fsap
->f_attributes
.nativeattr
.dirattr
=
400 ATTR_DIR_MOUNTSTATUS
;
401 fsap
->f_attributes
.nativeattr
.fileattr
=
402 ATTR_FILE_LINKCOUNT
| ATTR_FILE_TOTALSIZE
|
403 ATTR_FILE_IOBLOCKSIZE
| ATTR_FILE_DEVTYPE
|
404 ATTR_FILE_DATALENGTH
;
405 fsap
->f_attributes
.nativeattr
.forkattr
= 0;
407 VFSATTR_SET_SUPPORTED(fsap
, f_attributes
);
414 routefs_sync(__unused
struct mount
*mp
, __unused
int waitfor
, __unused vfs_context_t ctx
)
421 routefs_vget(__unused
struct mount
*mp
, __unused ino64_t ino
, __unused
struct vnode
**vpp
, __unused vfs_context_t ctx
)
427 routefs_fhtovp (__unused
struct mount
*mp
, __unused
int fhlen
, __unused
unsigned char *fhp
, __unused
struct vnode
**vpp
, __unused vfs_context_t ctx
)
434 routefs_vptofh (__unused
struct vnode
*vp
, __unused
int *fhlenp
, __unused
unsigned char *fhp
, __unused vfs_context_t ctx
)
440 routefs_sysctl(__unused
int *name
, __unused u_int namelen
, __unused user_addr_t oldp
,
441 __unused
size_t *oldlenp
, __unused user_addr_t newp
,
442 __unused
size_t newlen
, __unused vfs_context_t ctx
)
447 #include <sys/namei.h>
448 #define MOBILE_DIR_PATH "/private/var/mobile"
450 * Function: routefs_kernel_mount
452 * Mount routefs at the given mount point from within the kernel.
455 routefs_kernel_mount(char * routepath
)
458 vfs_context_t ctx
= vfs_context_kernel();
459 char fsname
[] = "routefs";
460 struct routefs_args args
;
461 char mounthere
[] = MOBILE_DIR_PATH
; /* !const because of internal casting */
463 bzero(&args
, sizeof(struct routefs_args
));
464 strlcpy(args
.route_path
, routepath
, MAXPATHLEN
);
465 error
= vnode_lookup(args
.route_path
, FREAD
|O_DIRECTORY
, &args
.route_rvp
, ctx
);
470 if (!vnode_isdir(args
.route_rvp
)) {
475 error
= kernel_mount(fsname
, NULLVP
, NULLVP
, mounthere
, &args
, 0, MNT_DONTBROWSE
, KERNEL_MOUNT_NOAUTH
, ctx
);
481 if(args
.route_rvp
!= NULLVP
)
482 (void) vnode_put(args
.route_rvp
);
486 struct vfsops routefs_vfsops
= {
487 .vfs_mount
= routefs_mount
,
488 .vfs_start
= routefs_start
,
489 .vfs_unmount
= routefs_unmount
,
490 .vfs_root
= routefs_root
,
491 .vfs_getattr
= routefs_vfs_getattr
,
492 .vfs_sync
= routefs_sync
,
493 .vfs_vget
= routefs_vget
,
494 .vfs_fhtovp
= routefs_fhtovp
,
495 .vfs_vptofh
= routefs_vptofh
,
496 .vfs_init
= routefs_init
,
497 .vfs_sysctl
= routefs_sysctl
,
498 // There are other VFS ops that we do not support
501 static int routefserr_lookup(__unused
struct vnop_lookup_args
* args
)
506 static int routefserr_setlabel(__unused
struct vnop_setlabel_args
* args
)
512 #define VOPFUNC int (*)(void *)
514 /* The following ops are used by directories and symlinks */
515 int (**routefs_vnodeop_p
)(void *);
516 static struct vnodeopv_entry_desc routefs_vnodeop_entries
[] = {
517 { &vnop_default_desc
, (VOPFUNC
)vn_default_error
},
518 { &vnop_lookup_desc
, (VOPFUNC
)routefserr_lookup
}, /* lookup */
519 { &vnop_create_desc
, (VOPFUNC
)err_create
}, /* create */
520 { &vnop_whiteout_desc
, (VOPFUNC
)err_whiteout
}, /* whiteout */
521 { &vnop_mknod_desc
, (VOPFUNC
)err_mknod
}, /* mknod */
522 { &vnop_open_desc
, (VOPFUNC
)err_open
}, /* open */
523 { &vnop_close_desc
, (VOPFUNC
)err_close
}, /* close */
524 { &vnop_getattr_desc
, (VOPFUNC
)err_getattr
}, /* getattr */
525 { &vnop_setattr_desc
, (VOPFUNC
)err_setattr
}, /* setattr */
526 { &vnop_read_desc
, (VOPFUNC
)err_read
}, /* read */
527 { &vnop_write_desc
, (VOPFUNC
)err_write
}, /* write */
528 { &vnop_ioctl_desc
, (VOPFUNC
)err_ioctl
}, /* ioctl */
529 { &vnop_select_desc
, (VOPFUNC
)err_select
}, /* select */
530 { &vnop_revoke_desc
, (VOPFUNC
)err_revoke
}, /* revoke */
531 { &vnop_mmap_desc
, (VOPFUNC
)err_mmap
}, /* mmap */
532 { &vnop_fsync_desc
, (VOPFUNC
)nop_fsync
}, /* fsync */
533 { &vnop_remove_desc
, (VOPFUNC
)err_remove
}, /* remove */
534 { &vnop_link_desc
, (VOPFUNC
)err_link
}, /* link */
535 { &vnop_rename_desc
, (VOPFUNC
)err_rename
}, /* rename */
536 { &vnop_mkdir_desc
, (VOPFUNC
)err_mkdir
}, /* mkdir */
537 { &vnop_rmdir_desc
, (VOPFUNC
)err_rmdir
}, /* rmdir */
538 { &vnop_symlink_desc
, (VOPFUNC
)err_symlink
}, /* symlink */
539 { &vnop_readdir_desc
, (VOPFUNC
)err_readdir
}, /* readdir */
540 { &vnop_readlink_desc
, (VOPFUNC
)err_readlink
}, /* readlink */
541 { &vnop_inactive_desc
, (VOPFUNC
)err_inactive
}, /* inactive */
542 { &vnop_reclaim_desc
, (VOPFUNC
)err_reclaim
}, /* reclaim */
543 { &vnop_strategy_desc
, (VOPFUNC
)err_strategy
}, /* strategy */
544 { &vnop_pathconf_desc
, (VOPFUNC
)err_pathconf
}, /* pathconf */
545 { &vnop_advlock_desc
, (VOPFUNC
)err_advlock
}, /* advlock */
546 { &vnop_bwrite_desc
, (VOPFUNC
)err_bwrite
},
547 { &vnop_pagein_desc
, (VOPFUNC
)err_pagein
}, /* Pagein */
548 { &vnop_pageout_desc
, (VOPFUNC
)err_pageout
}, /* Pageout */
549 { &vnop_copyfile_desc
, (VOPFUNC
)err_copyfile
}, /* Copyfile */
550 { &vnop_blktooff_desc
, (VOPFUNC
)err_blktooff
}, /* blktooff */
551 { &vnop_offtoblk_desc
, (VOPFUNC
)err_offtoblk
}, /* offtoblk */
552 { &vnop_blockmap_desc
, (VOPFUNC
)err_blockmap
}, /* blockmap */
554 { &vnop_setlabel_desc
, (VOPFUNC
)routefserr_setlabel
}, /* setlabel */
556 { (struct vnodeop_desc
*)NULL
, (int(*)(void *))NULL
}
558 struct vnodeopv_desc routefs_vnodeop_opv_desc
=
559 { &routefs_vnodeop_p
, routefs_vnodeop_entries
};