2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
27 * Copyright (c) 1992, 1993
28 * The Regents of the University of California. All rights reserved.
30 * This code is derived from software donated to Berkeley by
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by the University of
44 * California, Berkeley and its contributors.
45 * 4. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * @(#)fdesc_vnops.c 8.17 (Berkeley) 5/22/95
69 #include <sys/param.h>
70 #include <sys/systm.h>
71 #include <sys/types.h>
74 #include <sys/kernel.h> /* boottime */
75 #include <sys/resourcevar.h>
76 #include <sys/filedesc.h>
77 #include <sys/vnode.h>
78 #include <sys/malloc.h>
81 #include <sys/mount.h>
82 #include <sys/namei.h>
84 #include <sys/dirent.h>
86 #include <miscfs/fdesc/fdesc.h>
87 #include <vfs/vfs_support.h>
90 #define FDL_LOCKED 0x02
91 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 fdhashtbl
= hashinit(NFDCACHE
, M_CACHE
, &fdhash
);
116 fdesc_allocvp(ftype
, ix
, mp
, vpp
)
122 struct proc
*p
= current_proc(); /* XXX */
123 struct fdhashhead
*fc
;
124 struct fdescnode
*fd
;
129 for (fd
= fc
->lh_first
; fd
!= 0; fd
= fd
->fd_hash
.le_next
) {
130 if (fd
->fd_ix
== ix
&& fd
->fd_vnode
->v_mount
== mp
) {
131 if (vget(fd
->fd_vnode
, 0, p
))
139 * otherwise lock the array while we call getnewvnode
140 * since that can block.
142 if (fdcache_lock
& FDL_LOCKED
) {
143 fdcache_lock
|= FDL_WANT
;
144 sleep((caddr_t
) &fdcache_lock
, PINOD
);
147 fdcache_lock
|= FDL_LOCKED
;
149 MALLOC(fd
, void *, sizeof(struct fdescnode
), M_TEMP
, M_WAITOK
);
150 error
= getnewvnode(VT_FDESC
, mp
, fdesc_vnodeop_p
, vpp
);
161 LIST_INSERT_HEAD(fc
, fd
, fd_hash
);
164 fdcache_lock
&= ~FDL_LOCKED
;
166 if (fdcache_lock
& FDL_WANT
) {
167 fdcache_lock
&= ~FDL_WANT
;
168 wakeup((caddr_t
) &fdcache_lock
);
175 * vp is the current namei directory
176 * ndp is the name to locate in that directory...
180 struct vop_lookup_args
/* {
181 struct vnode * a_dvp;
182 struct vnode ** a_vpp;
183 struct componentname * a_cnp;
186 struct vnode
**vpp
= ap
->a_vpp
;
187 struct vnode
*dvp
= ap
->a_dvp
;
188 struct componentname
*cnp
= ap
->a_cnp
;
189 char *pname
= cnp
->cn_nameptr
;
190 struct proc
*p
= cnp
->cn_proc
;
191 int nfiles
= p
->p_fd
->fd_nfiles
;
197 VOP_UNLOCK(dvp
, 0, p
);
198 if (cnp
->cn_namelen
== 1 && *pname
== '.') {
201 vn_lock(dvp
, LK_SHARED
| LK_RETRY
, p
);
205 switch (VTOFDESC(dvp
)->fd_type
) {
213 if (cnp
->cn_namelen
== 2 && bcmp(pname
, "fd", 2) == 0) {
214 error
= fdesc_allocvp(Fdevfd
, FD_DEVFD
, dvp
->v_mount
, &fvp
);
219 vn_lock(fvp
, LK_SHARED
| LK_RETRY
, p
);
224 switch (cnp
->cn_namelen
) {
226 if (bcmp(pname
, "stdin", 5) == 0) {
232 if (bcmp(pname
, "stdout", 6) == 0) {
236 if (bcmp(pname
, "stderr", 6) == 0) {
244 error
= fdesc_allocvp(Flink
, fd
, dvp
->v_mount
, &fvp
);
247 VTOFDESC(fvp
)->fd_link
= ln
;
250 vn_lock(fvp
, LK_SHARED
| LK_RETRY
, p
);
260 if (cnp
->cn_namelen
== 2 && bcmp(pname
, "..", 2) == 0) {
261 if (error
= fdesc_root(dvp
->v_mount
, vpp
))
267 while (*pname
>= '0' && *pname
<= '9') {
268 fd
= 10 * fd
+ *pname
++ - '0';
273 if (*pname
!= '\0') {
279 *fdfile(p
, fd
) == NULL
||
280 (*fdflags(p
, fd
) & UF_RESERVED
)) {
285 error
= fdesc_allocvp(Fdesc
, FD_DESC
+fd
, dvp
->v_mount
, &fvp
);
288 VTOFDESC(fvp
)->fd_fd
= fd
;
289 vn_lock(fvp
, LK_SHARED
| LK_RETRY
, p
);
295 vn_lock(dvp
, LK_SHARED
| LK_RETRY
, p
);
302 struct vop_open_args
/* {
305 struct ucred *a_cred;
309 struct vnode
*vp
= ap
->a_vp
;
312 switch (VTOFDESC(vp
)->fd_type
) {
315 * XXX Kludge: set p->p_dupfd to contain the value of the
316 * the file descriptor being sought for duplication. The error
317 * return ensures that the vnode for this device will be
318 * released by vn_open. Open will detect this special error and
319 * take the actions in dupfdopen. Other callers of vn_open or
320 * VOP_OPEN will simply report the error.
322 ap
->a_p
->p_dupfd
= VTOFDESC(vp
)->fd_fd
; /* XXX */
332 fdesc_attr(fd
, vap
, cred
, p
)
342 if (error
= fdgetf(p
, fd
, &fp
))
344 switch (fp
->f_type
) {
346 error
= VOP_GETATTR((struct vnode
*) fp
->f_data
, vap
, cred
, p
);
347 if (error
== 0 && vap
->va_type
== VDIR
) {
349 * directories can cause loops in the namespace,
350 * so turn off the 'x' bits to avoid trouble.
352 vap
->va_mode
&= ~((VEXEC
)|(VEXEC
>>3)|(VEXEC
>>6));
357 error
= soo_stat((struct socket
*)fp
->f_data
, &stb
);
360 vap
->va_type
= VSOCK
;
361 vap
->va_mode
= stb
.st_mode
;
362 vap
->va_nlink
= stb
.st_nlink
;
363 vap
->va_uid
= stb
.st_uid
;
364 vap
->va_gid
= stb
.st_gid
;
365 vap
->va_fsid
= stb
.st_dev
;
366 vap
->va_fileid
= stb
.st_ino
;
367 vap
->va_size
= stb
.st_size
;
368 vap
->va_blocksize
= stb
.st_blksize
;
369 vap
->va_atime
= stb
.st_atimespec
;
370 vap
->va_mtime
= stb
.st_mtimespec
;
371 vap
->va_ctime
= stb
.st_ctimespec
;
372 vap
->va_gen
= stb
.st_gen
;
373 vap
->va_flags
= stb
.st_flags
;
374 vap
->va_rdev
= stb
.st_rdev
;
375 vap
->va_bytes
= stb
.st_blocks
* stb
.st_blksize
;
389 struct vop_getattr_args
/* {
392 struct ucred *a_cred;
396 struct vnode
*vp
= ap
->a_vp
;
397 struct vattr
*vap
= ap
->a_vap
;
401 switch (VTOFDESC(vp
)->fd_type
) {
405 bzero((caddr_t
) vap
, sizeof(*vap
));
407 vap
->va_fileid
= VTOFDESC(vp
)->fd_ix
;
411 vap
->va_fsid
= vp
->v_mount
->mnt_stat
.f_fsid
.val
[0];
412 vap
->va_blocksize
= DEV_BSIZE
;
413 vap
->va_atime
.tv_sec
= boottime
.tv_sec
;
414 vap
->va_atime
.tv_nsec
= 0;
415 vap
->va_mtime
= vap
->va_atime
;
416 vap
->va_ctime
= vap
->va_mtime
;
422 switch (VTOFDESC(vp
)->fd_type
) {
424 vap
->va_mode
= S_IRUSR
|S_IXUSR
|S_IRGRP
|S_IXGRP
|S_IROTH
|S_IXOTH
;
427 vap
->va_size
= strlen(VTOFDESC(vp
)->fd_link
);
431 vap
->va_mode
= S_IRUSR
|S_IXUSR
|S_IRGRP
|S_IXGRP
|S_IROTH
|S_IXOTH
;
434 vap
->va_size
= DEV_BSIZE
;
440 fd
= VTOFDESC(vp
)->fd_fd
;
441 error
= fdesc_attr(fd
, vap
, ap
->a_cred
, ap
->a_p
);
450 vp
->v_type
= vap
->va_type
;
458 struct vop_setattr_args
/* {
461 struct ucred *a_cred;
470 * Can't mess with the root vnode
472 switch (VTOFDESC(ap
->a_vp
)->fd_type
) {
480 fd
= VTOFDESC(ap
->a_vp
)->fd_fd
;
481 if (error
= fdgetf(ap
->a_p
, fd
, &fp
))
485 * Can setattr the underlying vnode, but not sockets!
487 switch (fp
->f_type
) {
489 error
= VOP_SETATTR((struct vnode
*) fp
->f_data
, ap
->a_vap
, ap
->a_cred
, ap
->a_p
);
497 kprintf("fp->f_type = %d\n", fp
->f_type
);
507 static struct dirtmp
{
513 { FD_DEVFD
, UIO_MX
, 2, "fd" },
514 { FD_STDIN
, UIO_MX
, 5, "stdin" },
515 { FD_STDOUT
, UIO_MX
, 6, "stdout" },
516 { FD_STDERR
, UIO_MX
, 6, "stderr" },
522 struct vop_readdir_args
/* {
525 struct ucred *a_cred;
531 struct uio
*uio
= ap
->a_uio
;
532 struct proc
*p
= uio
->uio_procp
;
536 * We don't allow exporting fdesc mounts, and currently local
537 * requests do not need cookies.
542 switch (VTOFDESC(ap
->a_vp
)->fd_type
) {
550 if (VTOFDESC(ap
->a_vp
)->fd_type
== Froot
) {
552 struct dirent
*dp
= &d
;
556 i
= uio
->uio_offset
/ UIO_MX
;
559 while (uio
->uio_resid
> 0) {
561 if (dt
->d_fileno
== 0) {
567 switch (dt
->d_fileno
) {
571 fd
= dt
->d_fileno
- FD_STDIN
;
572 if (fd
>= p
->p_fd
->fd_nfiles
)
574 if (*fdfile(p
, fd
) == NULL
&&
580 bzero((caddr_t
) dp
, UIO_MX
);
581 dp
->d_fileno
= dt
->d_fileno
;
582 dp
->d_namlen
= dt
->d_namlen
;
583 dp
->d_type
= DT_UNKNOWN
;
584 dp
->d_reclen
= dt
->d_reclen
;
585 bcopy(dt
->d_name
, dp
->d_name
, dp
->d_namlen
+1);
586 error
= uiomove((caddr_t
) dp
, UIO_MX
, uio
);
590 uio
->uio_offset
= i
* UIO_MX
;
594 i
= uio
->uio_offset
/ UIO_MX
;
596 while (uio
->uio_resid
> 0) {
597 if (i
>= p
->p_fd
->fd_nfiles
)
600 if (*fdfile(p
, i
) != NULL
&& !(*fdflags(p
, i
) & UF_RESERVED
)) {
602 struct dirent
*dp
= &d
;
604 bzero((caddr_t
) dp
, UIO_MX
);
606 dp
->d_namlen
= sprintf(dp
->d_name
, "%d", i
);
607 dp
->d_reclen
= UIO_MX
;
608 dp
->d_type
= DT_UNKNOWN
;
609 dp
->d_fileno
= i
+ FD_STDIN
;
611 * And ship to userland
613 error
= uiomove((caddr_t
) dp
, UIO_MX
, uio
);
620 uio
->uio_offset
= i
* UIO_MX
;
626 struct vop_readlink_args
/* {
629 struct ucred *a_cred;
632 struct vnode
*vp
= ap
->a_vp
;
635 if (vp
->v_type
!= VLNK
)
638 if (VTOFDESC(vp
)->fd_type
== Flink
) {
639 char *ln
= VTOFDESC(vp
)->fd_link
;
640 error
= uiomove(ln
, strlen(ln
), ap
->a_uio
);
650 struct vop_read_args
/* {
654 struct ucred *a_cred;
663 struct vop_write_args
/* {
667 struct ucred *a_cred;
675 struct vop_ioctl_args
/* {
680 struct ucred *a_cred;
689 struct vop_select_args
/* {
693 struct ucred *a_cred;
703 struct vop_inactive_args
/* {
708 struct vnode
*vp
= ap
->a_vp
;
711 * Clear out the v_type field to avoid
712 * nasty things happening in vgone().
714 VOP_UNLOCK(vp
, 0, ap
->a_p
);
721 struct vop_reclaim_args
/* {
725 struct vnode
*vp
= ap
->a_vp
;
726 struct fdescnode
*fd
= VTOFDESC(vp
);
728 LIST_REMOVE(fd
, fd_hash
);
729 FREE(vp
->v_data
, M_TEMP
);
736 * Return POSIX pathconf information applicable to special devices.
739 struct vop_pathconf_args
/* {
746 switch (ap
->a_name
) {
748 *ap
->a_retval
= LINK_MAX
;
751 *ap
->a_retval
= MAX_CANON
;
754 *ap
->a_retval
= MAX_INPUT
;
757 *ap
->a_retval
= PIPE_BUF
;
759 case _PC_CHOWN_RESTRICTED
:
763 *ap
->a_retval
= _POSIX_VDISABLE
;
772 * Print out the contents of a /dev/fd vnode.
777 struct vop_print_args
/* {
782 printf("tag VT_NON, fdesc vnode\n");
789 struct vop_vfree_args
/* {
800 * /dev/fd "should never get here" operation
810 #define VOPFUNC int (*)(void *)
812 #define fdesc_create ((int (*) __P((struct vop_create_args *)))eopnotsupp)
813 #define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))eopnotsupp)
814 #define fdesc_close ((int (*) __P((struct vop_close_args *)))nullop)
815 #define fdesc_access ((int (*) __P((struct vop_access_args *)))nullop)
816 #define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))eopnotsupp)
817 #define fdesc_revoke vop_revoke
818 #define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
819 #define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop)
820 #define fdesc_remove ((int (*) __P((struct vop_remove_args *)))eopnotsupp)
821 #define fdesc_link ((int (*) __P((struct vop_link_args *)))eopnotsupp)
822 #define fdesc_rename ((int (*) __P((struct vop_rename_args *)))eopnotsupp)
823 #define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))eopnotsupp)
824 #define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))eopnotsupp)
825 #define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
826 #define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
827 #define fdesc_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
828 #define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
829 #define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop)
830 #define fdesc_strategy ((int (*) __P((struct vop_strategy_args *)))fdesc_badop)
831 #define fdesc_islocked \
832 ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
833 #define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
834 #define fdesc_blkatoff \
835 ((int (*) __P((struct vop_blkatoff_args *)))eopnotsupp)
836 #define fdesc_valloc ((int(*) __P(( \
839 struct ucred *cred, \
840 struct vnode **vpp))) eopnotsupp)
841 #define fdesc_truncate \
842 ((int (*) __P((struct vop_truncate_args *)))eopnotsupp)
843 #define fdesc_update ((int (*) __P((struct vop_update_args *)))eopnotsupp)
844 #define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))eopnotsupp)
845 #define fdesc_blktooff ((int (*) __P((struct vop_blktooff_args *)))eopnotsupp)
846 #define fdesc_offtoblk ((int (*) __P((struct vop_offtoblk_args *)))eopnotsupp)
847 #define fdesc_cmap ((int (*) __P((struct vop_cmap_args *)))eopnotsupp)
849 int (**fdesc_vnodeop_p
)(void *);
850 struct vnodeopv_entry_desc fdesc_vnodeop_entries
[] = {
851 { &vop_default_desc
, (VOPFUNC
)vn_default_error
},
852 { &vop_lookup_desc
, (VOPFUNC
)fdesc_lookup
}, /* lookup */
853 { &vop_create_desc
, (VOPFUNC
)fdesc_create
}, /* create */
854 { &vop_mknod_desc
, (VOPFUNC
)fdesc_mknod
}, /* mknod */
855 { &vop_open_desc
, (VOPFUNC
)fdesc_open
}, /* open */
856 { &vop_close_desc
, (VOPFUNC
)fdesc_close
}, /* close */
857 { &vop_access_desc
, (VOPFUNC
)fdesc_access
}, /* access */
858 { &vop_getattr_desc
, (VOPFUNC
)fdesc_getattr
}, /* getattr */
859 { &vop_setattr_desc
, (VOPFUNC
)fdesc_setattr
}, /* setattr */
860 { &vop_read_desc
, (VOPFUNC
)fdesc_read
}, /* read */
861 { &vop_write_desc
, (VOPFUNC
)fdesc_write
}, /* write */
862 { &vop_ioctl_desc
, (VOPFUNC
)fdesc_ioctl
}, /* ioctl */
863 { &vop_select_desc
, (VOPFUNC
)fdesc_select
}, /* select */
864 { &vop_revoke_desc
, (VOPFUNC
)fdesc_revoke
}, /* revoke */
865 { &vop_mmap_desc
, (VOPFUNC
)fdesc_mmap
}, /* mmap */
866 { &vop_fsync_desc
, (VOPFUNC
)fdesc_fsync
}, /* fsync */
867 { &vop_seek_desc
, (VOPFUNC
)fdesc_seek
}, /* seek */
868 { &vop_remove_desc
, (VOPFUNC
)fdesc_remove
}, /* remove */
869 { &vop_link_desc
, (VOPFUNC
)fdesc_link
}, /* link */
870 { &vop_rename_desc
, (VOPFUNC
)fdesc_rename
}, /* rename */
871 { &vop_mkdir_desc
, (VOPFUNC
)fdesc_mkdir
}, /* mkdir */
872 { &vop_rmdir_desc
, (VOPFUNC
)fdesc_rmdir
}, /* rmdir */
873 { &vop_symlink_desc
, (VOPFUNC
)fdesc_symlink
}, /* symlink */
874 { &vop_readdir_desc
, (VOPFUNC
)fdesc_readdir
}, /* readdir */
875 { &vop_readlink_desc
, (VOPFUNC
)fdesc_readlink
},/* readlink */
876 { &vop_abortop_desc
, (VOPFUNC
)fdesc_abortop
}, /* abortop */
877 { &vop_inactive_desc
, (VOPFUNC
)fdesc_inactive
},/* inactive */
878 { &vop_reclaim_desc
, (VOPFUNC
)fdesc_reclaim
}, /* reclaim */
879 { &vop_lock_desc
, (VOPFUNC
)fdesc_lock
}, /* lock */
880 { &vop_unlock_desc
, (VOPFUNC
)fdesc_unlock
}, /* unlock */
881 { &vop_bmap_desc
, (VOPFUNC
)fdesc_bmap
}, /* bmap */
882 { &vop_strategy_desc
, (VOPFUNC
)fdesc_strategy
}, /* strategy */
883 { &vop_print_desc
, (VOPFUNC
)fdesc_print
}, /* print */
884 { &vop_islocked_desc
, (VOPFUNC
)fdesc_islocked
}, /* islocked */
885 { &vop_pathconf_desc
, (VOPFUNC
)fdesc_pathconf
}, /* pathconf */
886 { &vop_advlock_desc
, (VOPFUNC
)fdesc_advlock
}, /* advlock */
887 { &vop_blkatoff_desc
, (VOPFUNC
)fdesc_blkatoff
}, /* blkatoff */
888 { &vop_valloc_desc
, (VOPFUNC
)fdesc_valloc
}, /* valloc */
889 { &vop_vfree_desc
, (VOPFUNC
)fdesc_vfree
}, /* vfree */
890 { &vop_truncate_desc
, (VOPFUNC
)fdesc_truncate
}, /* truncate */
891 { &vop_update_desc
, (VOPFUNC
)fdesc_update
}, /* update */
892 { &vop_bwrite_desc
, (VOPFUNC
)fdesc_bwrite
}, /* bwrite */
893 { &vop_pagein_desc
, (VOPFUNC
)err_pagein
}, /* pagein */
894 { &vop_pageout_desc
, (VOPFUNC
)err_pageout
}, /* pageout */
895 { &vop_copyfile_desc
, (VOPFUNC
)err_copyfile
}, /* Copyfile */
896 { &vop_blktooff_desc
, (VOPFUNC
)fdesc_blktooff
}, /* blktooff */
897 { &vop_blktooff_desc
, (VOPFUNC
)fdesc_offtoblk
}, /* offtoblk */
898 { &vop_cmap_desc
, (VOPFUNC
)fdesc_cmap
}, /* cmap */
899 { (struct vnodeop_desc
*)NULL
, (VOPFUNC
)NULL
}
901 struct vnodeopv_desc fdesc_vnodeop_opv_desc
=
902 { &fdesc_vnodeop_p
, fdesc_vnodeop_entries
};