1 /* $NetBSD: puffs_vnops.c,v 1.154 2011/07/04 08:07:30 manu Exp $ */
4 * Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
6 * Development of this software was supported by the
7 * Google Summer of Code program and the Ulla Tuominen Foundation.
8 * The Google SoC project was mentored by Bill Studenmund.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
20 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/param.h>
34 #include <sys/lockf.h>
35 #include <sys/malloc.h>
36 #include <sys/mount.h>
37 #include <sys/namei.h>
38 #include <sys/vnode.h>
41 #include <vfs/fifofs/fifo.h>
43 #include <vfs/puffs/puffs_msgif.h>
44 #include <vfs/puffs/puffs_sys.h>
46 int (**puffs_vnodeop_p
)(void *);
52 } while (/*CONSTCOND*/0)
54 static int callremove(struct puffs_mount
*, puffs_cookie_t
, puffs_cookie_t
,
55 struct namecache
*, struct ucred
*);
56 static int callrmdir(struct puffs_mount
*, puffs_cookie_t
, puffs_cookie_t
,
57 struct namecache
*, struct ucred
*);
58 static void callinactive(struct puffs_mount
*, puffs_cookie_t
, int);
59 static void callreclaim(struct puffs_mount
*, puffs_cookie_t
);
60 static int flushvncache(struct vnode
*, int);
63 #define PUFFS_ABORT_LOOKUP 1
64 #define PUFFS_ABORT_CREATE 2
65 #define PUFFS_ABORT_MKNOD 3
66 #define PUFFS_ABORT_MKDIR 4
67 #define PUFFS_ABORT_SYMLINK 5
70 * Press the pani^Wabort button! Kernel resource allocation failed.
73 puffs_abortbutton(struct puffs_mount
*pmp
, int what
,
74 puffs_cookie_t dck
, puffs_cookie_t ck
,
75 struct namecache
*ncp
, struct ucred
*cred
)
79 case PUFFS_ABORT_CREATE
:
80 case PUFFS_ABORT_MKNOD
:
81 case PUFFS_ABORT_SYMLINK
:
82 callremove(pmp
, dck
, ck
, ncp
, cred
);
84 case PUFFS_ABORT_MKDIR
:
85 callrmdir(pmp
, dck
, ck
, ncp
, cred
);
89 callinactive(pmp
, ck
, 0);
94 * Begin vnode operations.
96 * A word from the keymaster about locks: generally we don't want
97 * to use the vnode locks at all: it creates an ugly dependency between
98 * the userlandia file server and the kernel. But we'll play along with
99 * the kernel vnode locks for now. However, even currently we attempt
100 * to release locks as early as possible. This is possible for some
101 * operations which a) don't need a locked vnode after the userspace op
102 * and b) return with the vnode unlocked. Theoretically we could
103 * unlock-do op-lock for others and order the graph in userspace, but I
104 * don't want to think of the consequences for the time being.
107 puffs_vnop_lookup(struct vop_nresolve_args
*ap
)
109 PUFFS_MSG_VARS(vn
, lookup
);
110 struct puffs_mount
*pmp
= MPTOPUFFSMP(ap
->a_dvp
->v_mount
);
111 struct nchandle
*nch
= ap
->a_nch
;
112 struct namecache
*ncp
= nch
->ncp
;
113 struct ucred
*cred
= ap
->a_cred
;
114 struct vnode
*vp
= NULL
, *dvp
= ap
->a_dvp
;
115 struct puffs_node
*dpn
;
118 DPRINTF(("puffs_lookup: \"%s\", parent vnode %p\n",
121 PUFFS_MSG_ALLOC(vn
, lookup
);
122 puffs_makecn(&lookup_msg
->pvnr_cn
, &lookup_msg
->pvnr_cn_cred
,
125 puffs_msg_setinfo(park_lookup
, PUFFSOP_VN
,
126 PUFFS_VN_LOOKUP
, VPTOPNC(dvp
));
127 PUFFS_MSG_ENQUEUEWAIT2(pmp
, park_lookup
, dvp
->v_data
, NULL
, error
);
128 DPRINTF(("puffs_lookup: return of the userspace, part %d\n", error
));
130 error
= checkerr(pmp
, error
, __func__
);
132 cache_setvp(nch
, NULL
);
137 * Check that we don't get our parent node back, that would cause
138 * a pretty obvious deadlock.
141 if (lookup_msg
->pvnr_newnode
== dpn
->pn_cookie
) {
142 puffs_senderr(pmp
, PUFFS_ERR_LOOKUP
, EINVAL
,
143 "lookup produced parent cookie", lookup_msg
->pvnr_newnode
);
148 error
= puffs_cookie2vnode(pmp
, lookup_msg
->pvnr_newnode
, 1, &vp
);
149 if (error
== PUFFS_NOSUCHCOOKIE
) {
150 error
= puffs_getvnode(dvp
->v_mount
,
151 lookup_msg
->pvnr_newnode
, lookup_msg
->pvnr_vtype
,
152 lookup_msg
->pvnr_size
, &vp
);
154 puffs_abortbutton(pmp
, PUFFS_ABORT_LOOKUP
, VPTOPNC(dvp
),
155 lookup_msg
->pvnr_newnode
, ncp
, cred
);
159 puffs_abortbutton(pmp
, PUFFS_ABORT_LOOKUP
, VPTOPNC(dvp
),
160 lookup_msg
->pvnr_newnode
, ncp
, cred
);
165 if (!error
&& vp
!= NULL
) {
167 cache_setvp(nch
, vp
);
170 DPRINTF(("puffs_lookup: returning %d\n", error
));
171 PUFFS_MSG_RELEASE(lookup
);
176 puffs_vnop_lookupdotdot(struct vop_nlookupdotdot_args
*ap
)
178 PUFFS_MSG_VARS(vn
, lookupdotdot
);
179 struct puffs_mount
*pmp
= MPTOPUFFSMP(ap
->a_dvp
->v_mount
);
180 struct ucred
*cred
= ap
->a_cred
;
181 struct vnode
*vp
, *dvp
= ap
->a_dvp
;
182 struct puffs_node
*dpn
;
187 DPRINTF(("puffs_lookupdotdot: vnode %p\n", dvp
));
189 PUFFS_MSG_ALLOC(vn
, lookupdotdot
);
190 puffs_credcvt(&lookupdotdot_msg
->pvnr_cred
, cred
);
192 puffs_msg_setinfo(park_lookupdotdot
, PUFFSOP_VN
,
193 PUFFS_VN_LOOKUPDOTDOT
, VPTOPNC(dvp
));
194 PUFFS_MSG_ENQUEUEWAIT2(pmp
, park_lookupdotdot
, dvp
->v_data
, NULL
,
196 DPRINTF(("puffs_lookupdotdot: return of the userspace, part %d\n",
199 error
= checkerr(pmp
, error
, __func__
);
204 * Check that we don't get our node back, that would cause
205 * a pretty obvious deadlock.
208 if (lookupdotdot_msg
->pvnr_newnode
== dpn
->pn_cookie
) {
209 puffs_senderr(pmp
, PUFFS_ERR_LOOKUP
, EINVAL
,
210 "lookupdotdot produced the same cookie",
211 lookupdotdot_msg
->pvnr_newnode
);
216 error
= puffs_cookie2vnode(pmp
, lookupdotdot_msg
->pvnr_newnode
,
218 if (error
== PUFFS_NOSUCHCOOKIE
) {
219 error
= puffs_getvnode(dvp
->v_mount
,
220 lookupdotdot_msg
->pvnr_newnode
, VDIR
, 0, &vp
);
222 puffs_abortbutton(pmp
, PUFFS_ABORT_LOOKUP
, VPTOPNC(dvp
),
223 lookupdotdot_msg
->pvnr_newnode
, NULL
, cred
);
227 puffs_abortbutton(pmp
, PUFFS_ABORT_LOOKUP
, VPTOPNC(dvp
),
228 lookupdotdot_msg
->pvnr_newnode
, NULL
, cred
);
236 DPRINTF(("puffs_lookupdotdot: returning %d %p\n", error
, *ap
->a_vpp
));
237 PUFFS_MSG_RELEASE(lookupdotdot
);
242 puffs_vnop_create(struct vop_ncreate_args
*ap
)
244 PUFFS_MSG_VARS(vn
, create
);
245 struct vnode
*dvp
= ap
->a_dvp
;
246 struct vattr
*vap
= ap
->a_vap
;
247 struct puffs_node
*dpn
= VPTOPP(dvp
);
248 struct nchandle
*nch
= ap
->a_nch
;
249 struct namecache
*ncp
= nch
->ncp
;
250 struct ucred
*cred
= ap
->a_cred
;
251 struct mount
*mp
= dvp
->v_mount
;
252 struct puffs_mount
*pmp
= MPTOPUFFSMP(mp
);
255 if (!EXISTSOP(pmp
, CREATE
))
258 DPRINTF(("puffs_create: dvp %p, name: %s\n",
261 if (vap
->va_type
!= VREG
&& vap
->va_type
!= VSOCK
)
264 if ((error
= vget(dvp
, LK_EXCLUSIVE
)) != 0) {
265 DPRINTF(("puffs_vnop_create: EAGAIN on ncp %p %s\n",
270 PUFFS_MSG_ALLOC(vn
, create
);
271 puffs_makecn(&create_msg
->pvnr_cn
, &create_msg
->pvnr_cn_cred
,
273 create_msg
->pvnr_va
= *ap
->a_vap
;
274 puffs_msg_setinfo(park_create
, PUFFSOP_VN
,
275 PUFFS_VN_CREATE
, VPTOPNC(dvp
));
276 PUFFS_MSG_ENQUEUEWAIT2(pmp
, park_create
, dvp
->v_data
, NULL
, error
);
278 error
= checkerr(pmp
, error
, __func__
);
282 error
= puffs_newnode(mp
, dvp
, ap
->a_vpp
,
283 create_msg
->pvnr_newnode
, vap
->va_type
);
285 puffs_abortbutton(pmp
, PUFFS_ABORT_CREATE
, dpn
->pn_cookie
,
286 create_msg
->pvnr_newnode
, ncp
, cred
);
289 DPRINTF(("puffs_create: return %d\n", error
));
292 cache_setunresolved(nch
);
293 cache_setvp(nch
, *ap
->a_vpp
);
295 PUFFS_MSG_RELEASE(create
);
300 puffs_vnop_mknod(struct vop_nmknod_args
*ap
)
302 PUFFS_MSG_VARS(vn
, mknod
);
303 struct vnode
*dvp
= ap
->a_dvp
;
304 struct vattr
*vap
= ap
->a_vap
;
305 struct puffs_node
*dpn
= VPTOPP(dvp
);
306 struct nchandle
*nch
= ap
->a_nch
;
307 struct namecache
*ncp
= nch
->ncp
;
308 struct ucred
*cred
= ap
->a_cred
;
309 struct mount
*mp
= dvp
->v_mount
;
310 struct puffs_mount
*pmp
= MPTOPUFFSMP(mp
);
313 if (!EXISTSOP(pmp
, MKNOD
))
316 DPRINTF(("puffs_mknod: dvp %p, name: %s\n",
319 if (vap
->va_type
!= VFIFO
)
322 if ((error
= vget(dvp
, LK_EXCLUSIVE
)) != 0) {
323 DPRINTF(("puffs_vnop_mknod: EAGAIN on ncp %p %s\n",
328 PUFFS_MSG_ALLOC(vn
, mknod
);
329 puffs_makecn(&mknod_msg
->pvnr_cn
, &mknod_msg
->pvnr_cn_cred
,
331 mknod_msg
->pvnr_va
= *ap
->a_vap
;
332 puffs_msg_setinfo(park_mknod
, PUFFSOP_VN
,
333 PUFFS_VN_MKNOD
, VPTOPNC(dvp
));
335 PUFFS_MSG_ENQUEUEWAIT2(pmp
, park_mknod
, dvp
->v_data
, NULL
, error
);
337 error
= checkerr(pmp
, error
, __func__
);
341 error
= puffs_newnode(mp
, dvp
, ap
->a_vpp
,
342 mknod_msg
->pvnr_newnode
, vap
->va_type
);
344 puffs_abortbutton(pmp
, PUFFS_ABORT_MKNOD
, dpn
->pn_cookie
,
345 mknod_msg
->pvnr_newnode
, ncp
, cred
);
350 cache_setunresolved(nch
);
351 cache_setvp(nch
, *ap
->a_vpp
);
353 PUFFS_MSG_RELEASE(mknod
);
358 puffs_vnop_open(struct vop_open_args
*ap
)
360 PUFFS_MSG_VARS(vn
, open
);
361 struct vnode
*vp
= ap
->a_vp
;
362 struct puffs_mount
*pmp
= MPTOPUFFSMP(vp
->v_mount
);
363 int mode
= ap
->a_mode
;
366 DPRINTF(("puffs_open: vp %p, mode 0x%x\n", vp
, mode
));
368 if (vp
->v_type
== VREG
&& mode
& FWRITE
&& !EXISTSOP(pmp
, WRITE
))
371 if (!EXISTSOP(pmp
, OPEN
))
374 PUFFS_MSG_ALLOC(vn
, open
);
375 open_msg
->pvnr_mode
= mode
;
376 puffs_credcvt(&open_msg
->pvnr_cred
, ap
->a_cred
);
377 puffs_msg_setinfo(park_open
, PUFFSOP_VN
,
378 PUFFS_VN_OPEN
, VPTOPNC(vp
));
380 PUFFS_MSG_ENQUEUEWAIT2(pmp
, park_open
, vp
->v_data
, NULL
, error
);
381 error
= checkerr(pmp
, error
, __func__
);
384 DPRINTF(("puffs_open: returning %d\n", error
));
385 PUFFS_MSG_RELEASE(open
);
388 return vop_stdopen(ap
);
392 puffs_vnop_close(struct vop_close_args
*ap
)
394 PUFFS_MSG_VARS(vn
, close
);
395 struct vnode
*vp
= ap
->a_vp
;
396 struct puffs_mount
*pmp
= MPTOPUFFSMP(vp
->v_mount
);
398 if (!EXISTSOP(pmp
, CLOSE
))
399 return vop_stdclose(ap
);
401 PUFFS_MSG_ALLOC(vn
, close
);
402 puffs_msg_setfaf(park_close
);
403 close_msg
->pvnr_fflag
= ap
->a_fflag
;
404 puffs_msg_setinfo(park_close
, PUFFSOP_VN
,
405 PUFFS_VN_CLOSE
, VPTOPNC(vp
));
407 puffs_msg_enqueue(pmp
, park_close
);
408 PUFFS_MSG_RELEASE(close
);
409 return vop_stdclose(ap
);
413 puffs_vnop_access(struct vop_access_args
*ap
)
415 PUFFS_MSG_VARS(vn
, access
);
416 struct vnode
*vp
= ap
->a_vp
;
417 struct puffs_mount
*pmp
= MPTOPUFFSMP(vp
->v_mount
);
418 int mode
= ap
->a_mode
;
422 switch (vp
->v_type
) {
426 if ((vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
427 || !EXISTSOP(pmp
, WRITE
))
435 if (!EXISTSOP(pmp
, ACCESS
))
438 PUFFS_MSG_ALLOC(vn
, access
);
439 access_msg
->pvnr_mode
= ap
->a_mode
;
440 puffs_credcvt(&access_msg
->pvnr_cred
, ap
->a_cred
);
441 puffs_msg_setinfo(park_access
, PUFFSOP_VN
,
442 PUFFS_VN_ACCESS
, VPTOPNC(vp
));
444 PUFFS_MSG_ENQUEUEWAIT2(pmp
, park_access
, vp
->v_data
, NULL
, error
);
445 error
= checkerr(pmp
, error
, __func__
);
446 PUFFS_MSG_RELEASE(access
);
452 puffs_vnop_getattr(struct vop_getattr_args
*ap
)
454 PUFFS_MSG_VARS(vn
, getattr
);
455 struct vnode
*vp
= ap
->a_vp
;
456 struct mount
*mp
= vp
->v_mount
;
457 struct puffs_mount
*pmp
= MPTOPUFFSMP(mp
);
458 struct vattr
*vap
, *rvap
;
459 struct puffs_node
*pn
= VPTOPP(vp
);
462 if (vp
->v_type
== VBLK
|| vp
->v_type
== VCHR
)
467 PUFFS_MSG_ALLOC(vn
, getattr
);
468 vattr_null(&getattr_msg
->pvnr_va
);
469 puffs_credcvt(&getattr_msg
->pvnr_cred
, curproc
->p_ucred
);
470 puffs_msg_setinfo(park_getattr
, PUFFSOP_VN
,
471 PUFFS_VN_GETATTR
, VPTOPNC(vp
));
473 PUFFS_MSG_ENQUEUEWAIT2(pmp
, park_getattr
, vp
->v_data
, NULL
, error
);
474 error
= checkerr(pmp
, error
, __func__
);
478 rvap
= &getattr_msg
->pvnr_va
;
480 (void) memcpy(vap
, rvap
, sizeof(struct vattr
));
481 vap
->va_fsid
= mp
->mnt_stat
.f_fsid
.val
[0];
483 if (pn
->pn_stat
& PNODE_METACACHE_ATIME
)
484 vap
->va_atime
= pn
->pn_mc_atime
;
485 if (pn
->pn_stat
& PNODE_METACACHE_CTIME
)
486 vap
->va_ctime
= pn
->pn_mc_ctime
;
487 if (pn
->pn_stat
& PNODE_METACACHE_MTIME
)
488 vap
->va_mtime
= pn
->pn_mc_mtime
;
489 if (pn
->pn_stat
& PNODE_METACACHE_SIZE
) {
490 vap
->va_size
= pn
->pn_mc_size
;
492 if (rvap
->va_size
!= VNOVAL
493 && vp
->v_type
!= VBLK
&& vp
->v_type
!= VCHR
) {
494 pn
->pn_serversize
= rvap
->va_size
;
495 if (vp
->v_type
== VREG
)
496 puffs_meta_setsize(vp
, rvap
->va_size
, 0);
501 PUFFS_MSG_RELEASE(getattr
);
505 #define SETATTR_CHSIZE 0x01
506 #define SETATTR_ASYNC 0x02
508 dosetattr(struct vnode
*vp
, struct vattr
*vap
, struct ucred
*cred
, int flags
)
510 PUFFS_MSG_VARS(vn
, setattr
);
511 struct puffs_mount
*pmp
= MPTOPUFFSMP(vp
->v_mount
);
512 struct puffs_node
*pn
= VPTOPP(vp
);
515 if ((vp
->v_mount
->mnt_flag
& MNT_RDONLY
) &&
516 (vap
->va_uid
!= (uid_t
)VNOVAL
|| vap
->va_gid
!= (gid_t
)VNOVAL
517 || vap
->va_atime
.tv_sec
!= VNOVAL
|| vap
->va_mtime
.tv_sec
!= VNOVAL
518 || vap
->va_mode
!= (mode_t
)VNOVAL
))
521 if ((vp
->v_mount
->mnt_flag
& MNT_RDONLY
)
522 && vp
->v_type
== VREG
&& vap
->va_size
!= VNOVAL
)
526 * Flush metacache first. If we are called with some explicit
527 * parameters, treat them as information overriding metacache
530 if (pn
->pn_stat
& PNODE_METACACHE_MASK
) {
531 if ((pn
->pn_stat
& PNODE_METACACHE_ATIME
)
532 && vap
->va_atime
.tv_sec
== VNOVAL
)
533 vap
->va_atime
= pn
->pn_mc_atime
;
534 if ((pn
->pn_stat
& PNODE_METACACHE_CTIME
)
535 && vap
->va_ctime
.tv_sec
== VNOVAL
)
536 vap
->va_ctime
= pn
->pn_mc_ctime
;
537 if ((pn
->pn_stat
& PNODE_METACACHE_MTIME
)
538 && vap
->va_mtime
.tv_sec
== VNOVAL
)
539 vap
->va_mtime
= pn
->pn_mc_mtime
;
540 if ((pn
->pn_stat
& PNODE_METACACHE_SIZE
)
541 && vap
->va_size
== VNOVAL
)
542 vap
->va_size
= pn
->pn_mc_size
;
544 pn
->pn_stat
&= ~PNODE_METACACHE_MASK
;
547 PUFFS_MSG_ALLOC(vn
, setattr
);
548 (void)memcpy(&setattr_msg
->pvnr_va
, vap
, sizeof(struct vattr
));
549 puffs_credcvt(&setattr_msg
->pvnr_cred
, cred
);
550 puffs_msg_setinfo(park_setattr
, PUFFSOP_VN
,
551 PUFFS_VN_SETATTR
, VPTOPNC(vp
));
552 if (flags
& SETATTR_ASYNC
)
553 puffs_msg_setfaf(park_setattr
);
555 puffs_msg_enqueue(pmp
, park_setattr
);
556 if ((flags
& SETATTR_ASYNC
) == 0)
557 error
= puffs_msg_wait2(pmp
, park_setattr
, vp
->v_data
, NULL
);
558 PUFFS_MSG_RELEASE(setattr
);
559 if ((flags
& SETATTR_ASYNC
) == 0) {
560 error
= checkerr(pmp
, error
, __func__
);
567 if (vap
->va_size
!= VNOVAL
) {
568 pn
->pn_serversize
= vap
->va_size
;
569 if (flags
& SETATTR_CHSIZE
)
570 puffs_meta_setsize(vp
, vap
->va_size
, 0);
577 puffs_vnop_setattr(struct vop_setattr_args
*ap
)
579 return dosetattr(ap
->a_vp
, ap
->a_vap
, ap
->a_cred
, SETATTR_CHSIZE
);
583 doinact(struct puffs_mount
*pmp
, int iaflag
)
586 if (EXISTSOP(pmp
, INACTIVE
))
587 if (pmp
->pmp_flags
& PUFFS_KFLAG_IAONDEMAND
)
588 if (iaflag
|| ALLOPS(pmp
))
599 callinactive(struct puffs_mount
*pmp
, puffs_cookie_t ck
, int iaflag
)
602 PUFFS_MSG_VARS(vn
, inactive
);
604 if (doinact(pmp
, iaflag
)) {
605 PUFFS_MSG_ALLOC(vn
, inactive
);
606 puffs_msg_setinfo(park_inactive
, PUFFSOP_VN
,
607 PUFFS_VN_INACTIVE
, ck
);
609 PUFFS_MSG_ENQUEUEWAIT(pmp
, park_inactive
, error
);
610 PUFFS_MSG_RELEASE(inactive
);
614 /* XXX: callinactive can't setback */
616 puffs_vnop_inactive(struct vop_inactive_args
*ap
)
618 PUFFS_MSG_VARS(vn
, inactive
);
619 struct vnode
*vp
= ap
->a_vp
;
620 struct puffs_mount
*pmp
= MPTOPUFFSMP(vp
->v_mount
);
621 struct puffs_node
*pnode
= VPTOPP(vp
);
623 flushvncache(vp
, MNT_NOWAIT
);
625 if (doinact(pmp
, pnode
->pn_stat
& PNODE_DOINACT
)) {
627 * do not wait for reply from userspace, otherwise it may
631 PUFFS_MSG_ALLOC(vn
, inactive
);
632 puffs_msg_setfaf(park_inactive
);
633 puffs_msg_setinfo(park_inactive
, PUFFSOP_VN
,
634 PUFFS_VN_INACTIVE
, VPTOPNC(vp
));
636 puffs_msg_enqueue(pmp
, park_inactive
);
637 PUFFS_MSG_RELEASE(inactive
);
639 pnode
->pn_stat
&= ~PNODE_DOINACT
;
642 * file server thinks it's gone? then don't be afraid care,
643 * node's life was already all it would ever be
645 if (pnode
->pn_stat
& PNODE_NOREFS
) {
646 pnode
->pn_stat
|= PNODE_DYING
;
654 callreclaim(struct puffs_mount
*pmp
, puffs_cookie_t ck
)
656 PUFFS_MSG_VARS(vn
, reclaim
);
658 if (!EXISTSOP(pmp
, RECLAIM
))
661 PUFFS_MSG_ALLOC(vn
, reclaim
);
662 puffs_msg_setfaf(park_reclaim
);
663 puffs_msg_setinfo(park_reclaim
, PUFFSOP_VN
, PUFFS_VN_RECLAIM
, ck
);
665 puffs_msg_enqueue(pmp
, park_reclaim
);
666 PUFFS_MSG_RELEASE(reclaim
);
670 * always FAF, we don't really care if the server wants to fail to
671 * reclaim the node or not
674 puffs_vnop_reclaim(struct vop_reclaim_args
*ap
)
676 struct vnode
*vp
= ap
->a_vp
;
677 struct puffs_mount
*pmp
= MPTOPUFFSMP(vp
->v_mount
);
678 struct puffs_node
*pnode
= VPTOPP(vp
);
679 boolean_t notifyserver
= TRUE
;
681 vinvalbuf(vp
, V_SAVE
, 0, 0);
684 * first things first: check if someone is trying to reclaim the
685 * root vnode. do not allow that to travel to userspace.
686 * Note that we don't need to take the lock similarly to
687 * puffs_root(), since there is only one of us.
689 if (vp
->v_flag
& VROOT
) {
690 lockmgr(&pmp
->pmp_lock
, LK_EXCLUSIVE
);
691 KKASSERT(pmp
->pmp_root
!= NULL
);
692 pmp
->pmp_root
= NULL
;
693 lockmgr(&pmp
->pmp_lock
, LK_RELEASE
);
694 notifyserver
= FALSE
;
698 * purge info from kernel before issueing FAF, since we
699 * don't really know when we'll get around to it after
700 * that and someone might race us into node creation
702 lockmgr(&pmp
->pmp_lock
, LK_EXCLUSIVE
);
703 LIST_REMOVE(pnode
, pn_hashent
);
704 lockmgr(&pmp
->pmp_lock
, LK_RELEASE
);
707 callreclaim(MPTOPUFFSMP(vp
->v_mount
), VPTOPNC(vp
));
715 #define CSIZE sizeof(**ap->a_cookies)
717 puffs_vnop_readdir(struct vop_readdir_args
*ap
)
719 PUFFS_MSG_VARS(vn
, readdir
);
720 struct vnode
*vp
= ap
->a_vp
;
721 struct puffs_mount
*pmp
= MPTOPUFFSMP(vp
->v_mount
);
722 size_t argsize
, tomove
, cookiemem
, cookiesmax
;
723 struct uio
*uio
= ap
->a_uio
;
724 size_t howmuch
, resid
;
727 if (!EXISTSOP(pmp
, READDIR
))
731 * ok, so we need: resid + cookiemem = maxreq
732 * => resid + cookiesize * (resid/minsize) = maxreq
733 * => resid + cookiesize/minsize * resid = maxreq
734 * => (cookiesize/minsize + 1) * resid = maxreq
735 * => resid = maxreq / (cookiesize/minsize + 1)
737 * Since cookiesize <= minsize and we're not very big on floats,
738 * we approximate that to be 1. Therefore:
740 * resid = maxreq / 2;
742 * Well, at least we didn't have to use differential equations
743 * or the Gram-Schmidt process.
745 * (yes, I'm very afraid of this)
747 KKASSERT(CSIZE
<= _DIRENT_RECLEN(1));
750 KKASSERT(ap
->a_ncookies
!= NULL
);
751 if (pmp
->pmp_args
.pa_fhsize
== 0)
753 resid
= PUFFS_TOMOVE(uio
->uio_resid
, pmp
) / 2;
754 cookiesmax
= resid
/_DIRENT_RECLEN(1);
755 cookiemem
= ALIGN(cookiesmax
*CSIZE
); /* play safe */
757 resid
= PUFFS_TOMOVE(uio
->uio_resid
, pmp
);
762 argsize
= sizeof(struct puffs_vnmsg_readdir
);
763 tomove
= resid
+ cookiemem
;
764 puffs_msgmem_alloc(argsize
+ tomove
, &park_readdir
,
765 (void *)&readdir_msg
, 1);
767 puffs_credcvt(&readdir_msg
->pvnr_cred
, ap
->a_cred
);
768 readdir_msg
->pvnr_offset
= uio
->uio_offset
;
769 readdir_msg
->pvnr_resid
= resid
;
770 readdir_msg
->pvnr_ncookies
= cookiesmax
;
771 readdir_msg
->pvnr_eofflag
= 0;
772 readdir_msg
->pvnr_dentoff
= cookiemem
;
773 puffs_msg_setinfo(park_readdir
, PUFFSOP_VN
,
774 PUFFS_VN_READDIR
, VPTOPNC(vp
));
775 puffs_msg_setdelta(park_readdir
, tomove
);
777 PUFFS_MSG_ENQUEUEWAIT2(pmp
, park_readdir
, vp
->v_data
, NULL
, error
);
778 error
= checkerr(pmp
, error
, __func__
);
782 /* userspace is cheating? */
783 if (readdir_msg
->pvnr_resid
> resid
) {
784 puffs_senderr(pmp
, PUFFS_ERR_READDIR
, E2BIG
,
785 "resid grew", VPTOPNC(vp
));
788 if (readdir_msg
->pvnr_ncookies
> cookiesmax
) {
789 puffs_senderr(pmp
, PUFFS_ERR_READDIR
, E2BIG
,
790 "too many cookies", VPTOPNC(vp
));
795 if (readdir_msg
->pvnr_eofflag
)
798 /* bouncy-wouncy with the directory data */
799 howmuch
= resid
- readdir_msg
->pvnr_resid
;
801 /* force eof if no data was returned (getcwd() needs this) */
807 error
= uiomove(readdir_msg
->pvnr_data
+ cookiemem
, howmuch
, uio
);
811 /* provide cookies to caller if so desired */
813 *ap
->a_cookies
= kmalloc(readdir_msg
->pvnr_ncookies
*CSIZE
,
815 *ap
->a_ncookies
= readdir_msg
->pvnr_ncookies
;
816 memcpy(*ap
->a_cookies
, readdir_msg
->pvnr_data
,
817 *ap
->a_ncookies
*CSIZE
);
820 /* next readdir starts here */
821 uio
->uio_offset
= readdir_msg
->pvnr_offset
;
824 puffs_msgmem_release(park_readdir
);
830 flushvncache(struct vnode
*vp
, int waitfor
)
832 struct puffs_node
*pn
= VPTOPP(vp
);
836 /* flush out information from our metacache, see vop_setattr */
837 if (pn
->pn_stat
& PNODE_METACACHE_MASK
838 && (pn
->pn_stat
& PNODE_DYING
) == 0) {
840 error
= dosetattr(vp
, &va
, FSCRED
, SETATTR_CHSIZE
|
841 (waitfor
== MNT_NOWAIT
? 0 : SETATTR_ASYNC
));
847 * flush pages to avoid being overly dirty
849 vfsync(vp
, waitfor
, 0, NULL
, NULL
);
855 puffs_vnop_fsync(struct vop_fsync_args
*ap
)
857 PUFFS_MSG_VARS(vn
, fsync
);
858 struct vnode
*vp
= ap
->a_vp
;
859 int waitfor
= ap
->a_waitfor
;
860 struct puffs_mount
*pmp
= MPTOPUFFSMP(vp
->v_mount
);
861 struct puffs_node
*pn
= VPTOPP(vp
);
864 error
= flushvncache(vp
, waitfor
);
869 * HELLO! We exit already here if the user server does not
870 * support fsync OR if we should call fsync for a node which
871 * has references neither in the kernel or the fs server.
872 * Otherwise we continue to issue fsync() forward.
874 if (!EXISTSOP(pmp
, FSYNC
) || (pn
->pn_stat
& PNODE_DYING
))
877 dofaf
= (waitfor
& MNT_WAIT
) == 0 || (waitfor
& MNT_LAZY
) != 0;
879 PUFFS_MSG_ALLOC(vn
, fsync
);
881 puffs_msg_setfaf(park_fsync
);
883 fsync_msg
->pvnr_flags
= ap
->a_flags
;
884 puffs_msg_setinfo(park_fsync
, PUFFSOP_VN
,
885 PUFFS_VN_FSYNC
, VPTOPNC(vp
));
887 PUFFS_MSG_ENQUEUEWAIT2(pmp
, park_fsync
, vp
->v_data
, NULL
, error
);
888 PUFFS_MSG_RELEASE(fsync
);
890 error
= checkerr(pmp
, error
, __func__
);
896 callremove(struct puffs_mount
*pmp
, puffs_cookie_t dck
, puffs_cookie_t ck
,
897 struct namecache
*ncp
, struct ucred
*cred
)
899 PUFFS_MSG_VARS(vn
, remove
);
902 PUFFS_MSG_ALLOC(vn
, remove
);
903 remove_msg
->pvnr_cookie_targ
= ck
;
904 puffs_makecn(&remove_msg
->pvnr_cn
, &remove_msg
->pvnr_cn_cred
,
906 puffs_msg_setinfo(park_remove
, PUFFSOP_VN
, PUFFS_VN_REMOVE
, dck
);
908 PUFFS_MSG_ENQUEUEWAIT(pmp
, park_remove
, error
);
909 PUFFS_MSG_RELEASE(remove
);
911 return checkerr(pmp
, error
, __func__
);
915 * XXX: can't use callremove now because can't catch setbacks with
916 * it due to lack of a pnode argument.
919 puffs_vnop_remove(struct vop_nremove_args
*ap
)
921 PUFFS_MSG_VARS(vn
, remove
);
922 struct vnode
*dvp
= ap
->a_dvp
;
924 struct puffs_node
*dpn
= VPTOPP(dvp
);
925 struct puffs_node
*pn
;
926 struct nchandle
*nch
= ap
->a_nch
;
927 struct namecache
*ncp
= nch
->ncp
;
928 struct ucred
*cred
= ap
->a_cred
;
929 struct mount
*mp
= dvp
->v_mount
;
930 struct puffs_mount
*pmp
= MPTOPUFFSMP(mp
);
933 if (!EXISTSOP(pmp
, REMOVE
))
936 error
= vget(dvp
, LK_EXCLUSIVE
);
938 DPRINTF(("puffs_vnop_remove: EAGAIN on parent vnode %p %s\n",
943 error
= cache_vget(nch
, cred
, LK_EXCLUSIVE
, &vp
);
945 DPRINTF(("puffs_vnop_remove: cache_vget error: %p %s\n",
949 if (vp
->v_type
== VDIR
) {
955 PUFFS_MSG_ALLOC(vn
, remove
);
956 remove_msg
->pvnr_cookie_targ
= VPTOPNC(vp
);
957 puffs_makecn(&remove_msg
->pvnr_cn
, &remove_msg
->pvnr_cn_cred
,
959 puffs_msg_setinfo(park_remove
, PUFFSOP_VN
,
960 PUFFS_VN_REMOVE
, VPTOPNC(dvp
));
962 puffs_msg_enqueue(pmp
, park_remove
);
963 error
= puffs_msg_wait2(pmp
, park_remove
, dpn
, pn
);
965 PUFFS_MSG_RELEASE(remove
);
967 error
= checkerr(pmp
, error
, __func__
);
973 cache_setunresolved(nch
);
974 cache_setvp(nch
, NULL
);
981 puffs_vnop_mkdir(struct vop_nmkdir_args
*ap
)
983 PUFFS_MSG_VARS(vn
, mkdir
);
984 struct vnode
*dvp
= ap
->a_dvp
;
985 struct puffs_node
*dpn
= VPTOPP(dvp
);
986 struct nchandle
*nch
= ap
->a_nch
;
987 struct namecache
*ncp
= nch
->ncp
;
988 struct ucred
*cred
= ap
->a_cred
;
989 struct mount
*mp
= dvp
->v_mount
;
990 struct puffs_mount
*pmp
= MPTOPUFFSMP(mp
);
993 if (!EXISTSOP(pmp
, MKDIR
))
996 if ((error
= vget(dvp
, LK_EXCLUSIVE
)) != 0) {
997 DPRINTF(("puffs_vnop_mkdir: EAGAIN on ncp %p %s\n",
1002 PUFFS_MSG_ALLOC(vn
, mkdir
);
1003 puffs_makecn(&mkdir_msg
->pvnr_cn
, &mkdir_msg
->pvnr_cn_cred
,
1005 mkdir_msg
->pvnr_va
= *ap
->a_vap
;
1006 puffs_msg_setinfo(park_mkdir
, PUFFSOP_VN
,
1007 PUFFS_VN_MKDIR
, VPTOPNC(dvp
));
1009 PUFFS_MSG_ENQUEUEWAIT2(pmp
, park_mkdir
, dvp
->v_data
, NULL
, error
);
1011 error
= checkerr(pmp
, error
, __func__
);
1015 error
= puffs_newnode(mp
, dvp
, ap
->a_vpp
,
1016 mkdir_msg
->pvnr_newnode
, VDIR
);
1018 puffs_abortbutton(pmp
, PUFFS_ABORT_MKDIR
, dpn
->pn_cookie
,
1019 mkdir_msg
->pvnr_newnode
, ncp
, cred
);
1024 cache_setunresolved(nch
);
1025 cache_setvp(nch
, *ap
->a_vpp
);
1027 PUFFS_MSG_RELEASE(mkdir
);
1032 callrmdir(struct puffs_mount
*pmp
, puffs_cookie_t dck
, puffs_cookie_t ck
,
1033 struct namecache
*ncp
, struct ucred
*cred
)
1035 PUFFS_MSG_VARS(vn
, rmdir
);
1038 PUFFS_MSG_ALLOC(vn
, rmdir
);
1039 rmdir_msg
->pvnr_cookie_targ
= ck
;
1040 puffs_makecn(&rmdir_msg
->pvnr_cn
, &rmdir_msg
->pvnr_cn_cred
,
1042 puffs_msg_setinfo(park_rmdir
, PUFFSOP_VN
, PUFFS_VN_RMDIR
, dck
);
1044 PUFFS_MSG_ENQUEUEWAIT(pmp
, park_rmdir
, error
);
1045 PUFFS_MSG_RELEASE(rmdir
);
1047 return checkerr(pmp
, error
, __func__
);
1051 puffs_vnop_rmdir(struct vop_nrmdir_args
*ap
)
1053 PUFFS_MSG_VARS(vn
, rmdir
);
1054 struct vnode
*dvp
= ap
->a_dvp
;
1056 struct puffs_node
*dpn
= VPTOPP(dvp
);
1057 struct puffs_node
*pn
;
1058 struct puffs_mount
*pmp
= MPTOPUFFSMP(dvp
->v_mount
);
1059 struct nchandle
*nch
= ap
->a_nch
;
1060 struct namecache
*ncp
= nch
->ncp
;
1061 struct ucred
*cred
= ap
->a_cred
;
1064 if (!EXISTSOP(pmp
, RMDIR
))
1067 error
= vget(dvp
, LK_EXCLUSIVE
);
1069 DPRINTF(("puffs_vnop_rmdir: EAGAIN on parent vnode %p %s\n",
1070 dvp
, ncp
->nc_name
));
1073 error
= cache_vget(nch
, cred
, LK_EXCLUSIVE
, &vp
);
1075 DPRINTF(("puffs_vnop_rmdir: cache_vget error: %p %s\n",
1076 dvp
, ncp
->nc_name
));
1079 if (vp
->v_type
!= VDIR
) {
1085 PUFFS_MSG_ALLOC(vn
, rmdir
);
1086 rmdir_msg
->pvnr_cookie_targ
= VPTOPNC(vp
);
1087 puffs_makecn(&rmdir_msg
->pvnr_cn
, &rmdir_msg
->pvnr_cn_cred
,
1089 puffs_msg_setinfo(park_rmdir
, PUFFSOP_VN
,
1090 PUFFS_VN_RMDIR
, VPTOPNC(dvp
));
1092 puffs_msg_enqueue(pmp
, park_rmdir
);
1093 error
= puffs_msg_wait2(pmp
, park_rmdir
, dpn
, pn
);
1095 PUFFS_MSG_RELEASE(rmdir
);
1097 error
= checkerr(pmp
, error
, __func__
);
1103 cache_setunresolved(nch
);
1104 cache_setvp(nch
, NULL
);
1111 puffs_vnop_link(struct vop_nlink_args
*ap
)
1113 PUFFS_MSG_VARS(vn
, link
);
1114 struct vnode
*dvp
= ap
->a_dvp
;
1115 struct vnode
*vp
= ap
->a_vp
;
1116 struct puffs_node
*dpn
= VPTOPP(dvp
);
1117 struct puffs_node
*pn
= VPTOPP(vp
);
1118 struct puffs_mount
*pmp
= MPTOPUFFSMP(dvp
->v_mount
);
1119 struct nchandle
*nch
= ap
->a_nch
;
1120 struct namecache
*ncp
= nch
->ncp
;
1121 struct ucred
*cred
= ap
->a_cred
;
1124 if (!EXISTSOP(pmp
, LINK
))
1127 if (vp
->v_mount
!= dvp
->v_mount
)
1130 if ((error
= vget(dvp
, LK_EXCLUSIVE
)) != 0) {
1131 DPRINTF(("puffs_vnop_link: EAGAIN on ncp %p %s\n",
1132 ncp
, ncp
->nc_name
));
1136 PUFFS_MSG_ALLOC(vn
, link
);
1137 link_msg
->pvnr_cookie_targ
= VPTOPNC(vp
);
1138 puffs_makecn(&link_msg
->pvnr_cn
, &link_msg
->pvnr_cn_cred
,
1140 puffs_msg_setinfo(park_link
, PUFFSOP_VN
,
1141 PUFFS_VN_LINK
, VPTOPNC(dvp
));
1143 puffs_msg_enqueue(pmp
, park_link
);
1144 error
= puffs_msg_wait2(pmp
, park_link
, dpn
, pn
);
1146 PUFFS_MSG_RELEASE(link
);
1148 error
= checkerr(pmp
, error
, __func__
);
1151 * XXX: stay in touch with the cache. I don't like this, but
1152 * don't have a better solution either. See also puffs_rename().
1155 puffs_updatenode(pn
, PUFFS_UPDATECTIME
);
1160 cache_setunresolved(nch
);
1161 cache_setvp(nch
, vp
);
1167 puffs_vnop_symlink(struct vop_nsymlink_args
*ap
)
1169 PUFFS_MSG_VARS(vn
, symlink
);
1170 struct vnode
*dvp
= ap
->a_dvp
;
1171 struct puffs_node
*dpn
= VPTOPP(dvp
);
1172 struct mount
*mp
= dvp
->v_mount
;
1173 struct puffs_mount
*pmp
= MPTOPUFFSMP(dvp
->v_mount
);
1174 struct nchandle
*nch
= ap
->a_nch
;
1175 struct namecache
*ncp
= nch
->ncp
;
1176 struct ucred
*cred
= ap
->a_cred
;
1179 if (!EXISTSOP(pmp
, SYMLINK
))
1182 if ((error
= vget(dvp
, LK_EXCLUSIVE
)) != 0) {
1183 DPRINTF(("puffs_vnop_symlink: EAGAIN on ncp %p %s\n",
1184 ncp
, ncp
->nc_name
));
1190 PUFFS_MSG_ALLOC(vn
, symlink
);
1191 puffs_makecn(&symlink_msg
->pvnr_cn
, &symlink_msg
->pvnr_cn_cred
,
1193 symlink_msg
->pvnr_va
= *ap
->a_vap
;
1194 (void)strlcpy(symlink_msg
->pvnr_link
, ap
->a_target
,
1195 sizeof(symlink_msg
->pvnr_link
));
1196 puffs_msg_setinfo(park_symlink
, PUFFSOP_VN
,
1197 PUFFS_VN_SYMLINK
, VPTOPNC(dvp
));
1199 PUFFS_MSG_ENQUEUEWAIT2(pmp
, park_symlink
, dvp
->v_data
, NULL
, error
);
1201 error
= checkerr(pmp
, error
, __func__
);
1205 error
= puffs_newnode(mp
, dvp
, ap
->a_vpp
,
1206 symlink_msg
->pvnr_newnode
, VLNK
);
1208 puffs_abortbutton(pmp
, PUFFS_ABORT_SYMLINK
, dpn
->pn_cookie
,
1209 symlink_msg
->pvnr_newnode
, ncp
, cred
);
1213 PUFFS_MSG_RELEASE(symlink
);
1215 cache_setunresolved(nch
);
1216 cache_setvp(nch
, *ap
->a_vpp
);
1222 puffs_vnop_readlink(struct vop_readlink_args
*ap
)
1224 PUFFS_MSG_VARS(vn
, readlink
);
1225 struct vnode
*vp
= ap
->a_vp
;
1226 struct puffs_mount
*pmp
= MPTOPUFFSMP(ap
->a_vp
->v_mount
);
1230 if (!EXISTSOP(pmp
, READLINK
))
1233 PUFFS_MSG_ALLOC(vn
, readlink
);
1234 puffs_credcvt(&readlink_msg
->pvnr_cred
, ap
->a_cred
);
1235 linklen
= sizeof(readlink_msg
->pvnr_link
);
1236 readlink_msg
->pvnr_linklen
= linklen
;
1237 puffs_msg_setinfo(park_readlink
, PUFFSOP_VN
,
1238 PUFFS_VN_READLINK
, VPTOPNC(vp
));
1240 PUFFS_MSG_ENQUEUEWAIT2(pmp
, park_readlink
, vp
->v_data
, NULL
, error
);
1241 error
= checkerr(pmp
, error
, __func__
);
1245 /* bad bad user file server */
1246 if (readlink_msg
->pvnr_linklen
> linklen
) {
1247 puffs_senderr(pmp
, PUFFS_ERR_READLINK
, E2BIG
,
1248 "linklen too big", VPTOPNC(ap
->a_vp
));
1253 error
= uiomove(readlink_msg
->pvnr_link
, readlink_msg
->pvnr_linklen
,
1256 PUFFS_MSG_RELEASE(readlink
);
1261 puffs_vnop_rename(struct vop_nrename_args
*ap
)
1263 PUFFS_MSG_VARS(vn
, rename
);
1264 struct nchandle
*fnch
= ap
->a_fnch
;
1265 struct nchandle
*tnch
= ap
->a_tnch
;
1266 struct vnode
*fdvp
= ap
->a_fdvp
;
1267 struct vnode
*fvp
= fnch
->ncp
->nc_vp
;
1268 struct vnode
*tdvp
= ap
->a_tdvp
;
1269 struct vnode
*tvp
= tnch
->ncp
->nc_vp
;
1270 struct ucred
*cred
= ap
->a_cred
;
1271 struct puffs_mount
*pmp
= MPTOPUFFSMP(fdvp
->v_mount
);
1274 if (!EXISTSOP(pmp
, RENAME
))
1277 error
= vget(tdvp
, LK_EXCLUSIVE
);
1279 DPRINTF(("puffs_vnop_rename: EAGAIN on tdvp vnode %p %s\n",
1280 tdvp
, tnch
->ncp
->nc_name
));
1284 error
= vget(tvp
, LK_EXCLUSIVE
);
1286 DPRINTF(("puffs_vnop_rename: EAGAIN on tvp vnode %p %s\n",
1287 tvp
, tnch
->ncp
->nc_name
));
1293 if ((fvp
->v_mount
!= tdvp
->v_mount
) ||
1294 (tvp
&& (fvp
->v_mount
!= tvp
->v_mount
))) {
1300 if (fvp
->v_type
== VDIR
&& tvp
->v_type
!= VDIR
) {
1303 } else if (fvp
->v_type
!= VDIR
&& tvp
->v_type
== VDIR
) {
1309 PUFFS_MSG_ALLOC(vn
, rename
);
1310 rename_msg
->pvnr_cookie_src
= VPTOPNC(fvp
);
1311 rename_msg
->pvnr_cookie_targdir
= VPTOPNC(tdvp
);
1313 rename_msg
->pvnr_cookie_targ
= VPTOPNC(tvp
);
1315 rename_msg
->pvnr_cookie_targ
= NULL
;
1316 puffs_makecn(&rename_msg
->pvnr_cn_src
, &rename_msg
->pvnr_cn_src_cred
,
1318 puffs_makecn(&rename_msg
->pvnr_cn_targ
, &rename_msg
->pvnr_cn_targ_cred
,
1320 puffs_msg_setinfo(park_rename
, PUFFSOP_VN
,
1321 PUFFS_VN_RENAME
, VPTOPNC(fdvp
));
1323 PUFFS_MSG_ENQUEUEWAIT2(pmp
, park_rename
, fdvp
->v_data
, NULL
, error
);
1324 PUFFS_MSG_RELEASE(rename
);
1325 error
= checkerr(pmp
, error
, __func__
);
1328 puffs_updatenode(VPTOPP(fvp
), PUFFS_UPDATECTIME
);
1336 cache_rename(fnch
, tnch
);
1345 puffs_vnop_read(struct vop_read_args
*ap
)
1347 struct vnode
*vp
= ap
->a_vp
;
1348 struct uio
*uio
= ap
->a_uio
;
1349 int ioflag
= ap
->a_ioflag
;
1350 struct ucred
* cred
= ap
->a_cred
;
1351 struct puffs_mount
*pmp
= MPTOPUFFSMP(vp
->v_mount
);
1354 if (!EXISTSOP(pmp
, READ
))
1357 if (vp
->v_type
== VDIR
)
1359 else if (vp
->v_type
!= VREG
)
1362 if (PUFFS_USE_PAGECACHE(pmp
))
1363 error
= puffs_bioread(vp
, uio
, ioflag
, cred
);
1365 error
= puffs_directread(vp
, uio
, ioflag
, cred
);
1371 puffs_vnop_write(struct vop_write_args
*ap
)
1373 struct vnode
*vp
= ap
->a_vp
;
1374 struct uio
*uio
= ap
->a_uio
;
1375 int ioflag
= ap
->a_ioflag
;
1376 struct ucred
* cred
= ap
->a_cred
;
1377 struct puffs_mount
*pmp
= MPTOPUFFSMP(vp
->v_mount
);
1380 if (!EXISTSOP(pmp
, WRITE
))
1383 if (vp
->v_type
== VDIR
)
1385 else if (vp
->v_type
!= VREG
)
1388 if (PUFFS_USE_PAGECACHE(pmp
))
1389 error
= puffs_biowrite(vp
, uio
, ioflag
, cred
);
1391 error
= puffs_directwrite(vp
, uio
, ioflag
, cred
);
1397 puffs_vnop_print(struct vop_print_args
*ap
)
1399 PUFFS_MSG_VARS(vn
, print
);
1400 struct vnode
*vp
= ap
->a_vp
;
1401 struct puffs_mount
*pmp
= MPTOPUFFSMP(vp
->v_mount
);
1402 struct puffs_node
*pn
= VPTOPP(vp
);
1405 /* kernel portion */
1406 kprintf("tag VT_PUFFS, vnode %p, puffs node: %p,\n"
1407 "\tuserspace cookie: %p", vp
, pn
, pn
->pn_cookie
);
1408 if (vp
->v_type
== VFIFO
)
1412 /* userspace portion */
1413 if (EXISTSOP(pmp
, PRINT
)) {
1414 PUFFS_MSG_ALLOC(vn
, print
);
1415 puffs_msg_setinfo(park_print
, PUFFSOP_VN
,
1416 PUFFS_VN_PRINT
, VPTOPNC(vp
));
1417 PUFFS_MSG_ENQUEUEWAIT2(pmp
, park_print
, vp
->v_data
,
1419 PUFFS_MSG_RELEASE(print
);
1426 puffs_vnop_pathconf(struct vop_pathconf_args
*ap
)
1428 PUFFS_MSG_VARS(vn
, pathconf
);
1429 struct vnode
*vp
= ap
->a_vp
;
1430 struct puffs_mount
*pmp
= MPTOPUFFSMP(vp
->v_mount
);
1433 if (!EXISTSOP(pmp
, PATHCONF
))
1436 PUFFS_MSG_ALLOC(vn
, pathconf
);
1437 pathconf_msg
->pvnr_name
= ap
->a_name
;
1438 puffs_msg_setinfo(park_pathconf
, PUFFSOP_VN
,
1439 PUFFS_VN_PATHCONF
, VPTOPNC(vp
));
1440 PUFFS_MSG_ENQUEUEWAIT2(pmp
, park_pathconf
, vp
->v_data
, NULL
, error
);
1441 error
= checkerr(pmp
, error
, __func__
);
1443 *ap
->a_retval
= pathconf_msg
->pvnr_retval
;
1444 PUFFS_MSG_RELEASE(pathconf
);
1450 puffs_vnop_advlock(struct vop_advlock_args
*ap
)
1452 PUFFS_MSG_VARS(vn
, advlock
);
1453 struct vnode
*vp
= ap
->a_vp
;
1454 struct puffs_node
*pn
= VPTOPP(vp
);
1455 struct puffs_mount
*pmp
= MPTOPUFFSMP(vp
->v_mount
);
1458 if (!EXISTSOP(pmp
, ADVLOCK
))
1459 return lf_advlock(ap
, &pn
->pn_lockf
, vp
->v_filesize
);
1461 PUFFS_MSG_ALLOC(vn
, advlock
);
1462 (void)memcpy(&advlock_msg
->pvnr_fl
, ap
->a_fl
,
1463 sizeof(advlock_msg
->pvnr_fl
));
1464 advlock_msg
->pvnr_id
= ap
->a_id
;
1465 advlock_msg
->pvnr_op
= ap
->a_op
;
1466 advlock_msg
->pvnr_flags
= ap
->a_flags
;
1467 puffs_msg_setinfo(park_advlock
, PUFFSOP_VN
,
1468 PUFFS_VN_ADVLOCK
, VPTOPNC(vp
));
1469 PUFFS_MSG_ENQUEUEWAIT2(pmp
, park_advlock
, vp
->v_data
, NULL
, error
);
1470 error
= checkerr(pmp
, error
, __func__
);
1471 PUFFS_MSG_RELEASE(advlock
);
1477 puffs_vnop_bmap(struct vop_bmap_args
*ap
)
1479 if (ap
->a_doffsetp
!= NULL
)
1480 *ap
->a_doffsetp
= ap
->a_loffset
;
1481 if (ap
->a_runp
!= NULL
)
1483 if (ap
->a_runb
!= NULL
)
1489 puffs_vnop_mmap(struct vop_mmap_args
*ap
)
1496 puffs_vnop_strategy(struct vop_strategy_args
*ap
)
1498 return puffs_doio(ap
->a_vp
, ap
->a_bio
, curthread
);
1501 struct vop_ops puffs_fifo_vops
= {
1502 .vop_default
= fifo_vnoperate
,
1503 .vop_access
= puffs_vnop_access
,
1504 .vop_getattr
= puffs_vnop_getattr
,
1505 .vop_setattr
= puffs_vnop_setattr
,
1506 .vop_inactive
= puffs_vnop_inactive
,
1507 .vop_reclaim
= puffs_vnop_reclaim
,
1508 .vop_print
= puffs_vnop_print
,
1511 struct vop_ops puffs_vnode_vops
= {
1512 .vop_default
= vop_defaultop
,
1513 .vop_nresolve
= puffs_vnop_lookup
,
1514 .vop_nlookupdotdot
= puffs_vnop_lookupdotdot
,
1515 .vop_ncreate
= puffs_vnop_create
,
1516 .vop_nmkdir
= puffs_vnop_mkdir
,
1517 .vop_nrmdir
= puffs_vnop_rmdir
,
1518 .vop_nremove
= puffs_vnop_remove
,
1519 .vop_nrename
= puffs_vnop_rename
,
1520 .vop_nlink
= puffs_vnop_link
,
1521 .vop_nsymlink
= puffs_vnop_symlink
,
1522 .vop_nmknod
= puffs_vnop_mknod
,
1523 .vop_access
= puffs_vnop_access
,
1524 .vop_getattr
= puffs_vnop_getattr
,
1525 .vop_setattr
= puffs_vnop_setattr
,
1526 .vop_readdir
= puffs_vnop_readdir
,
1527 .vop_open
= puffs_vnop_open
,
1528 .vop_close
= puffs_vnop_close
,
1529 .vop_read
= puffs_vnop_read
,
1530 .vop_write
= puffs_vnop_write
,
1531 .vop_readlink
= puffs_vnop_readlink
,
1532 .vop_advlock
= puffs_vnop_advlock
,
1533 .vop_bmap
= puffs_vnop_bmap
,
1534 .vop_mmap
= puffs_vnop_mmap
,
1535 .vop_strategy
= puffs_vnop_strategy
,
1536 .vop_getpages
= vop_stdgetpages
,
1537 .vop_putpages
= vop_stdputpages
,
1538 .vop_fsync
= puffs_vnop_fsync
,
1539 .vop_inactive
= puffs_vnop_inactive
,
1540 .vop_reclaim
= puffs_vnop_reclaim
,
1541 .vop_pathconf
= puffs_vnop_pathconf
,
1542 .vop_print
= puffs_vnop_print
,