1 /* $NetBSD: chfs_vnops.c,v 1.18 2013/10/20 17:18:38 christos Exp $ */
4 * Copyright (c) 2010 Department of Software Engineering,
5 * University of Szeged, Hungary
6 * Copyright (C) 2010 Tamas Toth <ttoth@inf.u-szeged.hu>
7 * Copyright (C) 2010 Adam Hoka <ahoka@NetBSD.org>
10 * This code is derived from software contributed to The NetBSD Foundation
11 * by the Department of Software Engineering, University of Szeged, Hungary
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/param.h>
36 #include <miscfs/specfs/specdev.h>
37 #include <miscfs/fifofs/fifo.h>
38 #include <miscfs/genfs/genfs.h>
39 #include <ufs/ufs/dir.h>
40 #include <ufs/ufs/ufs_extern.h>
42 #include <sys/namei.h>
44 #include <sys/fcntl.h>
46 #include <sys/fstrans.h>
47 #include <sys/vnode.h>
51 #define READ_S "chfs_read"
56 struct vnode
*dvp
= ((struct vop_lookup_args
*) v
)->a_dvp
;
57 struct vnode
**vpp
= ((struct vop_lookup_args
*) v
)->a_vpp
;
58 struct componentname
*cnp
= ((struct vop_lookup_args
*) v
)->a_cnp
;
61 struct chfs_inode
* ip
;
63 struct chfs_mount
* chmp
;
64 struct chfs_vnode_cache
* chvc
;
65 struct chfs_dirent
* fd
;
67 dbg("lookup(): %s\n", cnp
->cn_nameptr
);
69 KASSERT(VOP_ISLOCKED(dvp
));
73 /* Check accessibility of requested node as a first step. */
74 error
= VOP_ACCESS(dvp
, VEXEC
, cnp
->cn_cred
);
79 /* If requesting the last path component on a read-only file system
80 * with a write operation, deny it. */
81 if ((cnp
->cn_flags
& ISLASTCN
) && (dvp
->v_mount
->mnt_flag
& MNT_RDONLY
)
82 && (cnp
->cn_nameiop
== DELETE
|| cnp
->cn_nameiop
== RENAME
)) {
87 /* Avoid doing a linear scan of the directory if the requested
88 * directory/name couple is already in the cache. */
89 if (cache_lookup(dvp
, cnp
->cn_nameptr
, cnp
->cn_namelen
,
90 cnp
->cn_nameiop
, cnp
->cn_flags
, NULL
, vpp
)) {
91 error
= *vpp
== NULLVP
? ENOENT
: 0;
96 ump
= VFSTOUFS(dvp
->v_mount
);
99 ip
->ino
= ++chmp
->chm_max_vno
;
101 mutex_enter(&chmp
->chm_lock_vnocache
);
102 chvc
= chfs_vnode_cache_get(chmp
, ip
->ino
);
103 mutex_exit(&chmp
->chm_lock_vnocache
);
105 /* We cannot be requesting the parent directory of the root node. */
106 KASSERT(IMPLIES(ip
->ch_type
== CHT_DIR
&& chvc
->pvno
== chvc
->vno
,
107 !(cnp
->cn_flags
& ISDOTDOT
)));
109 if (cnp
->cn_flags
& ISDOTDOT
) {
111 error
= VFS_VGET(dvp
->v_mount
, ip
->chvc
->pvno
, vpp
);
112 vn_lock(dvp
, LK_EXCLUSIVE
| LK_RETRY
);
113 } else if (cnp
->cn_namelen
== 1 && cnp
->cn_nameptr
[0] == '.') {
118 fd
= chfs_dir_lookup(ip
, cnp
);
122 /* The entry was not found in the directory.
123 * This is OK if we are creating or renaming an
124 * entry and are working on the last component of
126 if ((cnp
->cn_flags
& ISLASTCN
) && (cnp
->cn_nameiop
== CREATE
127 || cnp
->cn_nameiop
== RENAME
)) {
128 error
= VOP_ACCESS(dvp
, VWRITE
, cnp
->cn_cred
);
130 dbg("after the entry was not found in dir\n");
134 dbg("return EJUSTRETURN\n");
140 /* If we are not at the last path component and
141 * found a non-directory or non-link entry (which
142 * may itself be pointing to a directory), raise
144 if ((fd
->type
!= CHT_DIR
&& fd
->type
!= CHT_LNK
) && !(cnp
->cn_flags
150 dbg("vno@allocating new vnode: %llu\n",
151 (unsigned long long)fd
->vno
);
152 error
= VFS_VGET(dvp
->v_mount
, fd
->vno
, vpp
);
155 /* Store the result of this lookup in the cache. Avoid this if the
156 * request was for creation, as it does not improve timings on
158 if (cnp
->cn_nameiop
!= CREATE
&& (cnp
->cn_flags
& ISDOTDOT
) == 0) {
159 cache_enter(dvp
, *vpp
, cnp
->cn_nameptr
, cnp
->cn_namelen
,
164 /* If there were no errors, *vpp cannot be null and it must be
166 KASSERT(IFF(error
== 0, *vpp
!= NULL
&& VOP_ISLOCKED(*vpp
)));
167 KASSERT(VOP_ISLOCKED(dvp
));
172 /* --------------------------------------------------------------------- */
177 struct vop_create_args
/* {
179 struct vnode **a_vpp;
180 struct componentname *a_cnp;
186 mode
= MAKEIMODE(ap
->a_vap
->va_type
, ap
->a_vap
->va_mode
);
188 if ((mode
& IFMT
) == 0) {
189 if (ap
->a_vap
->va_type
== VREG
)
191 if (ap
->a_vap
->va_type
== VSOCK
)
195 error
= chfs_makeinode(mode
, ap
->a_dvp
, ap
->a_vpp
, ap
->a_cnp
, ap
->a_vap
->va_type
);
198 dbg("error: %d\n", error
);
202 VN_KNOTE(ap
->a_dvp
, NOTE_WRITE
);
205 /* --------------------------------------------------------------------- */
210 struct vnode
*dvp
= ((struct vop_mknod_args
*) v
)->a_dvp
;
211 struct vnode
**vpp
= ((struct vop_mknod_args
*) v
)->a_vpp
;
212 struct componentname
*cnp
= ((struct vop_mknod_args
*) v
)->a_cnp
;
213 struct vattr
*vap
= ((struct vop_mknod_args
*) v
)->a_vap
;
215 struct chfs_inode
*ip
;
218 struct ufsmount
*ump
;
219 struct chfs_mount
*chmp
;
221 struct chfs_full_dnode
*fd
;
226 ump
= VFSTOUFS(dvp
->v_mount
);
229 /* Check type of node. */
230 if (vap
->va_type
!= VBLK
&& vap
->va_type
!= VCHR
&& vap
->va_type
!= VFIFO
)
235 mode
= MAKEIMODE(vap
->va_type
, vap
->va_mode
);
237 if ((mode
& IFMT
) == 0) {
238 switch (vap
->va_type
) {
253 /* Create a new node. */
254 err
= chfs_makeinode(mode
, dvp
, &vp
, cnp
, vap
->va_type
);
257 if (vap
->va_rdev
!= VNOVAL
)
258 ip
->rdev
= vap
->va_rdev
;
260 if (vap
->va_type
== VFIFO
)
261 vp
->v_op
= chfs_fifoop_p
;
263 vp
->v_op
= chfs_specop_p
;
264 spec_node_init(vp
, ip
->rdev
);
270 /* Device is written out as a data node. */
272 chfs_set_vnode_size(vp
, len
);
273 bp
= getiobuf(vp
, true);
274 bp
->b_bufsize
= bp
->b_resid
= len
;
275 bp
->b_data
= kmem_alloc(len
, KM_SLEEP
);
276 memcpy(bp
->b_data
, &ip
->rdev
, len
);
279 fd
= chfs_alloc_full_dnode();
281 mutex_enter(&chmp
->chm_lock_mountfields
);
283 err
= chfs_write_flash_dnode(chmp
, vp
, bp
, fd
);
285 mutex_exit(&chmp
->chm_lock_mountfields
);
286 kmem_free(bp
->b_data
, len
);
290 /* Add data node to the inode. */
291 err
= chfs_add_full_dnode_to_inode(chmp
, ip
, fd
);
293 mutex_exit(&chmp
->chm_lock_mountfields
);
294 kmem_free(bp
->b_data
, len
);
298 mutex_exit(&chmp
->chm_lock_mountfields
);
301 kmem_free(bp
->b_data
, len
);
307 /* --------------------------------------------------------------------- */
312 struct vnode
*vp
= ((struct vop_open_args
*) v
)->a_vp
;
313 int mode
= ((struct vop_open_args
*) v
)->a_mode
;
317 struct chfs_inode
*ip
;
319 KASSERT(VOP_ISLOCKED(vp
));
323 KASSERT(vp
->v_size
== ip
->size
);
324 if (ip
->chvc
->nlink
< 1) {
329 /* If the file is marked append-only, deny write requests. */
330 if (ip
->flags
& APPEND
&& (mode
& (FWRITE
| O_APPEND
)) == FWRITE
)
336 KASSERT(VOP_ISLOCKED(vp
));
340 /* --------------------------------------------------------------------- */
345 struct vnode
*vp
= ((struct vop_close_args
*) v
)->a_vp
;
348 struct chfs_inode
*ip
;
350 KASSERT(VOP_ISLOCKED(vp
));
354 if (ip
->chvc
->nlink
> 0) {
355 chfs_update(vp
, NULL
, NULL
, UPDATE_CLOSE
);
361 /* --------------------------------------------------------------------- */
366 struct vnode
*vp
= ((struct vop_access_args
*) v
)->a_vp
;
367 int mode
= ((struct vop_access_args
*) v
)->a_mode
;
368 kauth_cred_t cred
= ((struct vop_access_args
*) v
)->a_cred
;
371 struct chfs_inode
*ip
= VTOI(vp
);
374 switch (vp
->v_type
) {
378 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
391 if (mode
& VWRITE
&& ip
->flags
& IMMUTABLE
)
394 return kauth_authorize_vnode(cred
, KAUTH_ACCESS_ACTION(mode
, vp
->v_type
,
395 ip
->mode
& ALLPERMS
), vp
, NULL
, genfs_can_access(vp
->v_type
,
396 ip
->mode
& ALLPERMS
, ip
->uid
, ip
->gid
, mode
, cred
));
399 /* --------------------------------------------------------------------- */
402 chfs_getattr(void *v
)
404 struct vnode
*vp
= ((struct vop_getattr_args
*) v
)->a_vp
;
405 struct vattr
*vap
= ((struct vop_getattr_args
*) v
)->a_vap
;
407 struct chfs_inode
*ip
= VTOI(vp
);
410 KASSERT(vp
->v_size
== ip
->size
);
413 CHFS_ITIMES(ip
, NULL
, NULL
, NULL
);
415 vap
->va_type
= CHTTOVT(ip
->ch_type
);
416 vap
->va_mode
= ip
->mode
& ALLPERMS
;
417 vap
->va_nlink
= ip
->chvc
->nlink
;
418 vap
->va_uid
= ip
->uid
;
419 vap
->va_gid
= ip
->gid
;
420 vap
->va_fsid
= ip
->dev
;
421 vap
->va_fileid
= ip
->ino
;
422 vap
->va_size
= ip
->size
;
423 vap
->va_blocksize
= PAGE_SIZE
;
424 vap
->va_atime
.tv_sec
= ip
->atime
;
425 vap
->va_atime
.tv_nsec
= 0;
426 vap
->va_mtime
.tv_sec
= ip
->mtime
;
427 vap
->va_mtime
.tv_nsec
= 0;
428 vap
->va_ctime
.tv_sec
= ip
->ctime
;
429 vap
->va_ctime
.tv_nsec
= 0;
430 vap
->va_gen
= ip
->version
;
431 vap
->va_flags
= ip
->flags
;
432 vap
->va_rdev
= ip
->rdev
;
433 vap
->va_bytes
= round_page(ip
->size
);
434 vap
->va_filerev
= VNOVAL
;
436 vap
->va_spare
= VNOVAL
;
441 /* --------------------------------------------------------------------- */
443 /* Note: modelled after tmpfs's same function */
446 chfs_setattr(void *v
)
448 struct vnode
*vp
= ((struct vop_setattr_args
*) v
)->a_vp
;
449 struct vattr
*vap
= ((struct vop_setattr_args
*) v
)->a_vap
;
450 kauth_cred_t cred
= ((struct vop_setattr_args
*) v
)->a_cred
;
452 struct chfs_inode
*ip
;
453 struct ufsmount
*ump
= VFSTOUFS(vp
->v_mount
);
454 struct chfs_mount
*chmp
= ump
->um_chfs
;
459 KASSERT(VOP_ISLOCKED(vp
));
462 /* Abort if any unsettable attribute is given. */
463 if (vap
->va_type
!= VNON
|| vap
->va_nlink
!= VNOVAL
||
464 vap
->va_fsid
!= VNOVAL
|| vap
->va_fileid
!= VNOVAL
||
465 vap
->va_blocksize
!= VNOVAL
/*|| GOODTIME(&vap->va_ctime)*/ ||
466 vap
->va_gen
!= VNOVAL
|| vap
->va_rdev
!= VNOVAL
||
467 vap
->va_bytes
!= VNOVAL
) {
472 if (error
== 0 && (vap
->va_flags
!= VNOVAL
)) {
473 error
= chfs_chflags(vp
, vap
->va_flags
, cred
);
477 if (ip
->flags
& (IMMUTABLE
| APPEND
)) {
483 if (error
== 0 && (vap
->va_size
!= VNOVAL
)) {
484 error
= chfs_chsize(vp
, vap
->va_size
, cred
);
490 if (error
== 0 && (vap
->va_uid
!= VNOVAL
|| vap
->va_gid
!= VNOVAL
)) {
491 error
= chfs_chown(vp
, vap
->va_uid
, vap
->va_gid
, cred
);
497 if (error
== 0 && (vap
->va_mode
!= VNOVAL
)) {
498 error
= chfs_chmod(vp
, vap
->va_mode
, cred
);
504 if (vap
->va_atime
.tv_sec
!= VNOVAL
|| vap
->va_mtime
.tv_sec
!= VNOVAL
) {
505 error
= kauth_authorize_vnode(cred
, KAUTH_VNODE_WRITE_TIMES
, vp
,
506 NULL
, genfs_can_chtimes(vp
, vap
->va_vaflags
, ip
->uid
, cred
));
509 if (vap
->va_atime
.tv_sec
!= VNOVAL
)
510 ip
->iflag
|= IN_ACCESS
;
511 if (vap
->va_mtime
.tv_sec
!= VNOVAL
)
512 ip
->iflag
|= IN_CHANGE
| IN_UPDATE
;
513 error
= chfs_update(vp
,
514 &vap
->va_atime
, &vap
->va_mtime
, UPDATE_WAIT
);
520 mutex_enter(&chmp
->chm_lock_mountfields
);
521 error
= chfs_write_flash_vnode(chmp
, ip
, ALLOC_NORMAL
);
522 mutex_exit(&chmp
->chm_lock_mountfields
);
528 chfs_chmod(struct vnode
*vp
, int mode
, kauth_cred_t cred
)
530 struct chfs_inode
*ip
= VTOI(vp
);
534 error
= kauth_authorize_vnode(cred
, KAUTH_VNODE_WRITE_SECURITY
, vp
,
535 NULL
, genfs_can_chmod(vp
->v_type
, cred
, ip
->uid
, ip
->gid
, mode
));
538 ip
->mode
&= ~ALLPERMS
;
539 ip
->mode
|= (mode
& ALLPERMS
);
540 ip
->iflag
|= IN_CHANGE
;
542 error
= chfs_update(vp
, NULL
, NULL
, UPDATE_WAIT
);
550 chfs_chown(struct vnode
*vp
, uid_t uid
, gid_t gid
, kauth_cred_t cred
)
552 struct chfs_inode
*ip
= VTOI(vp
);
556 if (uid
== (uid_t
)VNOVAL
)
558 if (gid
== (gid_t
)VNOVAL
)
561 error
= kauth_authorize_vnode(cred
, KAUTH_VNODE_CHANGE_OWNERSHIP
, vp
,
562 NULL
, genfs_can_chown(cred
, ip
->uid
, ip
->gid
, uid
, gid
));
568 ip
->iflag
|= IN_CHANGE
;
570 error
= chfs_update(vp
, NULL
, NULL
, UPDATE_WAIT
);
578 /* --------------------------------------------------------------------- */
579 /* calculates ((off_t)blk * chmp->chm_chm_fs_bsize) */
580 #define chfs_lblktosize(chmp, blk) \
581 (((off_t)(blk)) << (chmp)->chm_fs_bshift)
583 /* calculates (loc % chmp->chm_chm_fs_bsize) */
584 #define chfs_blkoff(chmp, loc) \
585 ((loc) & (chmp)->chm_fs_qbmask)
587 /* calculates (loc / chmp->chm_chm_fs_bsize) */
588 #define chfs_lblkno(chmp, loc) \
589 ((loc) >> (chmp)->chm_fs_bshift)
591 /* calculates roundup(size, chmp->chm_chm_fs_fsize) */
592 #define chfs_fragroundup(chmp, size) \
593 (((size) + (chmp)->chm_fs_qfmask) & (chmp)->chm_fs_fmask)
595 #define chfs_blksize(chmp, ip, lbn) \
596 (((lbn) >= UFS_NDADDR || (ip)->size >= chfs_lblktosize(chmp, (lbn) + 1)) \
597 ? (chmp)->chm_fs_bsize \
598 : (chfs_fragroundup(chmp, chfs_blkoff(chmp, (ip)->size))))
600 /* calculates roundup(size, chmp->chm_chm_fs_bsize) */
601 #define chfs_blkroundup(chmp, size) \
602 (((size) + (chmp)->chm_fs_qbmask) & (chmp)->chm_fs_bmask)
608 struct vop_read_args
/* {
615 struct chfs_inode
*ip
;
617 struct ufsmount
*ump
;
619 struct chfs_mount
*chmp
;
620 daddr_t lbn
, nextlbn
;
622 long size
, xfersize
, blkoffset
;
633 ioflag
= ap
->a_ioflag
;
636 dbg("ip->size:%llu\n", (unsigned long long)ip
->size
);
639 if (uio
->uio_rw
!= UIO_READ
)
640 panic("%s: mode", READ_S
);
642 if (vp
->v_type
== VLNK
) {
643 if (ip
->size
< ump
->um_maxsymlinklen
)
644 panic("%s: short symlink", READ_S
);
645 } else if (vp
->v_type
!= VREG
&& vp
->v_type
!= VDIR
)
646 panic("%s: type %d", READ_S
, vp
->v_type
);
649 if ((u_int64_t
)uio
->uio_offset
> ump
->um_maxfilesize
)
651 if (uio
->uio_resid
== 0)
654 fstrans_start(vp
->v_mount
, FSTRANS_SHARED
);
656 if (uio
->uio_offset
>= ip
->size
)
659 usepc
= vp
->v_type
== VREG
;
662 const int advice
= IO_ADV_DECODE(ap
->a_ioflag
);
664 while (uio
->uio_resid
> 0) {
665 if (ioflag
& IO_DIRECT
) {
666 genfs_directio(vp
, uio
, ioflag
);
668 bytelen
= MIN(ip
->size
- uio
->uio_offset
,
672 error
= ubc_uiomove(&vp
->v_uobj
, uio
, bytelen
, advice
,
673 UBC_READ
| UBC_PARTIALOK
|
674 (UBC_WANT_UNMAP(vp
) ? UBC_UNMAP
: 0));
682 dbg("start reading\n");
683 for (error
= 0, bp
= NULL
; uio
->uio_resid
> 0; bp
= NULL
) {
684 bytesinfile
= ip
->size
- uio
->uio_offset
;
685 if (bytesinfile
<= 0)
687 lbn
= chfs_lblkno(chmp
, uio
->uio_offset
);
689 size
= chfs_blksize(chmp
, ip
, lbn
);
690 blkoffset
= chfs_blkoff(chmp
, uio
->uio_offset
);
691 xfersize
= MIN(MIN(chmp
->chm_fs_bsize
- blkoffset
, uio
->uio_resid
),
694 if (chfs_lblktosize(chmp
, nextlbn
) >= ip
->size
) {
695 error
= bread(vp
, lbn
, size
, NOCRED
, 0, &bp
);
696 dbg("after bread\n");
698 int nextsize
= chfs_blksize(chmp
, ip
, nextlbn
);
699 dbg("size: %ld\n", size
);
700 error
= breadn(vp
, lbn
,
701 size
, &nextlbn
, &nextsize
, 1, NOCRED
, 0, &bp
);
702 dbg("after breadN\n");
708 * We should only get non-zero b_resid when an I/O error
709 * has occurred, which should cause us to break above.
710 * However, if the short read did not cause an error,
711 * then we want to ensure that we do not uiomove bad
712 * or uninitialized data.
715 if (size
< xfersize
) {
721 error
= uiomove((char *)bp
->b_data
+ blkoffset
, xfersize
, uio
);
732 ip
->ino
= ip
->chvc
->vno
;
734 if (!(vp
->v_mount
->mnt_flag
& MNT_NOATIME
)) {
735 ip
->iflag
|= IN_ACCESS
;
736 if ((ap
->a_ioflag
& IO_SYNC
) == IO_SYNC
) {
738 fstrans_done(vp
->v_mount
);
741 error
= chfs_update(vp
, NULL
, NULL
, UPDATE_WAIT
);
746 fstrans_done(vp
->v_mount
);
752 /* --------------------------------------------------------------------- */
758 struct vop_write_args
/* {
766 struct chfs_inode
*ip
;
767 struct chfs_mount
*chmp
;
770 off_t osize
, origoff
, oldoff
, preallocoff
, endallocoff
, nsize
;
771 int blkoffset
, error
, flags
, ioflag
, resid
;
776 struct ufsmount
*ump
;
780 ioflag
= ap
->a_ioflag
;
788 KASSERT(vp
->v_size
== ip
->size
);
790 switch (vp
->v_type
) {
792 if (ioflag
& IO_APPEND
)
793 uio
->uio_offset
= ip
->size
;
794 if ((ip
->flags
& APPEND
) && uio
->uio_offset
!= ip
->size
)
800 if ((ioflag
& IO_SYNC
) == 0)
801 panic("chfs_write: nonsync dir write");
804 panic("chfs_write: type");
808 if (uio
->uio_offset
< 0 ||
809 (u_int64_t
)uio
->uio_offset
+
810 uio
->uio_resid
> ump
->um_maxfilesize
) {
811 dbg("uio->uio_offset = %lld | uio->uio_offset + "
812 "uio->uio_resid (%llu) > ump->um_maxfilesize (%lld)\n",
813 (long long)uio
->uio_offset
,
814 (uint64_t)uio
->uio_offset
+ uio
->uio_resid
,
815 (long long)ump
->um_maxfilesize
);
819 * Maybe this should be above the vnode op call, but so long as
820 * file servers have no limits, I don't think it matters.
823 if (vp
->v_type
== VREG
&& l
&&
824 uio
->uio_offset
+ uio
->uio_resid
>
825 l
->l_proc
->p_rlimit
[RLIMIT_FSIZE
].rlim_cur
) {
826 mutex_enter(proc_lock
);
827 psignal(l
->l_proc
, SIGXFSZ
);
828 mutex_exit(proc_lock
);
831 if (uio
->uio_resid
== 0)
834 fstrans_start(vp
->v_mount
, FSTRANS_SHARED
);
836 flags
= ioflag
& IO_SYNC
? B_SYNC
: 0;
837 async
= vp
->v_mount
->mnt_flag
& MNT_ASYNC
;
838 origoff
= uio
->uio_offset
;
839 resid
= uio
->uio_resid
;
843 preallocoff
= round_page(chfs_blkroundup(chmp
,
844 MAX(osize
, uio
->uio_offset
)));
845 aflag
= ioflag
& IO_SYNC
? B_SYNC
: 0;
846 nsize
= MAX(osize
, uio
->uio_offset
+ uio
->uio_resid
);
847 endallocoff
= nsize
- chfs_blkoff(chmp
, nsize
);
850 * if we're increasing the file size, deal with expanding
851 * the fragment if there is one.
854 if (nsize
> osize
&& chfs_lblkno(chmp
, osize
) < UFS_NDADDR
&&
855 chfs_lblkno(chmp
, osize
) != chfs_lblkno(chmp
, nsize
) &&
856 chfs_blkroundup(chmp
, osize
) != osize
) {
859 eob
= chfs_blkroundup(chmp
, osize
);
860 uvm_vnp_setwritesize(vp
, eob
);
861 error
= ufs_balloc_range(vp
, osize
, eob
- osize
, cred
, aflag
);
864 if (flags
& B_SYNC
) {
865 mutex_enter(vp
->v_interlock
);
867 trunc_page(osize
& chmp
->chm_fs_bmask
),
869 PGO_CLEANIT
| PGO_SYNCIO
| PGO_JOURNALLOCKED
);
873 while (uio
->uio_resid
> 0) {
874 int ubc_flags
= UBC_WRITE
;
875 bool overwrite
; /* if we're overwrite a whole block */
878 if (ioflag
& IO_DIRECT
) {
879 genfs_directio(vp
, uio
, ioflag
| IO_JOURNALLOCKED
);
882 oldoff
= uio
->uio_offset
;
883 blkoffset
= chfs_blkoff(chmp
, uio
->uio_offset
);
884 bytelen
= MIN(chmp
->chm_fs_bsize
- blkoffset
, uio
->uio_resid
);
890 * if we're filling in a hole, allocate the blocks now and
891 * initialize the pages first. if we're extending the file,
892 * we can safely allocate blocks without initializing pages
893 * since the new blocks will be inaccessible until the write
896 overwrite
= uio
->uio_offset
>= preallocoff
&&
897 uio
->uio_offset
< endallocoff
;
898 if (!overwrite
&& (vp
->v_vflag
& VV_MAPPED
) == 0 &&
899 chfs_blkoff(chmp
, uio
->uio_offset
) == 0 &&
900 (uio
->uio_offset
& PAGE_MASK
) == 0) {
903 len
= trunc_page(bytelen
);
904 len
-= chfs_blkoff(chmp
, len
);
911 newoff
= oldoff
+ bytelen
;
912 if (vp
->v_size
< newoff
) {
913 uvm_vnp_setwritesize(vp
, newoff
);
917 error
= ufs_balloc_range(vp
, uio
->uio_offset
, bytelen
,
922 genfs_node_wrlock(vp
);
923 error
= GOP_ALLOC(vp
, uio
->uio_offset
, bytelen
,
925 genfs_node_unlock(vp
);
928 ubc_flags
|= UBC_FAULTBUSY
;
935 ubc_flags
|= UBC_WANT_UNMAP(vp
) ? UBC_UNMAP
: 0;
936 error
= ubc_uiomove(&vp
->v_uobj
, uio
, bytelen
,
937 IO_ADV_DECODE(ioflag
), ubc_flags
);
940 * update UVM's notion of the size now that we've
941 * copied the data into the vnode's pages.
943 * we should update the size even when uiomove failed.
946 if (vp
->v_size
< newoff
) {
947 uvm_vnp_setsize(vp
, newoff
);
955 * flush what we just wrote if necessary.
956 * XXXUBC simplistic async flushing.
959 if (!async
&& oldoff
>> 16 != uio
->uio_offset
>> 16) {
960 mutex_enter(vp
->v_interlock
);
961 error
= VOP_PUTPAGES(vp
, (oldoff
>> 16) << 16,
962 (uio
->uio_offset
>> 16) << 16,
963 PGO_CLEANIT
| PGO_JOURNALLOCKED
);
969 if (error
== 0 && ioflag
& IO_SYNC
) {
970 mutex_enter(vp
->v_interlock
);
971 error
= VOP_PUTPAGES(vp
,
972 trunc_page(origoff
& chmp
->chm_fs_bmask
),
973 round_page(chfs_blkroundup(chmp
, uio
->uio_offset
)),
974 PGO_CLEANIT
| PGO_SYNCIO
| PGO_JOURNALLOCKED
);
976 ip
->iflag
|= IN_CHANGE
| IN_UPDATE
;
977 if (resid
> uio
->uio_resid
&& ap
->a_cred
) {
978 if (ip
->mode
& ISUID
) {
979 if (kauth_authorize_vnode(ap
->a_cred
,
980 KAUTH_VNODE_RETAIN_SUID
, vp
, NULL
, EPERM
) != 0)
984 if (ip
->mode
& ISGID
) {
985 if (kauth_authorize_vnode(ap
->a_cred
,
986 KAUTH_VNODE_RETAIN_SGID
, vp
, NULL
, EPERM
) != 0)
990 if (resid
> uio
->uio_resid
)
991 VN_KNOTE(vp
, NOTE_WRITE
| (extended
? NOTE_EXTEND
: 0));
993 (void) UFS_TRUNCATE(vp
, osize
, ioflag
& IO_SYNC
, ap
->a_cred
);
994 uio
->uio_offset
-= resid
- uio
->uio_resid
;
995 uio
->uio_resid
= resid
;
996 } else if (resid
> uio
->uio_resid
&& (ioflag
& IO_SYNC
) == IO_SYNC
)
997 error
= UFS_UPDATE(vp
, NULL
, NULL
, UPDATE_WAIT
);
1000 chfs_set_vnode_size(vp
, vp
->v_size
);
1003 KASSERT(vp
->v_size
== ip
->size
);
1004 fstrans_done(vp
->v_mount
);
1006 mutex_enter(&chmp
->chm_lock_mountfields
);
1007 error
= chfs_write_flash_vnode(chmp
, ip
, ALLOC_NORMAL
);
1008 mutex_exit(&chmp
->chm_lock_mountfields
);
1014 /* --------------------------------------------------------------------- */
1019 struct vop_fsync_args
/* {
1021 kauth_cred_t a_cred;
1026 struct vnode
*vp
= ap
->a_vp
;
1028 if (ap
->a_flags
& FSYNC_CACHE
) {
1031 vflushbuf(vp
, ap
->a_flags
);
1036 /* --------------------------------------------------------------------- */
1039 chfs_remove(void *v
)
1041 struct vnode
*dvp
= ((struct vop_remove_args
*) v
)->a_dvp
;
1042 struct vnode
*vp
= ((struct vop_remove_args
*) v
)->a_vp
;
1043 struct componentname
*cnp
= (((struct vop_remove_args
*) v
)->a_cnp
);
1046 KASSERT(VOP_ISLOCKED(dvp
));
1047 KASSERT(VOP_ISLOCKED(vp
));
1049 struct chfs_inode
*ip
= VTOI(vp
);
1050 struct chfs_inode
*parent
= VTOI(dvp
);
1053 if (vp
->v_type
== VDIR
|| (ip
->flags
& (IMMUTABLE
| APPEND
)) ||
1054 (parent
->flags
& APPEND
)) {
1059 KASSERT(ip
->chvc
->vno
!= ip
->chvc
->pvno
);
1061 error
= chfs_do_unlink(ip
,
1062 parent
, cnp
->cn_nameptr
, cnp
->cn_namelen
);
1071 /* --------------------------------------------------------------------- */
1076 struct vnode
*dvp
= ((struct vop_link_args
*) v
)->a_dvp
;
1077 struct vnode
*vp
= ((struct vop_link_args
*) v
)->a_vp
;
1078 struct componentname
*cnp
= ((struct vop_link_args
*) v
)->a_cnp
;
1080 struct chfs_inode
*ip
, *parent
;
1083 if (vp
->v_type
== VDIR
) {
1084 VOP_ABORTOP(dvp
, cnp
);
1088 if (dvp
->v_mount
!= vp
->v_mount
) {
1089 VOP_ABORTOP(dvp
, cnp
);
1093 if (dvp
!= vp
&& (error
= vn_lock(vp
, LK_EXCLUSIVE
))) {
1094 VOP_ABORTOP(dvp
, cnp
);
1101 error
= chfs_do_link(ip
,
1102 parent
, cnp
->cn_nameptr
, cnp
->cn_namelen
, ip
->ch_type
);
1111 /* --------------------------------------------------------------------- */
1114 chfs_rename(void *v
)
1116 struct vnode
*fdvp
= ((struct vop_rename_args
*) v
)->a_fdvp
;
1117 struct vnode
*fvp
= ((struct vop_rename_args
*) v
)->a_fvp
;
1118 struct componentname
*fcnp
= ((struct vop_rename_args
*) v
)->a_fcnp
;
1119 struct vnode
*tdvp
= ((struct vop_rename_args
*) v
)->a_tdvp
;
1120 struct vnode
*tvp
= ((struct vop_rename_args
*) v
)->a_tvp
;
1121 struct componentname
*tcnp
= ((struct vop_rename_args
*) v
)->a_tcnp
;
1123 struct chfs_inode
*oldparent
, *old
;
1124 struct chfs_inode
*newparent
;
1125 struct chfs_dirent
*fd
;
1126 struct chfs_inode
*ip
;
1130 KASSERT(VOP_ISLOCKED(tdvp
));
1131 KASSERT(IMPLIES(tvp
!= NULL
, VOP_ISLOCKED(tvp
) == LK_EXCLUSIVE
));
1133 oldparent
= VTOI(fdvp
);
1135 newparent
= VTOI(tdvp
);
1137 dbg("tvp not null\n");
1139 if (tvp
->v_type
== VDIR
) {
1140 TAILQ_FOREACH(fd
, &ip
->dents
, fds
) {
1147 error
= chfs_do_unlink(ip
,
1148 newparent
, tcnp
->cn_nameptr
, tcnp
->cn_namelen
);
1151 VFS_VGET(tdvp
->v_mount
, old
->ino
, &tvp
);
1155 error
= chfs_do_link(ip
,
1156 newparent
, tcnp
->cn_nameptr
, tcnp
->cn_namelen
, ip
->ch_type
);
1158 error
= chfs_do_unlink(old
,
1159 oldparent
, fcnp
->cn_nameptr
, fcnp
->cn_namelen
);
1162 /* Release target nodes. */
1170 /* Release source nodes. */
1177 /* --------------------------------------------------------------------- */
1182 struct vnode
*dvp
= ((struct vop_mkdir_args
*) v
)->a_dvp
;
1183 struct vnode
**vpp
= ((struct vop_mkdir_args
*)v
)->a_vpp
;
1184 struct componentname
*cnp
= ((struct vop_mkdir_args
*) v
)->a_cnp
;
1185 struct vattr
*vap
= ((struct vop_mkdir_args
*) v
)->a_vap
;
1190 mode
= vap
->va_mode
& ACCESSPERMS
;
1191 if ((mode
& IFMT
) == 0) {
1195 KASSERT(vap
->va_type
== VDIR
);
1197 return chfs_makeinode(mode
, dvp
, vpp
, cnp
, VDIR
);
1200 /* --------------------------------------------------------------------- */
1205 struct vnode
*dvp
= ((struct vop_rmdir_args
*) v
)->a_dvp
;
1206 struct vnode
*vp
= ((struct vop_rmdir_args
*) v
)->a_vp
;
1207 struct componentname
*cnp
= ((struct vop_rmdir_args
*) v
)->a_cnp
;
1210 KASSERT(VOP_ISLOCKED(dvp
));
1211 KASSERT(VOP_ISLOCKED(vp
));
1213 struct chfs_inode
*ip
= VTOI(vp
);
1214 struct chfs_inode
*parent
= VTOI(dvp
);
1215 struct chfs_dirent
*fd
;
1218 if (vp
->v_type
!= VDIR
) {
1223 KASSERT(ip
->chvc
->vno
!= ip
->chvc
->pvno
);
1225 TAILQ_FOREACH(fd
, &ip
->dents
, fds
) {
1232 error
= chfs_do_unlink(ip
,
1233 parent
, cnp
->cn_nameptr
, cnp
->cn_namelen
);
1242 /* --------------------------------------------------------------------- */
1245 chfs_symlink(void *v
)
1247 struct vnode
*dvp
= ((struct vop_symlink_args
*) v
)->a_dvp
;
1248 struct vnode
**vpp
= ((struct vop_symlink_args
*) v
)->a_vpp
;
1249 struct componentname
*cnp
= ((struct vop_symlink_args
*) v
)->a_cnp
;
1250 struct vattr
*vap
= ((struct vop_symlink_args
*) v
)->a_vap
;
1251 char *target
= ((struct vop_symlink_args
*) v
)->a_target
;
1253 struct ufsmount
*ump
;
1254 struct chfs_mount
*chmp
;
1256 struct chfs_inode
*ip
;
1258 struct chfs_full_dnode
*fd
;
1262 ump
= VFSTOUFS(dvp
->v_mount
);
1263 chmp
= ump
->um_chfs
;
1265 err
= chfs_makeinode(IFLNK
| vap
->va_mode
, dvp
, vpp
, cnp
, VLNK
);
1268 VN_KNOTE(dvp
, NOTE_WRITE
);
1270 len
= strlen(target
);
1272 /* TODO max symlink len instead of "100" */
1274 /* symlink path stored as a data node */
1275 ip
->target
= kmem_alloc(len
, KM_SLEEP
);
1276 memcpy(ip
->target
, target
, len
);
1277 chfs_set_vnode_size(vp
, len
);
1278 ip
->iflag
|= IN_CHANGE
| IN_UPDATE
;
1280 bp
= getiobuf(vp
, true);
1281 bp
->b_bufsize
= bp
->b_resid
= len
;
1282 bp
->b_data
= kmem_alloc(len
, KM_SLEEP
);
1283 memcpy(bp
->b_data
, target
, len
);
1286 fd
= chfs_alloc_full_dnode();
1288 mutex_enter(&chmp
->chm_lock_mountfields
);
1290 /* write out the data node */
1291 err
= chfs_write_flash_dnode(chmp
, vp
, bp
, fd
);
1293 mutex_exit(&chmp
->chm_lock_mountfields
);
1297 /* add it to the inode */
1298 err
= chfs_add_full_dnode_to_inode(chmp
, ip
, fd
);
1300 mutex_exit(&chmp
->chm_lock_mountfields
);
1304 mutex_exit(&chmp
->chm_lock_mountfields
);
1306 kmem_free(bp
->b_data
, len
);
1309 uvm_vnp_setsize(vp
, len
);
1311 err
= vn_rdwr(UIO_WRITE
, vp
, target
, len
, (off_t
)0,
1312 UIO_SYSSPACE
, IO_NODELOCKED
, cnp
->cn_cred
,
1323 /* --------------------------------------------------------------------- */
1326 chfs_readdir(void *v
)
1328 struct vnode
*vp
= ((struct vop_readdir_args
*) v
)->a_vp
;
1329 struct uio
*uio
= ((struct vop_readdir_args
*) v
)->a_uio
;
1330 int *eofflag
= ((struct vop_readdir_args
*) v
)->a_eofflag
;
1334 struct chfs_inode
*ip
;
1335 struct chfs_dirent
*fd
;
1337 struct ufsmount
*ump
;
1338 struct chfs_mount
*chmp
;
1339 struct chfs_vnode_cache
*chvc
;
1341 KASSERT(VOP_ISLOCKED(vp
));
1343 /* This operation only makes sense on directory nodes. */
1344 if (vp
->v_type
!= VDIR
) {
1351 /* uiomove in chfs_filldir automatically increments the
1352 * uio_offset by an arbitrary size, so we discard any change
1353 * to uio_offset and set it to our own value on return
1355 offset
= uio
->uio_offset
;
1357 /* Add this entry. */
1358 if (offset
== CHFS_OFFSET_DOT
) {
1359 error
= chfs_filldir(uio
, ip
->ino
, ".", 1, CHT_DIR
);
1363 } else if (error
!= 0)
1366 offset
= CHFS_OFFSET_DOTDOT
;
1369 /* Add parent entry. */
1370 if (offset
== CHFS_OFFSET_DOTDOT
) {
1371 ump
= VFSTOUFS(vp
->v_mount
);
1372 chmp
= ump
->um_chfs
;
1373 mutex_enter(&chmp
->chm_lock_vnocache
);
1374 chvc
= chfs_vnode_cache_get(chmp
, ip
->ino
);
1375 mutex_exit(&chmp
->chm_lock_vnocache
);
1377 error
= chfs_filldir(uio
, chvc
->pvno
, "..", 2, CHT_DIR
);
1381 } else if (error
!= 0) {
1385 /* Has child or not? */
1386 if (TAILQ_EMPTY(&ip
->dents
)) {
1387 offset
= CHFS_OFFSET_EOF
;
1389 offset
= CHFS_OFFSET_FIRST
;
1393 if (offset
!= CHFS_OFFSET_EOF
) {
1394 /* Child entries. */
1395 skip
= offset
- CHFS_OFFSET_FIRST
;
1397 TAILQ_FOREACH(fd
, &ip
->dents
, fds
) {
1398 /* seek to offset by skipping items */
1399 /* XXX race conditions by changed dirent? */
1406 error
= chfs_filldir(uio
, fd
->vno
,
1407 fd
->name
, fd
->nsize
, fd
->type
);
1411 } else if (error
!= 0) {
1412 dbg("err %d\n", error
);
1419 offset
= CHFS_OFFSET_EOF
;
1422 uio
->uio_offset
= offset
;
1424 if (eofflag
!= NULL
) {
1425 *eofflag
= (error
== 0 &&
1426 uio
->uio_offset
== CHFS_OFFSET_EOF
);
1430 KASSERT(VOP_ISLOCKED(vp
));
1435 /* --------------------------------------------------------------------- */
1438 chfs_readlink(void *v
)
1441 struct vnode
*vp
= ((struct vop_readlink_args
*) v
)->a_vp
;
1442 struct uio
*uio
= ((struct vop_readlink_args
*) v
)->a_uio
;
1443 kauth_cred_t cred
= ((struct vop_readlink_args
*) v
)->a_cred
;
1445 struct chfs_inode
*ip
= VTOI(vp
);
1447 dbg("readlink()\n");
1449 /* TODO max symlink len instead of "100" */
1450 if (ip
->size
< 100) {
1451 uiomove(ip
->target
, ip
->size
, uio
);
1455 return (VOP_READ(vp
, uio
, 0, cred
));
1458 /* --------------------------------------------------------------------- */
1461 chfs_inactive(void *v
)
1463 struct vnode
*vp
= ((struct vop_inactive_args
*) v
)->a_vp
;
1464 struct chfs_inode
*ip
= VTOI(vp
);
1465 struct chfs_vnode_cache
*chvc
;
1466 dbg("inactive | vno: %llu\n", (unsigned long long)ip
->ino
);
1468 KASSERT(VOP_ISLOCKED(vp
));
1470 /* Reclaim only if there is no link to the node. */
1474 *((struct vop_inactive_args
*) v
)->a_recycle
= 0;
1476 *((struct vop_inactive_args
*) v
)->a_recycle
= 1;
1484 /* --------------------------------------------------------------------- */
1487 chfs_reclaim(void *v
)
1489 struct vop_reclaim_args
*ap
= v
;
1490 struct vnode
*vp
= ap
->a_vp
;
1491 struct chfs_inode
*ip
= VTOI(vp
);
1492 struct chfs_mount
*chmp
= ip
->chmp
;
1493 struct chfs_dirent
*fd
;
1495 mutex_enter(&chmp
->chm_lock_mountfields
);
1497 mutex_enter(&chmp
->chm_lock_vnocache
);
1498 ip
->chvc
->state
= VNO_STATE_CHECKEDABSENT
;
1499 mutex_exit(&chmp
->chm_lock_vnocache
);
1501 chfs_update(vp
, NULL
, NULL
, UPDATE_CLOSE
);
1503 /* Clean fragments. */
1504 chfs_kill_fragtree(chmp
, &ip
->fragtree
);
1506 /* Clean dirents. */
1507 fd
= TAILQ_FIRST(&ip
->dents
);
1509 TAILQ_REMOVE(&ip
->dents
, fd
, fds
);
1510 chfs_free_dirent(fd
);
1511 fd
= TAILQ_FIRST(&ip
->dents
);
1521 genfs_node_destroy(vp
);
1522 pool_put(&chfs_inode_pool
, vp
->v_data
);
1525 mutex_exit(&chmp
->chm_lock_mountfields
);
1530 /* --------------------------------------------------------------------- */
1533 chfs_advlock(void *v
)
1538 /* --------------------------------------------------------------------- */
1540 chfs_strategy(void *v
)
1542 struct vop_strategy_args
/* {
1543 const struct vnodeop_desc *a_desc;
1547 struct chfs_full_dnode
*fd
;
1548 struct buf
*bp
= ap
->a_bp
;
1549 struct vnode
*vp
= ap
->a_vp
;
1550 struct chfs_inode
*ip
= VTOI(vp
);
1551 struct chfs_mount
*chmp
= ip
->chmp
;
1552 int read
= (bp
->b_flags
& B_READ
) ? 1 : 0;
1556 err
= chfs_read_data(chmp
, vp
, bp
);
1558 mutex_enter(&chmp
->chm_lock_mountfields
);
1560 fd
= chfs_alloc_full_dnode();
1562 err
= chfs_write_flash_dnode(chmp
, vp
, bp
, fd
);
1564 mutex_exit(&chmp
->chm_lock_mountfields
);
1569 err
= chfs_add_full_dnode_to_inode(chmp
, ip
, fd
);
1571 mutex_exit(&chmp
->chm_lock_mountfields
);
1581 struct vop_bmap_args
/* {
1584 struct vnode **a_vpp;
1589 if (ap
->a_vpp
!= NULL
)
1590 *ap
->a_vpp
= ap
->a_vp
;
1591 if (ap
->a_bnp
!= NULL
)
1592 *ap
->a_bnp
= ap
->a_bn
;
1593 if (ap
->a_runp
!= NULL
)
1599 * vnode operations vector used for files stored in a chfs file system.
1602 (**chfs_vnodeop_p
)(void *);
1603 const struct vnodeopv_entry_desc chfs_vnodeop_entries
[] =
1605 { &vop_default_desc
, vn_default_error
},
1606 { &vop_lookup_desc
, chfs_lookup
},
1607 { &vop_create_desc
, chfs_create
},
1608 { &vop_mknod_desc
, chfs_mknod
},
1609 { &vop_open_desc
, chfs_open
},
1610 { &vop_close_desc
, chfs_close
},
1611 { &vop_access_desc
, chfs_access
},
1612 { &vop_getattr_desc
, chfs_getattr
},
1613 { &vop_setattr_desc
, chfs_setattr
},
1614 { &vop_read_desc
, chfs_read
},
1615 { &vop_write_desc
, chfs_write
},
1616 { &vop_ioctl_desc
, genfs_enoioctl
},
1617 { &vop_fcntl_desc
, genfs_fcntl
},
1618 { &vop_poll_desc
, genfs_poll
},
1619 { &vop_kqfilter_desc
, genfs_kqfilter
},
1620 { &vop_revoke_desc
, genfs_revoke
},
1621 { &vop_mmap_desc
, genfs_mmap
},
1622 { &vop_fsync_desc
, chfs_fsync
},
1623 { &vop_seek_desc
, genfs_seek
},
1624 { &vop_remove_desc
, chfs_remove
},
1625 { &vop_link_desc
, chfs_link
},
1626 { &vop_rename_desc
, chfs_rename
},
1627 { &vop_mkdir_desc
, chfs_mkdir
},
1628 { &vop_rmdir_desc
, chfs_rmdir
},
1629 { &vop_symlink_desc
, chfs_symlink
},
1630 { &vop_readdir_desc
, chfs_readdir
},
1631 { &vop_readlink_desc
, chfs_readlink
},
1632 { &vop_abortop_desc
, genfs_abortop
},
1633 { &vop_inactive_desc
, chfs_inactive
},
1634 { &vop_reclaim_desc
, chfs_reclaim
},
1635 { &vop_lock_desc
, genfs_lock
},
1636 { &vop_unlock_desc
, genfs_unlock
},
1637 { &vop_bmap_desc
, chfs_bmap
},
1638 { &vop_strategy_desc
, chfs_strategy
},
1639 { &vop_print_desc
, ufs_print
},
1640 { &vop_pathconf_desc
, ufs_pathconf
},
1641 { &vop_islocked_desc
, genfs_islocked
},
1642 { &vop_advlock_desc
, chfs_advlock
},
1643 { &vop_bwrite_desc
, vn_bwrite
},
1644 { &vop_getpages_desc
, genfs_getpages
},
1645 { &vop_putpages_desc
, genfs_putpages
},
1648 const struct vnodeopv_desc chfs_vnodeop_opv_desc
=
1649 { &chfs_vnodeop_p
, chfs_vnodeop_entries
};
1651 /* --------------------------------------------------------------------- */
1654 * vnode operations vector used for special devices stored in a chfs
1658 (**chfs_specop_p
)(void *);
1659 const struct vnodeopv_entry_desc chfs_specop_entries
[] =
1661 { &vop_default_desc
, vn_default_error
},
1662 { &vop_lookup_desc
, spec_lookup
},
1663 { &vop_create_desc
, spec_create
},
1664 { &vop_mknod_desc
, spec_mknod
},
1665 { &vop_open_desc
, spec_open
},
1666 { &vop_close_desc
, ufsspec_close
},
1667 { &vop_access_desc
, chfs_access
},
1668 { &vop_getattr_desc
, chfs_getattr
},
1669 { &vop_setattr_desc
, chfs_setattr
},
1670 { &vop_read_desc
, chfs_read
},
1671 { &vop_write_desc
, chfs_write
},
1672 { &vop_ioctl_desc
, spec_ioctl
},
1673 { &vop_fcntl_desc
, genfs_fcntl
},
1674 { &vop_poll_desc
, spec_poll
},
1675 { &vop_kqfilter_desc
, spec_kqfilter
},
1676 { &vop_revoke_desc
, spec_revoke
},
1677 { &vop_mmap_desc
, spec_mmap
},
1678 { &vop_fsync_desc
, spec_fsync
},
1679 { &vop_seek_desc
, spec_seek
},
1680 { &vop_remove_desc
, spec_remove
},
1681 { &vop_link_desc
, spec_link
},
1682 { &vop_rename_desc
, spec_rename
},
1683 { &vop_mkdir_desc
, spec_mkdir
},
1684 { &vop_rmdir_desc
, spec_rmdir
},
1685 { &vop_symlink_desc
, spec_symlink
},
1686 { &vop_readdir_desc
, spec_readdir
},
1687 { &vop_readlink_desc
, spec_readlink
},
1688 { &vop_abortop_desc
, spec_abortop
},
1689 { &vop_inactive_desc
, chfs_inactive
},
1690 { &vop_reclaim_desc
, chfs_reclaim
},
1691 { &vop_lock_desc
, genfs_lock
},
1692 { &vop_unlock_desc
, genfs_unlock
},
1693 { &vop_bmap_desc
, spec_bmap
},
1694 { &vop_strategy_desc
, spec_strategy
},
1695 { &vop_print_desc
, ufs_print
},
1696 { &vop_pathconf_desc
, spec_pathconf
},
1697 { &vop_islocked_desc
, genfs_islocked
},
1698 { &vop_advlock_desc
, spec_advlock
},
1699 { &vop_bwrite_desc
, vn_bwrite
},
1700 { &vop_getpages_desc
, spec_getpages
},
1701 { &vop_putpages_desc
, spec_putpages
},
1704 const struct vnodeopv_desc chfs_specop_opv_desc
=
1705 { &chfs_specop_p
, chfs_specop_entries
};
1707 /* --------------------------------------------------------------------- */
1709 * vnode operations vector used for fifos stored in a chfs file system.
1712 (**chfs_fifoop_p
)(void *);
1713 const struct vnodeopv_entry_desc chfs_fifoop_entries
[] =
1715 { &vop_default_desc
, vn_default_error
},
1716 { &vop_lookup_desc
, vn_fifo_bypass
},
1717 { &vop_create_desc
, vn_fifo_bypass
},
1718 { &vop_mknod_desc
, vn_fifo_bypass
},
1719 { &vop_open_desc
, vn_fifo_bypass
},
1720 { &vop_close_desc
, ufsfifo_close
},
1721 { &vop_access_desc
, chfs_access
},
1722 { &vop_getattr_desc
, chfs_getattr
},
1723 { &vop_setattr_desc
, chfs_setattr
},
1724 { &vop_read_desc
, ufsfifo_read
},
1725 { &vop_write_desc
, ufsfifo_write
},
1726 { &vop_ioctl_desc
, vn_fifo_bypass
},
1727 { &vop_fcntl_desc
, genfs_fcntl
},
1728 { &vop_poll_desc
, vn_fifo_bypass
},
1729 { &vop_kqfilter_desc
, vn_fifo_bypass
},
1730 { &vop_revoke_desc
, vn_fifo_bypass
},
1731 { &vop_mmap_desc
, vn_fifo_bypass
},
1732 { &vop_fsync_desc
, vn_fifo_bypass
},
1733 { &vop_seek_desc
, vn_fifo_bypass
},
1734 { &vop_remove_desc
, vn_fifo_bypass
},
1735 { &vop_link_desc
, vn_fifo_bypass
},
1736 { &vop_rename_desc
, vn_fifo_bypass
},
1737 { &vop_mkdir_desc
, vn_fifo_bypass
},
1738 { &vop_rmdir_desc
, vn_fifo_bypass
},
1739 { &vop_symlink_desc
, vn_fifo_bypass
},
1740 { &vop_readdir_desc
, vn_fifo_bypass
},
1741 { &vop_readlink_desc
, vn_fifo_bypass
},
1742 { &vop_abortop_desc
, vn_fifo_bypass
},
1743 { &vop_inactive_desc
, chfs_inactive
},
1744 { &vop_reclaim_desc
, chfs_reclaim
},
1745 { &vop_lock_desc
, genfs_lock
},
1746 { &vop_unlock_desc
, genfs_unlock
},
1747 { &vop_bmap_desc
, vn_fifo_bypass
},
1748 { &vop_strategy_desc
, vn_fifo_bypass
},
1749 { &vop_print_desc
, ufs_print
},
1750 { &vop_pathconf_desc
, vn_fifo_bypass
},
1751 { &vop_islocked_desc
, genfs_islocked
},
1752 { &vop_advlock_desc
, vn_fifo_bypass
},
1753 { &vop_bwrite_desc
, genfs_nullop
},
1754 { &vop_getpages_desc
, genfs_badop
},
1755 { &vop_putpages_desc
, vn_fifo_bypass
},
1758 const struct vnodeopv_desc chfs_fifoop_opv_desc
=
1759 { &chfs_fifoop_p
, chfs_fifoop_entries
};