1 /* $NetBSD: efs_vnops.c,v 1.19 2009/07/03 21:17:41 elad Exp $ */
4 * Copyright (c) 2006 Stephen M. Rumble <rumble@ephemeral.org>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/cdefs.h>
20 __KERNEL_RCSID(0, "$NetBSD: efs_vnops.c,v 1.19 2009/07/03 21:17:41 elad Exp $");
22 #include <sys/param.h>
23 #include <sys/systm.h>
25 #include <sys/kernel.h>
26 #include <sys/vnode.h>
27 #include <sys/mount.h>
28 #include <sys/malloc.h>
29 #include <sys/namei.h>
30 #include <sys/dirent.h>
31 #include <sys/lockf.h>
32 #include <sys/unistd.h>
35 #include <miscfs/genfs/genfs.h>
36 #include <miscfs/genfs/genfs_node.h>
37 #include <miscfs/fifofs/fifo.h>
38 #include <miscfs/specfs/specdev.h>
40 #include <fs/efs/efs.h>
41 #include <fs/efs/efs_sb.h>
42 #include <fs/efs/efs_dir.h>
43 #include <fs/efs/efs_genfs.h>
44 #include <fs/efs/efs_mount.h>
45 #include <fs/efs/efs_extent.h>
46 #include <fs/efs/efs_dinode.h>
47 #include <fs/efs/efs_inode.h>
48 #include <fs/efs/efs_subr.h>
49 #include <fs/efs/efs_ihash.h>
51 MALLOC_DECLARE(M_EFSTMP
);
54 * Lookup a pathname component in the given directory.
56 * Returns 0 on success.
61 struct vop_lookup_args
/* {
64 struct componentname *a_cnp;
66 struct componentname
*cnp
= ap
->a_cnp
;
69 int err
, nameiop
= cnp
->cn_nameiop
;
71 /* ensure that the directory can be accessed first */
72 err
= VOP_ACCESS(ap
->a_dvp
, VEXEC
, cnp
->cn_cred
);
76 err
= cache_lookup(ap
->a_dvp
, ap
->a_vpp
, cnp
);
81 * Handle the three lookup types: '.', '..', and everything else.
83 if (cnp
->cn_namelen
== 1 && cnp
->cn_nameptr
[0] == '.') {
85 *ap
->a_vpp
= ap
->a_dvp
;
86 } else if (cnp
->cn_flags
& ISDOTDOT
) {
87 err
= efs_inode_lookup(VFSTOEFS(ap
->a_dvp
->v_mount
),
88 EFS_VTOI(ap
->a_dvp
), ap
->a_cnp
, &ino
);
92 VOP_UNLOCK(ap
->a_dvp
, 0); /* preserve lock order */
94 err
= VFS_VGET(ap
->a_dvp
->v_mount
, ino
, &vp
);
96 vn_lock(ap
->a_dvp
, LK_EXCLUSIVE
| LK_RETRY
);
99 vn_lock(ap
->a_dvp
, LK_EXCLUSIVE
| LK_RETRY
);
102 err
= efs_inode_lookup(VFSTOEFS(ap
->a_dvp
->v_mount
),
103 EFS_VTOI(ap
->a_dvp
), ap
->a_cnp
, &ino
);
105 if (err
== ENOENT
&& (cnp
->cn_flags
& MAKEENTRY
) &&
107 cache_enter(ap
->a_dvp
, NULL
, cnp
);
108 if (err
== ENOENT
&& (nameiop
== CREATE
||
109 nameiop
== RENAME
)) {
110 err
= VOP_ACCESS(ap
->a_dvp
, VWRITE
,
114 cnp
->cn_flags
|= SAVENAME
;
115 return (EJUSTRETURN
);
119 err
= VFS_VGET(ap
->a_dvp
->v_mount
, ino
, &vp
);
125 if (cnp
->cn_flags
& MAKEENTRY
)
126 cache_enter(ap
->a_dvp
, *ap
->a_vpp
, cnp
);
132 efs_check_possible(struct vnode
*vp
, struct efs_inode
*eip
, mode_t mode
)
135 if ((mode
& VWRITE
) && (vp
->v_mount
->mnt_flag
& MNT_RDONLY
))
142 * Determine the accessiblity of a file based on the permissions allowed by the
143 * specified credentials.
145 * Returns 0 on success.
148 efs_check_permitted(struct vnode
*vp
, struct efs_inode
*eip
, mode_t mode
,
152 return genfs_can_access(vp
->v_type
, eip
->ei_mode
, eip
->ei_uid
,
153 eip
->ei_gid
, mode
, cred
);
159 struct vop_access_args
/* {
160 const struct vnodeop_desc *a_desc;
163 struct ucred *a_cred;
165 struct vnode
*vp
= ap
->a_vp
;
166 struct efs_inode
*eip
= EFS_VTOI(vp
);
169 error
= efs_check_possible(vp
, eip
, ap
->a_mode
);
173 error
= efs_check_permitted(vp
, eip
, ap
->a_mode
, ap
->a_cred
);
179 * Get specific vnode attributes on a file. See vattr(9).
181 * Returns 0 on success.
186 struct vop_getattr_args
/* {
187 const struct vnodeop_desc *a_desc;
190 struct ucred *a_cred;
193 struct vattr
*vap
= ap
->a_vap
;
194 struct efs_inode
*eip
= EFS_VTOI(ap
->a_vp
);
196 vattr_null(ap
->a_vap
);
197 vap
->va_type
= ap
->a_vp
->v_type
;
198 vap
->va_mode
= eip
->ei_mode
;
199 vap
->va_nlink
= eip
->ei_nlink
;
200 vap
->va_uid
= eip
->ei_uid
;
201 vap
->va_gid
= eip
->ei_gid
;
202 vap
->va_fsid
= ap
->a_vp
->v_mount
->mnt_stat
.f_fsid
;
203 vap
->va_fileid
= eip
->ei_number
;
204 vap
->va_size
= eip
->ei_size
;
206 if (ap
->a_vp
->v_type
== VBLK
)
207 vap
->va_blocksize
= BLKDEV_IOSIZE
;
208 else if (ap
->a_vp
->v_type
== VCHR
)
209 vap
->va_blocksize
= MAXBSIZE
;
211 vap
->va_blocksize
= EFS_BB_SIZE
;
213 vap
->va_atime
.tv_sec
= eip
->ei_atime
;
214 vap
->va_mtime
.tv_sec
= eip
->ei_mtime
;
215 vap
->va_ctime
.tv_sec
= eip
->ei_ctime
;
216 /* vap->va_birthtime = */
217 vap
->va_gen
= eip
->ei_gen
;
218 vap
->va_flags
= ap
->a_vp
->v_vflag
|
219 ap
->a_vp
->v_iflag
| ap
->a_vp
->v_uflag
;
221 if (ap
->a_vp
->v_type
== VBLK
|| ap
->a_vp
->v_type
== VCHR
) {
224 if (be16toh(eip
->ei_di
.di_odev
) != EFS_DINODE_ODEV_INVALID
) {
225 dmaj
= EFS_DINODE_ODEV_MAJ(be16toh(eip
->ei_di
.di_odev
));
226 dmin
= EFS_DINODE_ODEV_MIN(be16toh(eip
->ei_di
.di_odev
));
228 dmaj
= EFS_DINODE_NDEV_MAJ(be32toh(eip
->ei_di
.di_ndev
));
229 dmin
= EFS_DINODE_NDEV_MIN(be32toh(eip
->ei_di
.di_ndev
));
232 vap
->va_rdev
= makedev(dmaj
, dmin
);
235 vap
->va_bytes
= eip
->ei_size
;
236 /* vap->va_filerev = */
237 /* vap->va_vaflags = */
245 * Returns 0 on success.
250 struct vop_read_args
/* {
251 const struct vnodeop_desc *a_desc;
255 struct ucred *a_cred;
257 struct efs_extent ex
;
258 struct efs_extent_iterator exi
;
259 struct uio
*uio
= ap
->a_uio
;
260 struct efs_inode
*eip
= EFS_VTOI(ap
->a_vp
);
264 const int advice
= IO_ADV_DECODE(ap
->a_ioflag
);
266 if (ap
->a_vp
->v_type
== VDIR
)
269 if (ap
->a_vp
->v_type
!= VREG
)
272 efs_extent_iterator_init(&exi
, eip
, uio
->uio_offset
);
273 ret
= efs_extent_iterator_next(&exi
, &ex
);
275 if (uio
->uio_offset
< 0 || uio
->uio_offset
>= eip
->ei_size
||
279 start
= ex
.ex_offset
* EFS_BB_SIZE
;
280 len
= ex
.ex_length
* EFS_BB_SIZE
;
282 if (!(uio
->uio_offset
>= start
&&
283 uio
->uio_offset
< (start
+ len
))) {
284 ret
= efs_extent_iterator_next(&exi
, &ex
);
288 start
= uio
->uio_offset
- start
;
290 len
= MIN(len
- start
, uio
->uio_resid
);
291 len
= MIN(len
, eip
->ei_size
- uio
->uio_offset
);
293 err
= ubc_uiomove(&ap
->a_vp
->v_uobj
, uio
, len
, advice
,
294 UBC_READ
| UBC_PARTIALOK
| UBC_UNMAP_FLAG(ap
->a_vp
));
296 EFS_DPRINTF(("efs_read: uiomove error %d\n",
302 return ((ret
== -1) ? 0 : ret
);
308 struct vop_readdir_args
/* {
309 const struct vnodeop_desc *a_desc;
312 struct ucred *a_cred;
318 struct efs_dinode edi
;
319 struct efs_extent ex
;
320 struct efs_extent_iterator exi
;
322 struct efs_dirent
*de
;
323 struct efs_dirblk
*db
;
324 struct uio
*uio
= ap
->a_uio
;
325 struct efs_inode
*ei
= EFS_VTOI(ap
->a_vp
);
326 off_t
*cookies
= NULL
;
328 int i
, j
, err
, ret
, s
, slot
, ncookies
, maxcookies
= 0;
330 if (ap
->a_vp
->v_type
!= VDIR
)
333 if (ap
->a_eofflag
!= NULL
)
334 *ap
->a_eofflag
= false;
336 if (ap
->a_ncookies
!= NULL
) {
339 uio
->uio_resid
/ _DIRENT_MINSIZE((struct dirent
*)0);
340 cookies
= malloc(maxcookies
* sizeof(off_t
), M_TEMP
, M_WAITOK
);
343 dp
= malloc(sizeof(struct dirent
), M_EFSTMP
, M_WAITOK
| M_ZERO
);
346 efs_extent_iterator_init(&exi
, ei
, 0);
347 while ((ret
= efs_extent_iterator_next(&exi
, &ex
)) == 0) {
348 for (i
= 0; i
< ex
.ex_length
; i
++) {
349 err
= efs_bread(VFSTOEFS(ap
->a_vp
->v_mount
),
350 ex
.ex_bn
+ i
, NULL
, &bp
);
356 db
= (struct efs_dirblk
*)bp
->b_data
;
358 if (be16toh(db
->db_magic
) != EFS_DIRBLK_MAGIC
) {
359 printf("efs_readdir: bad dirblk\n");
364 for (j
= 0; j
< db
->db_slots
; j
++) {
365 slot
= EFS_DIRENT_OFF_EXPND(db
->db_space
[j
]);
366 if (slot
== EFS_DIRBLK_SLOT_FREE
)
369 if (!EFS_DIRENT_OFF_VALID(slot
)) {
370 printf("efs_readdir: bad dirent\n");
374 de
= EFS_DIRBLK_TO_DIRENT(db
, slot
);
375 s
= _DIRENT_RECLEN(dp
, de
->de_namelen
);
377 if (offset
< uio
->uio_offset
) {
382 /* XXX - shouldn't happen, right? */
383 if (offset
> uio
->uio_offset
||
384 s
> uio
->uio_resid
) {
389 /* de_namelen is uint8_t, d.d_name is 512b */
390 KASSERT(sizeof(dp
->d_name
)-de
->de_namelen
> 0);
391 dp
->d_fileno
= be32toh(de
->de_inumber
);
393 dp
->d_namlen
= de
->de_namelen
;
394 memcpy(dp
->d_name
, de
->de_name
,
396 dp
->d_name
[de
->de_namelen
] = '\0';
398 /* look up inode to get type */
399 err
= efs_read_inode(
400 VFSTOEFS(ap
->a_vp
->v_mount
),
401 dp
->d_fileno
, NULL
, &edi
);
407 switch (be16toh(edi
.di_mode
) & EFS_IFMT
) {
409 dp
->d_type
= DT_FIFO
;
427 dp
->d_type
= DT_SOCK
;
430 dp
->d_type
= DT_UNKNOWN
;
434 err
= uiomove(dp
, s
, uio
);
442 if (cookies
!= NULL
&& maxcookies
!= 0) {
443 cookies
[ncookies
++] = offset
;
444 if (ncookies
== maxcookies
) {
460 if (ap
->a_eofflag
!= NULL
)
461 *ap
->a_eofflag
= true;
464 if (cookies
!= NULL
) {
465 *ap
->a_cookies
= cookies
;
466 *ap
->a_ncookies
= ncookies
;
469 uio
->uio_offset
= offset
;
477 free(cookies
, M_TEMP
);
485 efs_readlink(void *v
)
487 struct vop_readlink_args
/* {
488 const struct vnodeop_desc *a_desc;
491 struct ucred *a_cred;
493 struct uio
*uio
= ap
->a_uio
;
494 struct efs_inode
*eip
= EFS_VTOI(ap
->a_vp
);
499 if ((eip
->ei_mode
& EFS_IFMT
) != EFS_IFLNK
)
502 if (uio
->uio_resid
< 1)
505 buf
= malloc(eip
->ei_size
+ 1, M_EFSTMP
, M_ZERO
| M_WAITOK
);
507 /* symlinks are either inlined in the inode, or in extents */
508 if (eip
->ei_numextents
== 0) {
509 if (eip
->ei_size
> sizeof(eip
->ei_di
.di_symlink
)) {
510 EFS_DPRINTF(("efs_readlink: too big for inline\n"));
515 memcpy(buf
, eip
->ei_di
.di_symlink
, eip
->ei_size
);
516 len
= MIN(uio
->uio_resid
, eip
->ei_size
+ 1);
518 struct efs_extent_iterator exi
;
519 struct efs_extent ex
;
524 resid
= eip
->ei_size
;
526 efs_extent_iterator_init(&exi
, eip
, 0);
527 while ((ret
= efs_extent_iterator_next(&exi
, &ex
)) == 0) {
528 for (i
= 0; i
< ex
.ex_length
; i
++) {
529 err
= efs_bread(VFSTOEFS(ap
->a_vp
->v_mount
),
530 ex
.ex_bn
+ i
, NULL
, &bp
);
537 len
= MIN(resid
, bp
->b_bcount
);
538 memcpy(buf
+ off
, bp
->b_data
, len
);
552 if (ret
!= 0 && ret
!= -1) {
560 KASSERT(len
>= 1 && len
<= (eip
->ei_size
+ 1));
562 err
= uiomove(buf
, len
, uio
);
569 * Release an inactive vnode. The vnode _must_ be unlocked on return.
570 * It is either nolonger being used by the kernel, or an unmount is being
573 * Returns 0 on success.
576 efs_inactive(void *v
)
578 struct vop_inactive_args
/* {
579 const struct vnodeop_desc *a_desc;
583 struct efs_inode
*eip
= EFS_VTOI(ap
->a_vp
);
585 *ap
->a_recycle
= (eip
->ei_mode
== 0);
586 VOP_UNLOCK(ap
->a_vp
, 0);
594 struct vop_reclaim_args
/* {
595 const struct vnodeop_desc *a_desc;
598 struct vnode
*vp
= ap
->a_vp
;
600 efs_ihashrem(EFS_VTOI(vp
));
602 genfs_node_destroy(vp
);
603 pool_put(&efs_inode_pool
, vp
->v_data
);
612 struct vop_bmap_args
/* {
613 const struct vnodeop_desc *a_desc;
616 struct vnode **a_vpp;
620 struct efs_extent ex
;
621 struct efs_extent_iterator exi
;
622 struct vnode
*vp
= ap
->a_vp
;
623 struct efs_inode
*eip
= EFS_VTOI(vp
);
627 if (ap
->a_vpp
!= NULL
)
628 *ap
->a_vpp
= VFSTOEFS(vp
->v_mount
)->em_devvp
;
631 efs_extent_iterator_init(&exi
, eip
, ap
->a_bn
* EFS_BB_SIZE
);
632 while ((ret
= efs_extent_iterator_next(&exi
, &ex
)) == 0) {
633 if (ap
->a_bn
>= ex
.ex_offset
&&
634 ap
->a_bn
< (ex
.ex_offset
+ ex
.ex_length
)) {
640 KASSERT(!found
|| (found
&& ret
== 0));
643 EFS_DPRINTF(("efs_bmap: ap->a_bn not in extents\n"));
644 return ((ret
== -1) ? EIO
: ret
);
647 if (ex
.ex_magic
!= EFS_EXTENT_MAGIC
) {
648 EFS_DPRINTF(("efs_bmap: exn.ex_magic != EFS_EXTENT_MAGIC\n"));
652 if (ap
->a_bn
< ex
.ex_offset
) {
653 EFS_DPRINTF(("efs_bmap: ap->a_bn < exn.ex_offset\n"));
657 KASSERT(ap
->a_bn
>= ex
.ex_offset
);
658 KASSERT(ex
.ex_length
> ap
->a_bn
- ex
.ex_offset
);
660 *ap
->a_bnp
= ex
.ex_bn
+ (ap
->a_bn
- ex
.ex_offset
);
661 if (ap
->a_runp
!= NULL
)
662 *ap
->a_runp
= ex
.ex_length
- (ap
->a_bn
- ex
.ex_offset
) - 1;
668 efs_strategy(void *v
)
670 struct vop_strategy_args
/* {
671 const struct vnodeop_desc *a_desc;
675 struct vnode
*vp
= ap
->a_vp
;
676 struct buf
*bp
= ap
->a_bp
;
685 if (bp
->b_blkno
== bp
->b_lblkno
) {
686 error
= VOP_BMAP(vp
, bp
->b_lblkno
, NULL
, &bp
->b_blkno
, NULL
);
692 if ((long)bp
->b_blkno
== -1)
696 if ((long)bp
->b_blkno
== -1) {
701 return (VOP_STRATEGY(VFSTOEFS(vp
->v_mount
)->em_devvp
, bp
));
707 struct vop_print_args
/* {
708 const struct vnodeop_desc *a_desc;
711 struct efs_inode
*eip
= EFS_VTOI(ap
->a_vp
);
713 printf( "efs_inode (ino %lu):\n"
723 " ei_numextents: %d\n"
725 (unsigned long)eip
->ei_number
,
726 (unsigned int)eip
->ei_mode
,
731 (int32_t)eip
->ei_atime
,
732 (int32_t)eip
->ei_mtime
,
733 (int32_t)eip
->ei_ctime
,
742 efs_pathconf(void *v
)
744 struct vop_pathconf_args
/* {
745 const struct vnodeop_desc *a_desc;
748 register_t *a_retval;
752 switch (ap
->a_name
) {
754 *ap
->a_retval
= 30000;
760 *ap
->a_retval
= 1024;
765 case _PC_CHOWN_RESTRICTED
:
771 case _PC_FILESIZEBITS
:
784 struct vop_advlock_args
/* {
785 const struct vnodeop_desc *a_desc;
792 struct efs_inode
*eip
= EFS_VTOI(ap
->a_vp
);
794 return (lf_advlock(ap
, &eip
->ei_lockf
, eip
->ei_size
));
797 /* Global vfs data structures for efs */
798 int (**efs_vnodeop_p
)(void *);
799 const struct vnodeopv_entry_desc efs_vnodeop_entries
[] = {
800 { &vop_default_desc
, vn_default_error
}, /* error handler */
801 { &vop_lookup_desc
, efs_lookup
}, /* lookup */
802 { &vop_create_desc
, genfs_eopnotsupp
}, /* create */
803 { &vop_mknod_desc
, genfs_eopnotsupp
}, /* mknod */
804 { &vop_open_desc
, genfs_nullop
}, /* open */
805 { &vop_close_desc
, genfs_nullop
}, /* close */
806 { &vop_access_desc
, efs_access
}, /* access */
807 { &vop_getattr_desc
, efs_getattr
}, /* getattr */
808 { &vop_setattr_desc
, genfs_eopnotsupp
}, /* setattr */
809 { &vop_read_desc
, efs_read
}, /* read */
810 { &vop_write_desc
, genfs_eopnotsupp
}, /* write */
811 { &vop_ioctl_desc
, genfs_enoioctl
}, /* ioctl */
812 { &vop_fcntl_desc
, genfs_fcntl
}, /* fcntl */
813 { &vop_poll_desc
, genfs_poll
}, /* poll */
814 { &vop_kqfilter_desc
, genfs_kqfilter
}, /* kqfilter */
815 { &vop_revoke_desc
, genfs_revoke
}, /* revoke */
816 { &vop_mmap_desc
, genfs_mmap
}, /* mmap */
817 { &vop_fsync_desc
, genfs_eopnotsupp
}, /* fsync */
818 { &vop_seek_desc
, genfs_seek
}, /* seek */
819 { &vop_remove_desc
, genfs_eopnotsupp
}, /* remove */
820 { &vop_link_desc
, genfs_eopnotsupp
}, /* link */
821 { &vop_rename_desc
, genfs_eopnotsupp
}, /* rename */
822 { &vop_mkdir_desc
, genfs_eopnotsupp
}, /* mkdir */
823 { &vop_rmdir_desc
, genfs_eopnotsupp
}, /* rmdir */
824 { &vop_symlink_desc
, genfs_eopnotsupp
}, /* symlink */
825 { &vop_readdir_desc
, efs_readdir
}, /* readdir */
826 { &vop_readlink_desc
, efs_readlink
}, /* readlink */
827 { &vop_abortop_desc
, genfs_abortop
}, /* abortop */
828 { &vop_inactive_desc
, efs_inactive
}, /* inactive */
829 { &vop_reclaim_desc
, efs_reclaim
}, /* reclaim */
830 { &vop_lock_desc
, genfs_lock
, }, /* lock */
831 { &vop_unlock_desc
, genfs_unlock
, }, /* unlock */
832 { &vop_islocked_desc
, genfs_islocked
, }, /* islocked */
833 { &vop_bmap_desc
, efs_bmap
}, /* bmap */
834 { &vop_print_desc
, efs_print
}, /* print */
835 { &vop_pathconf_desc
, efs_pathconf
}, /* pathconf */
836 { &vop_advlock_desc
, efs_advlock
}, /* advlock */
843 { &vop_getpages_desc
, genfs_getpages
}, /* getpages */
844 { &vop_putpages_desc
, genfs_putpages
}, /* putpages */
845 { &vop_bwrite_desc
, vn_bwrite
}, /* bwrite */
846 { &vop_strategy_desc
, efs_strategy
}, /* strategy */
849 const struct vnodeopv_desc efs_vnodeop_opv_desc
= {
854 int (**efs_specop_p
)(void *);
855 const struct vnodeopv_entry_desc efs_specop_entries
[] = {
856 { &vop_default_desc
, vn_default_error
}, /* error handler */
857 { &vop_lookup_desc
, spec_lookup
}, /* lookup */
858 { &vop_create_desc
, spec_create
}, /* create */
859 { &vop_mknod_desc
, spec_mknod
}, /* mknod */
860 { &vop_open_desc
, spec_open
}, /* open */
861 { &vop_close_desc
, spec_close
}, /* close */
862 { &vop_access_desc
, efs_access
}, /* access */
863 { &vop_getattr_desc
, efs_getattr
}, /* getattr */
864 { &vop_setattr_desc
, genfs_eopnotsupp
}, /* setattr */
865 { &vop_read_desc
, spec_read
}, /* read */
866 { &vop_write_desc
, spec_write
}, /* write */
867 { &vop_ioctl_desc
, spec_ioctl
}, /* ioctl */
868 { &vop_fcntl_desc
, genfs_fcntl
}, /* fcntl */
869 { &vop_poll_desc
, spec_poll
}, /* poll */
870 { &vop_kqfilter_desc
, spec_kqfilter
}, /* kqfilter */
871 { &vop_revoke_desc
, spec_revoke
}, /* revoke */
872 { &vop_mmap_desc
, spec_mmap
}, /* mmap */
873 { &vop_fsync_desc
, spec_fsync
}, /* fsync */
874 { &vop_seek_desc
, spec_seek
}, /* seek */
875 { &vop_remove_desc
, spec_remove
}, /* remove */
876 { &vop_link_desc
, spec_link
}, /* link */
877 { &vop_rename_desc
, spec_rename
}, /* rename */
878 { &vop_mkdir_desc
, spec_mkdir
}, /* mkdir */
879 { &vop_rmdir_desc
, spec_rmdir
}, /* rmdir */
880 { &vop_symlink_desc
, spec_symlink
}, /* symlink */
881 { &vop_readdir_desc
, spec_readdir
}, /* readdir */
882 { &vop_readlink_desc
, spec_readlink
}, /* readlink */
883 { &vop_abortop_desc
, spec_abortop
}, /* abortop */
884 { &vop_inactive_desc
, efs_inactive
}, /* inactive */
885 { &vop_reclaim_desc
, efs_reclaim
}, /* reclaim */
886 { &vop_lock_desc
, genfs_lock
, }, /* lock */
887 { &vop_unlock_desc
, genfs_unlock
, }, /* unlock */
888 { &vop_islocked_desc
, genfs_islocked
, }, /* islocked */
889 { &vop_bmap_desc
, spec_bmap
}, /* bmap */
890 { &vop_print_desc
, efs_print
}, /* print */
891 { &vop_pathconf_desc
, spec_pathconf
}, /* pathconf */
892 { &vop_advlock_desc
, spec_advlock
}, /* advlock */
899 { &vop_getpages_desc
, spec_getpages
}, /* getpages */
900 { &vop_putpages_desc
, spec_putpages
}, /* putpages */
901 { &vop_bwrite_desc
, vn_bwrite
}, /* bwrite */
902 { &vop_strategy_desc
, spec_strategy
}, /* strategy */
905 const struct vnodeopv_desc efs_specop_opv_desc
= {
910 int (**efs_fifoop_p
)(void *);
911 const struct vnodeopv_entry_desc efs_fifoop_entries
[] = {
912 { &vop_default_desc
, vn_default_error
}, /* error handler */
913 { &vop_lookup_desc
, fifo_lookup
}, /* lookup */
914 { &vop_create_desc
, fifo_create
}, /* create */
915 { &vop_mknod_desc
, fifo_mknod
}, /* mknod */
916 { &vop_open_desc
, fifo_open
}, /* open */
917 { &vop_close_desc
, fifo_close
}, /* close */
918 { &vop_access_desc
, efs_access
}, /* access */
919 { &vop_getattr_desc
, efs_getattr
}, /* getattr */
920 { &vop_setattr_desc
, genfs_eopnotsupp
}, /* setattr */
921 { &vop_read_desc
, fifo_read
}, /* read */
922 { &vop_write_desc
, fifo_write
}, /* write */
923 { &vop_ioctl_desc
, fifo_ioctl
}, /* ioctl */
924 { &vop_fcntl_desc
, genfs_fcntl
}, /* fcntl */
925 { &vop_poll_desc
, fifo_poll
}, /* poll */
926 { &vop_kqfilter_desc
, fifo_kqfilter
}, /* kqfilter */
927 { &vop_revoke_desc
, fifo_revoke
}, /* revoke */
928 { &vop_mmap_desc
, fifo_mmap
}, /* mmap */
929 { &vop_fsync_desc
, fifo_fsync
}, /* fsync */
930 { &vop_seek_desc
, fifo_seek
}, /* seek */
931 { &vop_remove_desc
, fifo_remove
}, /* remove */
932 { &vop_link_desc
, fifo_link
}, /* link */
933 { &vop_rename_desc
, fifo_rename
}, /* rename */
934 { &vop_mkdir_desc
, fifo_mkdir
}, /* mkdir */
935 { &vop_rmdir_desc
, fifo_rmdir
}, /* rmdir */
936 { &vop_symlink_desc
, fifo_symlink
}, /* symlink */
937 { &vop_readdir_desc
, fifo_readdir
}, /* readdir */
938 { &vop_readlink_desc
, fifo_readlink
}, /* readlink */
939 { &vop_abortop_desc
, fifo_abortop
}, /* abortop */
940 { &vop_inactive_desc
, efs_inactive
}, /* inactive */
941 { &vop_reclaim_desc
, efs_reclaim
}, /* reclaim */
942 { &vop_lock_desc
, genfs_lock
, }, /* lock */
943 { &vop_unlock_desc
, genfs_unlock
, }, /* unlock */
944 { &vop_islocked_desc
, genfs_islocked
, }, /* islocked */
945 { &vop_bmap_desc
, fifo_bmap
}, /* bmap */
946 { &vop_print_desc
, efs_print
}, /* print */
947 { &vop_pathconf_desc
, fifo_pathconf
}, /* pathconf */
948 { &vop_advlock_desc
, fifo_advlock
}, /* advlock */
955 { &vop_bwrite_desc
, vn_bwrite
}, /* bwrite */
956 { &vop_strategy_desc
, fifo_strategy
}, /* strategy */
959 const struct vnodeopv_desc efs_fifoop_opv_desc
= {