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, *dvp = ap->a_dvp;
115 struct puffs_node *dpn;
118 DPRINTF(("puffs_lookup: \"%s\", parent vnode %p\n",
121 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
122 DPRINTF(("puffs_vnop_lookup: EAGAIN on ncp %p %s\n",
127 PUFFS_MSG_ALLOC(vn, lookup);
128 puffs_makecn(&lookup_msg->pvnr_cn, &lookup_msg->pvnr_cn_cred,
131 puffs_msg_setinfo(park_lookup, PUFFSOP_VN,
132 PUFFS_VN_LOOKUP, VPTOPNC(dvp));
133 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_lookup, dvp->v_data, NULL, error);
134 DPRINTF(("puffs_lookup: return of the userspace, part %d\n", error));
136 error = checkerr(pmp, error, __func__);
138 cache_setvp(nch, NULL);
143 * Check that we don't get our parent node back, that would cause
144 * a pretty obvious deadlock.
147 if (lookup_msg->pvnr_newnode == dpn->pn_cookie) {
148 puffs_senderr(pmp, PUFFS_ERR_LOOKUP, EINVAL,
149 "lookup produced parent cookie", lookup_msg->pvnr_newnode);
154 error = puffs_cookie2vnode(pmp, lookup_msg->pvnr_newnode, 1, &vp);
155 if (error == PUFFS_NOSUCHCOOKIE) {
156 error = puffs_getvnode(dvp->v_mount,
157 lookup_msg->pvnr_newnode, lookup_msg->pvnr_vtype,
158 lookup_msg->pvnr_size, &vp);
160 puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp),
161 lookup_msg->pvnr_newnode, ncp, cred);
165 puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp),
166 lookup_msg->pvnr_newnode, ncp, cred);
174 cache_setvp(nch, vp);
177 DPRINTF(("puffs_lookup: returning %d\n", error));
178 PUFFS_MSG_RELEASE(lookup);
183 puffs_vnop_lookupdotdot(struct vop_nlookupdotdot_args *ap)
185 PUFFS_MSG_VARS(vn, lookupdotdot);
186 struct puffs_mount *pmp = MPTOPUFFSMP(ap->a_dvp->v_mount);
187 struct ucred *cred = ap->a_cred;
188 struct vnode *vp, *dvp = ap->a_dvp;
189 struct puffs_node *dpn;
194 DPRINTF(("puffs_lookupdotdot: vnode %p\n", dvp));
196 PUFFS_MSG_ALLOC(vn, lookupdotdot);
197 puffs_credcvt(&lookupdotdot_msg->pvnr_cred, cred);
199 puffs_msg_setinfo(park_lookupdotdot, PUFFSOP_VN,
200 PUFFS_VN_LOOKUPDOTDOT, VPTOPNC(dvp));
201 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_lookupdotdot, dvp->v_data, NULL,
203 DPRINTF(("puffs_lookupdotdot: return of the userspace, part %d\n",
206 error = checkerr(pmp, error, __func__);
211 * Check that we don't get our node back, that would cause
212 * a pretty obvious deadlock.
215 if (lookupdotdot_msg->pvnr_newnode == dpn->pn_cookie) {
216 puffs_senderr(pmp, PUFFS_ERR_LOOKUP, EINVAL,
217 "lookupdotdot produced the same cookie",
218 lookupdotdot_msg->pvnr_newnode);
223 error = puffs_cookie2vnode(pmp, lookupdotdot_msg->pvnr_newnode,
225 if (error == PUFFS_NOSUCHCOOKIE) {
226 error = puffs_getvnode(dvp->v_mount,
227 lookupdotdot_msg->pvnr_newnode, VDIR, 0, &vp);
229 puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp),
230 lookupdotdot_msg->pvnr_newnode, NULL, cred);
234 puffs_abortbutton(pmp, PUFFS_ABORT_LOOKUP, VPTOPNC(dvp),
235 lookupdotdot_msg->pvnr_newnode, NULL, cred);
243 DPRINTF(("puffs_lookupdotdot: returning %d %p\n", error, *ap->a_vpp));
244 PUFFS_MSG_RELEASE(lookupdotdot);
249 puffs_vnop_create(struct vop_ncreate_args *ap)
251 PUFFS_MSG_VARS(vn, create);
252 struct vnode *dvp = ap->a_dvp;
253 struct vattr *vap = ap->a_vap;
254 struct puffs_node *dpn = VPTOPP(dvp);
255 struct nchandle *nch = ap->a_nch;
256 struct namecache *ncp = nch->ncp;
257 struct ucred *cred = ap->a_cred;
258 struct mount *mp = dvp->v_mount;
259 struct puffs_mount *pmp = MPTOPUFFSMP(mp);
262 DPRINTF(("puffs_create: dvp %p, name: %s\n",
265 if (vap->va_type != VREG && vap->va_type != VSOCK)
268 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
269 DPRINTF(("puffs_vnop_create: EAGAIN on ncp %p %s\n",
274 PUFFS_MSG_ALLOC(vn, create);
275 puffs_makecn(&create_msg->pvnr_cn, &create_msg->pvnr_cn_cred,
277 create_msg->pvnr_va = *ap->a_vap;
278 puffs_msg_setinfo(park_create, PUFFSOP_VN,
279 PUFFS_VN_CREATE, VPTOPNC(dvp));
280 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_create, dvp->v_data, NULL, error);
282 error = checkerr(pmp, error, __func__);
286 error = puffs_newnode(mp, dvp, ap->a_vpp,
287 create_msg->pvnr_newnode, vap->va_type);
289 puffs_abortbutton(pmp, PUFFS_ABORT_CREATE, dpn->pn_cookie,
290 create_msg->pvnr_newnode, ncp, cred);
293 DPRINTF(("puffs_create: return %d\n", error));
296 cache_setunresolved(nch);
297 cache_setvp(nch, *ap->a_vpp);
299 PUFFS_MSG_RELEASE(create);
304 puffs_vnop_mknod(struct vop_nmknod_args *ap)
306 PUFFS_MSG_VARS(vn, mknod);
307 struct vnode *dvp = ap->a_dvp;
308 struct vattr *vap = ap->a_vap;
309 struct puffs_node *dpn = VPTOPP(dvp);
310 struct nchandle *nch = ap->a_nch;
311 struct namecache *ncp = nch->ncp;
312 struct ucred *cred = ap->a_cred;
313 struct mount *mp = dvp->v_mount;
314 struct puffs_mount *pmp = MPTOPUFFSMP(mp);
317 DPRINTF(("puffs_mknod: dvp %p, name: %s\n",
320 if (vap->va_type != VFIFO)
323 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
324 DPRINTF(("puffs_vnop_mknod: EAGAIN on ncp %p %s\n",
329 PUFFS_MSG_ALLOC(vn, mknod);
330 puffs_makecn(&mknod_msg->pvnr_cn, &mknod_msg->pvnr_cn_cred,
332 mknod_msg->pvnr_va = *ap->a_vap;
333 puffs_msg_setinfo(park_mknod, PUFFSOP_VN,
334 PUFFS_VN_MKNOD, VPTOPNC(dvp));
336 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_mknod, dvp->v_data, NULL, error);
338 error = checkerr(pmp, error, __func__);
342 error = puffs_newnode(mp, dvp, ap->a_vpp,
343 mknod_msg->pvnr_newnode, vap->va_type);
345 puffs_abortbutton(pmp, PUFFS_ABORT_MKNOD, dpn->pn_cookie,
346 mknod_msg->pvnr_newnode, ncp, cred);
351 cache_setunresolved(nch);
352 cache_setvp(nch, *ap->a_vpp);
354 PUFFS_MSG_RELEASE(mknod);
359 puffs_vnop_open(struct vop_open_args *ap)
361 PUFFS_MSG_VARS(vn, open);
362 struct vnode *vp = ap->a_vp;
363 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
364 int mode = ap->a_mode;
367 DPRINTF(("puffs_open: vp %p, mode 0x%x\n", vp, mode));
369 if (vp->v_type == VREG && mode & FWRITE && !EXISTSOP(pmp, WRITE))
372 if (!EXISTSOP(pmp, OPEN))
375 PUFFS_MSG_ALLOC(vn, open);
376 open_msg->pvnr_mode = mode;
377 puffs_credcvt(&open_msg->pvnr_cred, ap->a_cred);
378 puffs_msg_setinfo(park_open, PUFFSOP_VN,
379 PUFFS_VN_OPEN, VPTOPNC(vp));
381 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_open, vp->v_data, NULL, error);
382 error = checkerr(pmp, error, __func__);
385 DPRINTF(("puffs_open: returning %d\n", error));
386 PUFFS_MSG_RELEASE(open);
389 return vop_stdopen(ap);
393 puffs_vnop_close(struct vop_close_args *ap)
395 PUFFS_MSG_VARS(vn, close);
396 struct vnode *vp = ap->a_vp;
397 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
399 PUFFS_MSG_ALLOC(vn, close);
400 puffs_msg_setfaf(park_close);
401 close_msg->pvnr_fflag = ap->a_fflag;
402 puffs_msg_setinfo(park_close, PUFFSOP_VN,
403 PUFFS_VN_CLOSE, VPTOPNC(vp));
405 puffs_msg_enqueue(pmp, park_close);
406 PUFFS_MSG_RELEASE(close);
407 return vop_stdclose(ap);
411 puffs_vnop_access(struct vop_access_args *ap)
413 PUFFS_MSG_VARS(vn, access);
414 struct vnode *vp = ap->a_vp;
415 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
416 int mode = ap->a_mode;
420 switch (vp->v_type) {
424 if ((vp->v_mount->mnt_flag & MNT_RDONLY)
425 || !EXISTSOP(pmp, WRITE))
433 if (!EXISTSOP(pmp, ACCESS))
436 PUFFS_MSG_ALLOC(vn, access);
437 access_msg->pvnr_mode = ap->a_mode;
438 puffs_credcvt(&access_msg->pvnr_cred, ap->a_cred);
439 puffs_msg_setinfo(park_access, PUFFSOP_VN,
440 PUFFS_VN_ACCESS, VPTOPNC(vp));
442 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_access, vp->v_data, NULL, error);
443 error = checkerr(pmp, error, __func__);
444 PUFFS_MSG_RELEASE(access);
450 puffs_vnop_getattr(struct vop_getattr_args *ap)
452 PUFFS_MSG_VARS(vn, getattr);
453 struct vnode *vp = ap->a_vp;
454 struct mount *mp = vp->v_mount;
455 struct puffs_mount *pmp = MPTOPUFFSMP(mp);
456 struct vattr *vap, *rvap;
457 struct puffs_node *pn = VPTOPP(vp);
460 if (vp->v_type == VBLK || vp->v_type == VCHR)
465 PUFFS_MSG_ALLOC(vn, getattr);
466 vattr_null(&getattr_msg->pvnr_va);
467 puffs_credcvt(&getattr_msg->pvnr_cred, curproc->p_ucred);
468 puffs_msg_setinfo(park_getattr, PUFFSOP_VN,
469 PUFFS_VN_GETATTR, VPTOPNC(vp));
471 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_getattr, vp->v_data, NULL, error);
472 error = checkerr(pmp, error, __func__);
476 rvap = &getattr_msg->pvnr_va;
478 (void) memcpy(vap, rvap, sizeof(struct vattr));
479 vap->va_fsid = mp->mnt_stat.f_fsid.val[0];
481 if (pn->pn_stat & PNODE_METACACHE_ATIME)
482 vap->va_atime = pn->pn_mc_atime;
483 if (pn->pn_stat & PNODE_METACACHE_CTIME)
484 vap->va_ctime = pn->pn_mc_ctime;
485 if (pn->pn_stat & PNODE_METACACHE_MTIME)
486 vap->va_mtime = pn->pn_mc_mtime;
487 if (pn->pn_stat & PNODE_METACACHE_SIZE) {
488 vap->va_size = pn->pn_mc_size;
490 if (rvap->va_size != VNOVAL
491 && vp->v_type != VBLK && vp->v_type != VCHR) {
492 pn->pn_serversize = rvap->va_size;
493 if (vp->v_type == VREG)
494 puffs_meta_setsize(vp, rvap->va_size, 0);
499 PUFFS_MSG_RELEASE(getattr);
503 #define SETATTR_CHSIZE 0x01
504 #define SETATTR_ASYNC 0x02
506 dosetattr(struct vnode *vp, struct vattr *vap, struct ucred *cred, int flags)
508 PUFFS_MSG_VARS(vn, setattr);
509 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
510 struct puffs_node *pn = VPTOPP(vp);
513 if ((vp->v_mount->mnt_flag & MNT_RDONLY) &&
514 (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL
515 || vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL
516 || vap->va_mode != (mode_t)VNOVAL))
519 if ((vp->v_mount->mnt_flag & MNT_RDONLY)
520 && vp->v_type == VREG && vap->va_size != VNOVAL)
524 * Flush metacache first. If we are called with some explicit
525 * parameters, treat them as information overriding metacache
528 if (pn->pn_stat & PNODE_METACACHE_MASK) {
529 if ((pn->pn_stat & PNODE_METACACHE_ATIME)
530 && vap->va_atime.tv_sec == VNOVAL)
531 vap->va_atime = pn->pn_mc_atime;
532 if ((pn->pn_stat & PNODE_METACACHE_CTIME)
533 && vap->va_ctime.tv_sec == VNOVAL)
534 vap->va_ctime = pn->pn_mc_ctime;
535 if ((pn->pn_stat & PNODE_METACACHE_MTIME)
536 && vap->va_mtime.tv_sec == VNOVAL)
537 vap->va_mtime = pn->pn_mc_mtime;
538 if ((pn->pn_stat & PNODE_METACACHE_SIZE)
539 && vap->va_size == VNOVAL)
540 vap->va_size = pn->pn_mc_size;
542 pn->pn_stat &= ~PNODE_METACACHE_MASK;
545 PUFFS_MSG_ALLOC(vn, setattr);
546 (void)memcpy(&setattr_msg->pvnr_va, vap, sizeof(struct vattr));
547 puffs_credcvt(&setattr_msg->pvnr_cred, cred);
548 puffs_msg_setinfo(park_setattr, PUFFSOP_VN,
549 PUFFS_VN_SETATTR, VPTOPNC(vp));
550 if (flags & SETATTR_ASYNC)
551 puffs_msg_setfaf(park_setattr);
553 puffs_msg_enqueue(pmp, park_setattr);
554 if ((flags & SETATTR_ASYNC) == 0)
555 error = puffs_msg_wait2(pmp, park_setattr, vp->v_data, NULL);
556 PUFFS_MSG_RELEASE(setattr);
557 if ((flags & SETATTR_ASYNC) == 0) {
558 error = checkerr(pmp, error, __func__);
565 if (vap->va_size != VNOVAL) {
566 pn->pn_serversize = vap->va_size;
567 if (flags & SETATTR_CHSIZE)
568 puffs_meta_setsize(vp, vap->va_size, 0);
575 puffs_vnop_setattr(struct vop_setattr_args *ap)
577 return dosetattr(ap->a_vp, ap->a_vap, ap->a_cred, SETATTR_CHSIZE);
581 doinact(struct puffs_mount *pmp, int iaflag)
584 if (EXISTSOP(pmp, INACTIVE))
585 if (pmp->pmp_flags & PUFFS_KFLAG_IAONDEMAND)
586 if (iaflag || ALLOPS(pmp))
597 callinactive(struct puffs_mount *pmp, puffs_cookie_t ck, int iaflag)
600 PUFFS_MSG_VARS(vn, inactive);
602 if (doinact(pmp, iaflag)) {
603 PUFFS_MSG_ALLOC(vn, inactive);
604 puffs_msg_setinfo(park_inactive, PUFFSOP_VN,
605 PUFFS_VN_INACTIVE, ck);
607 PUFFS_MSG_ENQUEUEWAIT(pmp, park_inactive, error);
608 PUFFS_MSG_RELEASE(inactive);
612 /* XXX: callinactive can't setback */
614 puffs_vnop_inactive(struct vop_inactive_args *ap)
616 PUFFS_MSG_VARS(vn, inactive);
617 struct vnode *vp = ap->a_vp;
618 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
619 struct puffs_node *pnode = VPTOPP(vp);
621 flushvncache(vp, MNT_NOWAIT);
623 if (doinact(pmp, pnode->pn_stat & PNODE_DOINACT)) {
625 * do not wait for reply from userspace, otherwise it may
629 PUFFS_MSG_ALLOC(vn, inactive);
630 puffs_msg_setfaf(park_inactive);
631 puffs_msg_setinfo(park_inactive, PUFFSOP_VN,
632 PUFFS_VN_INACTIVE, VPTOPNC(vp));
634 puffs_msg_enqueue(pmp, park_inactive);
635 PUFFS_MSG_RELEASE(inactive);
637 pnode->pn_stat &= ~PNODE_DOINACT;
640 * file server thinks it's gone? then don't be afraid care,
641 * node's life was already all it would ever be
643 if (pnode->pn_stat & PNODE_NOREFS) {
644 pnode->pn_stat |= PNODE_DYING;
652 callreclaim(struct puffs_mount *pmp, puffs_cookie_t ck)
654 PUFFS_MSG_VARS(vn, reclaim);
656 if (!EXISTSOP(pmp, RECLAIM))
659 PUFFS_MSG_ALLOC(vn, reclaim);
660 puffs_msg_setfaf(park_reclaim);
661 puffs_msg_setinfo(park_reclaim, PUFFSOP_VN, PUFFS_VN_RECLAIM, ck);
663 puffs_msg_enqueue(pmp, park_reclaim);
664 PUFFS_MSG_RELEASE(reclaim);
668 * always FAF, we don't really care if the server wants to fail to
669 * reclaim the node or not
672 puffs_vnop_reclaim(struct vop_reclaim_args *ap)
674 struct vnode *vp = ap->a_vp;
675 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
676 struct puffs_node *pnode = VPTOPP(vp);
677 boolean_t notifyserver = TRUE;
679 vinvalbuf(vp, V_SAVE, 0, 0);
682 * first things first: check if someone is trying to reclaim the
683 * root vnode. do not allow that to travel to userspace.
684 * Note that we don't need to take the lock similarly to
685 * puffs_root(), since there is only one of us.
687 if (vp->v_flag & VROOT) {
688 lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE);
689 KKASSERT(pmp->pmp_root != NULL);
690 pmp->pmp_root = NULL;
691 lockmgr(&pmp->pmp_lock, LK_RELEASE);
692 notifyserver = FALSE;
696 * purge info from kernel before issueing FAF, since we
697 * don't really know when we'll get around to it after
698 * that and someone might race us into node creation
700 lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE);
701 LIST_REMOVE(pnode, pn_hashent);
702 lockmgr(&pmp->pmp_lock, LK_RELEASE);
705 callreclaim(MPTOPUFFSMP(vp->v_mount), VPTOPNC(vp));
713 #define CSIZE sizeof(**ap->a_cookies)
715 puffs_vnop_readdir(struct vop_readdir_args *ap)
717 PUFFS_MSG_VARS(vn, readdir);
718 struct vnode *vp = ap->a_vp;
719 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
720 size_t argsize, tomove, cookiemem, cookiesmax;
721 struct uio *uio = ap->a_uio;
722 size_t howmuch, resid;
726 * ok, so we need: resid + cookiemem = maxreq
727 * => resid + cookiesize * (resid/minsize) = maxreq
728 * => resid + cookiesize/minsize * resid = maxreq
729 * => (cookiesize/minsize + 1) * resid = maxreq
730 * => resid = maxreq / (cookiesize/minsize + 1)
732 * Since cookiesize <= minsize and we're not very big on floats,
733 * we approximate that to be 1. Therefore:
735 * resid = maxreq / 2;
737 * Well, at least we didn't have to use differential equations
738 * or the Gram-Schmidt process.
740 * (yes, I'm very afraid of this)
742 KKASSERT(CSIZE <= _DIRENT_RECLEN(1));
745 KKASSERT(ap->a_ncookies != NULL);
746 if (pmp->pmp_args.pa_fhsize == 0)
748 resid = PUFFS_TOMOVE(uio->uio_resid, pmp) / 2;
749 cookiesmax = resid/_DIRENT_RECLEN(1);
750 cookiemem = ALIGN(cookiesmax*CSIZE); /* play safe */
752 resid = PUFFS_TOMOVE(uio->uio_resid, pmp);
757 argsize = sizeof(struct puffs_vnmsg_readdir);
758 tomove = resid + cookiemem;
759 puffs_msgmem_alloc(argsize + tomove, &park_readdir,
760 (void *)&readdir_msg, 1);
762 puffs_credcvt(&readdir_msg->pvnr_cred, ap->a_cred);
763 readdir_msg->pvnr_offset = uio->uio_offset;
764 readdir_msg->pvnr_resid = resid;
765 readdir_msg->pvnr_ncookies = cookiesmax;
766 readdir_msg->pvnr_eofflag = 0;
767 readdir_msg->pvnr_dentoff = cookiemem;
768 puffs_msg_setinfo(park_readdir, PUFFSOP_VN,
769 PUFFS_VN_READDIR, VPTOPNC(vp));
770 puffs_msg_setdelta(park_readdir, tomove);
772 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_readdir, vp->v_data, NULL, error);
773 error = checkerr(pmp, error, __func__);
777 /* userspace is cheating? */
778 if (readdir_msg->pvnr_resid > resid) {
779 puffs_senderr(pmp, PUFFS_ERR_READDIR, E2BIG,
780 "resid grew", VPTOPNC(vp));
783 if (readdir_msg->pvnr_ncookies > cookiesmax) {
784 puffs_senderr(pmp, PUFFS_ERR_READDIR, E2BIG,
785 "too many cookies", VPTOPNC(vp));
790 if (readdir_msg->pvnr_eofflag)
793 /* bouncy-wouncy with the directory data */
794 howmuch = resid - readdir_msg->pvnr_resid;
796 /* force eof if no data was returned (getcwd() needs this) */
802 error = uiomove(readdir_msg->pvnr_data + cookiemem, howmuch, uio);
806 /* provide cookies to caller if so desired */
808 *ap->a_cookies = kmalloc(readdir_msg->pvnr_ncookies*CSIZE,
810 *ap->a_ncookies = readdir_msg->pvnr_ncookies;
811 memcpy(*ap->a_cookies, readdir_msg->pvnr_data,
812 *ap->a_ncookies*CSIZE);
815 /* next readdir starts here */
816 uio->uio_offset = readdir_msg->pvnr_offset;
819 puffs_msgmem_release(park_readdir);
825 flushvncache(struct vnode *vp, int waitfor)
827 struct puffs_node *pn = VPTOPP(vp);
831 /* flush out information from our metacache, see vop_setattr */
832 if (pn->pn_stat & PNODE_METACACHE_MASK
833 && (pn->pn_stat & PNODE_DYING) == 0) {
835 error = dosetattr(vp, &va, FSCRED, SETATTR_CHSIZE |
836 (waitfor == MNT_NOWAIT ? 0 : SETATTR_ASYNC));
842 * flush pages to avoid being overly dirty
844 vfsync(vp, waitfor, 0, NULL, NULL);
850 puffs_vnop_fsync(struct vop_fsync_args *ap)
852 PUFFS_MSG_VARS(vn, fsync);
853 struct vnode *vp = ap->a_vp;
854 int waitfor = ap->a_waitfor;
855 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
856 struct puffs_node *pn = VPTOPP(vp);
859 error = flushvncache(vp, waitfor);
864 * HELLO! We exit already here if the user server does not
865 * support fsync OR if we should call fsync for a node which
866 * has references neither in the kernel or the fs server.
867 * Otherwise we continue to issue fsync() forward.
869 if (!EXISTSOP(pmp, FSYNC) || (pn->pn_stat & PNODE_DYING))
872 dofaf = (waitfor & MNT_WAIT) == 0 || (waitfor & MNT_LAZY) != 0;
874 PUFFS_MSG_ALLOC(vn, fsync);
876 puffs_msg_setfaf(park_fsync);
878 fsync_msg->pvnr_flags = ap->a_flags;
879 puffs_msg_setinfo(park_fsync, PUFFSOP_VN,
880 PUFFS_VN_FSYNC, VPTOPNC(vp));
882 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_fsync, vp->v_data, NULL, error);
883 PUFFS_MSG_RELEASE(fsync);
885 error = checkerr(pmp, error, __func__);
891 callremove(struct puffs_mount *pmp, puffs_cookie_t dck, puffs_cookie_t ck,
892 struct namecache *ncp, struct ucred *cred)
894 PUFFS_MSG_VARS(vn, remove);
897 PUFFS_MSG_ALLOC(vn, remove);
898 remove_msg->pvnr_cookie_targ = ck;
899 puffs_makecn(&remove_msg->pvnr_cn, &remove_msg->pvnr_cn_cred,
901 puffs_msg_setinfo(park_remove, PUFFSOP_VN, PUFFS_VN_REMOVE, dck);
903 PUFFS_MSG_ENQUEUEWAIT(pmp, park_remove, error);
904 PUFFS_MSG_RELEASE(remove);
906 return checkerr(pmp, error, __func__);
910 * XXX: can't use callremove now because can't catch setbacks with
911 * it due to lack of a pnode argument.
914 puffs_vnop_remove(struct vop_nremove_args *ap)
916 PUFFS_MSG_VARS(vn, remove);
917 struct vnode *dvp = ap->a_dvp;
919 struct puffs_node *dpn = VPTOPP(dvp);
920 struct puffs_node *pn;
921 struct nchandle *nch = ap->a_nch;
922 struct namecache *ncp = nch->ncp;
923 struct ucred *cred = ap->a_cred;
924 struct mount *mp = dvp->v_mount;
925 struct puffs_mount *pmp = MPTOPUFFSMP(mp);
928 error = vget(dvp, LK_EXCLUSIVE);
930 DPRINTF(("puffs_vnop_remove: EAGAIN on parent vnode %p %s\n",
935 error = cache_vget(nch, cred, LK_EXCLUSIVE, &vp);
937 DPRINTF(("puffs_vnop_remove: cache_vget error: %p %s\n",
941 if (vp->v_type == VDIR) {
947 PUFFS_MSG_ALLOC(vn, remove);
948 remove_msg->pvnr_cookie_targ = VPTOPNC(vp);
949 puffs_makecn(&remove_msg->pvnr_cn, &remove_msg->pvnr_cn_cred,
951 puffs_msg_setinfo(park_remove, PUFFSOP_VN,
952 PUFFS_VN_REMOVE, VPTOPNC(dvp));
954 puffs_msg_enqueue(pmp, park_remove);
955 error = puffs_msg_wait2(pmp, park_remove, dpn, pn);
957 PUFFS_MSG_RELEASE(remove);
959 error = checkerr(pmp, error, __func__);
965 cache_setunresolved(nch);
966 cache_setvp(nch, NULL);
973 puffs_vnop_mkdir(struct vop_nmkdir_args *ap)
975 PUFFS_MSG_VARS(vn, mkdir);
976 struct vnode *dvp = ap->a_dvp;
977 struct puffs_node *dpn = VPTOPP(dvp);
978 struct nchandle *nch = ap->a_nch;
979 struct namecache *ncp = nch->ncp;
980 struct ucred *cred = ap->a_cred;
981 struct mount *mp = dvp->v_mount;
982 struct puffs_mount *pmp = MPTOPUFFSMP(mp);
985 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
986 DPRINTF(("puffs_vnop_mkdir: EAGAIN on ncp %p %s\n",
991 PUFFS_MSG_ALLOC(vn, mkdir);
992 puffs_makecn(&mkdir_msg->pvnr_cn, &mkdir_msg->pvnr_cn_cred,
994 mkdir_msg->pvnr_va = *ap->a_vap;
995 puffs_msg_setinfo(park_mkdir, PUFFSOP_VN,
996 PUFFS_VN_MKDIR, VPTOPNC(dvp));
998 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_mkdir, dvp->v_data, NULL, error);
1000 error = checkerr(pmp, error, __func__);
1004 error = puffs_newnode(mp, dvp, ap->a_vpp,
1005 mkdir_msg->pvnr_newnode, VDIR);
1007 puffs_abortbutton(pmp, PUFFS_ABORT_MKDIR, dpn->pn_cookie,
1008 mkdir_msg->pvnr_newnode, ncp, cred);
1013 cache_setunresolved(nch);
1014 cache_setvp(nch, *ap->a_vpp);
1016 PUFFS_MSG_RELEASE(mkdir);
1021 callrmdir(struct puffs_mount *pmp, puffs_cookie_t dck, puffs_cookie_t ck,
1022 struct namecache *ncp, struct ucred *cred)
1024 PUFFS_MSG_VARS(vn, rmdir);
1027 PUFFS_MSG_ALLOC(vn, rmdir);
1028 rmdir_msg->pvnr_cookie_targ = ck;
1029 puffs_makecn(&rmdir_msg->pvnr_cn, &rmdir_msg->pvnr_cn_cred,
1031 puffs_msg_setinfo(park_rmdir, PUFFSOP_VN, PUFFS_VN_RMDIR, dck);
1033 PUFFS_MSG_ENQUEUEWAIT(pmp, park_rmdir, error);
1034 PUFFS_MSG_RELEASE(rmdir);
1036 return checkerr(pmp, error, __func__);
1040 puffs_vnop_rmdir(struct vop_nrmdir_args *ap)
1042 PUFFS_MSG_VARS(vn, rmdir);
1043 struct vnode *dvp = ap->a_dvp;
1045 struct puffs_node *dpn = VPTOPP(dvp);
1046 struct puffs_node *pn;
1047 struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1048 struct nchandle *nch = ap->a_nch;
1049 struct namecache *ncp = nch->ncp;
1050 struct ucred *cred = ap->a_cred;
1053 error = vget(dvp, LK_EXCLUSIVE);
1055 DPRINTF(("puffs_vnop_rmdir: EAGAIN on parent vnode %p %s\n",
1056 dvp, ncp->nc_name));
1059 error = cache_vget(nch, cred, LK_EXCLUSIVE, &vp);
1061 DPRINTF(("puffs_vnop_rmdir: cache_vget error: %p %s\n",
1062 dvp, ncp->nc_name));
1065 if (vp->v_type != VDIR) {
1071 PUFFS_MSG_ALLOC(vn, rmdir);
1072 rmdir_msg->pvnr_cookie_targ = VPTOPNC(vp);
1073 puffs_makecn(&rmdir_msg->pvnr_cn, &rmdir_msg->pvnr_cn_cred,
1075 puffs_msg_setinfo(park_rmdir, PUFFSOP_VN,
1076 PUFFS_VN_RMDIR, VPTOPNC(dvp));
1078 puffs_msg_enqueue(pmp, park_rmdir);
1079 error = puffs_msg_wait2(pmp, park_rmdir, dpn, pn);
1081 PUFFS_MSG_RELEASE(rmdir);
1083 error = checkerr(pmp, error, __func__);
1089 cache_setunresolved(nch);
1090 cache_setvp(nch, NULL);
1097 puffs_vnop_link(struct vop_nlink_args *ap)
1099 PUFFS_MSG_VARS(vn, link);
1100 struct vnode *dvp = ap->a_dvp;
1101 struct vnode *vp = ap->a_vp;
1102 struct puffs_node *dpn = VPTOPP(dvp);
1103 struct puffs_node *pn = VPTOPP(vp);
1104 struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1105 struct nchandle *nch = ap->a_nch;
1106 struct namecache *ncp = nch->ncp;
1107 struct ucred *cred = ap->a_cred;
1110 if (vp->v_mount != dvp->v_mount)
1113 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
1114 DPRINTF(("puffs_vnop_link: EAGAIN on ncp %p %s\n",
1115 ncp, ncp->nc_name));
1119 PUFFS_MSG_ALLOC(vn, link);
1120 link_msg->pvnr_cookie_targ = VPTOPNC(vp);
1121 puffs_makecn(&link_msg->pvnr_cn, &link_msg->pvnr_cn_cred,
1123 puffs_msg_setinfo(park_link, PUFFSOP_VN,
1124 PUFFS_VN_LINK, VPTOPNC(dvp));
1126 puffs_msg_enqueue(pmp, park_link);
1127 error = puffs_msg_wait2(pmp, park_link, dpn, pn);
1129 PUFFS_MSG_RELEASE(link);
1131 error = checkerr(pmp, error, __func__);
1134 * XXX: stay in touch with the cache. I don't like this, but
1135 * don't have a better solution either. See also puffs_rename().
1138 puffs_updatenode(pn, PUFFS_UPDATECTIME);
1143 cache_setunresolved(nch);
1144 cache_setvp(nch, vp);
1150 puffs_vnop_symlink(struct vop_nsymlink_args *ap)
1152 PUFFS_MSG_VARS(vn, symlink);
1153 struct vnode *dvp = ap->a_dvp;
1154 struct puffs_node *dpn = VPTOPP(dvp);
1155 struct mount *mp = dvp->v_mount;
1156 struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1157 struct nchandle *nch = ap->a_nch;
1158 struct namecache *ncp = nch->ncp;
1159 struct ucred *cred = ap->a_cred;
1162 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
1163 DPRINTF(("puffs_vnop_symlink: EAGAIN on ncp %p %s\n",
1164 ncp, ncp->nc_name));
1170 PUFFS_MSG_ALLOC(vn, symlink);
1171 puffs_makecn(&symlink_msg->pvnr_cn, &symlink_msg->pvnr_cn_cred,
1173 symlink_msg->pvnr_va = *ap->a_vap;
1174 (void)strlcpy(symlink_msg->pvnr_link, ap->a_target,
1175 sizeof(symlink_msg->pvnr_link));
1176 puffs_msg_setinfo(park_symlink, PUFFSOP_VN,
1177 PUFFS_VN_SYMLINK, VPTOPNC(dvp));
1179 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_symlink, dvp->v_data, NULL, error);
1181 error = checkerr(pmp, error, __func__);
1185 error = puffs_newnode(mp, dvp, ap->a_vpp,
1186 symlink_msg->pvnr_newnode, VLNK);
1188 puffs_abortbutton(pmp, PUFFS_ABORT_SYMLINK, dpn->pn_cookie,
1189 symlink_msg->pvnr_newnode, ncp, cred);
1193 PUFFS_MSG_RELEASE(symlink);
1195 cache_setunresolved(nch);
1196 cache_setvp(nch, *ap->a_vpp);
1202 puffs_vnop_readlink(struct vop_readlink_args *ap)
1204 PUFFS_MSG_VARS(vn, readlink);
1205 struct vnode *vp = ap->a_vp;
1206 struct puffs_mount *pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
1210 PUFFS_MSG_ALLOC(vn, readlink);
1211 puffs_credcvt(&readlink_msg->pvnr_cred, ap->a_cred);
1212 linklen = sizeof(readlink_msg->pvnr_link);
1213 readlink_msg->pvnr_linklen = linklen;
1214 puffs_msg_setinfo(park_readlink, PUFFSOP_VN,
1215 PUFFS_VN_READLINK, VPTOPNC(vp));
1217 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_readlink, vp->v_data, NULL, error);
1218 error = checkerr(pmp, error, __func__);
1222 /* bad bad user file server */
1223 if (readlink_msg->pvnr_linklen > linklen) {
1224 puffs_senderr(pmp, PUFFS_ERR_READLINK, E2BIG,
1225 "linklen too big", VPTOPNC(ap->a_vp));
1230 error = uiomove(readlink_msg->pvnr_link, readlink_msg->pvnr_linklen,
1233 PUFFS_MSG_RELEASE(readlink);
1238 puffs_vnop_rename(struct vop_nrename_args *ap)
1240 PUFFS_MSG_VARS(vn, rename);
1241 struct nchandle *fnch = ap->a_fnch;
1242 struct nchandle *tnch = ap->a_tnch;
1243 struct vnode *fdvp = ap->a_fdvp;
1244 struct vnode *fvp = fnch->ncp->nc_vp;
1245 struct vnode *tdvp = ap->a_tdvp;
1246 struct vnode *tvp = tnch->ncp->nc_vp;
1247 struct ucred *cred = ap->a_cred;
1248 struct puffs_mount *pmp = MPTOPUFFSMP(fdvp->v_mount);
1250 boolean_t doabort = TRUE;
1252 error = vget(tdvp, LK_EXCLUSIVE);
1254 DPRINTF(("puffs_vnop_rename: EAGAIN on tdvp vnode %p %s\n",
1255 tdvp, tnch->ncp->nc_name));
1259 error = vget(tvp, LK_EXCLUSIVE);
1261 DPRINTF(("puffs_vnop_rename: EAGAIN on tvp vnode %p %s\n",
1262 tvp, tnch->ncp->nc_name));
1268 if ((fvp->v_mount != tdvp->v_mount) ||
1269 (tvp && (fvp->v_mount != tvp->v_mount))) {
1275 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1278 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1284 PUFFS_MSG_ALLOC(vn, rename);
1285 rename_msg->pvnr_cookie_src = VPTOPNC(fvp);
1286 rename_msg->pvnr_cookie_targdir = VPTOPNC(tdvp);
1288 rename_msg->pvnr_cookie_targ = VPTOPNC(tvp);
1290 rename_msg->pvnr_cookie_targ = NULL;
1291 puffs_makecn(&rename_msg->pvnr_cn_src, &rename_msg->pvnr_cn_src_cred,
1293 puffs_makecn(&rename_msg->pvnr_cn_targ, &rename_msg->pvnr_cn_targ_cred,
1295 puffs_msg_setinfo(park_rename, PUFFSOP_VN,
1296 PUFFS_VN_RENAME, VPTOPNC(fdvp));
1298 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_rename, fdvp->v_data, NULL, error);
1300 PUFFS_MSG_RELEASE(rename);
1301 error = checkerr(pmp, error, __func__);
1304 puffs_updatenode(VPTOPP(fvp), PUFFS_UPDATECTIME);
1312 cache_rename(fnch, tnch);
1321 puffs_vnop_read(struct vop_read_args *ap)
1323 struct vnode *vp = ap->a_vp;
1324 struct uio *uio = ap->a_uio;
1325 int ioflag = ap->a_ioflag;
1326 struct ucred * cred = ap->a_cred;
1327 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1330 if (vp->v_type == VDIR)
1332 else if (vp->v_type != VREG)
1335 if (PUFFS_USE_PAGECACHE(pmp))
1336 error = puffs_bioread(vp, uio, ioflag, cred);
1338 error = puffs_directread(vp, uio, ioflag, cred);
1344 puffs_vnop_write(struct vop_write_args *ap)
1346 struct vnode *vp = ap->a_vp;
1347 struct uio *uio = ap->a_uio;
1348 int ioflag = ap->a_ioflag;
1349 struct ucred * cred = ap->a_cred;
1350 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1353 if (vp->v_type == VDIR)
1355 else if (vp->v_type != VREG)
1358 if (PUFFS_USE_PAGECACHE(pmp))
1359 error = puffs_biowrite(vp, uio, ioflag, cred);
1361 error = puffs_directwrite(vp, uio, ioflag, cred);
1367 puffs_vnop_print(struct vop_print_args *ap)
1369 PUFFS_MSG_VARS(vn, print);
1370 struct vnode *vp = ap->a_vp;
1371 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1372 struct puffs_node *pn = VPTOPP(vp);
1375 /* kernel portion */
1376 kprintf("tag VT_PUFFS, vnode %p, puffs node: %p,\n"
1377 "\tuserspace cookie: %p", vp, pn, pn->pn_cookie);
1378 if (vp->v_type == VFIFO)
1382 /* userspace portion */
1383 if (EXISTSOP(pmp, PRINT)) {
1384 PUFFS_MSG_ALLOC(vn, print);
1385 puffs_msg_setinfo(park_print, PUFFSOP_VN,
1386 PUFFS_VN_PRINT, VPTOPNC(vp));
1387 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_print, vp->v_data,
1389 PUFFS_MSG_RELEASE(print);
1396 puffs_vnop_pathconf(struct vop_pathconf_args *ap)
1398 PUFFS_MSG_VARS(vn, pathconf);
1399 struct vnode *vp = ap->a_vp;
1400 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1403 PUFFS_MSG_ALLOC(vn, pathconf);
1404 pathconf_msg->pvnr_name = ap->a_name;
1405 puffs_msg_setinfo(park_pathconf, PUFFSOP_VN,
1406 PUFFS_VN_PATHCONF, VPTOPNC(vp));
1407 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_pathconf, vp->v_data, NULL, error);
1408 error = checkerr(pmp, error, __func__);
1410 *ap->a_retval = pathconf_msg->pvnr_retval;
1411 PUFFS_MSG_RELEASE(pathconf);
1417 puffs_vnop_advlock(struct vop_advlock_args *ap)
1419 PUFFS_MSG_VARS(vn, advlock);
1420 struct vnode *vp = ap->a_vp;
1421 struct puffs_node *pn = VPTOPP(vp);
1422 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1425 if (!EXISTSOP(pmp, ADVLOCK))
1426 return lf_advlock(ap, &pn->pn_lockf, vp->v_filesize);
1428 PUFFS_MSG_ALLOC(vn, advlock);
1429 (void)memcpy(&advlock_msg->pvnr_fl, ap->a_fl,
1430 sizeof(advlock_msg->pvnr_fl));
1431 advlock_msg->pvnr_id = ap->a_id;
1432 advlock_msg->pvnr_op = ap->a_op;
1433 advlock_msg->pvnr_flags = ap->a_flags;
1434 puffs_msg_setinfo(park_advlock, PUFFSOP_VN,
1435 PUFFS_VN_ADVLOCK, VPTOPNC(vp));
1436 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_advlock, vp->v_data, NULL, error);
1437 error = checkerr(pmp, error, __func__);
1438 PUFFS_MSG_RELEASE(advlock);
1444 puffs_vnop_bmap(struct vop_bmap_args *ap)
1446 if (ap->a_doffsetp != NULL)
1447 *ap->a_doffsetp = ap->a_loffset;
1448 if (ap->a_runp != NULL)
1450 if (ap->a_runb != NULL)
1456 puffs_vnop_mmap(struct vop_mmap_args *ap)
1463 puffs_vnop_strategy(struct vop_strategy_args *ap)
1465 return puffs_doio(ap->a_vp, ap->a_bio, curthread);
1468 struct vop_ops puffs_fifo_vops = {
1469 .vop_default = fifo_vnoperate,
1470 .vop_access = puffs_vnop_access,
1471 .vop_getattr = puffs_vnop_getattr,
1472 .vop_setattr = puffs_vnop_setattr,
1473 .vop_inactive = puffs_vnop_inactive,
1474 .vop_reclaim = puffs_vnop_reclaim,
1475 .vop_print = puffs_vnop_print,
1478 struct vop_ops puffs_vnode_vops = {
1479 .vop_default = vop_defaultop,
1480 .vop_nresolve = puffs_vnop_lookup,
1481 .vop_nlookupdotdot = puffs_vnop_lookupdotdot,
1482 .vop_ncreate = puffs_vnop_create,
1483 .vop_nmkdir = puffs_vnop_mkdir,
1484 .vop_nrmdir = puffs_vnop_rmdir,
1485 .vop_nremove = puffs_vnop_remove,
1486 .vop_nrename = puffs_vnop_rename,
1487 .vop_nlink = puffs_vnop_link,
1488 .vop_nsymlink = puffs_vnop_symlink,
1489 .vop_nmknod = puffs_vnop_mknod,
1490 .vop_access = puffs_vnop_access,
1491 .vop_getattr = puffs_vnop_getattr,
1492 .vop_setattr = puffs_vnop_setattr,
1493 .vop_readdir = puffs_vnop_readdir,
1494 .vop_open = puffs_vnop_open,
1495 .vop_close = puffs_vnop_close,
1496 .vop_read = puffs_vnop_read,
1497 .vop_write = puffs_vnop_write,
1498 .vop_readlink = puffs_vnop_readlink,
1499 .vop_advlock = puffs_vnop_advlock,
1500 .vop_bmap = puffs_vnop_bmap,
1501 .vop_mmap = puffs_vnop_mmap,
1502 .vop_strategy = puffs_vnop_strategy,
1503 .vop_getpages = vop_stdgetpages,
1504 .vop_putpages = vop_stdputpages,
1505 .vop_fsync = puffs_vnop_fsync,
1506 .vop_inactive = puffs_vnop_inactive,
1507 .vop_reclaim = puffs_vnop_reclaim,
1508 .vop_pathconf = puffs_vnop_pathconf,
1509 .vop_print = puffs_vnop_print,