2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
24 * Copyright (c) 1992, 1993
25 * The Regents of the University of California. All rights reserved.
27 * This code is derived from software donated to Berkeley by
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the University of
41 * California, Berkeley and its contributors.
42 * 4. Neither the name of the University nor the names of its contributors
43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * @(#)fdesc_vnops.c 8.17 (Berkeley) 5/22/95
66 #include <sys/param.h>
67 #include <sys/systm.h>
68 #include <sys/types.h>
71 #include <sys/kernel.h> /* boottime */
72 #include <sys/resourcevar.h>
73 #include <sys/filedesc.h>
74 #include <sys/vnode.h>
75 #include <sys/malloc.h>
78 #include <sys/mount.h>
79 #include <sys/namei.h>
81 #include <sys/dirent.h>
83 #include <miscfs/fdesc/fdesc.h>
84 #include <vfs/vfs_support.h>
86 #define cttyvp(p) ((p)->p_flag & P_CONTROLT ? (p)->p_session->s_ttyvp : NULL)
89 #define FDL_LOCKED 0x02
90 static int fdcache_lock
;
94 #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1)
95 FD_STDIN
, FD_STDOUT
, FD_STDERR must be a sequence n
, n
+1, n
+2
100 #define FD_NHASH(ix) \
101 (&fdhashtbl[(ix) & fdhash])
102 LIST_HEAD(fdhashhead
, fdescnode
) *fdhashtbl
;
106 * Initialise cache headers
109 struct vfsconf
*vfsp
;
112 devctty
= makedev(nchrdev
, 0);
113 fdhashtbl
= hashinit(NFDCACHE
, M_CACHE
, &fdhash
);
117 fdesc_allocvp(ftype
, ix
, mp
, vpp
)
123 struct proc
*p
= current_proc(); /* XXX */
124 struct fdhashhead
*fc
;
125 struct fdescnode
*fd
;
130 for (fd
= fc
->lh_first
; fd
!= 0; fd
= fd
->fd_hash
.le_next
) {
131 if (fd
->fd_ix
== ix
&& fd
->fd_vnode
->v_mount
== mp
) {
132 if (vget(fd
->fd_vnode
, 0, p
))
140 * otherwise lock the array while we call getnewvnode
141 * since that can block.
143 if (fdcache_lock
& FDL_LOCKED
) {
144 fdcache_lock
|= FDL_WANT
;
145 sleep((caddr_t
) &fdcache_lock
, PINOD
);
148 fdcache_lock
|= FDL_LOCKED
;
150 MALLOC(fd
, void *, sizeof(struct fdescnode
), M_TEMP
, M_WAITOK
);
151 error
= getnewvnode(VT_FDESC
, mp
, fdesc_vnodeop_p
, vpp
);
162 LIST_INSERT_HEAD(fc
, fd
, fd_hash
);
165 fdcache_lock
&= ~FDL_LOCKED
;
167 if (fdcache_lock
& FDL_WANT
) {
168 fdcache_lock
&= ~FDL_WANT
;
169 wakeup((caddr_t
) &fdcache_lock
);
176 * vp is the current namei directory
177 * ndp is the name to locate in that directory...
181 struct vop_lookup_args
/* {
182 struct vnode * a_dvp;
183 struct vnode ** a_vpp;
184 struct componentname * a_cnp;
187 struct vnode
**vpp
= ap
->a_vpp
;
188 struct vnode
*dvp
= ap
->a_dvp
;
189 struct componentname
*cnp
= ap
->a_cnp
;
190 char *pname
= cnp
->cn_nameptr
;
191 struct proc
*p
= cnp
->cn_proc
;
192 int nfiles
= p
->p_fd
->fd_nfiles
;
198 VOP_UNLOCK(dvp
, 0, p
);
199 if (cnp
->cn_namelen
== 1 && *pname
== '.') {
202 vn_lock(dvp
, LK_SHARED
| LK_RETRY
, p
);
206 switch (VTOFDESC(dvp
)->fd_type
) {
215 if (cnp
->cn_namelen
== 2 && bcmp(pname
, "fd", 2) == 0) {
216 error
= fdesc_allocvp(Fdevfd
, FD_DEVFD
, dvp
->v_mount
, &fvp
);
221 vn_lock(fvp
, LK_SHARED
| LK_RETRY
, p
);
225 if (cnp
->cn_namelen
== 3 && bcmp(pname
, "tty", 3) == 0) {
226 struct vnode
*ttyvp
= cttyvp(p
);
231 error
= fdesc_allocvp(Fctty
, FD_CTTY
, dvp
->v_mount
, &fvp
);
236 vn_lock(fvp
, LK_SHARED
| LK_RETRY
, p
);
241 switch (cnp
->cn_namelen
) {
243 if (bcmp(pname
, "stdin", 5) == 0) {
249 if (bcmp(pname
, "stdout", 6) == 0) {
253 if (bcmp(pname
, "stderr", 6) == 0) {
261 error
= fdesc_allocvp(Flink
, fd
, dvp
->v_mount
, &fvp
);
264 VTOFDESC(fvp
)->fd_link
= ln
;
267 vn_lock(fvp
, LK_SHARED
| LK_RETRY
, p
);
277 if (cnp
->cn_namelen
== 2 && bcmp(pname
, "..", 2) == 0) {
278 if (error
= fdesc_root(dvp
->v_mount
, vpp
))
284 while (*pname
>= '0' && *pname
<= '9') {
285 fd
= 10 * fd
+ *pname
++ - '0';
290 if (*pname
!= '\0') {
296 *fdfile(p
, fd
) == NULL
||
297 (*fdflags(p
, fd
) & UF_RESERVED
)) {
302 error
= fdesc_allocvp(Fdesc
, FD_DESC
+fd
, dvp
->v_mount
, &fvp
);
305 VTOFDESC(fvp
)->fd_fd
= fd
;
306 vn_lock(fvp
, LK_SHARED
| LK_RETRY
, p
);
312 vn_lock(dvp
, LK_SHARED
| LK_RETRY
, p
);
319 struct vop_open_args
/* {
322 struct ucred *a_cred;
326 struct vnode
*vp
= ap
->a_vp
;
329 switch (VTOFDESC(vp
)->fd_type
) {
332 * XXX Kludge: set p->p_dupfd to contain the value of the
333 * the file descriptor being sought for duplication. The error
334 * return ensures that the vnode for this device will be
335 * released by vn_open. Open will detect this special error and
336 * take the actions in dupfdopen. Other callers of vn_open or
337 * VOP_OPEN will simply report the error.
339 ap
->a_p
->p_dupfd
= VTOFDESC(vp
)->fd_fd
; /* XXX */
344 error
= cttyopen(devctty
, ap
->a_mode
, 0, ap
->a_p
);
352 fdesc_attr(fd
, vap
, cred
, p
)
362 if (error
= fdgetf(p
, fd
, &fp
))
364 switch (fp
->f_type
) {
366 error
= VOP_GETATTR((struct vnode
*) fp
->f_data
, vap
, cred
, p
);
367 if (error
== 0 && vap
->va_type
== VDIR
) {
369 * directories can cause loops in the namespace,
370 * so turn off the 'x' bits to avoid trouble.
372 vap
->va_mode
&= ~((VEXEC
)|(VEXEC
>>3)|(VEXEC
>>6));
377 error
= soo_stat((struct socket
*)fp
->f_data
, &stb
);
380 vap
->va_type
= VSOCK
;
381 vap
->va_mode
= stb
.st_mode
;
382 vap
->va_nlink
= stb
.st_nlink
;
383 vap
->va_uid
= stb
.st_uid
;
384 vap
->va_gid
= stb
.st_gid
;
385 vap
->va_fsid
= stb
.st_dev
;
386 vap
->va_fileid
= stb
.st_ino
;
387 vap
->va_size
= stb
.st_size
;
388 vap
->va_blocksize
= stb
.st_blksize
;
389 vap
->va_atime
= stb
.st_atimespec
;
390 vap
->va_mtime
= stb
.st_mtimespec
;
391 vap
->va_ctime
= stb
.st_ctimespec
;
392 vap
->va_gen
= stb
.st_gen
;
393 vap
->va_flags
= stb
.st_flags
;
394 vap
->va_rdev
= stb
.st_rdev
;
395 vap
->va_bytes
= stb
.st_blocks
* stb
.st_blksize
;
409 struct vop_getattr_args
/* {
412 struct ucred *a_cred;
416 struct vnode
*vp
= ap
->a_vp
;
417 struct vattr
*vap
= ap
->a_vap
;
421 switch (VTOFDESC(vp
)->fd_type
) {
426 bzero((caddr_t
) vap
, sizeof(*vap
));
428 vap
->va_fileid
= VTOFDESC(vp
)->fd_ix
;
432 vap
->va_fsid
= vp
->v_mount
->mnt_stat
.f_fsid
.val
[0];
433 vap
->va_blocksize
= DEV_BSIZE
;
434 vap
->va_atime
.tv_sec
= boottime
.tv_sec
;
435 vap
->va_atime
.tv_nsec
= 0;
436 vap
->va_mtime
= vap
->va_atime
;
437 vap
->va_ctime
= vap
->va_mtime
;
443 switch (VTOFDESC(vp
)->fd_type
) {
445 vap
->va_mode
= S_IRUSR
|S_IXUSR
|S_IRGRP
|S_IXGRP
|S_IROTH
|S_IXOTH
;
448 vap
->va_size
= strlen(VTOFDESC(vp
)->fd_link
);
452 vap
->va_mode
= S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IWGRP
|S_IROTH
|S_IWOTH
;
456 vap
->va_rdev
= devctty
;
460 vap
->va_mode
= S_IRUSR
|S_IXUSR
|S_IRGRP
|S_IXGRP
|S_IROTH
|S_IXOTH
;
463 vap
->va_size
= DEV_BSIZE
;
469 fd
= VTOFDESC(vp
)->fd_fd
;
470 error
= fdesc_attr(fd
, vap
, ap
->a_cred
, ap
->a_p
);
474 panic("fdesc_getattr");
479 vp
->v_type
= vap
->va_type
;
487 struct vop_setattr_args
/* {
490 struct ucred *a_cred;
499 * Can't mess with the root vnode
501 switch (VTOFDESC(ap
->a_vp
)->fd_type
) {
512 fd
= VTOFDESC(ap
->a_vp
)->fd_fd
;
513 if (error
= fdgetf(ap
->a_p
, fd
, &fp
))
517 * Can setattr the underlying vnode, but not sockets!
519 switch (fp
->f_type
) {
521 error
= VOP_SETATTR((struct vnode
*) fp
->f_data
, ap
->a_vap
, ap
->a_cred
, ap
->a_p
);
529 kprintf("fp->f_type = %d\n", fp
->f_type
);
539 static struct dirtmp
{
545 { FD_DEVFD
, UIO_MX
, 2, "fd" },
546 { FD_STDIN
, UIO_MX
, 5, "stdin" },
547 { FD_STDOUT
, UIO_MX
, 6, "stdout" },
548 { FD_STDERR
, UIO_MX
, 6, "stderr" },
549 { FD_CTTY
, UIO_MX
, 3, "tty" },
555 struct vop_readdir_args
/* {
558 struct ucred *a_cred;
564 struct uio
*uio
= ap
->a_uio
;
565 struct proc
*p
= uio
->uio_procp
;
569 * We don't allow exporting fdesc mounts, and currently local
570 * requests do not need cookies.
573 panic("fdesc_readdir: not hungry");
575 switch (VTOFDESC(ap
->a_vp
)->fd_type
) {
586 if (VTOFDESC(ap
->a_vp
)->fd_type
== Froot
) {
588 struct dirent
*dp
= &d
;
592 i
= uio
->uio_offset
/ UIO_MX
;
595 while (uio
->uio_resid
> 0) {
597 if (dt
->d_fileno
== 0) {
603 switch (dt
->d_fileno
) {
605 if (cttyvp(uio
->uio_procp
) == NULL
)
612 fd
= dt
->d_fileno
- FD_STDIN
;
613 if (fd
>= p
->p_fd
->fd_nfiles
)
615 if (*fdfile(p
, fd
) == NULL
&&
621 bzero((caddr_t
) dp
, UIO_MX
);
622 dp
->d_fileno
= dt
->d_fileno
;
623 dp
->d_namlen
= dt
->d_namlen
;
624 dp
->d_type
= DT_UNKNOWN
;
625 dp
->d_reclen
= dt
->d_reclen
;
626 bcopy(dt
->d_name
, dp
->d_name
, dp
->d_namlen
+1);
627 error
= uiomove((caddr_t
) dp
, UIO_MX
, uio
);
631 uio
->uio_offset
= i
* UIO_MX
;
635 i
= uio
->uio_offset
/ UIO_MX
;
637 while (uio
->uio_resid
> 0) {
638 if (i
>= p
->p_fd
->fd_nfiles
)
641 if (*fdfile(p
, i
) != NULL
&& !(*fdflags(p
, i
) & UF_RESERVED
)) {
643 struct dirent
*dp
= &d
;
645 bzero((caddr_t
) dp
, UIO_MX
);
647 dp
->d_namlen
= sprintf(dp
->d_name
, "%d", i
);
648 dp
->d_reclen
= UIO_MX
;
649 dp
->d_type
= DT_UNKNOWN
;
650 dp
->d_fileno
= i
+ FD_STDIN
;
652 * And ship to userland
654 error
= uiomove((caddr_t
) dp
, UIO_MX
, uio
);
661 uio
->uio_offset
= i
* UIO_MX
;
667 struct vop_readlink_args
/* {
670 struct ucred *a_cred;
673 struct vnode
*vp
= ap
->a_vp
;
676 if (vp
->v_type
!= VLNK
)
679 if (VTOFDESC(vp
)->fd_type
== Flink
) {
680 char *ln
= VTOFDESC(vp
)->fd_link
;
681 error
= uiomove(ln
, strlen(ln
), ap
->a_uio
);
691 struct vop_read_args
/* {
695 struct ucred *a_cred;
698 int error
= EOPNOTSUPP
;
700 switch (VTOFDESC(ap
->a_vp
)->fd_type
) {
702 error
= cttyread(devctty
, ap
->a_uio
, ap
->a_ioflag
);
715 struct vop_write_args
/* {
719 struct ucred *a_cred;
722 int error
= EOPNOTSUPP
;
724 switch (VTOFDESC(ap
->a_vp
)->fd_type
) {
726 error
= cttywrite(devctty
, ap
->a_uio
, ap
->a_ioflag
);
739 struct vop_ioctl_args
/* {
744 struct ucred *a_cred;
748 int error
= EOPNOTSUPP
;
750 switch (VTOFDESC(ap
->a_vp
)->fd_type
) {
752 error
= cttyioctl(devctty
, ap
->a_command
, ap
->a_data
,
753 ap
->a_fflag
, ap
->a_p
);
766 struct vop_select_args
/* {
770 struct ucred *a_cred;
775 int error
= EOPNOTSUPP
;
777 switch (VTOFDESC(ap
->a_vp
)->fd_type
) {
779 error
= cttyselect(devctty
, ap
->a_fflags
, ap
->a_wql
, ap
->a_p
);
792 struct vop_inactive_args
/* {
797 struct vnode
*vp
= ap
->a_vp
;
800 * Clear out the v_type field to avoid
801 * nasty things happening in vgone().
803 VOP_UNLOCK(vp
, 0, ap
->a_p
);
810 struct vop_reclaim_args
/* {
814 struct vnode
*vp
= ap
->a_vp
;
815 struct fdescnode
*fd
= VTOFDESC(vp
);
817 LIST_REMOVE(fd
, fd_hash
);
818 FREE(vp
->v_data
, M_TEMP
);
825 * Return POSIX pathconf information applicable to special devices.
828 struct vop_pathconf_args
/* {
835 switch (ap
->a_name
) {
837 *ap
->a_retval
= LINK_MAX
;
840 *ap
->a_retval
= MAX_CANON
;
843 *ap
->a_retval
= MAX_INPUT
;
846 *ap
->a_retval
= PIPE_BUF
;
848 case _PC_CHOWN_RESTRICTED
:
852 *ap
->a_retval
= _POSIX_VDISABLE
;
861 * Print out the contents of a /dev/fd vnode.
866 struct vop_print_args
/* {
871 printf("tag VT_NON, fdesc vnode\n");
878 struct vop_vfree_args
/* {
889 * /dev/fd "should never get here" operation
895 panic("fdesc: bad op");
899 #define VOPFUNC int (*)(void *)
901 #define fdesc_create ((int (*) __P((struct vop_create_args *)))eopnotsupp)
902 #define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))eopnotsupp)
903 #define fdesc_close ((int (*) __P((struct vop_close_args *)))nullop)
904 #define fdesc_access ((int (*) __P((struct vop_access_args *)))nullop)
905 #define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))eopnotsupp)
906 #define fdesc_revoke vop_revoke
907 #define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
908 #define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop)
909 #define fdesc_remove ((int (*) __P((struct vop_remove_args *)))eopnotsupp)
910 #define fdesc_link ((int (*) __P((struct vop_link_args *)))eopnotsupp)
911 #define fdesc_rename ((int (*) __P((struct vop_rename_args *)))eopnotsupp)
912 #define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))eopnotsupp)
913 #define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))eopnotsupp)
914 #define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
915 #define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
916 #define fdesc_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
917 #define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
918 #define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop)
919 #define fdesc_strategy ((int (*) __P((struct vop_strategy_args *)))fdesc_badop)
920 #define fdesc_islocked \
921 ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
922 #define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
923 #define fdesc_blkatoff \
924 ((int (*) __P((struct vop_blkatoff_args *)))eopnotsupp)
925 #define fdesc_valloc ((int(*) __P(( \
928 struct ucred *cred, \
929 struct vnode **vpp))) eopnotsupp)
930 #define fdesc_truncate \
931 ((int (*) __P((struct vop_truncate_args *)))eopnotsupp)
932 #define fdesc_update ((int (*) __P((struct vop_update_args *)))eopnotsupp)
933 #define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))eopnotsupp)
934 #define fdesc_blktooff ((int (*) __P((struct vop_blktooff_args *)))eopnotsupp)
935 #define fdesc_offtoblk ((int (*) __P((struct vop_offtoblk_args *)))eopnotsupp)
936 #define fdesc_cmap ((int (*) __P((struct vop_cmap_args *)))eopnotsupp)
938 int (**fdesc_vnodeop_p
)(void *);
939 struct vnodeopv_entry_desc fdesc_vnodeop_entries
[] = {
940 { &vop_default_desc
, (VOPFUNC
)vn_default_error
},
941 { &vop_lookup_desc
, (VOPFUNC
)fdesc_lookup
}, /* lookup */
942 { &vop_create_desc
, (VOPFUNC
)fdesc_create
}, /* create */
943 { &vop_mknod_desc
, (VOPFUNC
)fdesc_mknod
}, /* mknod */
944 { &vop_open_desc
, (VOPFUNC
)fdesc_open
}, /* open */
945 { &vop_close_desc
, (VOPFUNC
)fdesc_close
}, /* close */
946 { &vop_access_desc
, (VOPFUNC
)fdesc_access
}, /* access */
947 { &vop_getattr_desc
, (VOPFUNC
)fdesc_getattr
}, /* getattr */
948 { &vop_setattr_desc
, (VOPFUNC
)fdesc_setattr
}, /* setattr */
949 { &vop_read_desc
, (VOPFUNC
)fdesc_read
}, /* read */
950 { &vop_write_desc
, (VOPFUNC
)fdesc_write
}, /* write */
951 { &vop_ioctl_desc
, (VOPFUNC
)fdesc_ioctl
}, /* ioctl */
952 { &vop_select_desc
, (VOPFUNC
)fdesc_select
}, /* select */
953 { &vop_revoke_desc
, (VOPFUNC
)fdesc_revoke
}, /* revoke */
954 { &vop_mmap_desc
, (VOPFUNC
)fdesc_mmap
}, /* mmap */
955 { &vop_fsync_desc
, (VOPFUNC
)fdesc_fsync
}, /* fsync */
956 { &vop_seek_desc
, (VOPFUNC
)fdesc_seek
}, /* seek */
957 { &vop_remove_desc
, (VOPFUNC
)fdesc_remove
}, /* remove */
958 { &vop_link_desc
, (VOPFUNC
)fdesc_link
}, /* link */
959 { &vop_rename_desc
, (VOPFUNC
)fdesc_rename
}, /* rename */
960 { &vop_mkdir_desc
, (VOPFUNC
)fdesc_mkdir
}, /* mkdir */
961 { &vop_rmdir_desc
, (VOPFUNC
)fdesc_rmdir
}, /* rmdir */
962 { &vop_symlink_desc
, (VOPFUNC
)fdesc_symlink
}, /* symlink */
963 { &vop_readdir_desc
, (VOPFUNC
)fdesc_readdir
}, /* readdir */
964 { &vop_readlink_desc
, (VOPFUNC
)fdesc_readlink
},/* readlink */
965 { &vop_abortop_desc
, (VOPFUNC
)fdesc_abortop
}, /* abortop */
966 { &vop_inactive_desc
, (VOPFUNC
)fdesc_inactive
},/* inactive */
967 { &vop_reclaim_desc
, (VOPFUNC
)fdesc_reclaim
}, /* reclaim */
968 { &vop_lock_desc
, (VOPFUNC
)fdesc_lock
}, /* lock */
969 { &vop_unlock_desc
, (VOPFUNC
)fdesc_unlock
}, /* unlock */
970 { &vop_bmap_desc
, (VOPFUNC
)fdesc_bmap
}, /* bmap */
971 { &vop_strategy_desc
, (VOPFUNC
)fdesc_strategy
}, /* strategy */
972 { &vop_print_desc
, (VOPFUNC
)fdesc_print
}, /* print */
973 { &vop_islocked_desc
, (VOPFUNC
)fdesc_islocked
}, /* islocked */
974 { &vop_pathconf_desc
, (VOPFUNC
)fdesc_pathconf
}, /* pathconf */
975 { &vop_advlock_desc
, (VOPFUNC
)fdesc_advlock
}, /* advlock */
976 { &vop_blkatoff_desc
, (VOPFUNC
)fdesc_blkatoff
}, /* blkatoff */
977 { &vop_valloc_desc
, (VOPFUNC
)fdesc_valloc
}, /* valloc */
978 { &vop_vfree_desc
, (VOPFUNC
)fdesc_vfree
}, /* vfree */
979 { &vop_truncate_desc
, (VOPFUNC
)fdesc_truncate
}, /* truncate */
980 { &vop_update_desc
, (VOPFUNC
)fdesc_update
}, /* update */
981 { &vop_bwrite_desc
, (VOPFUNC
)fdesc_bwrite
}, /* bwrite */
982 { &vop_pagein_desc
, (VOPFUNC
)err_pagein
}, /* pagein */
983 { &vop_pageout_desc
, (VOPFUNC
)err_pageout
}, /* pageout */
984 { &vop_copyfile_desc
, (VOPFUNC
)err_copyfile
}, /* Copyfile */
985 { &vop_blktooff_desc
, (VOPFUNC
)fdesc_blktooff
}, /* blktooff */
986 { &vop_blktooff_desc
, (VOPFUNC
)fdesc_offtoblk
}, /* offtoblk */
987 { &vop_cmap_desc
, (VOPFUNC
)fdesc_cmap
}, /* cmap */
988 { (struct vnodeop_desc
*)NULL
, (VOPFUNC
)NULL
}
990 struct vnodeopv_desc fdesc_vnodeop_opv_desc
=
991 { &fdesc_vnodeop_p
, fdesc_vnodeop_entries
};