2 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
30 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
32 * Copyright (c) 1992, 1993
33 * The Regents of the University of California. All rights reserved.
35 * This code is derived from software donated to Berkeley by
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the University of
49 * California, Berkeley and its contributors.
50 * 4. Neither the name of the University nor the names of its contributors
51 * may be used to endorse or promote products derived from this software
52 * without specific prior written permission.
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66 * @(#)fdesc_vnops.c 8.17 (Berkeley) 5/22/95
74 #include <sys/param.h>
75 #include <sys/systm.h>
76 #include <sys/types.h>
78 #include <sys/proc_internal.h>
79 #include <sys/kernel.h> /* boottime */
80 #include <sys/resourcevar.h>
81 #include <sys/filedesc.h>
82 #include <sys/kauth.h>
83 #include <sys/vnode_internal.h>
84 #include <sys/malloc.h>
85 #include <sys/file_internal.h>
87 #include <sys/mount_internal.h>
88 #include <sys/namei.h>
89 #include <sys/dirent.h>
91 #include <sys/socketvar.h>
93 #include <sys/uio_internal.h>
94 #include <miscfs/fdesc/fdesc.h>
95 #include <vfs/vfs_support.h>
96 #include <pexpert/pexpert.h>
99 #define FDL_LOCKED 0x02
100 static int fdcache_lock
;
103 #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1)
104 FD_STDIN
, FD_STDOUT
, FD_STDERR must be a sequence n
, n
+1, n
+2
109 #define FD_NHASH(ix) \
110 (&fdhashtbl[(ix) & fdhash])
111 LIST_HEAD(fdhashhead
, fdescnode
) *fdhashtbl
;
114 static int fdesc_attr(int fd
, struct vnode_attr
*vap
, vfs_context_t a_context
);
118 * Initialise cache headers
121 fdesc_init(__unused
struct vfsconf
*vfsp
)
124 fdhashtbl
= hashinit(NFDCACHE
, M_CACHE
, &fdhash
);
130 fdesc_allocvp(ftype
, ix
, mp
, vpp
, vtype
)
137 struct fdhashhead
*fc
;
138 struct fdescnode
*fd
;
141 struct vnode_fsparam vfsp
;
145 for (fd
= fc
->lh_first
; fd
!= 0; fd
= fd
->fd_hash
.le_next
) {
146 if (fd
->fd_ix
== ix
&& vnode_mount(fd
->fd_vnode
) == mp
) {
148 * doing a vnode_getwithvid isn't technically
149 * necessary since fdesc is an unsafe filesystem
150 * and we're running behind a funnel at this point
151 * however, vnode_get always succeeds, which isn't
152 * what we want if this vnode is in the process of
155 vid
= vnode_vid(fd
->fd_vnode
);
157 if (vnode_getwithvid(fd
->fd_vnode
, vid
))
160 (*vpp
)->v_type
= vtype
;
167 * otherwise lock the array while we call getnewvnode
168 * since that can block.
170 if (fdcache_lock
& FDL_LOCKED
) {
171 fdcache_lock
|= FDL_WANT
;
172 sleep((caddr_t
) &fdcache_lock
, PINOD
);
175 fdcache_lock
|= FDL_LOCKED
;
177 MALLOC(fd
, void *, sizeof(struct fdescnode
), M_TEMP
, M_WAITOK
);
180 vfsp
.vnfs_vtype
= vtype
;
181 vfsp
.vnfs_str
= "fdesc";
183 vfsp
.vnfs_fsnode
= fd
;
185 vfsp
.vnfs_vops
= fdesc_vnodeop_p
;
187 vfsp
.vnfs_filesize
= 0;
188 vfsp
.vnfs_flags
= VNFS_NOCACHE
| VNFS_CANTCACHE
;
189 vfsp
.vnfs_marksystem
= 0;
191 vfsp
.vnfs_markroot
= 1;
193 vfsp
.vnfs_markroot
= 0;
195 error
= vnode_create(VNCREATE_FLAVOR
, VCREATESIZE
, &vfsp
, vpp
);
200 (*vpp
)->v_tag
= VT_FDESC
;
206 LIST_INSERT_HEAD(fc
, fd
, fd_hash
);
209 fdcache_lock
&= ~FDL_LOCKED
;
211 if (fdcache_lock
& FDL_WANT
) {
212 fdcache_lock
&= ~FDL_WANT
;
213 wakeup((caddr_t
) &fdcache_lock
);
220 * vp is the current namei directory
221 * ndp is the name to locate in that directory...
225 struct vnop_lookup_args
/* {
226 struct vnode * a_dvp;
227 struct vnode ** a_vpp;
228 struct componentname * a_cnp;
229 vfs_context_t a_context;
232 struct vnode
**vpp
= ap
->a_vpp
;
233 struct vnode
*dvp
= ap
->a_dvp
;
234 struct componentname
*cnp
= ap
->a_cnp
;
235 char *pname
= cnp
->cn_nameptr
;
236 struct proc
*p
= vfs_context_proc(ap
->a_context
);
237 int numfiles
= p
->p_fd
->fd_nfiles
;
243 if (cnp
->cn_namelen
== 1 && *pname
== '.') {
246 if ( (error
= vnode_get(dvp
)) ) {
252 switch (VTOFDESC(dvp
)->fd_type
) {
256 /* should never happen */
261 if (cnp
->cn_namelen
== 2 && bcmp(pname
, "fd", 2) == 0) {
262 error
= fdesc_allocvp(Fdevfd
, FD_DEVFD
, dvp
->v_mount
, &fvp
, VDIR
);
270 switch (cnp
->cn_namelen
) {
272 if (bcmp(pname
, "stdin", 5) == 0) {
278 if (bcmp(pname
, "stdout", 6) == 0) {
282 if (bcmp(pname
, "stderr", 6) == 0) {
290 error
= fdesc_allocvp(Flink
, fd
, dvp
->v_mount
, &fvp
, VLNK
);
293 VTOFDESC(fvp
)->fd_link
= ln
;
304 if (cnp
->cn_namelen
== 2 && bcmp(pname
, "..", 2) == 0) {
305 if ((error
= fdesc_root(dvp
->v_mount
, vpp
, ap
->a_context
)))
311 while (*pname
>= '0' && *pname
<= '9') {
312 fd
= 10 * fd
+ *pname
++ - '0';
317 if (*pname
!= '\0') {
322 if (fd
< 0 || fd
>= numfiles
||
323 *fdfile(p
, fd
) == NULL
||
324 (*fdflags(p
, fd
) & UF_RESERVED
)) {
329 error
= fdesc_allocvp(Fdesc
, FD_DESC
+fd
, dvp
->v_mount
, &fvp
, VNON
);
332 VTOFDESC(fvp
)->fd_fd
= fd
;
344 struct vnop_open_args
/* {
347 vfs_context_t a_context;
350 struct vnode
*vp
= ap
->a_vp
;
351 struct proc
*p
= vfs_context_proc(ap
->a_context
);
354 switch (VTOFDESC(vp
)->fd_type
) {
357 * XXX Kludge: set p->p_dupfd to contain the value of the
358 * the file descriptor being sought for duplication. The error
359 * return ensures that the vnode for this device will be
360 * released by vn_open. Open will detect this special error and
361 * take the actions in dupfdopen. Other callers of vn_open or
362 * vnop_open will simply report the error.
364 p
->p_dupfd
= VTOFDESC(vp
)->fd_fd
; /* XXX */
374 fdesc_attr(int fd
, struct vnode_attr
*vap
, vfs_context_t a_context
)
377 struct proc
*p
= vfs_context_proc(a_context
);
381 if ((error
= fp_lookup(p
, fd
, &fp
, 0)))
383 switch (fp
->f_fglob
->fg_type
) {
385 if(error
= vnode_getwithref((struct vnode
*) fp
->f_fglob
->fg_data
)) {
388 if ((error
= vnode_authorize((struct vnode
*)fp
->f_fglob
->fg_data
,
390 KAUTH_VNODE_READ_ATTRIBUTES
| KAUTH_VNODE_READ_SECURITY
,
392 error
= vnode_getattr((struct vnode
*)fp
->f_fglob
->fg_data
, vap
, a_context
);
393 if (error
== 0 && vap
->va_type
== VDIR
) {
395 * directories can cause loops in the namespace,
396 * so turn off the 'x' bits to avoid trouble.
398 * XXX ACLs break this, of course
400 vap
->va_mode
&= ~((VEXEC
)|(VEXEC
>>3)|(VEXEC
>>6));
402 (void)vnode_put((struct vnode
*) fp
->f_fglob
->fg_data
);
407 if (fp
->f_fglob
->fg_type
== DTYPE_SOCKET
)
408 error
= soo_stat((struct socket
*)fp
->f_fglob
->fg_data
, &stb
);
410 error
= pipe_stat((struct socket
*)fp
->f_fglob
->fg_data
, &stb
);
413 if (fp
->f_fglob
->fg_type
== DTYPE_SOCKET
)
414 VATTR_RETURN(vap
, va_type
, VSOCK
);
416 VATTR_RETURN(vap
, va_type
, VFIFO
);
418 VATTR_RETURN(vap
, va_mode
, stb
.st_mode
);
419 VATTR_RETURN(vap
, va_nlink
, stb
.st_nlink
);
420 VATTR_RETURN(vap
, va_uid
, stb
.st_uid
);
421 VATTR_RETURN(vap
, va_gid
, stb
.st_gid
);
422 VATTR_RETURN(vap
, va_fsid
, stb
.st_dev
);
423 VATTR_RETURN(vap
, va_fileid
, stb
.st_ino
);
424 VATTR_RETURN(vap
, va_data_size
, stb
.st_size
);
425 VATTR_RETURN(vap
, va_access_time
, stb
.st_atimespec
);
426 VATTR_RETURN(vap
, va_modify_time
, stb
.st_mtimespec
);
427 VATTR_RETURN(vap
, va_change_time
, stb
.st_ctimespec
);
428 VATTR_RETURN(vap
, va_gen
, stb
.st_gen
);
429 VATTR_RETURN(vap
, va_flags
, stb
.st_flags
);
430 VATTR_RETURN(vap
, va_rdev
, stb
.st_rdev
);
431 VATTR_RETURN(vap
, va_total_alloc
, stb
.st_blocks
* stb
.st_blksize
);
432 VATTR_RETURN(vap
, va_acl
, NULL
);
440 fp_drop(p
, fd
, fp
, 0);
446 struct vnop_getattr_args
/* {
448 struct vnode_attr *a_vap;
449 vfs_context_t a_context;
452 struct vnode
*vp
= ap
->a_vp
;
453 struct vnode_attr
*vap
= ap
->a_vap
;
458 switch (VTOFDESC(vp
)->fd_type
) {
462 VATTR_RETURN(vap
, va_fileid
, VTOFDESC(vp
)->fd_ix
);
463 VATTR_RETURN(vap
, va_uid
, 0);
464 VATTR_RETURN(vap
, va_gid
, 0);
465 VATTR_RETURN(vap
, va_fsid
, vp
->v_mount
->mnt_vfsstat
.f_fsid
.val
[0]);
466 VATTR_RETURN(vap
, va_iosize
, DEV_BSIZE
);
467 ts
.tv_sec
= boottime_sec();
469 VATTR_RETURN(vap
, va_access_time
, ts
);
470 VATTR_RETURN(vap
, va_modify_time
, ts
);
471 VATTR_RETURN(vap
, va_change_time
, ts
);
472 VATTR_RETURN(vap
, va_gen
, 0);
473 VATTR_RETURN(vap
, va_flags
, 0);
474 VATTR_RETURN(vap
, va_rdev
, 0);
475 VATTR_RETURN(vap
, va_acl
, NULL
);
477 switch (VTOFDESC(vp
)->fd_type
) {
479 VATTR_RETURN(vap
, va_mode
, S_IRUSR
|S_IRGRP
|S_IROTH
);
480 VATTR_RETURN(vap
, va_type
, VLNK
); /* not strictly required */
481 VATTR_RETURN(vap
, va_nlink
, 1);
482 VATTR_RETURN(vap
, va_data_size
, strlen(VTOFDESC(vp
)->fd_link
));
486 VATTR_RETURN(vap
, va_mode
, S_IRUSR
|S_IXUSR
|S_IRGRP
|S_IXGRP
|S_IROTH
|S_IXOTH
);
487 VATTR_RETURN(vap
, va_type
, VDIR
);
488 VATTR_RETURN(vap
, va_nlink
, 2);
489 VATTR_RETURN(vap
, va_data_size
, DEV_BSIZE
);
495 fd
= VTOFDESC(vp
)->fd_fd
;
496 error
= fdesc_attr(fd
, vap
, ap
->a_context
);
505 vp
->v_type
= vap
->va_type
;
513 struct vnop_setattr_args
/* {
515 struct vnode_attr *a_vap;
516 vfs_context_t a_context;
522 struct proc
* p
= vfs_context_proc(ap
->a_context
);
525 * Can't mess with the root vnode
527 switch (VTOFDESC(ap
->a_vp
)->fd_type
) {
535 fd
= VTOFDESC(ap
->a_vp
)->fd_fd
;
536 if ((error
= fp_lookup(vfs_context_proc(ap
->a_context
), fd
, &fp
, 0)))
540 * Can setattr the underlying vnode, but not sockets!
542 switch (fp
->f_fglob
->fg_type
) {
545 if ((error
= vnode_getwithref((struct vnode
*) fp
->f_fglob
->fg_data
)) != 0)
547 error
= vnode_setattr((struct vnode
*) fp
->f_fglob
->fg_data
, ap
->a_vap
, ap
->a_context
);
548 (void)vnode_put((struct vnode
*) fp
->f_fglob
->fg_data
);
558 kprintf("fp->f_fglob->fg_type = %d\n", fp
->f_fglob
->fg_type
);
563 fp_drop(p
, fd
, fp
, 0);
569 static struct dirtmp
{
575 { FD_DEVFD
, UIO_MX
, 2, "fd" },
576 { FD_STDIN
, UIO_MX
, 5, "stdin" },
577 { FD_STDOUT
, UIO_MX
, 6, "stdout" },
578 { FD_STDERR
, UIO_MX
, 6, "stderr" },
584 struct vnop_readdir_args
/* {
590 vfs_context_t a_context;
593 struct uio
*uio
= ap
->a_uio
;
594 struct proc
*p
= current_proc();
598 * We don't allow exporting fdesc mounts, and currently local
599 * requests do not need cookies.
601 if (ap
->a_flags
& (VNODE_READDIR_EXTENDED
| VNODE_READDIR_REQSEEKOFF
))
604 switch (VTOFDESC(ap
->a_vp
)->fd_type
) {
612 if (VTOFDESC(ap
->a_vp
)->fd_type
== Froot
) {
614 struct dirent
*dp
= &d
;
618 i
= uio
->uio_offset
/ UIO_MX
;
621 while (uio_resid(uio
) > 0) {
623 if (dt
->d_fileno
== 0) {
629 switch (dt
->d_fileno
) {
633 fd
= dt
->d_fileno
- FD_STDIN
;
634 if (fd
>= p
->p_fd
->fd_nfiles
)
636 if (*fdfile(p
, fd
) == NULL
&&
642 bzero((caddr_t
) dp
, UIO_MX
);
643 dp
->d_fileno
= dt
->d_fileno
;
644 dp
->d_namlen
= dt
->d_namlen
;
645 dp
->d_type
= DT_UNKNOWN
;
646 dp
->d_reclen
= dt
->d_reclen
;
647 bcopy(dt
->d_name
, dp
->d_name
, dp
->d_namlen
+1);
648 error
= uiomove((caddr_t
) dp
, UIO_MX
, uio
);
652 uio
->uio_offset
= i
* UIO_MX
;
656 i
= uio
->uio_offset
/ UIO_MX
;
658 while (uio_resid(uio
) > 0) {
659 if (i
>= p
->p_fd
->fd_nfiles
)
662 if (*fdfile(p
, i
) != NULL
&& !(*fdflags(p
, i
) & UF_RESERVED
)) {
664 struct dirent
*dp
= &d
;
666 bzero((caddr_t
) dp
, UIO_MX
);
668 dp
->d_namlen
= sprintf(dp
->d_name
, "%d", i
);
669 dp
->d_reclen
= UIO_MX
;
670 dp
->d_type
= DT_UNKNOWN
;
671 dp
->d_fileno
= i
+ FD_STDIN
;
673 * And ship to userland
675 error
= uiomove((caddr_t
) dp
, UIO_MX
, uio
);
682 uio
->uio_offset
= i
* UIO_MX
;
688 struct vnop_readlink_args
/* {
691 vfs_context_t a_context;
694 struct vnode
*vp
= ap
->a_vp
;
697 if (vp
->v_type
!= VLNK
)
700 if (VTOFDESC(vp
)->fd_type
== Flink
) {
701 char *ln
= VTOFDESC(vp
)->fd_link
;
702 error
= uiomove(ln
, strlen(ln
), ap
->a_uio
);
711 fdesc_read(__unused
struct vnop_read_args
*ap
)
718 fdesc_write(__unused
struct vnop_write_args
*ap
)
724 fdesc_ioctl(__unused
struct vnop_ioctl_args
*ap
)
730 fdesc_select(__unused
struct vnop_select_args
*ap
)
737 struct vnop_inactive_args
/* {
739 vfs_context_t a_context;
742 struct vnode
*vp
= ap
->a_vp
;
745 * Clear out the v_type field to avoid
746 * nasty things happening in vgone().
754 struct vnop_reclaim_args
/* {
756 vfs_context_t a_context;
759 struct vnode
*vp
= ap
->a_vp
;
760 struct fdescnode
*fd
= VTOFDESC(vp
);
762 LIST_REMOVE(fd
, fd_hash
);
763 FREE(vp
->v_data
, M_TEMP
);
770 * Return POSIX pathconf information applicable to special devices.
774 struct vnop_pathconf_args
/* {
778 vfs_context_t a_context;
782 switch (ap
->a_name
) {
784 *ap
->a_retval
= LINK_MAX
;
787 *ap
->a_retval
= MAX_CANON
;
790 *ap
->a_retval
= MAX_INPUT
;
793 *ap
->a_retval
= PIPE_BUF
;
795 case _PC_CHOWN_RESTRICTED
:
799 *ap
->a_retval
= _POSIX_VDISABLE
;
810 fdesc_vfree(__unused
struct vnop_vfree_args
*ap
)
817 * /dev/fd "should never get here" operation
827 #define VOPFUNC int (*)(void *)
829 #define fdesc_create (int (*) (struct vnop_create_args *))eopnotsupp
830 #define fdesc_mknod (int (*) (struct vnop_mknod_args *))eopnotsupp
831 #define fdesc_close (int (*) (struct vnop_close_args *))nullop
832 #define fdesc_access (int (*) (struct vnop_access_args *))nullop
833 #define fdesc_mmap (int (*) (struct vnop_mmap_args *))eopnotsupp
834 #define fdesc_revoke nop_revoke
835 #define fdesc_fsync (int (*) (struct vnop_fsync_args *))nullop
836 #define fdesc_remove (int (*) (struct vnop_remove_args *))eopnotsupp
837 #define fdesc_link (int (*) (struct vnop_link_args *))eopnotsupp
838 #define fdesc_rename (int (*) (struct vnop_rename_args *))eopnotsupp
839 #define fdesc_mkdir (int (*) (struct vnop_mkdir_args *))eopnotsupp
840 #define fdesc_rmdir (int (*) (struct vnop_rmdir_args *))eopnotsupp
841 #define fdesc_symlink (int (*) (struct vnop_symlink_args *))eopnotsupp
842 #define fdesc_strategy (int (*) (struct vnop_strategy_args *))fdesc_badop
843 #define fdesc_advlock (int (*) (struct vnop_advlock_args *))eopnotsupp
844 #define fdesc_bwrite (int (*) (struct vnop_bwrite_args *))eopnotsupp
845 #define fdesc_blktooff (int (*) (struct vnop_blktooff_args *))eopnotsupp
846 #define fdesc_offtoblk (int (*) (struct vnop_offtoblk_args *))eopnotsupp
847 #define fdesc_blockmap (int (*) (struct vnop_blockmap_args *))eopnotsupp
849 int (**fdesc_vnodeop_p
)(void *);
850 struct vnodeopv_entry_desc fdesc_vnodeop_entries
[] = {
851 { &vnop_default_desc
, (VOPFUNC
)vn_default_error
},
852 { &vnop_lookup_desc
, (VOPFUNC
)fdesc_lookup
}, /* lookup */
853 { &vnop_create_desc
, (VOPFUNC
)fdesc_create
}, /* create */
854 { &vnop_mknod_desc
, (VOPFUNC
)fdesc_mknod
}, /* mknod */
855 { &vnop_open_desc
, (VOPFUNC
)fdesc_open
}, /* open */
856 { &vnop_close_desc
, (VOPFUNC
)fdesc_close
}, /* close */
857 { &vnop_access_desc
, (VOPFUNC
)fdesc_access
}, /* access */
858 { &vnop_getattr_desc
, (VOPFUNC
)fdesc_getattr
}, /* getattr */
859 { &vnop_setattr_desc
, (VOPFUNC
)fdesc_setattr
}, /* setattr */
860 { &vnop_read_desc
, (VOPFUNC
)fdesc_read
}, /* read */
861 { &vnop_write_desc
, (VOPFUNC
)fdesc_write
}, /* write */
862 { &vnop_ioctl_desc
, (VOPFUNC
)fdesc_ioctl
}, /* ioctl */
863 { &vnop_select_desc
, (VOPFUNC
)fdesc_select
}, /* select */
864 { &vnop_revoke_desc
, (VOPFUNC
)fdesc_revoke
}, /* revoke */
865 { &vnop_mmap_desc
, (VOPFUNC
)fdesc_mmap
}, /* mmap */
866 { &vnop_fsync_desc
, (VOPFUNC
)fdesc_fsync
}, /* fsync */
867 { &vnop_remove_desc
, (VOPFUNC
)fdesc_remove
}, /* remove */
868 { &vnop_link_desc
, (VOPFUNC
)fdesc_link
}, /* link */
869 { &vnop_rename_desc
, (VOPFUNC
)fdesc_rename
}, /* rename */
870 { &vnop_mkdir_desc
, (VOPFUNC
)fdesc_mkdir
}, /* mkdir */
871 { &vnop_rmdir_desc
, (VOPFUNC
)fdesc_rmdir
}, /* rmdir */
872 { &vnop_symlink_desc
, (VOPFUNC
)fdesc_symlink
}, /* symlink */
873 { &vnop_readdir_desc
, (VOPFUNC
)fdesc_readdir
}, /* readdir */
874 { &vnop_readlink_desc
, (VOPFUNC
)fdesc_readlink
},/* readlink */
875 { &vnop_inactive_desc
, (VOPFUNC
)fdesc_inactive
},/* inactive */
876 { &vnop_reclaim_desc
, (VOPFUNC
)fdesc_reclaim
}, /* reclaim */
877 { &vnop_strategy_desc
, (VOPFUNC
)fdesc_strategy
}, /* strategy */
878 { &vnop_pathconf_desc
, (VOPFUNC
)fdesc_pathconf
}, /* pathconf */
879 { &vnop_advlock_desc
, (VOPFUNC
)fdesc_advlock
}, /* advlock */
880 { &vnop_bwrite_desc
, (VOPFUNC
)fdesc_bwrite
}, /* bwrite */
881 { &vnop_pagein_desc
, (VOPFUNC
)err_pagein
}, /* pagein */
882 { &vnop_pageout_desc
, (VOPFUNC
)err_pageout
}, /* pageout */
883 { &vnop_copyfile_desc
, (VOPFUNC
)err_copyfile
}, /* Copyfile */
884 { &vnop_blktooff_desc
, (VOPFUNC
)fdesc_blktooff
}, /* blktooff */
885 { &vnop_blktooff_desc
, (VOPFUNC
)fdesc_offtoblk
}, /* offtoblk */
886 { &vnop_blockmap_desc
, (VOPFUNC
)fdesc_blockmap
}, /* blockmap */
887 { (struct vnodeop_desc
*)NULL
, (VOPFUNC
)NULL
}
889 struct vnodeopv_desc fdesc_vnodeop_opv_desc
=
890 { &fdesc_vnodeop_p
, fdesc_vnodeop_entries
};