1 /* $NetBSD: chfs_vnops.c,v 1.2 2011/11/24 21:09:37 agc 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 error
= cache_lookup(dvp
, vpp
, cnp
);
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(dvp
->v_type
== VDIR
&& 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
!= VDIR
&& fd
->type
!= VLNK
) && !(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_flags
& MAKEENTRY
) && cnp
->cn_nameiop
!= CREATE
158 && (cnp
->cn_flags
& ISDOTDOT
) == 0)
159 cache_enter(dvp
, *vpp
, cnp
);
162 // If there were no errors, *vpp cannot be null and it must be
164 KASSERT(IFF(error
== 0, *vpp
!= NULL
&& VOP_ISLOCKED(*vpp
)));
166 // dvp must always be locked.
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
;
222 struct chfs_full_dnode
*fd
;
227 ump
= VFSTOUFS(dvp
->v_mount
);
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 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
);
271 chfs_set_vnode_size(vp
, len
);
272 bp
= getiobuf(vp
, true);
273 bp
->b_bufsize
= bp
->b_resid
= len
;
274 bp
->b_data
= kmem_alloc(len
, KM_SLEEP
);
275 memcpy(bp
->b_data
, &ip
->rdev
, len
);
278 fd
= chfs_alloc_full_dnode();
280 mutex_enter(&chmp
->chm_lock_mountfields
);
282 err
= chfs_write_flash_dnode(chmp
, vp
, bp
, fd
);
284 mutex_exit(&chmp
->chm_lock_mountfields
);
285 kmem_free(bp
->b_data
, len
);
289 err
= chfs_add_full_dnode_to_inode(chmp
, ip
, fd
);
291 mutex_exit(&chmp
->chm_lock_mountfields
);
292 kmem_free(bp
->b_data
, len
);
296 mutex_exit(&chmp
->chm_lock_mountfields
);
299 kmem_free(bp
->b_data
, len
);
305 /* --------------------------------------------------------------------- */
310 struct vnode
*vp
= ((struct vop_open_args
*) v
)->a_vp
;
311 int mode
= ((struct vop_open_args
*) v
)->a_mode
;
315 struct chfs_inode
*ip
;
317 KASSERT(VOP_ISLOCKED(vp
));
321 KASSERT(vp
->v_size
== ip
->size
);
322 if (ip
->chvc
->nlink
< 1) {
327 // If the file is marked append-only, deny write requests.
328 if (ip
->flags
& APPEND
&& (mode
& (FWRITE
| O_APPEND
)) == FWRITE
)
334 KASSERT(VOP_ISLOCKED(vp
));
338 /* --------------------------------------------------------------------- */
343 struct vnode
*vp
= ((struct vop_close_args
*) v
)->a_vp
;
346 struct chfs_inode
*ip
;
348 KASSERT(VOP_ISLOCKED(vp
));
352 if (ip
->chvc
->nlink
> 0) {
353 //ip->chvc->nlink = 0;
354 chfs_update(vp
, NULL
, NULL
, UPDATE_CLOSE
);
360 /* --------------------------------------------------------------------- */
365 struct vnode
*vp
= ((struct vop_access_args
*) v
)->a_vp
;
366 int mode
= ((struct vop_access_args
*) v
)->a_mode
;
367 kauth_cred_t cred
= ((struct vop_access_args
*) v
)->a_cred
;
370 struct chfs_inode
*ip
= VTOI(vp
);
373 switch (vp
->v_type
) {
377 if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
390 if (mode
& VWRITE
&& ip
->flags
& IMMUTABLE
)
393 return genfs_can_access(vp
->v_type
, ip
->mode
& ALLPERMS
,
394 ip
->uid
, ip
->gid
, mode
, cred
);
397 /* --------------------------------------------------------------------- */
400 chfs_getattr(void *v
)
402 struct vnode
*vp
= ((struct vop_getattr_args
*) v
)->a_vp
;
403 struct vattr
*vap
= ((struct vop_getattr_args
*) v
)->a_vap
;
405 struct chfs_inode
*ip
= VTOI(vp
);
408 KASSERT(vp
->v_size
== ip
->size
);
411 CHFS_ITIMES(ip
, NULL
, NULL
, NULL
);
413 vap
->va_type
= vp
->v_type
;
414 vap
->va_mode
= ip
->mode
& ALLPERMS
;
415 vap
->va_nlink
= ip
->chvc
->nlink
;
416 vap
->va_uid
= ip
->uid
;
417 vap
->va_gid
= ip
->gid
;
418 vap
->va_fsid
= ip
->dev
;
419 vap
->va_fileid
= ip
->ino
;
420 vap
->va_size
= ip
->size
;
421 vap
->va_blocksize
= PAGE_SIZE
;
422 vap
->va_atime
.tv_sec
= ip
->atime
;
423 vap
->va_atime
.tv_nsec
= 0;
424 vap
->va_mtime
.tv_sec
= ip
->mtime
;
425 vap
->va_mtime
.tv_nsec
= 0;
426 vap
->va_ctime
.tv_sec
= ip
->ctime
;
427 vap
->va_ctime
.tv_nsec
= 0;
428 vap
->va_gen
= ip
->version
;
429 vap
->va_flags
= ip
->flags
;
430 vap
->va_rdev
= ip
->rdev
;
431 vap
->va_bytes
= round_page(ip
->size
);
432 vap
->va_filerev
= VNOVAL
;
434 vap
->va_spare
= VNOVAL
;
439 /* --------------------------------------------------------------------- */
441 /* Note: modelled after tmpfs's same function */
444 chfs_setattr(void *v
)
446 struct vnode
*vp
= ((struct vop_setattr_args
*) v
)->a_vp
;
447 struct vattr
*vap
= ((struct vop_setattr_args
*) v
)->a_vap
;
448 kauth_cred_t cred
= ((struct vop_setattr_args
*) v
)->a_cred
;
450 struct chfs_inode
*ip
;
451 struct ufsmount
*ump
= VFSTOUFS(vp
->v_mount
);
452 struct chfs_mount
*chmp
= ump
->um_chfs
;
457 KASSERT(VOP_ISLOCKED(vp
));
460 /* Abort if any unsettable attribute is given. */
461 if (vap
->va_type
!= VNON
|| vap
->va_nlink
!= VNOVAL
||
462 vap
->va_fsid
!= VNOVAL
|| vap
->va_fileid
!= VNOVAL
||
463 vap
->va_blocksize
!= VNOVAL
/*|| GOODTIME(&vap->va_ctime)*/ ||
464 vap
->va_gen
!= VNOVAL
|| vap
->va_rdev
!= VNOVAL
||
465 vap
->va_bytes
!= VNOVAL
) {
469 if (error
== 0 && (vap
->va_flags
!= VNOVAL
))
470 error
= chfs_chflags(vp
, vap
->va_flags
, cred
);
472 if (error
== 0 && (vap
->va_size
!= VNOVAL
))
473 error
= chfs_chsize(vp
, vap
->va_size
, cred
);
475 if (error
== 0 && (vap
->va_uid
!= VNOVAL
|| vap
->va_gid
!= VNOVAL
))
476 error
= chfs_chown(vp
, vap
->va_uid
, vap
->va_gid
, cred
);
478 if (error
== 0 && (vap
->va_mode
!= VNOVAL
))
479 error
= chfs_chmod(vp
, vap
->va_mode
, cred
);
482 /* why do we need that? */
483 if (ip
->flags
& (IMMUTABLE
| APPEND
))
487 if (vap
->va_atime
.tv_sec
!= VNOVAL
|| vap
->va_mtime
.tv_sec
!= VNOVAL
) {
488 error
= genfs_can_chtimes(vp
, vap
->va_vaflags
, ip
->uid
, cred
);
491 if (vap
->va_atime
.tv_sec
!= VNOVAL
)
492 ip
->iflag
|= IN_ACCESS
;
493 if (vap
->va_mtime
.tv_sec
!= VNOVAL
)
494 ip
->iflag
|= IN_CHANGE
| IN_UPDATE
;
495 error
= chfs_update(vp
,
496 &vap
->va_atime
, &vap
->va_mtime
, UPDATE_WAIT
);
501 mutex_enter(&chmp
->chm_lock_mountfields
);
502 error
= chfs_write_flash_vnode(chmp
, ip
, ALLOC_NORMAL
);
503 mutex_exit(&chmp
->chm_lock_mountfields
);
509 chfs_chmod(struct vnode
*vp
, int mode
, kauth_cred_t cred
)
511 struct chfs_inode
*ip
= VTOI(vp
);
515 error
= genfs_can_chmod(vp
, cred
, ip
->uid
, ip
->gid
, mode
);
518 ip
->mode
&= ~ALLPERMS
;
519 ip
->mode
|= (mode
& ALLPERMS
);
520 ip
->iflag
|= IN_CHANGE
;
522 error
= chfs_update(vp
, NULL
, NULL
, UPDATE_WAIT
);
530 chfs_chown(struct vnode
*vp
, uid_t uid
, gid_t gid
, kauth_cred_t cred
)
532 struct chfs_inode
*ip
= VTOI(vp
);
536 if (uid
== (uid_t
)VNOVAL
)
538 if (gid
== (gid_t
)VNOVAL
)
541 error
= genfs_can_chown(vp
, cred
, ip
->uid
, ip
->gid
, uid
, gid
);
547 ip
->iflag
|= IN_CHANGE
;
549 error
= chfs_update(vp
, NULL
, NULL
, UPDATE_WAIT
);
557 /* --------------------------------------------------------------------- */
558 /* calculates ((off_t)blk * chmp->chm_chm_fs_bsize) */
559 #define lblktosize(chmp, blk) \
560 (((off_t)(blk)) << (chmp)->chm_fs_bshift)
562 /* calculates (loc % chmp->chm_chm_fs_bsize) */
563 #define blkoff(chmp, loc) \
564 ((loc) & (chmp)->chm_fs_qbmask)
566 /* calculates (loc / chmp->chm_chm_fs_bsize) */
567 #define lblkno(chmp, loc) \
568 ((loc) >> (chmp)->chm_fs_bshift)
570 /* calculates roundup(size, chmp->chm_chm_fs_fsize) */
571 #define fragroundup(chmp, size) \
572 (((size) + (chmp)->chm_fs_qfmask) & (chmp)->chm_fs_fmask)
574 #define blksize(chmp, ip, lbn) \
575 (((lbn) >= NDADDR || (ip)->size >= lblktosize(chmp, (lbn) + 1)) \
576 ? (chmp)->chm_fs_bsize \
577 : (fragroundup(chmp, blkoff(chmp, (ip)->size))))
579 /* calculates roundup(size, chmp->chm_chm_fs_bsize) */
580 #define blkroundup(chmp, size) \
581 (((size) + (chmp)->chm_fs_qbmask) & (chmp)->chm_fs_bmask)
586 struct vop_read_args
/* {
593 struct chfs_inode
*ip
;
595 struct ufsmount
*ump
;
597 struct chfs_mount
*chmp
;
598 daddr_t lbn
, nextlbn
;
600 long size
, xfersize
, blkoffset
;
611 ioflag
= ap
->a_ioflag
;
614 dbg("ip->size:%llu\n", (unsigned long long)ip
->size
);
617 if (uio
->uio_rw
!= UIO_READ
)
618 panic("%s: mode", READ_S
);
620 if (vp
->v_type
== VLNK
) {
621 if (ip
->size
< ump
->um_maxsymlinklen
)
622 panic("%s: short symlink", READ_S
);
623 } else if (vp
->v_type
!= VREG
&& vp
->v_type
!= VDIR
)
624 panic("%s: type %d", READ_S
, vp
->v_type
);
627 if ((u_int64_t
)uio
->uio_offset
> ump
->um_maxfilesize
)
629 if (uio
->uio_resid
== 0)
632 fstrans_start(vp
->v_mount
, FSTRANS_SHARED
);
634 if (uio
->uio_offset
>= ip
->size
)
637 usepc
= vp
->v_type
== VREG
;
640 const int advice
= IO_ADV_DECODE(ap
->a_ioflag
);
642 while (uio
->uio_resid
> 0) {
643 if (ioflag
& IO_DIRECT
) {
644 genfs_directio(vp
, uio
, ioflag
);
646 bytelen
= MIN(ip
->size
- uio
->uio_offset
,
650 error
= ubc_uiomove(&vp
->v_uobj
, uio
, bytelen
, advice
,
651 UBC_READ
| UBC_PARTIALOK
|
652 (UBC_WANT_UNMAP(vp
) ? UBC_UNMAP
: 0));
661 dbg("start reading\n");
662 for (error
= 0, bp
= NULL
; uio
->uio_resid
> 0; bp
= NULL
) {
663 bytesinfile
= ip
->size
- uio
->uio_offset
;
664 if (bytesinfile
<= 0)
666 lbn
= lblkno(chmp
, uio
->uio_offset
);
668 size
= blksize(chmp
, ip
, lbn
);
669 blkoffset
= blkoff(chmp
, uio
->uio_offset
);
670 xfersize
= MIN(MIN(chmp
->chm_fs_bsize
- blkoffset
, uio
->uio_resid
),
673 if (lblktosize(chmp
, nextlbn
) >= ip
->size
) {
674 error
= bread(vp
, lbn
, size
, NOCRED
, 0, &bp
);
675 dbg("after bread\n");
677 int nextsize
= blksize(chmp
, ip
, nextlbn
);
678 dbg("size: %ld\n", size
);
679 error
= breadn(vp
, lbn
,
680 size
, &nextlbn
, &nextsize
, 1, NOCRED
, 0, &bp
);
681 dbg("after breadN\n");
687 * We should only get non-zero b_resid when an I/O error
688 * has occurred, which should cause us to break above.
689 * However, if the short read did not cause an error,
690 * then we want to ensure that we do not uiomove bad
691 * or uninitialized data.
694 if (size
< xfersize
) {
700 error
= uiomove((char *)bp
->b_data
+ blkoffset
, xfersize
, uio
);
709 if (!(vp
->v_mount
->mnt_flag
& MNT_NOATIME
)) {
710 ip
->iflag
|= IN_ACCESS
;
711 if ((ap
->a_ioflag
& IO_SYNC
) == IO_SYNC
) {
712 //error = UFS_WAPBL_BEGIN(vp->v_mount);
714 fstrans_done(vp
->v_mount
);
717 error
= chfs_update(vp
, NULL
, NULL
, UPDATE_WAIT
);
718 //UFS_WAPBL_END(vp->v_mount);
723 fstrans_done(vp
->v_mount
);
728 /* --------------------------------------------------------------------- */
734 struct vop_write_args
/* {
742 struct chfs_inode
*ip
;
743 struct chfs_mount
*chmp
;
746 off_t osize
, origoff
, oldoff
, preallocoff
, endallocoff
, nsize
;
747 int blkoffset
, error
, flags
, ioflag
, resid
;
752 struct ufsmount
*ump
;
756 ioflag
= ap
->a_ioflag
;
760 //dbg("file size (vp): %llu\n", (unsigned long long)vp->v_size);
761 //dbg("file size (ip): %llu\n", (unsigned long long)ip->i_size);
764 //dbg("uio->resid: %d\n", uio->uio_resid);
767 KASSERT(vp
->v_size
== ip
->size
);
769 switch (vp
->v_type
) {
771 if (ioflag
& IO_APPEND
)
772 uio
->uio_offset
= ip
->size
;
773 if ((ip
->flags
& APPEND
) && uio
->uio_offset
!= ip
->size
)
779 if ((ioflag
& IO_SYNC
) == 0)
780 panic("chfs_write: nonsync dir write");
783 panic("chfs_write: type");
787 if (uio
->uio_offset
< 0 ||
788 (u_int64_t
)uio
->uio_offset
+
789 uio
->uio_resid
> ump
->um_maxfilesize
) {
790 dbg("uio->uio_offset = %lld | uio->uio_offset + "
791 "uio->uio_resid (%llu) > ump->um_maxfilesize (%lld)\n",
792 (long long)uio
->uio_offset
,
793 (uint64_t)uio
->uio_offset
+ uio
->uio_resid
,
794 (long long)ump
->um_maxfilesize
);
798 * Maybe this should be above the vnode op call, but so long as
799 * file servers have no limits, I don't think it matters.
802 if (vp
->v_type
== VREG
&& l
&&
803 uio
->uio_offset
+ uio
->uio_resid
>
804 l
->l_proc
->p_rlimit
[RLIMIT_FSIZE
].rlim_cur
) {
805 mutex_enter(proc_lock
);
806 psignal(l
->l_proc
, SIGXFSZ
);
807 mutex_exit(proc_lock
);
810 if (uio
->uio_resid
== 0)
813 //mutex_enter(&ip->inode_lock);
814 fstrans_start(vp
->v_mount
, FSTRANS_SHARED
);
816 flags
= ioflag
& IO_SYNC
? B_SYNC
: 0;
817 async
= vp
->v_mount
->mnt_flag
& MNT_ASYNC
;
818 origoff
= uio
->uio_offset
;
819 resid
= uio
->uio_resid
;
824 /*if ((ioflag & IO_JOURNALLOCKED) == 0) {
825 error = UFS_WAPBL_BEGIN(vp->v_mount);
827 fstrans_done(vp->v_mount);
832 preallocoff
= round_page(blkroundup(chmp
,
833 MAX(osize
, uio
->uio_offset
)));
834 aflag
= ioflag
& IO_SYNC
? B_SYNC
: 0;
835 nsize
= MAX(osize
, uio
->uio_offset
+ uio
->uio_resid
);
836 endallocoff
= nsize
- blkoff(chmp
, nsize
);
839 * if we're increasing the file size, deal with expanding
840 * the fragment if there is one.
843 if (nsize
> osize
&& lblkno(chmp
, osize
) < NDADDR
&&
844 lblkno(chmp
, osize
) != lblkno(chmp
, nsize
) &&
845 blkroundup(chmp
, osize
) != osize
) {
848 eob
= blkroundup(chmp
, osize
);
849 uvm_vnp_setwritesize(vp
, eob
);
850 error
= ufs_balloc_range(vp
, osize
, eob
- osize
, cred
, aflag
);
853 if (flags
& B_SYNC
) {
854 mutex_enter(vp
->v_interlock
);
856 trunc_page(osize
& chmp
->chm_fs_bmask
),
858 PGO_CLEANIT
| PGO_SYNCIO
| PGO_JOURNALLOCKED
);
862 while (uio
->uio_resid
> 0) {
863 int ubc_flags
= UBC_WRITE
;
864 bool overwrite
; /* if we're overwrite a whole block */
867 if (ioflag
& IO_DIRECT
) {
868 genfs_directio(vp
, uio
, ioflag
| IO_JOURNALLOCKED
);
871 oldoff
= uio
->uio_offset
;
872 blkoffset
= blkoff(chmp
, uio
->uio_offset
);
873 bytelen
= MIN(chmp
->chm_fs_bsize
- blkoffset
, uio
->uio_resid
);
879 * if we're filling in a hole, allocate the blocks now and
880 * initialize the pages first. if we're extending the file,
881 * we can safely allocate blocks without initializing pages
882 * since the new blocks will be inaccessible until the write
885 overwrite
= uio
->uio_offset
>= preallocoff
&&
886 uio
->uio_offset
< endallocoff
;
887 if (!overwrite
&& (vp
->v_vflag
& VV_MAPPED
) == 0 &&
888 blkoff(chmp
, uio
->uio_offset
) == 0 &&
889 (uio
->uio_offset
& PAGE_MASK
) == 0) {
892 len
= trunc_page(bytelen
);
893 len
-= blkoff(chmp
, len
);
900 newoff
= oldoff
+ bytelen
;
901 if (vp
->v_size
< newoff
) {
902 uvm_vnp_setwritesize(vp
, newoff
);
906 error
= ufs_balloc_range(vp
, uio
->uio_offset
, bytelen
,
911 genfs_node_wrlock(vp
);
912 error
= GOP_ALLOC(vp
, uio
->uio_offset
, bytelen
,
914 genfs_node_unlock(vp
);
917 ubc_flags
|= UBC_FAULTBUSY
;
924 ubc_flags
|= UBC_WANT_UNMAP(vp
) ? UBC_UNMAP
: 0;
925 error
= ubc_uiomove(&vp
->v_uobj
, uio
, bytelen
,
926 IO_ADV_DECODE(ioflag
), ubc_flags
);
929 * update UVM's notion of the size now that we've
930 * copied the data into the vnode's pages.
932 * we should update the size even when uiomove failed.
935 if (vp
->v_size
< newoff
) {
936 uvm_vnp_setsize(vp
, newoff
);
944 * flush what we just wrote if necessary.
945 * XXXUBC simplistic async flushing.
948 if (!async
&& oldoff
>> 16 != uio
->uio_offset
>> 16) {
949 mutex_enter(vp
->v_interlock
);
950 error
= VOP_PUTPAGES(vp
, (oldoff
>> 16) << 16,
951 (uio
->uio_offset
>> 16) << 16,
952 PGO_CLEANIT
| PGO_JOURNALLOCKED
);
958 if (error
== 0 && ioflag
& IO_SYNC
) {
959 mutex_enter(vp
->v_interlock
);
960 error
= VOP_PUTPAGES(vp
,
961 trunc_page(origoff
& chmp
->chm_fs_bmask
),
962 round_page(blkroundup(chmp
, uio
->uio_offset
)),
963 PGO_CLEANIT
| PGO_SYNCIO
| PGO_JOURNALLOCKED
);
965 ip
->iflag
|= IN_CHANGE
| IN_UPDATE
;
966 if (resid
> uio
->uio_resid
&& ap
->a_cred
&&
967 kauth_authorize_generic(ap
->a_cred
, KAUTH_GENERIC_ISSUSER
, NULL
)) {
968 ip
->mode
&= ~(ISUID
| ISGID
);
970 if (resid
> uio
->uio_resid
)
971 VN_KNOTE(vp
, NOTE_WRITE
| (extended
? NOTE_EXTEND
: 0));
973 (void) UFS_TRUNCATE(vp
, osize
, ioflag
& IO_SYNC
, ap
->a_cred
);
974 uio
->uio_offset
-= resid
- uio
->uio_resid
;
975 uio
->uio_resid
= resid
;
976 } else if (resid
> uio
->uio_resid
&& (ioflag
& IO_SYNC
) == IO_SYNC
)
977 error
= UFS_UPDATE(vp
, NULL
, NULL
, UPDATE_WAIT
);
979 //XXX hack, i write the next line after i know ip->i_size and vp->v_size don't equal
980 chfs_set_vnode_size(vp
, vp
->v_size
);
983 //dbg("end file size (vp): %llu\n", (unsigned long long)vp->v_size);
984 //dbg("end file size (ip): %llu\n", (unsigned long long)ip->i_size);
985 KASSERT(vp
->v_size
== ip
->size
);
986 fstrans_done(vp
->v_mount
);
988 mutex_enter(&chmp
->chm_lock_mountfields
);
989 error
= chfs_write_flash_vnode(chmp
, ip
, ALLOC_NORMAL
);
990 mutex_exit(&chmp
->chm_lock_mountfields
);
992 //mutex_exit(&ip->inode_lock);
998 /* --------------------------------------------------------------------- */
1004 struct vop_fsync_args
/* {
1006 kauth_cred_t a_cred;
1011 struct vnode
*vp
= ap
->a_vp
;
1014 if (ap
->a_flags
& FSYNC_CACHE
) {
1017 wait
= (ap
->a_flags
& FSYNC_WAIT
) != 0;
1018 vflushbuf(vp
, wait
);
1019 //struct chfs_inode *ip = VTOI(vp);
1020 //chfs_set_vnode_size(vp, ip->write_size);
1025 /* --------------------------------------------------------------------- */
1028 chfs_remove(void *v
)
1030 struct vnode
*dvp
= ((struct vop_remove_args
*) v
)->a_dvp
;
1031 struct vnode
*vp
= ((struct vop_remove_args
*) v
)->a_vp
;
1032 struct componentname
*cnp
= (((struct vop_remove_args
*) v
)->a_cnp
);
1035 KASSERT(VOP_ISLOCKED(dvp
));
1036 KASSERT(VOP_ISLOCKED(vp
));
1038 struct chfs_inode
*ip
= VTOI(vp
);
1039 struct chfs_inode
*parent
= VTOI(dvp
);
1042 KASSERT(ip
->chvc
->vno
!= ip
->chvc
->pvno
);
1044 error
= chfs_do_unlink(ip
,
1045 parent
, cnp
->cn_nameptr
, cnp
->cn_namelen
);
1053 /* --------------------------------------------------------------------- */
1058 struct vnode
*dvp
= ((struct vop_link_args
*) v
)->a_dvp
;
1059 struct vnode
*vp
= ((struct vop_link_args
*) v
)->a_vp
;
1060 struct componentname
*cnp
= ((struct vop_link_args
*) v
)->a_cnp
;
1062 struct chfs_inode
*ip
, *parent
;
1065 if (vp
->v_type
== VDIR
) {
1066 VOP_ABORTOP(dvp
, cnp
);
1070 if (dvp
->v_mount
!= vp
->v_mount
) {
1071 VOP_ABORTOP(dvp
, cnp
);
1075 if (dvp
!= vp
&& (error
= vn_lock(vp
, LK_EXCLUSIVE
))) {
1076 VOP_ABORTOP(dvp
, cnp
);
1083 error
= chfs_do_link(ip
,
1084 parent
, cnp
->cn_nameptr
, cnp
->cn_namelen
, vp
->v_type
);
1093 /* --------------------------------------------------------------------- */
1096 chfs_rename(void *v
)
1098 struct vnode
*fdvp
= ((struct vop_rename_args
*) v
)->a_fdvp
;
1099 struct vnode
*fvp
= ((struct vop_rename_args
*) v
)->a_fvp
;
1100 struct componentname
*fcnp
= ((struct vop_rename_args
*) v
)->a_fcnp
;
1101 struct vnode
*tdvp
= ((struct vop_rename_args
*) v
)->a_tdvp
;
1102 struct vnode
*tvp
= ((struct vop_rename_args
*) v
)->a_tvp
;
1103 struct componentname
*tcnp
= ((struct vop_rename_args
*) v
)->a_tcnp
;
1105 struct chfs_inode
*oldparent
, *old
;
1106 struct chfs_inode
*newparent
;
1107 struct chfs_dirent
*fd
;//, *oldfd;
1108 struct chfs_inode
*ip
;
1112 KASSERT(VOP_ISLOCKED(tdvp
));
1113 KASSERT(IMPLIES(tvp
!= NULL
, VOP_ISLOCKED(tvp
) == LK_EXCLUSIVE
));
1115 oldparent
= VTOI(fdvp
);
1117 newparent
= VTOI(tdvp
);
1119 dbg("tvp not null\n");
1121 if (tvp
->v_type
== VDIR
) {
1125 TAILQ_FOREACH(fd
, &ip
->dents
, fds
) {
1135 error
= chfs_do_unlink(ip
,
1136 newparent
, tcnp
->cn_nameptr
, tcnp
->cn_namelen
);
1139 VFS_VGET(tdvp
->v_mount
, old
->ino
, &tvp
);
1142 // for (oldfd = oldparent->dents;
1143 // oldfd->vno != old->ino;
1144 // oldfd = oldfd->next);
1146 error
= chfs_do_link(ip
,
1147 newparent
, tcnp
->cn_nameptr
, tcnp
->cn_namelen
, tvp
->v_type
);
1148 error
= chfs_do_unlink(old
,
1149 oldparent
, fcnp
->cn_nameptr
, fcnp
->cn_namelen
);
1152 // if (fchnode != tchnode)
1153 // VOP_UNLOCK(fdvp, 0);
1156 // Release target nodes.
1164 // Release source nodes.
1171 /* --------------------------------------------------------------------- */
1176 struct vnode
*dvp
= ((struct vop_mkdir_args
*) v
)->a_dvp
;
1177 struct vnode
**vpp
= ((struct vop_mkdir_args
*)v
)->a_vpp
;
1178 struct componentname
*cnp
= ((struct vop_mkdir_args
*) v
)->a_cnp
;
1179 struct vattr
*vap
= ((struct vop_mkdir_args
*) v
)->a_vap
;
1184 mode
= vap
->va_mode
& ACCESSPERMS
;
1185 if ((mode
& IFMT
) == 0) {
1189 KASSERT(vap
->va_type
== VDIR
);
1191 return chfs_makeinode(mode
, dvp
, vpp
, cnp
, VDIR
);
1194 /* --------------------------------------------------------------------- */
1199 struct vnode
*dvp
= ((struct vop_rmdir_args
*) v
)->a_dvp
;
1200 struct vnode
*vp
= ((struct vop_rmdir_args
*) v
)->a_vp
;
1201 struct componentname
*cnp
= ((struct vop_rmdir_args
*) v
)->a_cnp
;
1204 KASSERT(VOP_ISLOCKED(dvp
));
1205 KASSERT(VOP_ISLOCKED(vp
));
1207 struct chfs_inode
*ip
= VTOI(vp
);
1208 struct chfs_inode
*parent
= VTOI(dvp
);
1209 struct chfs_dirent
*fd
;
1212 if (vp
->v_type
!= VDIR
) {
1217 KASSERT(ip
->chvc
->vno
!= ip
->chvc
->pvno
);
1219 // for (fd = ip->dents; fd; fd = fd->next) {
1220 TAILQ_FOREACH(fd
, &ip
->dents
, fds
) {
1227 error
= chfs_do_unlink(ip
,
1228 parent
, cnp
->cn_nameptr
, cnp
->cn_namelen
);
1237 /* --------------------------------------------------------------------- */
1240 chfs_symlink(void *v
)
1242 struct vnode
*dvp
= ((struct vop_symlink_args
*) v
)->a_dvp
;
1243 struct vnode
**vpp
= ((struct vop_symlink_args
*) v
)->a_vpp
;
1244 struct componentname
*cnp
= ((struct vop_symlink_args
*) v
)->a_cnp
;
1245 struct vattr
*vap
= ((struct vop_symlink_args
*) v
)->a_vap
;
1246 char *target
= ((struct vop_symlink_args
*) v
)->a_target
;
1248 struct ufsmount
*ump
;
1249 struct chfs_mount
*chmp
;
1251 struct chfs_inode
*ip
;
1253 struct chfs_full_dnode
*fd
;
1257 ump
= VFSTOUFS(dvp
->v_mount
);
1258 chmp
= ump
->um_chfs
;
1260 err
= chfs_makeinode(IFLNK
| vap
->va_mode
, dvp
, vpp
, cnp
, VLNK
);
1263 VN_KNOTE(dvp
, NOTE_WRITE
);
1265 len
= strlen(target
);
1267 /* TODO max symlink len instead of "100" */
1269 ip
->target
= kmem_alloc(len
, KM_SLEEP
);
1270 memcpy(ip
->target
, target
, len
);
1271 chfs_set_vnode_size(vp
, len
);
1272 ip
->iflag
|= IN_CHANGE
| IN_UPDATE
;
1274 bp
= getiobuf(vp
, true);
1275 bp
->b_bufsize
= bp
->b_resid
= len
;
1276 bp
->b_data
= kmem_alloc(len
, KM_SLEEP
);
1277 memcpy(bp
->b_data
, target
, len
);
1280 fd
= chfs_alloc_full_dnode();
1282 mutex_enter(&chmp
->chm_lock_mountfields
);
1284 err
= chfs_write_flash_dnode(chmp
, vp
, bp
, fd
);
1286 mutex_exit(&chmp
->chm_lock_mountfields
);
1290 err
= chfs_add_full_dnode_to_inode(chmp
, ip
, fd
);
1292 mutex_exit(&chmp
->chm_lock_mountfields
);
1296 mutex_exit(&chmp
->chm_lock_mountfields
);
1298 kmem_free(bp
->b_data
, len
);
1301 uvm_vnp_setsize(vp
, len
);
1303 err
= vn_rdwr(UIO_WRITE
, vp
, target
, len
, (off_t
)0,
1304 UIO_SYSSPACE
, IO_NODELOCKED
, cnp
->cn_cred
,
1315 /* --------------------------------------------------------------------- */
1318 chfs_readdir(void *v
)
1320 struct vnode
*vp
= ((struct vop_readdir_args
*) v
)->a_vp
;
1321 struct uio
*uio
= ((struct vop_readdir_args
*) v
)->a_uio
;
1322 int *eofflag
= ((struct vop_readdir_args
*) v
)->a_eofflag
;
1326 struct chfs_inode
*ip
;
1327 struct chfs_dirent
*fd
;
1329 struct ufsmount
*ump
;
1330 struct chfs_mount
*chmp
;
1331 struct chfs_vnode_cache
*chvc
;
1333 KASSERT(VOP_ISLOCKED(vp
));
1335 /* This operation only makes sense on directory nodes. */
1336 if (vp
->v_type
!= VDIR
) {
1343 /* uiomove in chfs_filldir automatically increments the
1344 * uio_offset by an arbitrary size, so we discard any change
1345 * to uio_offset and set it to our own value on return
1347 offset
= uio
->uio_offset
;
1349 if (offset
== CHFS_OFFSET_DOT
) {
1350 error
= chfs_filldir(uio
, ip
->ino
, ".", 1, VDIR
);
1354 } else if (error
!= 0)
1357 offset
= CHFS_OFFSET_DOTDOT
;
1360 if (offset
== CHFS_OFFSET_DOTDOT
) {
1361 ump
= VFSTOUFS(vp
->v_mount
);
1362 chmp
= ump
->um_chfs
;
1363 mutex_enter(&chmp
->chm_lock_vnocache
);
1364 chvc
= chfs_vnode_cache_get(chmp
, ip
->ino
);
1365 mutex_exit(&chmp
->chm_lock_vnocache
);
1367 error
= chfs_filldir(uio
, chvc
->pvno
, "..", 2, VDIR
);
1371 } else if (error
!= 0) {
1375 if (TAILQ_EMPTY(&ip
->dents
)) {
1376 offset
= CHFS_OFFSET_EOF
;
1378 offset
= CHFS_OFFSET_FIRST
;
1382 if (offset
!= CHFS_OFFSET_EOF
) {
1383 skip
= offset
- CHFS_OFFSET_FIRST
;
1385 TAILQ_FOREACH(fd
, &ip
->dents
, fds
) {
1386 /* seek to offset by skipping items */
1387 /* XXX race conditions by changed dirent? */
1394 error
= chfs_filldir(uio
, fd
->vno
,
1395 fd
->name
, fd
->nsize
, fd
->type
);
1399 } else if (error
!= 0) {
1400 dbg("err %d\n", error
);
1407 offset
= CHFS_OFFSET_EOF
;
1410 uio
->uio_offset
= offset
;
1412 if (eofflag
!= NULL
) {
1413 *eofflag
= (error
== 0 &&
1414 uio
->uio_offset
== CHFS_OFFSET_EOF
);
1418 KASSERT(VOP_ISLOCKED(vp
));
1423 /* --------------------------------------------------------------------- */
1426 chfs_readlink(void *v
)
1429 struct vnode
*vp
= ((struct vop_readlink_args
*) v
)->a_vp
;
1430 struct uio
*uio
= ((struct vop_readlink_args
*) v
)->a_uio
;
1431 kauth_cred_t cred
= ((struct vop_readlink_args
*) v
)->a_cred
;
1433 struct chfs_inode
*ip
= VTOI(vp
);
1435 dbg("readlink()\n");
1437 /* TODO max symlink len instead of "100" */
1438 if (ip
->size
< 100) {
1439 uiomove(ip
->target
, ip
->size
, uio
);
1443 return (VOP_READ(vp
, uio
, 0, cred
));
1446 /* --------------------------------------------------------------------- */
1449 chfs_inactive(void *v
)
1451 struct vnode
*vp
= ((struct vop_inactive_args
*) v
)->a_vp
;
1452 struct chfs_inode
*ip
= VTOI(vp
);
1453 struct chfs_vnode_cache
*chvc
;
1454 dbg("inactive | vno: %llu\n", (unsigned long long)ip
->ino
);
1456 KASSERT(VOP_ISLOCKED(vp
));
1461 *((struct vop_inactive_args
*) v
)->a_recycle
= 0;
1463 *((struct vop_inactive_args
*) v
)->a_recycle
= 1;
1471 /* --------------------------------------------------------------------- */
1474 chfs_reclaim(void *v
)
1476 struct vop_reclaim_args
*ap
= v
;
1477 struct vnode
*vp
= ap
->a_vp
;
1478 struct chfs_inode
*ip
= VTOI(vp
);
1479 struct chfs_mount
*chmp
= ip
->chmp
;
1480 struct chfs_dirent
*fd
;
1482 //dbg("reclaim() | ino: %llu\n", (unsigned long long)ip->ino);
1483 //mutex_enter(&ip->inode_lock);
1485 mutex_enter(&chmp
->chm_lock_vnocache
);
1486 chfs_vnode_cache_set_state(chmp
,
1487 ip
->chvc
, VNO_STATE_CHECKEDABSENT
);
1488 mutex_exit(&chmp
->chm_lock_vnocache
);
1490 chfs_update(vp
, NULL
, NULL
, UPDATE_CLOSE
);
1492 if (vp
->v_type
== VREG
|| vp
->v_type
== VLNK
|| vp
->v_type
== VCHR
||
1493 vp
->v_type
== VBLK
|| vp
->v_type
== VFIFO
|| vp
->v_type
== VSOCK
)
1494 chfs_kill_fragtree(&ip
->fragtree
);
1496 fd
= TAILQ_FIRST(&ip
->dents
);
1498 TAILQ_REMOVE(&ip
->dents
, fd
, fds
);
1499 chfs_free_dirent(fd
);
1500 fd
= TAILQ_FIRST(&ip
->dents
);
1502 //mutex_exit(&ip->inode_lock);
1503 //mutex_destroy(&ip->inode_lock);
1512 genfs_node_destroy(vp
);
1513 pool_put(&chfs_inode_pool
, vp
->v_data
);
1518 /* --------------------------------------------------------------------- */
1521 chfs_advlock(void *v
)
1523 //struct vnode *vp = ((struct vop_advlock_args *) v)->a_vp;
1526 struct chfs_node *node;
1528 node = VP_TO_CHFS_NODE(vp);
1530 return lf_advlock(v, &node->chn_lockf, node->chn_size);
1535 /* --------------------------------------------------------------------- */
1537 chfs_strategy(void *v
)
1539 struct vop_strategy_args
/* {
1540 const struct vnodeop_desc *a_desc;
1544 struct chfs_full_dnode
*fd
;
1545 struct buf
*bp
= ap
->a_bp
;
1546 struct vnode
*vp
= ap
->a_vp
;
1547 struct chfs_inode
*ip
= VTOI(vp
);
1548 struct chfs_mount
*chmp
= ip
->chmp
;
1549 int read
= (bp
->b_flags
& B_READ
) ? 1 : 0;
1552 /* dbg("bp dump:\n");
1553 dbg(" ->b_bcount: %d\n", bp->b_bcount);
1554 dbg(" ->b_resid: %d\n", bp->b_resid);
1555 dbg(" ->b_blkno: %llu\n", (unsigned long long)bp->b_blkno);
1556 dbg(" ->b_error: %d\n", bp->b_error);*/
1558 err
= chfs_read_data(chmp
, vp
, bp
);
1560 fd
= chfs_alloc_full_dnode();
1562 mutex_enter(&chmp
->chm_lock_mountfields
);
1564 err
= chfs_write_flash_dnode(chmp
, vp
, bp
, fd
);
1566 mutex_exit(&chmp
->chm_lock_mountfields
);
1570 err
= chfs_add_full_dnode_to_inode(chmp
, ip
, fd
);
1572 mutex_exit(&chmp->chm_lock_mountfields);
1576 mutex_exit(&chmp
->chm_lock_mountfields
);
1587 struct vop_bmap_args
/* {
1590 struct vnode **a_vpp;
1595 if (ap
->a_vpp
!= NULL
)
1596 *ap
->a_vpp
= ap
->a_vp
;
1597 if (ap
->a_bnp
!= NULL
)
1598 *ap
->a_bnp
= ap
->a_bn
;
1599 if (ap
->a_runp
!= NULL
)
1605 * vnode operations vector used for files stored in a chfs file system.
1608 (**chfs_vnodeop_p
)(void *);
1609 const struct vnodeopv_entry_desc chfs_vnodeop_entries
[] =
1611 { &vop_default_desc
, vn_default_error
},
1612 { &vop_lookup_desc
, chfs_lookup
},
1613 { &vop_create_desc
, chfs_create
},
1614 { &vop_mknod_desc
, chfs_mknod
},
1615 { &vop_open_desc
, chfs_open
},
1616 { &vop_close_desc
, chfs_close
},
1617 { &vop_access_desc
, chfs_access
},
1618 { &vop_getattr_desc
, chfs_getattr
},
1619 { &vop_setattr_desc
, chfs_setattr
},
1620 { &vop_read_desc
, chfs_read
},
1621 { &vop_write_desc
, chfs_write
},
1622 { &vop_ioctl_desc
, genfs_enoioctl
},
1623 { &vop_fcntl_desc
, genfs_fcntl
},
1624 { &vop_poll_desc
, genfs_poll
},
1625 { &vop_kqfilter_desc
, genfs_kqfilter
},
1626 { &vop_revoke_desc
, genfs_revoke
},
1627 { &vop_mmap_desc
, genfs_mmap
},
1628 { &vop_fsync_desc
, chfs_fsync
},
1629 { &vop_seek_desc
, genfs_seek
},
1630 { &vop_remove_desc
, chfs_remove
},
1631 { &vop_link_desc
, chfs_link
},
1632 { &vop_rename_desc
, chfs_rename
},
1633 { &vop_mkdir_desc
, chfs_mkdir
},
1634 { &vop_rmdir_desc
, chfs_rmdir
},
1635 { &vop_symlink_desc
, chfs_symlink
},
1636 { &vop_readdir_desc
, chfs_readdir
},
1637 { &vop_readlink_desc
, chfs_readlink
},
1638 { &vop_abortop_desc
, genfs_abortop
},
1639 { &vop_inactive_desc
, chfs_inactive
},
1640 { &vop_reclaim_desc
, chfs_reclaim
},
1641 { &vop_lock_desc
, genfs_lock
},
1642 { &vop_unlock_desc
, genfs_unlock
},
1643 { &vop_bmap_desc
, chfs_bmap
},
1644 { &vop_strategy_desc
, chfs_strategy
},
1645 { &vop_print_desc
, ufs_print
},
1646 { &vop_pathconf_desc
, ufs_pathconf
},
1647 { &vop_islocked_desc
, genfs_islocked
},
1648 { &vop_advlock_desc
, chfs_advlock
},
1649 { &vop_bwrite_desc
, vn_bwrite
},
1650 { &vop_getpages_desc
, genfs_getpages
},
1651 { &vop_putpages_desc
, genfs_putpages
},
1654 const struct vnodeopv_desc chfs_vnodeop_opv_desc
=
1655 { &chfs_vnodeop_p
, chfs_vnodeop_entries
};
1657 /* --------------------------------------------------------------------- */
1660 * vnode operations vector used for special devices stored in a chfs
1664 (**chfs_specop_p
)(void *);
1665 const struct vnodeopv_entry_desc chfs_specop_entries
[] =
1667 { &vop_default_desc
, vn_default_error
},
1668 { &vop_lookup_desc
, spec_lookup
},
1669 { &vop_create_desc
, spec_create
},
1670 { &vop_mknod_desc
, spec_mknod
},
1671 { &vop_open_desc
, spec_open
},
1672 { &vop_close_desc
, ufsspec_close
},
1673 { &vop_access_desc
, chfs_access
},
1674 { &vop_getattr_desc
, chfs_getattr
},
1675 { &vop_setattr_desc
, chfs_setattr
},
1676 { &vop_read_desc
, chfs_read
},
1677 { &vop_write_desc
, chfs_write
},
1678 { &vop_ioctl_desc
, spec_ioctl
},
1679 { &vop_fcntl_desc
, genfs_fcntl
},
1680 { &vop_poll_desc
, spec_poll
},
1681 { &vop_kqfilter_desc
, spec_kqfilter
},
1682 { &vop_revoke_desc
, spec_revoke
},
1683 { &vop_mmap_desc
, spec_mmap
},
1684 { &vop_fsync_desc
, spec_fsync
},
1685 { &vop_seek_desc
, spec_seek
},
1686 { &vop_remove_desc
, spec_remove
},
1687 { &vop_link_desc
, spec_link
},
1688 { &vop_rename_desc
, spec_rename
},
1689 { &vop_mkdir_desc
, spec_mkdir
},
1690 { &vop_rmdir_desc
, spec_rmdir
},
1691 { &vop_symlink_desc
, spec_symlink
},
1692 { &vop_readdir_desc
, spec_readdir
},
1693 { &vop_readlink_desc
, spec_readlink
},
1694 { &vop_abortop_desc
, spec_abortop
},
1695 { &vop_inactive_desc
, chfs_inactive
},
1696 { &vop_reclaim_desc
, chfs_reclaim
},
1697 { &vop_lock_desc
, genfs_lock
},
1698 { &vop_unlock_desc
, genfs_unlock
},
1699 { &vop_bmap_desc
, spec_bmap
},
1700 { &vop_strategy_desc
, spec_strategy
},
1701 { &vop_print_desc
, ufs_print
},
1702 { &vop_pathconf_desc
, spec_pathconf
},
1703 { &vop_islocked_desc
, genfs_islocked
},
1704 { &vop_advlock_desc
, spec_advlock
},
1705 { &vop_bwrite_desc
, vn_bwrite
},
1706 { &vop_getpages_desc
, spec_getpages
},
1707 { &vop_putpages_desc
, spec_putpages
},
1710 const struct vnodeopv_desc chfs_specop_opv_desc
=
1711 { &chfs_specop_p
, chfs_specop_entries
};
1713 /* --------------------------------------------------------------------- */
1715 * vnode operations vector used for fifos stored in a chfs file system.
1718 (**chfs_fifoop_p
)(void *);
1719 const struct vnodeopv_entry_desc chfs_fifoop_entries
[] =
1721 { &vop_default_desc
, vn_default_error
},
1722 { &vop_lookup_desc
, vn_fifo_bypass
},
1723 { &vop_create_desc
, vn_fifo_bypass
},
1724 { &vop_mknod_desc
, vn_fifo_bypass
},
1725 { &vop_open_desc
, vn_fifo_bypass
},
1726 { &vop_close_desc
, ufsfifo_close
},
1727 { &vop_access_desc
, chfs_access
},
1728 { &vop_getattr_desc
, chfs_getattr
},
1729 { &vop_setattr_desc
, chfs_setattr
},
1730 { &vop_read_desc
, ufsfifo_read
},
1731 { &vop_write_desc
, ufsfifo_write
},
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
};