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>
87 #define FDL_LOCKED 0x02
88 static int fdcache_lock
;
91 #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1)
92 FD_STDIN
, FD_STDOUT
, FD_STDERR must be a sequence n
, n
+1, n
+2
97 #define FD_NHASH(ix) \
98 (&fdhashtbl[(ix) & fdhash])
99 LIST_HEAD(fdhashhead
, fdescnode
) *fdhashtbl
;
103 * Initialise cache headers
106 struct vfsconf
*vfsp
;
109 fdhashtbl
= hashinit(NFDCACHE
, M_CACHE
, &fdhash
);
113 fdesc_allocvp(ftype
, ix
, mp
, vpp
)
119 struct proc
*p
= current_proc(); /* XXX */
120 struct fdhashhead
*fc
;
121 struct fdescnode
*fd
;
126 for (fd
= fc
->lh_first
; fd
!= 0; fd
= fd
->fd_hash
.le_next
) {
127 if (fd
->fd_ix
== ix
&& fd
->fd_vnode
->v_mount
== mp
) {
128 if (vget(fd
->fd_vnode
, 0, p
))
136 * otherwise lock the array while we call getnewvnode
137 * since that can block.
139 if (fdcache_lock
& FDL_LOCKED
) {
140 fdcache_lock
|= FDL_WANT
;
141 sleep((caddr_t
) &fdcache_lock
, PINOD
);
144 fdcache_lock
|= FDL_LOCKED
;
146 MALLOC(fd
, void *, sizeof(struct fdescnode
), M_TEMP
, M_WAITOK
);
147 error
= getnewvnode(VT_FDESC
, mp
, fdesc_vnodeop_p
, vpp
);
158 LIST_INSERT_HEAD(fc
, fd
, fd_hash
);
161 fdcache_lock
&= ~FDL_LOCKED
;
163 if (fdcache_lock
& FDL_WANT
) {
164 fdcache_lock
&= ~FDL_WANT
;
165 wakeup((caddr_t
) &fdcache_lock
);
172 * vp is the current namei directory
173 * ndp is the name to locate in that directory...
177 struct vop_lookup_args
/* {
178 struct vnode * a_dvp;
179 struct vnode ** a_vpp;
180 struct componentname * a_cnp;
183 struct vnode
**vpp
= ap
->a_vpp
;
184 struct vnode
*dvp
= ap
->a_dvp
;
185 struct componentname
*cnp
= ap
->a_cnp
;
186 char *pname
= cnp
->cn_nameptr
;
187 struct proc
*p
= cnp
->cn_proc
;
188 int nfiles
= p
->p_fd
->fd_nfiles
;
194 VOP_UNLOCK(dvp
, 0, p
);
195 if (cnp
->cn_namelen
== 1 && *pname
== '.') {
198 vn_lock(dvp
, LK_SHARED
| LK_RETRY
, p
);
202 switch (VTOFDESC(dvp
)->fd_type
) {
210 if (cnp
->cn_namelen
== 2 && bcmp(pname
, "fd", 2) == 0) {
211 error
= fdesc_allocvp(Fdevfd
, FD_DEVFD
, dvp
->v_mount
, &fvp
);
216 vn_lock(fvp
, LK_SHARED
| LK_RETRY
, p
);
221 switch (cnp
->cn_namelen
) {
223 if (bcmp(pname
, "stdin", 5) == 0) {
229 if (bcmp(pname
, "stdout", 6) == 0) {
233 if (bcmp(pname
, "stderr", 6) == 0) {
241 error
= fdesc_allocvp(Flink
, fd
, dvp
->v_mount
, &fvp
);
244 VTOFDESC(fvp
)->fd_link
= ln
;
247 vn_lock(fvp
, LK_SHARED
| LK_RETRY
, p
);
257 if (cnp
->cn_namelen
== 2 && bcmp(pname
, "..", 2) == 0) {
258 if (error
= fdesc_root(dvp
->v_mount
, vpp
))
264 while (*pname
>= '0' && *pname
<= '9') {
265 fd
= 10 * fd
+ *pname
++ - '0';
270 if (*pname
!= '\0') {
276 *fdfile(p
, fd
) == NULL
||
277 (*fdflags(p
, fd
) & UF_RESERVED
)) {
282 error
= fdesc_allocvp(Fdesc
, FD_DESC
+fd
, dvp
->v_mount
, &fvp
);
285 VTOFDESC(fvp
)->fd_fd
= fd
;
286 vn_lock(fvp
, LK_SHARED
| LK_RETRY
, p
);
292 vn_lock(dvp
, LK_SHARED
| LK_RETRY
, p
);
299 struct vop_open_args
/* {
302 struct ucred *a_cred;
306 struct vnode
*vp
= ap
->a_vp
;
309 switch (VTOFDESC(vp
)->fd_type
) {
312 * XXX Kludge: set p->p_dupfd to contain the value of the
313 * the file descriptor being sought for duplication. The error
314 * return ensures that the vnode for this device will be
315 * released by vn_open. Open will detect this special error and
316 * take the actions in dupfdopen. Other callers of vn_open or
317 * VOP_OPEN will simply report the error.
319 ap
->a_p
->p_dupfd
= VTOFDESC(vp
)->fd_fd
; /* XXX */
329 fdesc_attr(fd
, vap
, cred
, p
)
339 if (error
= fdgetf(p
, fd
, &fp
))
341 switch (fp
->f_type
) {
343 error
= VOP_GETATTR((struct vnode
*) fp
->f_data
, vap
, cred
, p
);
344 if (error
== 0 && vap
->va_type
== VDIR
) {
346 * directories can cause loops in the namespace,
347 * so turn off the 'x' bits to avoid trouble.
349 vap
->va_mode
&= ~((VEXEC
)|(VEXEC
>>3)|(VEXEC
>>6));
354 error
= soo_stat((struct socket
*)fp
->f_data
, &stb
);
357 vap
->va_type
= VSOCK
;
358 vap
->va_mode
= stb
.st_mode
;
359 vap
->va_nlink
= stb
.st_nlink
;
360 vap
->va_uid
= stb
.st_uid
;
361 vap
->va_gid
= stb
.st_gid
;
362 vap
->va_fsid
= stb
.st_dev
;
363 vap
->va_fileid
= stb
.st_ino
;
364 vap
->va_size
= stb
.st_size
;
365 vap
->va_blocksize
= stb
.st_blksize
;
366 vap
->va_atime
= stb
.st_atimespec
;
367 vap
->va_mtime
= stb
.st_mtimespec
;
368 vap
->va_ctime
= stb
.st_ctimespec
;
369 vap
->va_gen
= stb
.st_gen
;
370 vap
->va_flags
= stb
.st_flags
;
371 vap
->va_rdev
= stb
.st_rdev
;
372 vap
->va_bytes
= stb
.st_blocks
* stb
.st_blksize
;
386 struct vop_getattr_args
/* {
389 struct ucred *a_cred;
393 struct vnode
*vp
= ap
->a_vp
;
394 struct vattr
*vap
= ap
->a_vap
;
398 switch (VTOFDESC(vp
)->fd_type
) {
402 bzero((caddr_t
) vap
, sizeof(*vap
));
404 vap
->va_fileid
= VTOFDESC(vp
)->fd_ix
;
408 vap
->va_fsid
= vp
->v_mount
->mnt_stat
.f_fsid
.val
[0];
409 vap
->va_blocksize
= DEV_BSIZE
;
410 vap
->va_atime
.tv_sec
= boottime
.tv_sec
;
411 vap
->va_atime
.tv_nsec
= 0;
412 vap
->va_mtime
= vap
->va_atime
;
413 vap
->va_ctime
= vap
->va_mtime
;
419 switch (VTOFDESC(vp
)->fd_type
) {
421 vap
->va_mode
= S_IRUSR
|S_IXUSR
|S_IRGRP
|S_IXGRP
|S_IROTH
|S_IXOTH
;
424 vap
->va_size
= strlen(VTOFDESC(vp
)->fd_link
);
428 vap
->va_mode
= S_IRUSR
|S_IXUSR
|S_IRGRP
|S_IXGRP
|S_IROTH
|S_IXOTH
;
431 vap
->va_size
= DEV_BSIZE
;
437 fd
= VTOFDESC(vp
)->fd_fd
;
438 error
= fdesc_attr(fd
, vap
, ap
->a_cred
, ap
->a_p
);
447 vp
->v_type
= vap
->va_type
;
455 struct vop_setattr_args
/* {
458 struct ucred *a_cred;
467 * Can't mess with the root vnode
469 switch (VTOFDESC(ap
->a_vp
)->fd_type
) {
477 fd
= VTOFDESC(ap
->a_vp
)->fd_fd
;
478 if (error
= fdgetf(ap
->a_p
, fd
, &fp
))
482 * Can setattr the underlying vnode, but not sockets!
484 switch (fp
->f_type
) {
486 error
= VOP_SETATTR((struct vnode
*) fp
->f_data
, ap
->a_vap
, ap
->a_cred
, ap
->a_p
);
494 kprintf("fp->f_type = %d\n", fp
->f_type
);
504 static struct dirtmp
{
510 { FD_DEVFD
, UIO_MX
, 2, "fd" },
511 { FD_STDIN
, UIO_MX
, 5, "stdin" },
512 { FD_STDOUT
, UIO_MX
, 6, "stdout" },
513 { FD_STDERR
, UIO_MX
, 6, "stderr" },
519 struct vop_readdir_args
/* {
522 struct ucred *a_cred;
528 struct uio
*uio
= ap
->a_uio
;
529 struct proc
*p
= uio
->uio_procp
;
533 * We don't allow exporting fdesc mounts, and currently local
534 * requests do not need cookies.
539 switch (VTOFDESC(ap
->a_vp
)->fd_type
) {
547 if (VTOFDESC(ap
->a_vp
)->fd_type
== Froot
) {
549 struct dirent
*dp
= &d
;
553 i
= uio
->uio_offset
/ UIO_MX
;
556 while (uio
->uio_resid
> 0) {
558 if (dt
->d_fileno
== 0) {
564 switch (dt
->d_fileno
) {
568 fd
= dt
->d_fileno
- FD_STDIN
;
569 if (fd
>= p
->p_fd
->fd_nfiles
)
571 if (*fdfile(p
, fd
) == NULL
&&
577 bzero((caddr_t
) dp
, UIO_MX
);
578 dp
->d_fileno
= dt
->d_fileno
;
579 dp
->d_namlen
= dt
->d_namlen
;
580 dp
->d_type
= DT_UNKNOWN
;
581 dp
->d_reclen
= dt
->d_reclen
;
582 bcopy(dt
->d_name
, dp
->d_name
, dp
->d_namlen
+1);
583 error
= uiomove((caddr_t
) dp
, UIO_MX
, uio
);
587 uio
->uio_offset
= i
* UIO_MX
;
591 i
= uio
->uio_offset
/ UIO_MX
;
593 while (uio
->uio_resid
> 0) {
594 if (i
>= p
->p_fd
->fd_nfiles
)
597 if (*fdfile(p
, i
) != NULL
&& !(*fdflags(p
, i
) & UF_RESERVED
)) {
599 struct dirent
*dp
= &d
;
601 bzero((caddr_t
) dp
, UIO_MX
);
603 dp
->d_namlen
= sprintf(dp
->d_name
, "%d", i
);
604 dp
->d_reclen
= UIO_MX
;
605 dp
->d_type
= DT_UNKNOWN
;
606 dp
->d_fileno
= i
+ FD_STDIN
;
608 * And ship to userland
610 error
= uiomove((caddr_t
) dp
, UIO_MX
, uio
);
617 uio
->uio_offset
= i
* UIO_MX
;
623 struct vop_readlink_args
/* {
626 struct ucred *a_cred;
629 struct vnode
*vp
= ap
->a_vp
;
632 if (vp
->v_type
!= VLNK
)
635 if (VTOFDESC(vp
)->fd_type
== Flink
) {
636 char *ln
= VTOFDESC(vp
)->fd_link
;
637 error
= uiomove(ln
, strlen(ln
), ap
->a_uio
);
647 struct vop_read_args
/* {
651 struct ucred *a_cred;
660 struct vop_write_args
/* {
664 struct ucred *a_cred;
672 struct vop_ioctl_args
/* {
677 struct ucred *a_cred;
686 struct vop_select_args
/* {
690 struct ucred *a_cred;
700 struct vop_inactive_args
/* {
705 struct vnode
*vp
= ap
->a_vp
;
708 * Clear out the v_type field to avoid
709 * nasty things happening in vgone().
711 VOP_UNLOCK(vp
, 0, ap
->a_p
);
718 struct vop_reclaim_args
/* {
722 struct vnode
*vp
= ap
->a_vp
;
723 struct fdescnode
*fd
= VTOFDESC(vp
);
725 LIST_REMOVE(fd
, fd_hash
);
726 FREE(vp
->v_data
, M_TEMP
);
733 * Return POSIX pathconf information applicable to special devices.
736 struct vop_pathconf_args
/* {
743 switch (ap
->a_name
) {
745 *ap
->a_retval
= LINK_MAX
;
748 *ap
->a_retval
= MAX_CANON
;
751 *ap
->a_retval
= MAX_INPUT
;
754 *ap
->a_retval
= PIPE_BUF
;
756 case _PC_CHOWN_RESTRICTED
:
760 *ap
->a_retval
= _POSIX_VDISABLE
;
769 * Print out the contents of a /dev/fd vnode.
774 struct vop_print_args
/* {
779 printf("tag VT_NON, fdesc vnode\n");
786 struct vop_vfree_args
/* {
797 * /dev/fd "should never get here" operation
807 #define VOPFUNC int (*)(void *)
809 #define fdesc_create ((int (*) __P((struct vop_create_args *)))eopnotsupp)
810 #define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))eopnotsupp)
811 #define fdesc_close ((int (*) __P((struct vop_close_args *)))nullop)
812 #define fdesc_access ((int (*) __P((struct vop_access_args *)))nullop)
813 #define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))eopnotsupp)
814 #define fdesc_revoke vop_revoke
815 #define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop)
816 #define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop)
817 #define fdesc_remove ((int (*) __P((struct vop_remove_args *)))eopnotsupp)
818 #define fdesc_link ((int (*) __P((struct vop_link_args *)))eopnotsupp)
819 #define fdesc_rename ((int (*) __P((struct vop_rename_args *)))eopnotsupp)
820 #define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))eopnotsupp)
821 #define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))eopnotsupp)
822 #define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
823 #define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop)
824 #define fdesc_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock)
825 #define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock)
826 #define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop)
827 #define fdesc_strategy ((int (*) __P((struct vop_strategy_args *)))fdesc_badop)
828 #define fdesc_islocked \
829 ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
830 #define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
831 #define fdesc_blkatoff \
832 ((int (*) __P((struct vop_blkatoff_args *)))eopnotsupp)
833 #define fdesc_valloc ((int(*) __P(( \
836 struct ucred *cred, \
837 struct vnode **vpp))) eopnotsupp)
838 #define fdesc_truncate \
839 ((int (*) __P((struct vop_truncate_args *)))eopnotsupp)
840 #define fdesc_update ((int (*) __P((struct vop_update_args *)))eopnotsupp)
841 #define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))eopnotsupp)
842 #define fdesc_blktooff ((int (*) __P((struct vop_blktooff_args *)))eopnotsupp)
843 #define fdesc_offtoblk ((int (*) __P((struct vop_offtoblk_args *)))eopnotsupp)
844 #define fdesc_cmap ((int (*) __P((struct vop_cmap_args *)))eopnotsupp)
846 int (**fdesc_vnodeop_p
)(void *);
847 struct vnodeopv_entry_desc fdesc_vnodeop_entries
[] = {
848 { &vop_default_desc
, (VOPFUNC
)vn_default_error
},
849 { &vop_lookup_desc
, (VOPFUNC
)fdesc_lookup
}, /* lookup */
850 { &vop_create_desc
, (VOPFUNC
)fdesc_create
}, /* create */
851 { &vop_mknod_desc
, (VOPFUNC
)fdesc_mknod
}, /* mknod */
852 { &vop_open_desc
, (VOPFUNC
)fdesc_open
}, /* open */
853 { &vop_close_desc
, (VOPFUNC
)fdesc_close
}, /* close */
854 { &vop_access_desc
, (VOPFUNC
)fdesc_access
}, /* access */
855 { &vop_getattr_desc
, (VOPFUNC
)fdesc_getattr
}, /* getattr */
856 { &vop_setattr_desc
, (VOPFUNC
)fdesc_setattr
}, /* setattr */
857 { &vop_read_desc
, (VOPFUNC
)fdesc_read
}, /* read */
858 { &vop_write_desc
, (VOPFUNC
)fdesc_write
}, /* write */
859 { &vop_ioctl_desc
, (VOPFUNC
)fdesc_ioctl
}, /* ioctl */
860 { &vop_select_desc
, (VOPFUNC
)fdesc_select
}, /* select */
861 { &vop_revoke_desc
, (VOPFUNC
)fdesc_revoke
}, /* revoke */
862 { &vop_mmap_desc
, (VOPFUNC
)fdesc_mmap
}, /* mmap */
863 { &vop_fsync_desc
, (VOPFUNC
)fdesc_fsync
}, /* fsync */
864 { &vop_seek_desc
, (VOPFUNC
)fdesc_seek
}, /* seek */
865 { &vop_remove_desc
, (VOPFUNC
)fdesc_remove
}, /* remove */
866 { &vop_link_desc
, (VOPFUNC
)fdesc_link
}, /* link */
867 { &vop_rename_desc
, (VOPFUNC
)fdesc_rename
}, /* rename */
868 { &vop_mkdir_desc
, (VOPFUNC
)fdesc_mkdir
}, /* mkdir */
869 { &vop_rmdir_desc
, (VOPFUNC
)fdesc_rmdir
}, /* rmdir */
870 { &vop_symlink_desc
, (VOPFUNC
)fdesc_symlink
}, /* symlink */
871 { &vop_readdir_desc
, (VOPFUNC
)fdesc_readdir
}, /* readdir */
872 { &vop_readlink_desc
, (VOPFUNC
)fdesc_readlink
},/* readlink */
873 { &vop_abortop_desc
, (VOPFUNC
)fdesc_abortop
}, /* abortop */
874 { &vop_inactive_desc
, (VOPFUNC
)fdesc_inactive
},/* inactive */
875 { &vop_reclaim_desc
, (VOPFUNC
)fdesc_reclaim
}, /* reclaim */
876 { &vop_lock_desc
, (VOPFUNC
)fdesc_lock
}, /* lock */
877 { &vop_unlock_desc
, (VOPFUNC
)fdesc_unlock
}, /* unlock */
878 { &vop_bmap_desc
, (VOPFUNC
)fdesc_bmap
}, /* bmap */
879 { &vop_strategy_desc
, (VOPFUNC
)fdesc_strategy
}, /* strategy */
880 { &vop_print_desc
, (VOPFUNC
)fdesc_print
}, /* print */
881 { &vop_islocked_desc
, (VOPFUNC
)fdesc_islocked
}, /* islocked */
882 { &vop_pathconf_desc
, (VOPFUNC
)fdesc_pathconf
}, /* pathconf */
883 { &vop_advlock_desc
, (VOPFUNC
)fdesc_advlock
}, /* advlock */
884 { &vop_blkatoff_desc
, (VOPFUNC
)fdesc_blkatoff
}, /* blkatoff */
885 { &vop_valloc_desc
, (VOPFUNC
)fdesc_valloc
}, /* valloc */
886 { &vop_vfree_desc
, (VOPFUNC
)fdesc_vfree
}, /* vfree */
887 { &vop_truncate_desc
, (VOPFUNC
)fdesc_truncate
}, /* truncate */
888 { &vop_update_desc
, (VOPFUNC
)fdesc_update
}, /* update */
889 { &vop_bwrite_desc
, (VOPFUNC
)fdesc_bwrite
}, /* bwrite */
890 { &vop_pagein_desc
, (VOPFUNC
)err_pagein
}, /* pagein */
891 { &vop_pageout_desc
, (VOPFUNC
)err_pageout
}, /* pageout */
892 { &vop_copyfile_desc
, (VOPFUNC
)err_copyfile
}, /* Copyfile */
893 { &vop_blktooff_desc
, (VOPFUNC
)fdesc_blktooff
}, /* blktooff */
894 { &vop_blktooff_desc
, (VOPFUNC
)fdesc_offtoblk
}, /* offtoblk */
895 { &vop_cmap_desc
, (VOPFUNC
)fdesc_cmap
}, /* cmap */
896 { (struct vnodeop_desc
*)NULL
, (VOPFUNC
)NULL
}
898 struct vnodeopv_desc fdesc_vnodeop_opv_desc
=
899 { &fdesc_vnodeop_p
, fdesc_vnodeop_entries
};