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 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);
172 if (!error && vp != NULL) {
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 if (!EXISTSOP(pmp, CREATE))
265 DPRINTF(("puffs_create: dvp %p, name: %s\n",
268 if (vap->va_type != VREG && vap->va_type != VSOCK)
271 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
272 DPRINTF(("puffs_vnop_create: EAGAIN on ncp %p %s\n",
277 PUFFS_MSG_ALLOC(vn, create);
278 puffs_makecn(&create_msg->pvnr_cn, &create_msg->pvnr_cn_cred,
280 create_msg->pvnr_va = *ap->a_vap;
281 puffs_msg_setinfo(park_create, PUFFSOP_VN,
282 PUFFS_VN_CREATE, VPTOPNC(dvp));
283 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_create, dvp->v_data, NULL, error);
285 error = checkerr(pmp, error, __func__);
289 error = puffs_newnode(mp, dvp, ap->a_vpp,
290 create_msg->pvnr_newnode, vap->va_type);
292 puffs_abortbutton(pmp, PUFFS_ABORT_CREATE, dpn->pn_cookie,
293 create_msg->pvnr_newnode, ncp, cred);
296 DPRINTF(("puffs_create: return %d\n", error));
299 cache_setunresolved(nch);
300 cache_setvp(nch, *ap->a_vpp);
302 PUFFS_MSG_RELEASE(create);
307 puffs_vnop_mknod(struct vop_nmknod_args *ap)
309 PUFFS_MSG_VARS(vn, mknod);
310 struct vnode *dvp = ap->a_dvp;
311 struct vattr *vap = ap->a_vap;
312 struct puffs_node *dpn = VPTOPP(dvp);
313 struct nchandle *nch = ap->a_nch;
314 struct namecache *ncp = nch->ncp;
315 struct ucred *cred = ap->a_cred;
316 struct mount *mp = dvp->v_mount;
317 struct puffs_mount *pmp = MPTOPUFFSMP(mp);
320 if (!EXISTSOP(pmp, MKNOD))
323 DPRINTF(("puffs_mknod: dvp %p, name: %s\n",
326 if (vap->va_type != VFIFO)
329 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
330 DPRINTF(("puffs_vnop_mknod: EAGAIN on ncp %p %s\n",
335 PUFFS_MSG_ALLOC(vn, mknod);
336 puffs_makecn(&mknod_msg->pvnr_cn, &mknod_msg->pvnr_cn_cred,
338 mknod_msg->pvnr_va = *ap->a_vap;
339 puffs_msg_setinfo(park_mknod, PUFFSOP_VN,
340 PUFFS_VN_MKNOD, VPTOPNC(dvp));
342 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_mknod, dvp->v_data, NULL, error);
344 error = checkerr(pmp, error, __func__);
348 error = puffs_newnode(mp, dvp, ap->a_vpp,
349 mknod_msg->pvnr_newnode, vap->va_type);
351 puffs_abortbutton(pmp, PUFFS_ABORT_MKNOD, dpn->pn_cookie,
352 mknod_msg->pvnr_newnode, ncp, cred);
357 cache_setunresolved(nch);
358 cache_setvp(nch, *ap->a_vpp);
360 PUFFS_MSG_RELEASE(mknod);
365 puffs_vnop_open(struct vop_open_args *ap)
367 PUFFS_MSG_VARS(vn, open);
368 struct vnode *vp = ap->a_vp;
369 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
370 int mode = ap->a_mode;
373 DPRINTF(("puffs_open: vp %p, mode 0x%x\n", vp, mode));
375 if (vp->v_type == VREG && mode & FWRITE && !EXISTSOP(pmp, WRITE))
378 if (!EXISTSOP(pmp, OPEN))
381 PUFFS_MSG_ALLOC(vn, open);
382 open_msg->pvnr_mode = mode;
383 puffs_credcvt(&open_msg->pvnr_cred, ap->a_cred);
384 puffs_msg_setinfo(park_open, PUFFSOP_VN,
385 PUFFS_VN_OPEN, VPTOPNC(vp));
387 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_open, vp->v_data, NULL, error);
388 error = checkerr(pmp, error, __func__);
391 DPRINTF(("puffs_open: returning %d\n", error));
392 PUFFS_MSG_RELEASE(open);
395 return vop_stdopen(ap);
399 puffs_vnop_close(struct vop_close_args *ap)
401 PUFFS_MSG_VARS(vn, close);
402 struct vnode *vp = ap->a_vp;
403 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
405 if (!EXISTSOP(pmp, CLOSE))
406 return vop_stdclose(ap);
408 PUFFS_MSG_ALLOC(vn, close);
409 puffs_msg_setfaf(park_close);
410 close_msg->pvnr_fflag = ap->a_fflag;
411 puffs_msg_setinfo(park_close, PUFFSOP_VN,
412 PUFFS_VN_CLOSE, VPTOPNC(vp));
414 puffs_msg_enqueue(pmp, park_close);
415 PUFFS_MSG_RELEASE(close);
416 return vop_stdclose(ap);
420 puffs_vnop_access(struct vop_access_args *ap)
422 PUFFS_MSG_VARS(vn, access);
423 struct vnode *vp = ap->a_vp;
424 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
425 int mode = ap->a_mode;
429 switch (vp->v_type) {
433 if ((vp->v_mount->mnt_flag & MNT_RDONLY)
434 || !EXISTSOP(pmp, WRITE))
442 if (!EXISTSOP(pmp, ACCESS))
445 PUFFS_MSG_ALLOC(vn, access);
446 access_msg->pvnr_mode = ap->a_mode;
447 puffs_credcvt(&access_msg->pvnr_cred, ap->a_cred);
448 puffs_msg_setinfo(park_access, PUFFSOP_VN,
449 PUFFS_VN_ACCESS, VPTOPNC(vp));
451 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_access, vp->v_data, NULL, error);
452 error = checkerr(pmp, error, __func__);
453 PUFFS_MSG_RELEASE(access);
459 puffs_vnop_getattr(struct vop_getattr_args *ap)
461 PUFFS_MSG_VARS(vn, getattr);
462 struct vnode *vp = ap->a_vp;
463 struct mount *mp = vp->v_mount;
464 struct puffs_mount *pmp = MPTOPUFFSMP(mp);
465 struct vattr *vap, *rvap;
466 struct puffs_node *pn = VPTOPP(vp);
469 if (vp->v_type == VBLK || vp->v_type == VCHR)
474 PUFFS_MSG_ALLOC(vn, getattr);
475 vattr_null(&getattr_msg->pvnr_va);
476 puffs_credcvt(&getattr_msg->pvnr_cred, curproc->p_ucred);
477 puffs_msg_setinfo(park_getattr, PUFFSOP_VN,
478 PUFFS_VN_GETATTR, VPTOPNC(vp));
480 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_getattr, vp->v_data, NULL, error);
481 error = checkerr(pmp, error, __func__);
485 rvap = &getattr_msg->pvnr_va;
487 (void) memcpy(vap, rvap, sizeof(struct vattr));
488 vap->va_fsid = mp->mnt_stat.f_fsid.val[0];
490 if (pn->pn_stat & PNODE_METACACHE_ATIME)
491 vap->va_atime = pn->pn_mc_atime;
492 if (pn->pn_stat & PNODE_METACACHE_CTIME)
493 vap->va_ctime = pn->pn_mc_ctime;
494 if (pn->pn_stat & PNODE_METACACHE_MTIME)
495 vap->va_mtime = pn->pn_mc_mtime;
496 if (pn->pn_stat & PNODE_METACACHE_SIZE) {
497 vap->va_size = pn->pn_mc_size;
499 if (rvap->va_size != VNOVAL
500 && vp->v_type != VBLK && vp->v_type != VCHR) {
501 pn->pn_serversize = rvap->va_size;
502 if (vp->v_type == VREG)
503 puffs_meta_setsize(vp, rvap->va_size, 0);
508 PUFFS_MSG_RELEASE(getattr);
512 #define SETATTR_CHSIZE 0x01
513 #define SETATTR_ASYNC 0x02
515 dosetattr(struct vnode *vp, struct vattr *vap, struct ucred *cred, int flags)
517 PUFFS_MSG_VARS(vn, setattr);
518 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
519 struct puffs_node *pn = VPTOPP(vp);
522 if ((vp->v_mount->mnt_flag & MNT_RDONLY) &&
523 (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL
524 || vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL
525 || vap->va_mode != (mode_t)VNOVAL))
528 if ((vp->v_mount->mnt_flag & MNT_RDONLY)
529 && vp->v_type == VREG && vap->va_size != VNOVAL)
533 * Flush metacache first. If we are called with some explicit
534 * parameters, treat them as information overriding metacache
537 if (pn->pn_stat & PNODE_METACACHE_MASK) {
538 if ((pn->pn_stat & PNODE_METACACHE_ATIME)
539 && vap->va_atime.tv_sec == VNOVAL)
540 vap->va_atime = pn->pn_mc_atime;
541 if ((pn->pn_stat & PNODE_METACACHE_CTIME)
542 && vap->va_ctime.tv_sec == VNOVAL)
543 vap->va_ctime = pn->pn_mc_ctime;
544 if ((pn->pn_stat & PNODE_METACACHE_MTIME)
545 && vap->va_mtime.tv_sec == VNOVAL)
546 vap->va_mtime = pn->pn_mc_mtime;
547 if ((pn->pn_stat & PNODE_METACACHE_SIZE)
548 && vap->va_size == VNOVAL)
549 vap->va_size = pn->pn_mc_size;
551 pn->pn_stat &= ~PNODE_METACACHE_MASK;
554 PUFFS_MSG_ALLOC(vn, setattr);
555 (void)memcpy(&setattr_msg->pvnr_va, vap, sizeof(struct vattr));
556 puffs_credcvt(&setattr_msg->pvnr_cred, cred);
557 puffs_msg_setinfo(park_setattr, PUFFSOP_VN,
558 PUFFS_VN_SETATTR, VPTOPNC(vp));
559 if (flags & SETATTR_ASYNC)
560 puffs_msg_setfaf(park_setattr);
562 puffs_msg_enqueue(pmp, park_setattr);
563 if ((flags & SETATTR_ASYNC) == 0)
564 error = puffs_msg_wait2(pmp, park_setattr, vp->v_data, NULL);
565 PUFFS_MSG_RELEASE(setattr);
566 if ((flags & SETATTR_ASYNC) == 0) {
567 error = checkerr(pmp, error, __func__);
574 if (vap->va_size != VNOVAL) {
575 pn->pn_serversize = vap->va_size;
576 if (flags & SETATTR_CHSIZE)
577 puffs_meta_setsize(vp, vap->va_size, 0);
584 puffs_vnop_setattr(struct vop_setattr_args *ap)
586 return dosetattr(ap->a_vp, ap->a_vap, ap->a_cred, SETATTR_CHSIZE);
590 doinact(struct puffs_mount *pmp, int iaflag)
593 if (EXISTSOP(pmp, INACTIVE))
594 if (pmp->pmp_flags & PUFFS_KFLAG_IAONDEMAND)
595 if (iaflag || ALLOPS(pmp))
606 callinactive(struct puffs_mount *pmp, puffs_cookie_t ck, int iaflag)
609 PUFFS_MSG_VARS(vn, inactive);
611 if (doinact(pmp, iaflag)) {
612 PUFFS_MSG_ALLOC(vn, inactive);
613 puffs_msg_setinfo(park_inactive, PUFFSOP_VN,
614 PUFFS_VN_INACTIVE, ck);
616 PUFFS_MSG_ENQUEUEWAIT(pmp, park_inactive, error);
617 PUFFS_MSG_RELEASE(inactive);
621 /* XXX: callinactive can't setback */
623 puffs_vnop_inactive(struct vop_inactive_args *ap)
625 PUFFS_MSG_VARS(vn, inactive);
626 struct vnode *vp = ap->a_vp;
627 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
628 struct puffs_node *pnode = VPTOPP(vp);
630 flushvncache(vp, MNT_NOWAIT);
632 if (doinact(pmp, pnode->pn_stat & PNODE_DOINACT)) {
634 * do not wait for reply from userspace, otherwise it may
638 PUFFS_MSG_ALLOC(vn, inactive);
639 puffs_msg_setfaf(park_inactive);
640 puffs_msg_setinfo(park_inactive, PUFFSOP_VN,
641 PUFFS_VN_INACTIVE, VPTOPNC(vp));
643 puffs_msg_enqueue(pmp, park_inactive);
644 PUFFS_MSG_RELEASE(inactive);
646 pnode->pn_stat &= ~PNODE_DOINACT;
649 * file server thinks it's gone? then don't be afraid care,
650 * node's life was already all it would ever be
652 if (pnode->pn_stat & PNODE_NOREFS) {
653 pnode->pn_stat |= PNODE_DYING;
661 callreclaim(struct puffs_mount *pmp, puffs_cookie_t ck)
663 PUFFS_MSG_VARS(vn, reclaim);
665 if (!EXISTSOP(pmp, RECLAIM))
668 PUFFS_MSG_ALLOC(vn, reclaim);
669 puffs_msg_setfaf(park_reclaim);
670 puffs_msg_setinfo(park_reclaim, PUFFSOP_VN, PUFFS_VN_RECLAIM, ck);
672 puffs_msg_enqueue(pmp, park_reclaim);
673 PUFFS_MSG_RELEASE(reclaim);
677 * always FAF, we don't really care if the server wants to fail to
678 * reclaim the node or not
681 puffs_vnop_reclaim(struct vop_reclaim_args *ap)
683 struct vnode *vp = ap->a_vp;
684 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
685 struct puffs_node *pnode = VPTOPP(vp);
686 boolean_t notifyserver = TRUE;
688 vinvalbuf(vp, V_SAVE, 0, 0);
691 * first things first: check if someone is trying to reclaim the
692 * root vnode. do not allow that to travel to userspace.
693 * Note that we don't need to take the lock similarly to
694 * puffs_root(), since there is only one of us.
696 if (vp->v_flag & VROOT) {
697 lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE);
698 KKASSERT(pmp->pmp_root != NULL);
699 pmp->pmp_root = NULL;
700 lockmgr(&pmp->pmp_lock, LK_RELEASE);
701 notifyserver = FALSE;
705 * purge info from kernel before issueing FAF, since we
706 * don't really know when we'll get around to it after
707 * that and someone might race us into node creation
709 lockmgr(&pmp->pmp_lock, LK_EXCLUSIVE);
710 LIST_REMOVE(pnode, pn_hashent);
711 lockmgr(&pmp->pmp_lock, LK_RELEASE);
714 callreclaim(MPTOPUFFSMP(vp->v_mount), VPTOPNC(vp));
722 #define CSIZE sizeof(**ap->a_cookies)
724 puffs_vnop_readdir(struct vop_readdir_args *ap)
726 PUFFS_MSG_VARS(vn, readdir);
727 struct vnode *vp = ap->a_vp;
728 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
729 size_t argsize, tomove, cookiemem, cookiesmax;
730 struct uio *uio = ap->a_uio;
731 size_t howmuch, resid;
734 if (!EXISTSOP(pmp, READDIR))
738 * ok, so we need: resid + cookiemem = maxreq
739 * => resid + cookiesize * (resid/minsize) = maxreq
740 * => resid + cookiesize/minsize * resid = maxreq
741 * => (cookiesize/minsize + 1) * resid = maxreq
742 * => resid = maxreq / (cookiesize/minsize + 1)
744 * Since cookiesize <= minsize and we're not very big on floats,
745 * we approximate that to be 1. Therefore:
747 * resid = maxreq / 2;
749 * Well, at least we didn't have to use differential equations
750 * or the Gram-Schmidt process.
752 * (yes, I'm very afraid of this)
754 KKASSERT(CSIZE <= _DIRENT_RECLEN(1));
757 KKASSERT(ap->a_ncookies != NULL);
758 if (pmp->pmp_args.pa_fhsize == 0)
760 resid = PUFFS_TOMOVE(uio->uio_resid, pmp) / 2;
761 cookiesmax = resid/_DIRENT_RECLEN(1);
762 cookiemem = ALIGN(cookiesmax*CSIZE); /* play safe */
764 resid = PUFFS_TOMOVE(uio->uio_resid, pmp);
769 argsize = sizeof(struct puffs_vnmsg_readdir);
770 tomove = resid + cookiemem;
771 puffs_msgmem_alloc(argsize + tomove, &park_readdir,
772 (void *)&readdir_msg, 1);
774 puffs_credcvt(&readdir_msg->pvnr_cred, ap->a_cred);
775 readdir_msg->pvnr_offset = uio->uio_offset;
776 readdir_msg->pvnr_resid = resid;
777 readdir_msg->pvnr_ncookies = cookiesmax;
778 readdir_msg->pvnr_eofflag = 0;
779 readdir_msg->pvnr_dentoff = cookiemem;
780 puffs_msg_setinfo(park_readdir, PUFFSOP_VN,
781 PUFFS_VN_READDIR, VPTOPNC(vp));
782 puffs_msg_setdelta(park_readdir, tomove);
784 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_readdir, vp->v_data, NULL, error);
785 error = checkerr(pmp, error, __func__);
789 /* userspace is cheating? */
790 if (readdir_msg->pvnr_resid > resid) {
791 puffs_senderr(pmp, PUFFS_ERR_READDIR, E2BIG,
792 "resid grew", VPTOPNC(vp));
795 if (readdir_msg->pvnr_ncookies > cookiesmax) {
796 puffs_senderr(pmp, PUFFS_ERR_READDIR, E2BIG,
797 "too many cookies", VPTOPNC(vp));
802 if (readdir_msg->pvnr_eofflag)
805 /* bouncy-wouncy with the directory data */
806 howmuch = resid - readdir_msg->pvnr_resid;
808 /* force eof if no data was returned (getcwd() needs this) */
814 error = uiomove(readdir_msg->pvnr_data + cookiemem, howmuch, uio);
818 /* provide cookies to caller if so desired */
820 *ap->a_cookies = kmalloc(readdir_msg->pvnr_ncookies*CSIZE,
822 *ap->a_ncookies = readdir_msg->pvnr_ncookies;
823 memcpy(*ap->a_cookies, readdir_msg->pvnr_data,
824 *ap->a_ncookies*CSIZE);
827 /* next readdir starts here */
828 uio->uio_offset = readdir_msg->pvnr_offset;
831 puffs_msgmem_release(park_readdir);
837 flushvncache(struct vnode *vp, int waitfor)
839 struct puffs_node *pn = VPTOPP(vp);
843 /* flush out information from our metacache, see vop_setattr */
844 if (pn->pn_stat & PNODE_METACACHE_MASK
845 && (pn->pn_stat & PNODE_DYING) == 0) {
847 error = dosetattr(vp, &va, FSCRED, SETATTR_CHSIZE |
848 (waitfor == MNT_NOWAIT ? 0 : SETATTR_ASYNC));
854 * flush pages to avoid being overly dirty
856 vfsync(vp, waitfor, 0, NULL, NULL);
862 puffs_vnop_fsync(struct vop_fsync_args *ap)
864 PUFFS_MSG_VARS(vn, fsync);
865 struct vnode *vp = ap->a_vp;
866 int waitfor = ap->a_waitfor;
867 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
868 struct puffs_node *pn = VPTOPP(vp);
871 error = flushvncache(vp, waitfor);
876 * HELLO! We exit already here if the user server does not
877 * support fsync OR if we should call fsync for a node which
878 * has references neither in the kernel or the fs server.
879 * Otherwise we continue to issue fsync() forward.
881 if (!EXISTSOP(pmp, FSYNC) || (pn->pn_stat & PNODE_DYING))
884 dofaf = (waitfor & MNT_WAIT) == 0 || (waitfor & MNT_LAZY) != 0;
886 PUFFS_MSG_ALLOC(vn, fsync);
888 puffs_msg_setfaf(park_fsync);
890 fsync_msg->pvnr_flags = ap->a_flags;
891 puffs_msg_setinfo(park_fsync, PUFFSOP_VN,
892 PUFFS_VN_FSYNC, VPTOPNC(vp));
894 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_fsync, vp->v_data, NULL, error);
895 PUFFS_MSG_RELEASE(fsync);
897 error = checkerr(pmp, error, __func__);
903 callremove(struct puffs_mount *pmp, puffs_cookie_t dck, puffs_cookie_t ck,
904 struct namecache *ncp, struct ucred *cred)
906 PUFFS_MSG_VARS(vn, remove);
909 PUFFS_MSG_ALLOC(vn, remove);
910 remove_msg->pvnr_cookie_targ = ck;
911 puffs_makecn(&remove_msg->pvnr_cn, &remove_msg->pvnr_cn_cred,
913 puffs_msg_setinfo(park_remove, PUFFSOP_VN, PUFFS_VN_REMOVE, dck);
915 PUFFS_MSG_ENQUEUEWAIT(pmp, park_remove, error);
916 PUFFS_MSG_RELEASE(remove);
918 return checkerr(pmp, error, __func__);
922 * XXX: can't use callremove now because can't catch setbacks with
923 * it due to lack of a pnode argument.
926 puffs_vnop_remove(struct vop_nremove_args *ap)
928 PUFFS_MSG_VARS(vn, remove);
929 struct vnode *dvp = ap->a_dvp;
931 struct puffs_node *dpn = VPTOPP(dvp);
932 struct puffs_node *pn;
933 struct nchandle *nch = ap->a_nch;
934 struct namecache *ncp = nch->ncp;
935 struct ucred *cred = ap->a_cred;
936 struct mount *mp = dvp->v_mount;
937 struct puffs_mount *pmp = MPTOPUFFSMP(mp);
940 if (!EXISTSOP(pmp, REMOVE))
943 error = vget(dvp, LK_EXCLUSIVE);
945 DPRINTF(("puffs_vnop_remove: EAGAIN on parent vnode %p %s\n",
950 error = cache_vget(nch, cred, LK_EXCLUSIVE, &vp);
952 DPRINTF(("puffs_vnop_remove: cache_vget error: %p %s\n",
956 if (vp->v_type == VDIR) {
962 PUFFS_MSG_ALLOC(vn, remove);
963 remove_msg->pvnr_cookie_targ = VPTOPNC(vp);
964 puffs_makecn(&remove_msg->pvnr_cn, &remove_msg->pvnr_cn_cred,
966 puffs_msg_setinfo(park_remove, PUFFSOP_VN,
967 PUFFS_VN_REMOVE, VPTOPNC(dvp));
969 puffs_msg_enqueue(pmp, park_remove);
970 error = puffs_msg_wait2(pmp, park_remove, dpn, pn);
972 PUFFS_MSG_RELEASE(remove);
974 error = checkerr(pmp, error, __func__);
980 cache_setunresolved(nch);
981 cache_setvp(nch, NULL);
988 puffs_vnop_mkdir(struct vop_nmkdir_args *ap)
990 PUFFS_MSG_VARS(vn, mkdir);
991 struct vnode *dvp = ap->a_dvp;
992 struct puffs_node *dpn = VPTOPP(dvp);
993 struct nchandle *nch = ap->a_nch;
994 struct namecache *ncp = nch->ncp;
995 struct ucred *cred = ap->a_cred;
996 struct mount *mp = dvp->v_mount;
997 struct puffs_mount *pmp = MPTOPUFFSMP(mp);
1000 if (!EXISTSOP(pmp, MKDIR))
1003 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
1004 DPRINTF(("puffs_vnop_mkdir: EAGAIN on ncp %p %s\n",
1005 ncp, ncp->nc_name));
1009 PUFFS_MSG_ALLOC(vn, mkdir);
1010 puffs_makecn(&mkdir_msg->pvnr_cn, &mkdir_msg->pvnr_cn_cred,
1012 mkdir_msg->pvnr_va = *ap->a_vap;
1013 puffs_msg_setinfo(park_mkdir, PUFFSOP_VN,
1014 PUFFS_VN_MKDIR, VPTOPNC(dvp));
1016 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_mkdir, dvp->v_data, NULL, error);
1018 error = checkerr(pmp, error, __func__);
1022 error = puffs_newnode(mp, dvp, ap->a_vpp,
1023 mkdir_msg->pvnr_newnode, VDIR);
1025 puffs_abortbutton(pmp, PUFFS_ABORT_MKDIR, dpn->pn_cookie,
1026 mkdir_msg->pvnr_newnode, ncp, cred);
1031 cache_setunresolved(nch);
1032 cache_setvp(nch, *ap->a_vpp);
1034 PUFFS_MSG_RELEASE(mkdir);
1039 callrmdir(struct puffs_mount *pmp, puffs_cookie_t dck, puffs_cookie_t ck,
1040 struct namecache *ncp, struct ucred *cred)
1042 PUFFS_MSG_VARS(vn, rmdir);
1045 PUFFS_MSG_ALLOC(vn, rmdir);
1046 rmdir_msg->pvnr_cookie_targ = ck;
1047 puffs_makecn(&rmdir_msg->pvnr_cn, &rmdir_msg->pvnr_cn_cred,
1049 puffs_msg_setinfo(park_rmdir, PUFFSOP_VN, PUFFS_VN_RMDIR, dck);
1051 PUFFS_MSG_ENQUEUEWAIT(pmp, park_rmdir, error);
1052 PUFFS_MSG_RELEASE(rmdir);
1054 return checkerr(pmp, error, __func__);
1058 puffs_vnop_rmdir(struct vop_nrmdir_args *ap)
1060 PUFFS_MSG_VARS(vn, rmdir);
1061 struct vnode *dvp = ap->a_dvp;
1063 struct puffs_node *dpn = VPTOPP(dvp);
1064 struct puffs_node *pn;
1065 struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1066 struct nchandle *nch = ap->a_nch;
1067 struct namecache *ncp = nch->ncp;
1068 struct ucred *cred = ap->a_cred;
1071 if (!EXISTSOP(pmp, RMDIR))
1074 error = vget(dvp, LK_EXCLUSIVE);
1076 DPRINTF(("puffs_vnop_rmdir: EAGAIN on parent vnode %p %s\n",
1077 dvp, ncp->nc_name));
1080 error = cache_vget(nch, cred, LK_EXCLUSIVE, &vp);
1082 DPRINTF(("puffs_vnop_rmdir: cache_vget error: %p %s\n",
1083 dvp, ncp->nc_name));
1086 if (vp->v_type != VDIR) {
1092 PUFFS_MSG_ALLOC(vn, rmdir);
1093 rmdir_msg->pvnr_cookie_targ = VPTOPNC(vp);
1094 puffs_makecn(&rmdir_msg->pvnr_cn, &rmdir_msg->pvnr_cn_cred,
1096 puffs_msg_setinfo(park_rmdir, PUFFSOP_VN,
1097 PUFFS_VN_RMDIR, VPTOPNC(dvp));
1099 puffs_msg_enqueue(pmp, park_rmdir);
1100 error = puffs_msg_wait2(pmp, park_rmdir, dpn, pn);
1102 PUFFS_MSG_RELEASE(rmdir);
1104 error = checkerr(pmp, error, __func__);
1110 cache_setunresolved(nch);
1111 cache_setvp(nch, NULL);
1118 puffs_vnop_link(struct vop_nlink_args *ap)
1120 PUFFS_MSG_VARS(vn, link);
1121 struct vnode *dvp = ap->a_dvp;
1122 struct vnode *vp = ap->a_vp;
1123 struct puffs_node *dpn = VPTOPP(dvp);
1124 struct puffs_node *pn = VPTOPP(vp);
1125 struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1126 struct nchandle *nch = ap->a_nch;
1127 struct namecache *ncp = nch->ncp;
1128 struct ucred *cred = ap->a_cred;
1131 if (!EXISTSOP(pmp, LINK))
1134 if (vp->v_mount != dvp->v_mount)
1137 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
1138 DPRINTF(("puffs_vnop_link: EAGAIN on ncp %p %s\n",
1139 ncp, ncp->nc_name));
1143 PUFFS_MSG_ALLOC(vn, link);
1144 link_msg->pvnr_cookie_targ = VPTOPNC(vp);
1145 puffs_makecn(&link_msg->pvnr_cn, &link_msg->pvnr_cn_cred,
1147 puffs_msg_setinfo(park_link, PUFFSOP_VN,
1148 PUFFS_VN_LINK, VPTOPNC(dvp));
1150 puffs_msg_enqueue(pmp, park_link);
1151 error = puffs_msg_wait2(pmp, park_link, dpn, pn);
1153 PUFFS_MSG_RELEASE(link);
1155 error = checkerr(pmp, error, __func__);
1158 * XXX: stay in touch with the cache. I don't like this, but
1159 * don't have a better solution either. See also puffs_rename().
1162 puffs_updatenode(pn, PUFFS_UPDATECTIME);
1167 cache_setunresolved(nch);
1168 cache_setvp(nch, vp);
1174 puffs_vnop_symlink(struct vop_nsymlink_args *ap)
1176 PUFFS_MSG_VARS(vn, symlink);
1177 struct vnode *dvp = ap->a_dvp;
1178 struct puffs_node *dpn = VPTOPP(dvp);
1179 struct mount *mp = dvp->v_mount;
1180 struct puffs_mount *pmp = MPTOPUFFSMP(dvp->v_mount);
1181 struct nchandle *nch = ap->a_nch;
1182 struct namecache *ncp = nch->ncp;
1183 struct ucred *cred = ap->a_cred;
1186 if (!EXISTSOP(pmp, SYMLINK))
1189 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) {
1190 DPRINTF(("puffs_vnop_symlink: EAGAIN on ncp %p %s\n",
1191 ncp, ncp->nc_name));
1197 PUFFS_MSG_ALLOC(vn, symlink);
1198 puffs_makecn(&symlink_msg->pvnr_cn, &symlink_msg->pvnr_cn_cred,
1200 symlink_msg->pvnr_va = *ap->a_vap;
1201 (void)strlcpy(symlink_msg->pvnr_link, ap->a_target,
1202 sizeof(symlink_msg->pvnr_link));
1203 puffs_msg_setinfo(park_symlink, PUFFSOP_VN,
1204 PUFFS_VN_SYMLINK, VPTOPNC(dvp));
1206 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_symlink, dvp->v_data, NULL, error);
1208 error = checkerr(pmp, error, __func__);
1212 error = puffs_newnode(mp, dvp, ap->a_vpp,
1213 symlink_msg->pvnr_newnode, VLNK);
1215 puffs_abortbutton(pmp, PUFFS_ABORT_SYMLINK, dpn->pn_cookie,
1216 symlink_msg->pvnr_newnode, ncp, cred);
1220 PUFFS_MSG_RELEASE(symlink);
1222 cache_setunresolved(nch);
1223 cache_setvp(nch, *ap->a_vpp);
1229 puffs_vnop_readlink(struct vop_readlink_args *ap)
1231 PUFFS_MSG_VARS(vn, readlink);
1232 struct vnode *vp = ap->a_vp;
1233 struct puffs_mount *pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
1237 if (!EXISTSOP(pmp, READLINK))
1240 PUFFS_MSG_ALLOC(vn, readlink);
1241 puffs_credcvt(&readlink_msg->pvnr_cred, ap->a_cred);
1242 linklen = sizeof(readlink_msg->pvnr_link);
1243 readlink_msg->pvnr_linklen = linklen;
1244 puffs_msg_setinfo(park_readlink, PUFFSOP_VN,
1245 PUFFS_VN_READLINK, VPTOPNC(vp));
1247 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_readlink, vp->v_data, NULL, error);
1248 error = checkerr(pmp, error, __func__);
1252 /* bad bad user file server */
1253 if (readlink_msg->pvnr_linklen > linklen) {
1254 puffs_senderr(pmp, PUFFS_ERR_READLINK, E2BIG,
1255 "linklen too big", VPTOPNC(ap->a_vp));
1260 error = uiomove(readlink_msg->pvnr_link, readlink_msg->pvnr_linklen,
1263 PUFFS_MSG_RELEASE(readlink);
1268 puffs_vnop_rename(struct vop_nrename_args *ap)
1270 PUFFS_MSG_VARS(vn, rename);
1271 struct nchandle *fnch = ap->a_fnch;
1272 struct nchandle *tnch = ap->a_tnch;
1273 struct vnode *fdvp = ap->a_fdvp;
1274 struct vnode *fvp = fnch->ncp->nc_vp;
1275 struct vnode *tdvp = ap->a_tdvp;
1276 struct vnode *tvp = tnch->ncp->nc_vp;
1277 struct ucred *cred = ap->a_cred;
1278 struct puffs_mount *pmp = MPTOPUFFSMP(fdvp->v_mount);
1280 boolean_t doabort = TRUE;
1282 if (!EXISTSOP(pmp, RENAME))
1285 error = vget(tdvp, LK_EXCLUSIVE);
1287 DPRINTF(("puffs_vnop_rename: EAGAIN on tdvp vnode %p %s\n",
1288 tdvp, tnch->ncp->nc_name));
1292 error = vget(tvp, LK_EXCLUSIVE);
1294 DPRINTF(("puffs_vnop_rename: EAGAIN on tvp vnode %p %s\n",
1295 tvp, tnch->ncp->nc_name));
1301 if ((fvp->v_mount != tdvp->v_mount) ||
1302 (tvp && (fvp->v_mount != tvp->v_mount))) {
1308 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1311 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1317 PUFFS_MSG_ALLOC(vn, rename);
1318 rename_msg->pvnr_cookie_src = VPTOPNC(fvp);
1319 rename_msg->pvnr_cookie_targdir = VPTOPNC(tdvp);
1321 rename_msg->pvnr_cookie_targ = VPTOPNC(tvp);
1323 rename_msg->pvnr_cookie_targ = NULL;
1324 puffs_makecn(&rename_msg->pvnr_cn_src, &rename_msg->pvnr_cn_src_cred,
1326 puffs_makecn(&rename_msg->pvnr_cn_targ, &rename_msg->pvnr_cn_targ_cred,
1328 puffs_msg_setinfo(park_rename, PUFFSOP_VN,
1329 PUFFS_VN_RENAME, VPTOPNC(fdvp));
1331 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_rename, fdvp->v_data, NULL, error);
1333 PUFFS_MSG_RELEASE(rename);
1334 error = checkerr(pmp, error, __func__);
1337 puffs_updatenode(VPTOPP(fvp), PUFFS_UPDATECTIME);
1345 cache_rename(fnch, tnch);
1354 puffs_vnop_read(struct vop_read_args *ap)
1356 struct vnode *vp = ap->a_vp;
1357 struct uio *uio = ap->a_uio;
1358 int ioflag = ap->a_ioflag;
1359 struct ucred * cred = ap->a_cred;
1360 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1363 if (!EXISTSOP(pmp, READ))
1366 if (vp->v_type == VDIR)
1368 else if (vp->v_type != VREG)
1371 if (PUFFS_USE_PAGECACHE(pmp))
1372 error = puffs_bioread(vp, uio, ioflag, cred);
1374 error = puffs_directread(vp, uio, ioflag, cred);
1380 puffs_vnop_write(struct vop_write_args *ap)
1382 struct vnode *vp = ap->a_vp;
1383 struct uio *uio = ap->a_uio;
1384 int ioflag = ap->a_ioflag;
1385 struct ucred * cred = ap->a_cred;
1386 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1389 if (!EXISTSOP(pmp, WRITE))
1392 if (vp->v_type == VDIR)
1394 else if (vp->v_type != VREG)
1397 if (PUFFS_USE_PAGECACHE(pmp))
1398 error = puffs_biowrite(vp, uio, ioflag, cred);
1400 error = puffs_directwrite(vp, uio, ioflag, cred);
1406 puffs_vnop_print(struct vop_print_args *ap)
1408 PUFFS_MSG_VARS(vn, print);
1409 struct vnode *vp = ap->a_vp;
1410 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1411 struct puffs_node *pn = VPTOPP(vp);
1414 /* kernel portion */
1415 kprintf("tag VT_PUFFS, vnode %p, puffs node: %p,\n"
1416 "\tuserspace cookie: %p", vp, pn, pn->pn_cookie);
1417 if (vp->v_type == VFIFO)
1421 /* userspace portion */
1422 if (EXISTSOP(pmp, PRINT)) {
1423 PUFFS_MSG_ALLOC(vn, print);
1424 puffs_msg_setinfo(park_print, PUFFSOP_VN,
1425 PUFFS_VN_PRINT, VPTOPNC(vp));
1426 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_print, vp->v_data,
1428 PUFFS_MSG_RELEASE(print);
1435 puffs_vnop_pathconf(struct vop_pathconf_args *ap)
1437 PUFFS_MSG_VARS(vn, pathconf);
1438 struct vnode *vp = ap->a_vp;
1439 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1442 if (!EXISTSOP(pmp, PATHCONF))
1445 PUFFS_MSG_ALLOC(vn, pathconf);
1446 pathconf_msg->pvnr_name = ap->a_name;
1447 puffs_msg_setinfo(park_pathconf, PUFFSOP_VN,
1448 PUFFS_VN_PATHCONF, VPTOPNC(vp));
1449 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_pathconf, vp->v_data, NULL, error);
1450 error = checkerr(pmp, error, __func__);
1452 *ap->a_retval = pathconf_msg->pvnr_retval;
1453 PUFFS_MSG_RELEASE(pathconf);
1459 puffs_vnop_advlock(struct vop_advlock_args *ap)
1461 PUFFS_MSG_VARS(vn, advlock);
1462 struct vnode *vp = ap->a_vp;
1463 struct puffs_node *pn = VPTOPP(vp);
1464 struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1467 if (!EXISTSOP(pmp, ADVLOCK))
1468 return lf_advlock(ap, &pn->pn_lockf, vp->v_filesize);
1470 PUFFS_MSG_ALLOC(vn, advlock);
1471 (void)memcpy(&advlock_msg->pvnr_fl, ap->a_fl,
1472 sizeof(advlock_msg->pvnr_fl));
1473 advlock_msg->pvnr_id = ap->a_id;
1474 advlock_msg->pvnr_op = ap->a_op;
1475 advlock_msg->pvnr_flags = ap->a_flags;
1476 puffs_msg_setinfo(park_advlock, PUFFSOP_VN,
1477 PUFFS_VN_ADVLOCK, VPTOPNC(vp));
1478 PUFFS_MSG_ENQUEUEWAIT2(pmp, park_advlock, vp->v_data, NULL, error);
1479 error = checkerr(pmp, error, __func__);
1480 PUFFS_MSG_RELEASE(advlock);
1486 puffs_vnop_bmap(struct vop_bmap_args *ap)
1488 if (ap->a_doffsetp != NULL)
1489 *ap->a_doffsetp = ap->a_loffset;
1490 if (ap->a_runp != NULL)
1492 if (ap->a_runb != NULL)
1498 puffs_vnop_mmap(struct vop_mmap_args *ap)
1505 puffs_vnop_strategy(struct vop_strategy_args *ap)
1507 return puffs_doio(ap->a_vp, ap->a_bio, curthread);
1510 struct vop_ops puffs_fifo_vops = {
1511 .vop_default = fifo_vnoperate,
1512 .vop_access = puffs_vnop_access,
1513 .vop_getattr = puffs_vnop_getattr,
1514 .vop_setattr = puffs_vnop_setattr,
1515 .vop_inactive = puffs_vnop_inactive,
1516 .vop_reclaim = puffs_vnop_reclaim,
1517 .vop_print = puffs_vnop_print,
1520 struct vop_ops puffs_vnode_vops = {
1521 .vop_default = vop_defaultop,
1522 .vop_nresolve = puffs_vnop_lookup,
1523 .vop_nlookupdotdot = puffs_vnop_lookupdotdot,
1524 .vop_ncreate = puffs_vnop_create,
1525 .vop_nmkdir = puffs_vnop_mkdir,
1526 .vop_nrmdir = puffs_vnop_rmdir,
1527 .vop_nremove = puffs_vnop_remove,
1528 .vop_nrename = puffs_vnop_rename,
1529 .vop_nlink = puffs_vnop_link,
1530 .vop_nsymlink = puffs_vnop_symlink,
1531 .vop_nmknod = puffs_vnop_mknod,
1532 .vop_access = puffs_vnop_access,
1533 .vop_getattr = puffs_vnop_getattr,
1534 .vop_setattr = puffs_vnop_setattr,
1535 .vop_readdir = puffs_vnop_readdir,
1536 .vop_open = puffs_vnop_open,
1537 .vop_close = puffs_vnop_close,
1538 .vop_read = puffs_vnop_read,
1539 .vop_write = puffs_vnop_write,
1540 .vop_readlink = puffs_vnop_readlink,
1541 .vop_advlock = puffs_vnop_advlock,
1542 .vop_bmap = puffs_vnop_bmap,
1543 .vop_mmap = puffs_vnop_mmap,
1544 .vop_strategy = puffs_vnop_strategy,
1545 .vop_getpages = vop_stdgetpages,
1546 .vop_putpages = vop_stdputpages,
1547 .vop_fsync = puffs_vnop_fsync,
1548 .vop_inactive = puffs_vnop_inactive,
1549 .vop_reclaim = puffs_vnop_reclaim,
1550 .vop_pathconf = puffs_vnop_pathconf,
1551 .vop_print = puffs_vnop_print,