1 /* $NetBSD: chfs_vnops.c,v 1.28 2015/04/20 23:03:09 riastradh 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_v2_args
*) v
)->a_dvp
;
57 struct vnode
**vpp
= ((struct vop_lookup_v2_args
*) v
)->a_vpp
;
58 struct componentname
*cnp
= ((struct vop_lookup_v2_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 return (*vpp
== NULLVP
? ENOENT
: 0);
95 ump
= VFSTOUFS(dvp
->v_mount
);
98 ip
->ino
= ++chmp
->chm_max_vno
;
100 mutex_enter(&chmp
->chm_lock_vnocache
);
101 chvc
= chfs_vnode_cache_get(chmp
, ip
->ino
);
102 mutex_exit(&chmp
->chm_lock_vnocache
);
104 /* We cannot be requesting the parent directory of the root node. */
105 KASSERT(IMPLIES(ip
->ch_type
== CHT_DIR
&& chvc
->pvno
== chvc
->vno
,
106 !(cnp
->cn_flags
& ISDOTDOT
)));
108 if (cnp
->cn_flags
& ISDOTDOT
) {
110 error
= VFS_VGET(dvp
->v_mount
, ip
->chvc
->pvno
, vpp
);
111 vn_lock(dvp
, LK_EXCLUSIVE
| LK_RETRY
);
112 } else if (cnp
->cn_namelen
== 1 && cnp
->cn_nameptr
[0] == '.') {
117 fd
= chfs_dir_lookup(ip
, cnp
);
121 /* The entry was not found in the directory.
122 * This is OK if we are creating or renaming an
123 * entry and are working on the last component of
125 if ((cnp
->cn_flags
& ISLASTCN
) && (cnp
->cn_nameiop
== CREATE
126 || cnp
->cn_nameiop
== RENAME
)) {
127 error
= VOP_ACCESS(dvp
, VWRITE
, cnp
->cn_cred
);
129 dbg("after the entry was not found in dir\n");
133 dbg("return EJUSTRETURN\n");
139 /* If we are not at the last path component and
140 * found a non-directory or non-link entry (which
141 * may itself be pointing to a directory), raise
143 if ((fd
->type
!= CHT_DIR
&& fd
->type
!= CHT_LNK
) && !(cnp
->cn_flags
149 dbg("vno@allocating new vnode: %llu\n",
150 (unsigned long long)fd
->vno
);
151 error
= VFS_VGET(dvp
->v_mount
, fd
->vno
, vpp
);
154 /* Store the result of this lookup in the cache. Avoid this if the
155 * request was for creation, as it does not improve timings on
157 if (cnp
->cn_nameiop
!= CREATE
&& (cnp
->cn_flags
& ISDOTDOT
) == 0) {
158 cache_enter(dvp
, *vpp
, cnp
->cn_nameptr
, cnp
->cn_namelen
,
163 /* If there were no errors, *vpp cannot be NULL. */
164 KASSERT(IFF(error
== 0, *vpp
!= NULL
));
165 KASSERT(VOP_ISLOCKED(dvp
));
174 /* --------------------------------------------------------------------- */
179 struct vop_create_v3_args
/* {
181 struct vnode **a_vpp;
182 struct componentname *a_cnp;
188 mode
= MAKEIMODE(ap
->a_vap
->va_type
, ap
->a_vap
->va_mode
);
190 if ((mode
& IFMT
) == 0) {
191 if (ap
->a_vap
->va_type
== VREG
)
193 if (ap
->a_vap
->va_type
== VSOCK
)
197 error
= chfs_makeinode(mode
, ap
->a_dvp
, ap
->a_vpp
, ap
->a_cnp
, ap
->a_vap
->va_type
);
200 dbg("error: %d\n", error
);
204 VN_KNOTE(ap
->a_dvp
, NOTE_WRITE
);
207 /* --------------------------------------------------------------------- */
212 struct vnode
*dvp
= ((struct vop_mknod_v3_args
*) v
)->a_dvp
;
213 struct vnode
**vpp
= ((struct vop_mknod_v3_args
*) v
)->a_vpp
;
214 struct componentname
*cnp
= ((struct vop_mknod_v3_args
*) v
)->a_cnp
;
215 struct vattr
*vap
= ((struct vop_mknod_v3_args
*) v
)->a_vap
;
217 struct chfs_inode
*ip
;
220 struct ufsmount
*ump
;
221 struct chfs_mount
*chmp
;
223 struct chfs_full_dnode
*fd
;
228 ump
= VFSTOUFS(dvp
->v_mount
);
231 /* Check type of node. */
232 if (vap
->va_type
!= VBLK
&& vap
->va_type
!= VCHR
&& vap
->va_type
!= VFIFO
)
237 mode
= MAKEIMODE(vap
->va_type
, vap
->va_mode
);
239 if ((mode
& IFMT
) == 0) {
240 switch (vap
->va_type
) {
255 /* Create a new node. */
256 err
= chfs_makeinode(mode
, dvp
, &vp
, cnp
, vap
->va_type
);
259 if (vap
->va_rdev
!= VNOVAL
)
260 ip
->rdev
= vap
->va_rdev
;
262 if (vap
->va_type
== VFIFO
)
263 vp
->v_op
= chfs_fifoop_p
;
265 vp
->v_op
= chfs_specop_p
;
266 spec_node_init(vp
, ip
->rdev
);
272 /* Device is written out as a data node. */
274 chfs_set_vnode_size(vp
, len
);
275 bp
= getiobuf(vp
, true);
276 bp
->b_bufsize
= bp
->b_resid
= len
;
277 bp
->b_data
= kmem_alloc(len
, KM_SLEEP
);
278 memcpy(bp
->b_data
, &ip
->rdev
, len
);
281 fd
= chfs_alloc_full_dnode();
283 mutex_enter(&chmp
->chm_lock_mountfields
);
285 err
= chfs_write_flash_dnode(chmp
, vp
, bp
, fd
);
287 mutex_exit(&chmp
->chm_lock_mountfields
);
288 kmem_free(bp
->b_data
, len
);
292 /* Add data node to the inode. */
293 err
= chfs_add_full_dnode_to_inode(chmp
, ip
, fd
);
295 mutex_exit(&chmp
->chm_lock_mountfields
);
296 kmem_free(bp
->b_data
, len
);
300 mutex_exit(&chmp
->chm_lock_mountfields
);
303 kmem_free(bp
->b_data
, len
);
309 /* --------------------------------------------------------------------- */
314 struct vnode
*vp
= ((struct vop_open_args
*) v
)->a_vp
;
315 int mode
= ((struct vop_open_args
*) v
)->a_mode
;
319 struct chfs_inode
*ip
;
321 KASSERT(VOP_ISLOCKED(vp
));
325 KASSERT(vp
->v_size
== ip
->size
);
326 if (ip
->chvc
->nlink
< 1) {
331 /* If the file is marked append-only, deny write requests. */
332 if (ip
->flags
& APPEND
&& (mode
& (FWRITE
| O_APPEND
)) == FWRITE
)
338 KASSERT(VOP_ISLOCKED(vp
));
342 /* --------------------------------------------------------------------- */
347 struct vnode
*vp
= ((struct vop_close_args
*) v
)->a_vp
;
350 struct chfs_inode
*ip
;
352 KASSERT(VOP_ISLOCKED(vp
));
356 if (ip
->chvc
->nlink
> 0) {
357 chfs_update(vp
, NULL
, NULL
, UPDATE_CLOSE
);
363 /* --------------------------------------------------------------------- */
368 struct vnode
*vp
= ((struct vop_access_args
*) v
)->a_vp
;
369 int mode
= ((struct vop_access_args
*) v
)->a_mode
;
370 kauth_cred_t cred
= ((struct vop_access_args
*) v
)->a_cred
;
373 struct chfs_inode
*ip
= VTOI(vp
);
376 switch (vp
->v_type
) {
380 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
393 if (mode
& VWRITE
&& ip
->flags
& IMMUTABLE
)
396 return kauth_authorize_vnode(cred
, KAUTH_ACCESS_ACTION(mode
, vp
->v_type
,
397 ip
->mode
& ALLPERMS
), vp
, NULL
, genfs_can_access(vp
->v_type
,
398 ip
->mode
& ALLPERMS
, ip
->uid
, ip
->gid
, mode
, cred
));
401 /* --------------------------------------------------------------------- */
404 chfs_getattr(void *v
)
406 struct vnode
*vp
= ((struct vop_getattr_args
*) v
)->a_vp
;
407 struct vattr
*vap
= ((struct vop_getattr_args
*) v
)->a_vap
;
409 struct chfs_inode
*ip
= VTOI(vp
);
412 KASSERT(vp
->v_size
== ip
->size
);
415 CHFS_ITIMES(ip
, NULL
, NULL
, NULL
);
417 vap
->va_type
= CHTTOVT(ip
->ch_type
);
418 vap
->va_mode
= ip
->mode
& ALLPERMS
;
419 vap
->va_nlink
= ip
->chvc
->nlink
;
420 vap
->va_uid
= ip
->uid
;
421 vap
->va_gid
= ip
->gid
;
422 vap
->va_fsid
= ip
->dev
;
423 vap
->va_fileid
= ip
->ino
;
424 vap
->va_size
= ip
->size
;
425 vap
->va_blocksize
= PAGE_SIZE
;
426 vap
->va_atime
.tv_sec
= ip
->atime
;
427 vap
->va_atime
.tv_nsec
= 0;
428 vap
->va_mtime
.tv_sec
= ip
->mtime
;
429 vap
->va_mtime
.tv_nsec
= 0;
430 vap
->va_ctime
.tv_sec
= ip
->ctime
;
431 vap
->va_ctime
.tv_nsec
= 0;
432 vap
->va_gen
= ip
->version
;
433 vap
->va_flags
= ip
->flags
;
434 vap
->va_rdev
= ip
->rdev
;
435 vap
->va_bytes
= round_page(ip
->size
);
436 vap
->va_filerev
= VNOVAL
;
438 vap
->va_spare
= VNOVAL
;
443 /* --------------------------------------------------------------------- */
445 /* Note: modelled after tmpfs's same function */
448 chfs_setattr(void *v
)
450 struct vnode
*vp
= ((struct vop_setattr_args
*) v
)->a_vp
;
451 struct vattr
*vap
= ((struct vop_setattr_args
*) v
)->a_vap
;
452 kauth_cred_t cred
= ((struct vop_setattr_args
*) v
)->a_cred
;
454 struct chfs_inode
*ip
;
455 struct ufsmount
*ump
= VFSTOUFS(vp
->v_mount
);
456 struct chfs_mount
*chmp
= ump
->um_chfs
;
461 KASSERT(VOP_ISLOCKED(vp
));
464 /* Abort if any unsettable attribute is given. */
465 if (vap
->va_type
!= VNON
|| vap
->va_nlink
!= VNOVAL
||
466 vap
->va_fsid
!= VNOVAL
|| vap
->va_fileid
!= VNOVAL
||
467 vap
->va_blocksize
!= VNOVAL
/*|| GOODTIME(&vap->va_ctime)*/ ||
468 vap
->va_gen
!= VNOVAL
|| vap
->va_rdev
!= VNOVAL
||
469 vap
->va_bytes
!= VNOVAL
) {
474 if (error
== 0 && (vap
->va_flags
!= VNOVAL
)) {
475 error
= chfs_chflags(vp
, vap
->va_flags
, cred
);
479 if (ip
->flags
& (IMMUTABLE
| APPEND
)) {
485 if (error
== 0 && (vap
->va_size
!= VNOVAL
)) {
486 error
= chfs_chsize(vp
, vap
->va_size
, cred
);
492 if (error
== 0 && (vap
->va_uid
!= VNOVAL
|| vap
->va_gid
!= VNOVAL
)) {
493 error
= chfs_chown(vp
, vap
->va_uid
, vap
->va_gid
, cred
);
499 if (error
== 0 && (vap
->va_mode
!= VNOVAL
)) {
500 error
= chfs_chmod(vp
, vap
->va_mode
, cred
);
506 if (vap
->va_atime
.tv_sec
!= VNOVAL
|| vap
->va_mtime
.tv_sec
!= VNOVAL
) {
507 error
= kauth_authorize_vnode(cred
, KAUTH_VNODE_WRITE_TIMES
, vp
,
508 NULL
, genfs_can_chtimes(vp
, vap
->va_vaflags
, ip
->uid
, cred
));
511 if (vap
->va_atime
.tv_sec
!= VNOVAL
)
512 ip
->iflag
|= IN_ACCESS
;
513 if (vap
->va_mtime
.tv_sec
!= VNOVAL
)
514 ip
->iflag
|= IN_CHANGE
| IN_UPDATE
;
515 error
= chfs_update(vp
,
516 &vap
->va_atime
, &vap
->va_mtime
, UPDATE_WAIT
);
522 mutex_enter(&chmp
->chm_lock_mountfields
);
523 error
= chfs_write_flash_vnode(chmp
, ip
, ALLOC_NORMAL
);
524 mutex_exit(&chmp
->chm_lock_mountfields
);
530 chfs_chmod(struct vnode
*vp
, int mode
, kauth_cred_t cred
)
532 struct chfs_inode
*ip
= VTOI(vp
);
536 error
= kauth_authorize_vnode(cred
, KAUTH_VNODE_WRITE_SECURITY
, vp
,
537 NULL
, genfs_can_chmod(vp
->v_type
, cred
, ip
->uid
, ip
->gid
, mode
));
540 ip
->mode
&= ~ALLPERMS
;
541 ip
->mode
|= (mode
& ALLPERMS
);
542 ip
->iflag
|= IN_CHANGE
;
544 error
= chfs_update(vp
, NULL
, NULL
, UPDATE_WAIT
);
552 chfs_chown(struct vnode
*vp
, uid_t uid
, gid_t gid
, kauth_cred_t cred
)
554 struct chfs_inode
*ip
= VTOI(vp
);
558 if (uid
== (uid_t
)VNOVAL
)
560 if (gid
== (gid_t
)VNOVAL
)
563 error
= kauth_authorize_vnode(cred
, KAUTH_VNODE_CHANGE_OWNERSHIP
, vp
,
564 NULL
, genfs_can_chown(cred
, ip
->uid
, ip
->gid
, uid
, gid
));
570 ip
->iflag
|= IN_CHANGE
;
572 error
= chfs_update(vp
, NULL
, NULL
, UPDATE_WAIT
);
580 /* --------------------------------------------------------------------- */
581 /* calculates ((off_t)blk * chmp->chm_chm_fs_bsize) */
582 #define chfs_lblktosize(chmp, blk) \
583 (((off_t)(blk)) << (chmp)->chm_fs_bshift)
585 /* calculates (loc % chmp->chm_chm_fs_bsize) */
586 #define chfs_blkoff(chmp, loc) \
587 ((loc) & (chmp)->chm_fs_qbmask)
589 /* calculates (loc / chmp->chm_chm_fs_bsize) */
590 #define chfs_lblkno(chmp, loc) \
591 ((loc) >> (chmp)->chm_fs_bshift)
593 /* calculates roundup(size, chmp->chm_chm_fs_fsize) */
594 #define chfs_fragroundup(chmp, size) \
595 (((size) + (chmp)->chm_fs_qfmask) & (chmp)->chm_fs_fmask)
597 #define chfs_blksize(chmp, ip, lbn) \
598 (((lbn) >= UFS_NDADDR || (ip)->size >= chfs_lblktosize(chmp, (lbn) + 1)) \
599 ? (chmp)->chm_fs_bsize \
600 : (chfs_fragroundup(chmp, chfs_blkoff(chmp, (ip)->size))))
602 /* calculates roundup(size, chmp->chm_chm_fs_bsize) */
603 #define chfs_blkroundup(chmp, size) \
604 (((size) + (chmp)->chm_fs_qbmask) & (chmp)->chm_fs_bmask)
610 struct vop_read_args
/* {
617 struct chfs_inode
*ip
;
619 struct ufsmount
*ump
;
621 struct chfs_mount
*chmp
;
622 daddr_t lbn
, nextlbn
;
624 long size
, xfersize
, blkoffset
;
635 ioflag
= ap
->a_ioflag
;
638 dbg("ip->size:%llu\n", (unsigned long long)ip
->size
);
641 if (uio
->uio_rw
!= UIO_READ
)
642 panic("%s: mode", READ_S
);
644 if (vp
->v_type
== VLNK
) {
645 if (ip
->size
< ump
->um_maxsymlinklen
)
646 panic("%s: short symlink", READ_S
);
647 } else if (vp
->v_type
!= VREG
&& vp
->v_type
!= VDIR
)
648 panic("%s: type %d", READ_S
, vp
->v_type
);
651 if ((u_int64_t
)uio
->uio_offset
> ump
->um_maxfilesize
)
653 if (uio
->uio_resid
== 0)
656 fstrans_start(vp
->v_mount
, FSTRANS_SHARED
);
658 if (uio
->uio_offset
>= ip
->size
)
661 usepc
= vp
->v_type
== VREG
;
664 const int advice
= IO_ADV_DECODE(ap
->a_ioflag
);
666 while (uio
->uio_resid
> 0) {
667 if (ioflag
& IO_DIRECT
) {
668 genfs_directio(vp
, uio
, ioflag
);
670 bytelen
= MIN(ip
->size
- uio
->uio_offset
,
674 error
= ubc_uiomove(&vp
->v_uobj
, uio
, bytelen
, advice
,
675 UBC_READ
| UBC_PARTIALOK
|
676 (UBC_WANT_UNMAP(vp
) ? UBC_UNMAP
: 0));
684 dbg("start reading\n");
685 for (error
= 0, bp
= NULL
; uio
->uio_resid
> 0; bp
= NULL
) {
686 bytesinfile
= ip
->size
- uio
->uio_offset
;
687 if (bytesinfile
<= 0)
689 lbn
= chfs_lblkno(chmp
, uio
->uio_offset
);
691 size
= chfs_blksize(chmp
, ip
, lbn
);
692 blkoffset
= chfs_blkoff(chmp
, uio
->uio_offset
);
693 xfersize
= MIN(MIN(chmp
->chm_fs_bsize
- blkoffset
, uio
->uio_resid
),
696 if (chfs_lblktosize(chmp
, nextlbn
) >= ip
->size
) {
697 error
= bread(vp
, lbn
, size
, 0, &bp
);
698 dbg("after bread\n");
700 int nextsize
= chfs_blksize(chmp
, ip
, nextlbn
);
701 dbg("size: %ld\n", size
);
702 error
= breadn(vp
, lbn
,
703 size
, &nextlbn
, &nextsize
, 1, 0, &bp
);
704 dbg("after breadN\n");
710 * We should only get non-zero b_resid when an I/O error
711 * has occurred, which should cause us to break above.
712 * However, if the short read did not cause an error,
713 * then we want to ensure that we do not uiomove bad
714 * or uninitialized data.
717 if (size
< xfersize
) {
723 error
= uiomove((char *)bp
->b_data
+ blkoffset
, xfersize
, uio
);
734 ip
->ino
= ip
->chvc
->vno
;
736 if (!(vp
->v_mount
->mnt_flag
& MNT_NOATIME
)) {
737 ip
->iflag
|= IN_ACCESS
;
738 if ((ap
->a_ioflag
& IO_SYNC
) == IO_SYNC
) {
740 fstrans_done(vp
->v_mount
);
743 error
= chfs_update(vp
, NULL
, NULL
, UPDATE_WAIT
);
748 fstrans_done(vp
->v_mount
);
754 /* --------------------------------------------------------------------- */
760 struct vop_write_args
/* {
768 struct chfs_inode
*ip
;
769 struct chfs_mount
*chmp
;
772 off_t osize
, origoff
, oldoff
, preallocoff
, endallocoff
, nsize
;
773 int blkoffset
, error
, flags
, ioflag
, resid
;
778 struct ufsmount
*ump
;
782 ioflag
= ap
->a_ioflag
;
790 KASSERT(vp
->v_size
== ip
->size
);
792 switch (vp
->v_type
) {
794 if (ioflag
& IO_APPEND
)
795 uio
->uio_offset
= ip
->size
;
796 if ((ip
->flags
& APPEND
) && uio
->uio_offset
!= ip
->size
)
802 if ((ioflag
& IO_SYNC
) == 0)
803 panic("chfs_write: nonsync dir write");
806 panic("chfs_write: type");
810 if (uio
->uio_offset
< 0 ||
811 (u_int64_t
)uio
->uio_offset
+
812 uio
->uio_resid
> ump
->um_maxfilesize
) {
813 dbg("uio->uio_offset = %lld | uio->uio_offset + "
814 "uio->uio_resid (%llu) > ump->um_maxfilesize (%lld)\n",
815 (long long)uio
->uio_offset
,
816 (uint64_t)uio
->uio_offset
+ uio
->uio_resid
,
817 (long long)ump
->um_maxfilesize
);
821 * Maybe this should be above the vnode op call, but so long as
822 * file servers have no limits, I don't think it matters.
825 if (vp
->v_type
== VREG
&& l
&&
826 uio
->uio_offset
+ uio
->uio_resid
>
827 l
->l_proc
->p_rlimit
[RLIMIT_FSIZE
].rlim_cur
) {
828 mutex_enter(proc_lock
);
829 psignal(l
->l_proc
, SIGXFSZ
);
830 mutex_exit(proc_lock
);
833 if (uio
->uio_resid
== 0)
836 fstrans_start(vp
->v_mount
, FSTRANS_SHARED
);
838 flags
= ioflag
& IO_SYNC
? B_SYNC
: 0;
839 async
= vp
->v_mount
->mnt_flag
& MNT_ASYNC
;
840 origoff
= uio
->uio_offset
;
841 resid
= uio
->uio_resid
;
845 preallocoff
= round_page(chfs_blkroundup(chmp
,
846 MAX(osize
, uio
->uio_offset
)));
847 aflag
= ioflag
& IO_SYNC
? B_SYNC
: 0;
848 nsize
= MAX(osize
, uio
->uio_offset
+ uio
->uio_resid
);
849 endallocoff
= nsize
- chfs_blkoff(chmp
, nsize
);
852 * if we're increasing the file size, deal with expanding
853 * the fragment if there is one.
856 if (nsize
> osize
&& chfs_lblkno(chmp
, osize
) < UFS_NDADDR
&&
857 chfs_lblkno(chmp
, osize
) != chfs_lblkno(chmp
, nsize
) &&
858 chfs_blkroundup(chmp
, osize
) != osize
) {
861 eob
= chfs_blkroundup(chmp
, osize
);
862 uvm_vnp_setwritesize(vp
, eob
);
863 error
= ufs_balloc_range(vp
, osize
, eob
- osize
, cred
, aflag
);
866 if (flags
& B_SYNC
) {
867 mutex_enter(vp
->v_interlock
);
869 trunc_page(osize
& chmp
->chm_fs_bmask
),
871 PGO_CLEANIT
| PGO_SYNCIO
| PGO_JOURNALLOCKED
);
875 while (uio
->uio_resid
> 0) {
876 int ubc_flags
= UBC_WRITE
;
877 bool overwrite
; /* if we're overwrite a whole block */
880 if (ioflag
& IO_DIRECT
) {
881 genfs_directio(vp
, uio
, ioflag
| IO_JOURNALLOCKED
);
884 oldoff
= uio
->uio_offset
;
885 blkoffset
= chfs_blkoff(chmp
, uio
->uio_offset
);
886 bytelen
= MIN(chmp
->chm_fs_bsize
- blkoffset
, uio
->uio_resid
);
892 * if we're filling in a hole, allocate the blocks now and
893 * initialize the pages first. if we're extending the file,
894 * we can safely allocate blocks without initializing pages
895 * since the new blocks will be inaccessible until the write
898 overwrite
= uio
->uio_offset
>= preallocoff
&&
899 uio
->uio_offset
< endallocoff
;
900 if (!overwrite
&& (vp
->v_vflag
& VV_MAPPED
) == 0 &&
901 chfs_blkoff(chmp
, uio
->uio_offset
) == 0 &&
902 (uio
->uio_offset
& PAGE_MASK
) == 0) {
905 len
= trunc_page(bytelen
);
906 len
-= chfs_blkoff(chmp
, len
);
913 newoff
= oldoff
+ bytelen
;
914 if (vp
->v_size
< newoff
) {
915 uvm_vnp_setwritesize(vp
, newoff
);
919 error
= ufs_balloc_range(vp
, uio
->uio_offset
, bytelen
,
924 genfs_node_wrlock(vp
);
925 error
= GOP_ALLOC(vp
, uio
->uio_offset
, bytelen
,
927 genfs_node_unlock(vp
);
930 ubc_flags
|= UBC_FAULTBUSY
;
937 ubc_flags
|= UBC_WANT_UNMAP(vp
) ? UBC_UNMAP
: 0;
938 error
= ubc_uiomove(&vp
->v_uobj
, uio
, bytelen
,
939 IO_ADV_DECODE(ioflag
), ubc_flags
);
942 * update UVM's notion of the size now that we've
943 * copied the data into the vnode's pages.
945 * we should update the size even when uiomove failed.
948 if (vp
->v_size
< newoff
) {
949 uvm_vnp_setsize(vp
, newoff
);
957 * flush what we just wrote if necessary.
958 * XXXUBC simplistic async flushing.
961 if (!async
&& oldoff
>> 16 != uio
->uio_offset
>> 16) {
962 mutex_enter(vp
->v_interlock
);
963 error
= VOP_PUTPAGES(vp
, (oldoff
>> 16) << 16,
964 (uio
->uio_offset
>> 16) << 16,
965 PGO_CLEANIT
| PGO_JOURNALLOCKED
);
971 if (error
== 0 && ioflag
& IO_SYNC
) {
972 mutex_enter(vp
->v_interlock
);
973 error
= VOP_PUTPAGES(vp
,
974 trunc_page(origoff
& chmp
->chm_fs_bmask
),
975 round_page(chfs_blkroundup(chmp
, uio
->uio_offset
)),
976 PGO_CLEANIT
| PGO_SYNCIO
| PGO_JOURNALLOCKED
);
978 ip
->iflag
|= IN_CHANGE
| IN_UPDATE
;
979 if (resid
> uio
->uio_resid
&& ap
->a_cred
) {
980 if (ip
->mode
& ISUID
) {
981 if (kauth_authorize_vnode(ap
->a_cred
,
982 KAUTH_VNODE_RETAIN_SUID
, vp
, NULL
, EPERM
) != 0)
986 if (ip
->mode
& ISGID
) {
987 if (kauth_authorize_vnode(ap
->a_cred
,
988 KAUTH_VNODE_RETAIN_SGID
, vp
, NULL
, EPERM
) != 0)
992 if (resid
> uio
->uio_resid
)
993 VN_KNOTE(vp
, NOTE_WRITE
| (extended
? NOTE_EXTEND
: 0));
995 (void) UFS_TRUNCATE(vp
, osize
, ioflag
& IO_SYNC
, ap
->a_cred
);
996 uio
->uio_offset
-= resid
- uio
->uio_resid
;
997 uio
->uio_resid
= resid
;
998 } else if (resid
> uio
->uio_resid
&& (ioflag
& IO_SYNC
) == IO_SYNC
)
999 error
= UFS_UPDATE(vp
, NULL
, NULL
, UPDATE_WAIT
);
1002 chfs_set_vnode_size(vp
, vp
->v_size
);
1005 KASSERT(vp
->v_size
== ip
->size
);
1006 fstrans_done(vp
->v_mount
);
1008 mutex_enter(&chmp
->chm_lock_mountfields
);
1009 error
= chfs_write_flash_vnode(chmp
, ip
, ALLOC_NORMAL
);
1010 mutex_exit(&chmp
->chm_lock_mountfields
);
1016 /* --------------------------------------------------------------------- */
1021 struct vop_fsync_args
/* {
1023 kauth_cred_t a_cred;
1028 struct vnode
*vp
= ap
->a_vp
;
1030 if (ap
->a_flags
& FSYNC_CACHE
) {
1033 vflushbuf(vp
, ap
->a_flags
);
1038 /* --------------------------------------------------------------------- */
1041 chfs_remove(void *v
)
1043 struct vnode
*dvp
= ((struct vop_remove_args
*) v
)->a_dvp
;
1044 struct vnode
*vp
= ((struct vop_remove_args
*) v
)->a_vp
;
1045 struct componentname
*cnp
= (((struct vop_remove_args
*) v
)->a_cnp
);
1048 KASSERT(VOP_ISLOCKED(dvp
));
1049 KASSERT(VOP_ISLOCKED(vp
));
1051 struct chfs_inode
*ip
= VTOI(vp
);
1052 struct chfs_inode
*parent
= VTOI(dvp
);
1055 if (vp
->v_type
== VDIR
|| (ip
->flags
& (IMMUTABLE
| APPEND
)) ||
1056 (parent
->flags
& APPEND
)) {
1061 KASSERT(ip
->chvc
->vno
!= ip
->chvc
->pvno
);
1063 error
= chfs_do_unlink(ip
,
1064 parent
, cnp
->cn_nameptr
, cnp
->cn_namelen
);
1073 /* --------------------------------------------------------------------- */
1078 struct vnode
*dvp
= ((struct vop_link_v2_args
*) v
)->a_dvp
;
1079 struct vnode
*vp
= ((struct vop_link_v2_args
*) v
)->a_vp
;
1080 struct componentname
*cnp
= ((struct vop_link_v2_args
*) v
)->a_cnp
;
1082 struct chfs_inode
*ip
, *parent
;
1085 if (vp
->v_type
== VDIR
) {
1086 VOP_ABORTOP(dvp
, cnp
);
1090 if (dvp
->v_mount
!= vp
->v_mount
) {
1091 VOP_ABORTOP(dvp
, cnp
);
1095 if (dvp
!= vp
&& (error
= vn_lock(vp
, LK_EXCLUSIVE
))) {
1096 VOP_ABORTOP(dvp
, cnp
);
1103 error
= chfs_do_link(ip
,
1104 parent
, cnp
->cn_nameptr
, cnp
->cn_namelen
, ip
->ch_type
);
1112 /* --------------------------------------------------------------------- */
1115 chfs_rename(void *v
)
1117 struct vnode
*fdvp
= ((struct vop_rename_args
*) v
)->a_fdvp
;
1118 struct vnode
*fvp
= ((struct vop_rename_args
*) v
)->a_fvp
;
1119 struct componentname
*fcnp
= ((struct vop_rename_args
*) v
)->a_fcnp
;
1120 struct vnode
*tdvp
= ((struct vop_rename_args
*) v
)->a_tdvp
;
1121 struct vnode
*tvp
= ((struct vop_rename_args
*) v
)->a_tvp
;
1122 struct componentname
*tcnp
= ((struct vop_rename_args
*) v
)->a_tcnp
;
1124 struct chfs_inode
*oldparent
, *old
;
1125 struct chfs_inode
*newparent
;
1126 struct chfs_dirent
*fd
;
1127 struct chfs_inode
*ip
;
1131 KASSERT(VOP_ISLOCKED(tdvp
));
1132 KASSERT(IMPLIES(tvp
!= NULL
, VOP_ISLOCKED(tvp
) == LK_EXCLUSIVE
));
1134 oldparent
= VTOI(fdvp
);
1136 newparent
= VTOI(tdvp
);
1138 dbg("tvp not null\n");
1140 if (tvp
->v_type
== VDIR
) {
1141 TAILQ_FOREACH(fd
, &ip
->dents
, fds
) {
1148 error
= chfs_do_unlink(ip
,
1149 newparent
, tcnp
->cn_nameptr
, tcnp
->cn_namelen
);
1152 VFS_VGET(tdvp
->v_mount
, old
->ino
, &tvp
);
1156 error
= chfs_do_link(ip
,
1157 newparent
, tcnp
->cn_nameptr
, tcnp
->cn_namelen
, ip
->ch_type
);
1159 error
= chfs_do_unlink(old
,
1160 oldparent
, fcnp
->cn_nameptr
, fcnp
->cn_namelen
);
1163 /* Release target nodes. */
1171 /* Release source nodes. */
1178 /* --------------------------------------------------------------------- */
1183 struct vnode
*dvp
= ((struct vop_mkdir_v3_args
*) v
)->a_dvp
;
1184 struct vnode
**vpp
= ((struct vop_mkdir_v3_args
*)v
)->a_vpp
;
1185 struct componentname
*cnp
= ((struct vop_mkdir_v3_args
*) v
)->a_cnp
;
1186 struct vattr
*vap
= ((struct vop_mkdir_v3_args
*) v
)->a_vap
;
1191 mode
= vap
->va_mode
& ACCESSPERMS
;
1192 if ((mode
& IFMT
) == 0) {
1196 KASSERT(vap
->va_type
== VDIR
);
1198 return chfs_makeinode(mode
, dvp
, vpp
, cnp
, VDIR
);
1201 /* --------------------------------------------------------------------- */
1206 struct vnode
*dvp
= ((struct vop_rmdir_args
*) v
)->a_dvp
;
1207 struct vnode
*vp
= ((struct vop_rmdir_args
*) v
)->a_vp
;
1208 struct componentname
*cnp
= ((struct vop_rmdir_args
*) v
)->a_cnp
;
1211 KASSERT(VOP_ISLOCKED(dvp
));
1212 KASSERT(VOP_ISLOCKED(vp
));
1214 struct chfs_inode
*ip
= VTOI(vp
);
1215 struct chfs_inode
*parent
= VTOI(dvp
);
1216 struct chfs_dirent
*fd
;
1219 if (vp
->v_type
!= VDIR
) {
1224 KASSERT(ip
->chvc
->vno
!= ip
->chvc
->pvno
);
1226 TAILQ_FOREACH(fd
, &ip
->dents
, fds
) {
1233 error
= chfs_do_unlink(ip
,
1234 parent
, cnp
->cn_nameptr
, cnp
->cn_namelen
);
1243 /* --------------------------------------------------------------------- */
1246 chfs_symlink(void *v
)
1248 struct vnode
*dvp
= ((struct vop_symlink_v3_args
*) v
)->a_dvp
;
1249 struct vnode
**vpp
= ((struct vop_symlink_v3_args
*) v
)->a_vpp
;
1250 struct componentname
*cnp
= ((struct vop_symlink_v3_args
*) v
)->a_cnp
;
1251 struct vattr
*vap
= ((struct vop_symlink_v3_args
*) v
)->a_vap
;
1252 char *target
= ((struct vop_symlink_v3_args
*) v
)->a_target
;
1254 struct ufsmount
*ump
;
1255 struct chfs_mount
*chmp
;
1257 struct chfs_inode
*ip
;
1259 struct chfs_full_dnode
*fd
;
1263 ump
= VFSTOUFS(dvp
->v_mount
);
1264 chmp
= ump
->um_chfs
;
1266 err
= chfs_makeinode(IFLNK
| vap
->va_mode
, dvp
, vpp
, cnp
, VLNK
);
1269 VN_KNOTE(dvp
, NOTE_WRITE
);
1271 len
= strlen(target
);
1273 /* TODO max symlink len instead of "100" */
1275 /* symlink path stored as a data node */
1276 ip
->target
= kmem_alloc(len
, KM_SLEEP
);
1277 memcpy(ip
->target
, target
, len
);
1278 chfs_set_vnode_size(vp
, len
);
1279 ip
->iflag
|= IN_CHANGE
| IN_UPDATE
;
1281 bp
= getiobuf(vp
, true);
1282 bp
->b_bufsize
= bp
->b_resid
= len
;
1283 bp
->b_data
= kmem_alloc(len
, KM_SLEEP
);
1284 memcpy(bp
->b_data
, target
, len
);
1287 fd
= chfs_alloc_full_dnode();
1289 mutex_enter(&chmp
->chm_lock_mountfields
);
1291 /* write out the data node */
1292 err
= chfs_write_flash_dnode(chmp
, vp
, bp
, fd
);
1294 mutex_exit(&chmp
->chm_lock_mountfields
);
1298 /* add it to the inode */
1299 err
= chfs_add_full_dnode_to_inode(chmp
, ip
, fd
);
1301 mutex_exit(&chmp
->chm_lock_mountfields
);
1305 mutex_exit(&chmp
->chm_lock_mountfields
);
1307 kmem_free(bp
->b_data
, len
);
1310 uvm_vnp_setsize(vp
, len
);
1312 err
= ufs_bufio(UIO_WRITE
, vp
, target
, len
, (off_t
)0,
1313 IO_NODELOCKED
, cnp
->cn_cred
, (size_t *)0, NULL
);
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 (UFS_BUFRD(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
);
1515 vcache_remove(vp
->v_mount
, &ip
->ino
, sizeof(ip
->ino
));
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_fallocate_desc
, genfs_eopnotsupp
},
1617 { &vop_fdiscard_desc
, genfs_eopnotsupp
},
1618 { &vop_ioctl_desc
, genfs_enoioctl
},
1619 { &vop_fcntl_desc
, genfs_fcntl
},
1620 { &vop_poll_desc
, genfs_poll
},
1621 { &vop_kqfilter_desc
, genfs_kqfilter
},
1622 { &vop_revoke_desc
, genfs_revoke
},
1623 { &vop_mmap_desc
, genfs_mmap
},
1624 { &vop_fsync_desc
, chfs_fsync
},
1625 { &vop_seek_desc
, genfs_seek
},
1626 { &vop_remove_desc
, chfs_remove
},
1627 { &vop_link_desc
, chfs_link
},
1628 { &vop_rename_desc
, chfs_rename
},
1629 { &vop_mkdir_desc
, chfs_mkdir
},
1630 { &vop_rmdir_desc
, chfs_rmdir
},
1631 { &vop_symlink_desc
, chfs_symlink
},
1632 { &vop_readdir_desc
, chfs_readdir
},
1633 { &vop_readlink_desc
, chfs_readlink
},
1634 { &vop_abortop_desc
, genfs_abortop
},
1635 { &vop_inactive_desc
, chfs_inactive
},
1636 { &vop_reclaim_desc
, chfs_reclaim
},
1637 { &vop_lock_desc
, genfs_lock
},
1638 { &vop_unlock_desc
, genfs_unlock
},
1639 { &vop_bmap_desc
, chfs_bmap
},
1640 { &vop_strategy_desc
, chfs_strategy
},
1641 { &vop_print_desc
, ufs_print
},
1642 { &vop_pathconf_desc
, ufs_pathconf
},
1643 { &vop_islocked_desc
, genfs_islocked
},
1644 { &vop_advlock_desc
, chfs_advlock
},
1645 { &vop_bwrite_desc
, vn_bwrite
},
1646 { &vop_getpages_desc
, genfs_getpages
},
1647 { &vop_putpages_desc
, genfs_putpages
},
1650 const struct vnodeopv_desc chfs_vnodeop_opv_desc
=
1651 { &chfs_vnodeop_p
, chfs_vnodeop_entries
};
1653 /* --------------------------------------------------------------------- */
1656 * vnode operations vector used for special devices stored in a chfs
1660 (**chfs_specop_p
)(void *);
1661 const struct vnodeopv_entry_desc chfs_specop_entries
[] =
1663 { &vop_default_desc
, vn_default_error
},
1664 { &vop_lookup_desc
, spec_lookup
},
1665 { &vop_create_desc
, spec_create
},
1666 { &vop_mknod_desc
, spec_mknod
},
1667 { &vop_open_desc
, spec_open
},
1668 { &vop_close_desc
, ufsspec_close
},
1669 { &vop_access_desc
, chfs_access
},
1670 { &vop_getattr_desc
, chfs_getattr
},
1671 { &vop_setattr_desc
, chfs_setattr
},
1672 { &vop_read_desc
, chfs_read
},
1673 { &vop_write_desc
, chfs_write
},
1674 { &vop_fallocate_desc
, spec_fallocate
},
1675 { &vop_fdiscard_desc
, spec_fdiscard
},
1676 { &vop_ioctl_desc
, spec_ioctl
},
1677 { &vop_fcntl_desc
, genfs_fcntl
},
1678 { &vop_poll_desc
, spec_poll
},
1679 { &vop_kqfilter_desc
, spec_kqfilter
},
1680 { &vop_revoke_desc
, spec_revoke
},
1681 { &vop_mmap_desc
, spec_mmap
},
1682 { &vop_fsync_desc
, spec_fsync
},
1683 { &vop_seek_desc
, spec_seek
},
1684 { &vop_remove_desc
, spec_remove
},
1685 { &vop_link_desc
, spec_link
},
1686 { &vop_rename_desc
, spec_rename
},
1687 { &vop_mkdir_desc
, spec_mkdir
},
1688 { &vop_rmdir_desc
, spec_rmdir
},
1689 { &vop_symlink_desc
, spec_symlink
},
1690 { &vop_readdir_desc
, spec_readdir
},
1691 { &vop_readlink_desc
, spec_readlink
},
1692 { &vop_abortop_desc
, spec_abortop
},
1693 { &vop_inactive_desc
, chfs_inactive
},
1694 { &vop_reclaim_desc
, chfs_reclaim
},
1695 { &vop_lock_desc
, genfs_lock
},
1696 { &vop_unlock_desc
, genfs_unlock
},
1697 { &vop_bmap_desc
, spec_bmap
},
1698 { &vop_strategy_desc
, spec_strategy
},
1699 { &vop_print_desc
, ufs_print
},
1700 { &vop_pathconf_desc
, spec_pathconf
},
1701 { &vop_islocked_desc
, genfs_islocked
},
1702 { &vop_advlock_desc
, spec_advlock
},
1703 { &vop_bwrite_desc
, vn_bwrite
},
1704 { &vop_getpages_desc
, spec_getpages
},
1705 { &vop_putpages_desc
, spec_putpages
},
1708 const struct vnodeopv_desc chfs_specop_opv_desc
=
1709 { &chfs_specop_p
, chfs_specop_entries
};
1711 /* --------------------------------------------------------------------- */
1713 * vnode operations vector used for fifos stored in a chfs file system.
1716 (**chfs_fifoop_p
)(void *);
1717 const struct vnodeopv_entry_desc chfs_fifoop_entries
[] =
1719 { &vop_default_desc
, vn_default_error
},
1720 { &vop_lookup_desc
, vn_fifo_bypass
},
1721 { &vop_create_desc
, vn_fifo_bypass
},
1722 { &vop_mknod_desc
, vn_fifo_bypass
},
1723 { &vop_open_desc
, vn_fifo_bypass
},
1724 { &vop_close_desc
, ufsfifo_close
},
1725 { &vop_access_desc
, chfs_access
},
1726 { &vop_getattr_desc
, chfs_getattr
},
1727 { &vop_setattr_desc
, chfs_setattr
},
1728 { &vop_read_desc
, ufsfifo_read
},
1729 { &vop_write_desc
, ufsfifo_write
},
1730 { &vop_fallocate_desc
, vn_fifo_bypass
},
1731 { &vop_fdiscard_desc
, vn_fifo_bypass
},
1732 { &vop_ioctl_desc
, vn_fifo_bypass
},
1733 { &vop_fcntl_desc
, genfs_fcntl
},
1734 { &vop_poll_desc
, vn_fifo_bypass
},
1735 { &vop_kqfilter_desc
, vn_fifo_bypass
},
1736 { &vop_revoke_desc
, vn_fifo_bypass
},
1737 { &vop_mmap_desc
, vn_fifo_bypass
},
1738 { &vop_fsync_desc
, vn_fifo_bypass
},
1739 { &vop_seek_desc
, vn_fifo_bypass
},
1740 { &vop_remove_desc
, vn_fifo_bypass
},
1741 { &vop_link_desc
, vn_fifo_bypass
},
1742 { &vop_rename_desc
, vn_fifo_bypass
},
1743 { &vop_mkdir_desc
, vn_fifo_bypass
},
1744 { &vop_rmdir_desc
, vn_fifo_bypass
},
1745 { &vop_symlink_desc
, vn_fifo_bypass
},
1746 { &vop_readdir_desc
, vn_fifo_bypass
},
1747 { &vop_readlink_desc
, vn_fifo_bypass
},
1748 { &vop_abortop_desc
, vn_fifo_bypass
},
1749 { &vop_inactive_desc
, chfs_inactive
},
1750 { &vop_reclaim_desc
, chfs_reclaim
},
1751 { &vop_lock_desc
, genfs_lock
},
1752 { &vop_unlock_desc
, genfs_unlock
},
1753 { &vop_bmap_desc
, vn_fifo_bypass
},
1754 { &vop_strategy_desc
, vn_fifo_bypass
},
1755 { &vop_print_desc
, ufs_print
},
1756 { &vop_pathconf_desc
, vn_fifo_bypass
},
1757 { &vop_islocked_desc
, genfs_islocked
},
1758 { &vop_advlock_desc
, vn_fifo_bypass
},
1759 { &vop_bwrite_desc
, genfs_nullop
},
1760 { &vop_getpages_desc
, genfs_badop
},
1761 { &vop_putpages_desc
, vn_fifo_bypass
},
1764 const struct vnodeopv_desc chfs_fifoop_opv_desc
=
1765 { &chfs_fifoop_p
, chfs_fifoop_entries
};