Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/fs/puffs/puffs_vfsops.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/fs/puffs/puffs_vfsops.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.28.6.12 retrieving revision 1.29 diff -u -p -r1.28.6.12 -r1.29 --- src/sys/fs/puffs/puffs_vfsops.c 2007/10/28 22:01:25 1.28.6.12 +++ src/sys/fs/puffs/puffs_vfsops.c 2007/03/13 14:16:07 1.29 @@ -1,4 +1,4 @@ -/* $NetBSD: puffs_vfsops.c,v 1.28.6.12 2007/10/28 22:01:25 ad Exp $ */ +/* $NetBSD: puffs_vfsops.c,v 1.29 2007/03/13 14:16:07 ad Exp $ */ /* * Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved. @@ -15,6 +15,9 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * 3. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -30,7 +33,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.28.6.12 2007/10/28 22:01:25 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.29 2007/03/13 14:16:07 ad Exp $"); #include #include @@ -41,46 +44,36 @@ __KERNEL_RCSID(0, "$NetBSD: puffs_vfsops #include #include #include -#include #include #include #include -#include /* for fh sizes */ - VFS_PROTOS(puffs); -MALLOC_JUSTDEFINE(M_PUFFS, "puffs", "Pass-to-Userspace Framework File System"); +MALLOC_DEFINE(M_PUFFS, "puffs", "pass-to-userspace file system structures"); #ifndef PUFFS_PNODEBUCKETS #define PUFFS_PNODEBUCKETS 256 #endif #ifndef PUFFS_MAXPNODEBUCKETS -#define PUFFS_MAXPNODEBUCKETS 8192 +#define PUFFS_MAXPNODEBUCKETS 65536 #endif -int puffs_pnodebuckets_default = PUFFS_PNODEBUCKETS; -int puffs_maxpnodebuckets = PUFFS_MAXPNODEBUCKETS; +int puffs_pnodebuckets = PUFFS_PNODEBUCKETS; int -puffs_mount(struct mount *mp, const char *path, void *data, size_t *data_len, - struct lwp *l) +puffs_mount(struct mount *mp, const char *path, void *data, + struct nameidata *ndp, struct lwp *l) { struct puffs_mount *pmp = NULL; - struct puffs_kargs *args; - char fstype[_VFS_NAMELEN]; - char *p; + struct puffs_args *args; + char namebuf[PUFFSNAMESIZE+sizeof(PUFFS_NAMEPREFIX)+1]; /* spooky */ int error = 0, i; - if (*data_len < sizeof *args) - return EINVAL; - if (mp->mnt_flag & MNT_GETARGS) { pmp = MPTOPUFFSMP(mp); - *(struct puffs_kargs *)data = pmp->pmp_args; - *data_len = sizeof *args; - return 0; + return copyout(&pmp->pmp_args, data, sizeof(struct puffs_args)); } /* update is not supported currently */ @@ -93,114 +86,43 @@ puffs_mount(struct mount *mp, const char if (!data) return EINVAL; - MALLOC(args, struct puffs_kargs *, sizeof(struct puffs_kargs), + MALLOC(args, struct puffs_args *, sizeof(struct puffs_args), M_PUFFS, M_WAITOK); - *args = *(struct puffs_kargs *)data; + error = copyin(data, args, sizeof(struct puffs_args)); + if (error) + goto out; /* devel phase */ if (args->pa_vers != (PUFFSVERSION | PUFFSDEVELVERS)) { - printf("puffs_mount: development version mismatch: " - "kernel %d, lib %d\n", - PUFFSVERSION, args->pa_vers & ~PUFFSDEVELVERS); - error = EINVAL; - goto out; - } - - if ((args->pa_flags & ~PUFFS_KFLAG_MASK) != 0) { - printf("puffs_mount: invalid KFLAGs 0x%x\n", args->pa_flags); + printf("puffs_mount: development version mismatch\n"); error = EINVAL; goto out; } - if ((args->pa_fhflags & ~PUFFS_FHFLAG_MASK) != 0) { - printf("puffs_mount: invalid FHFLAGs 0x%x\n", args->pa_fhflags); - error = EINVAL; - goto out; - } - - /* use dummy value for passthrough */ - if (args->pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) - args->pa_fhsize = sizeof(struct fid); - - /* sanitize file handle length */ - if (PUFFS_TOFHSIZE(args->pa_fhsize) > FHANDLE_SIZE_MAX) { - printf("puffs_mount: handle size %zu too large\n", - args->pa_fhsize); - error = EINVAL; - goto out; - } - /* sanity check file handle max sizes */ - if (args->pa_fhsize && args->pa_fhflags & PUFFS_FHFLAG_PROTOMASK) { - size_t kfhsize = PUFFS_TOFHSIZE(args->pa_fhsize); - - if (args->pa_fhflags & PUFFS_FHFLAG_NFSV2) { - if (NFSX_FHTOOBIG_P(kfhsize, 0)) { - printf("puffs_mount: fhsize larger than " - "NFSv2 max %d\n", - PUFFS_FROMFHSIZE(NFSX_V2FH)); - error = EINVAL; - goto out; - } - } - - if (args->pa_fhflags & PUFFS_FHFLAG_NFSV3) { - if (NFSX_FHTOOBIG_P(kfhsize, 1)) { - printf("puffs_mount: fhsize larger than " - "NFSv3 max %d\n", - PUFFS_FROMFHSIZE(NFSX_V3FHMAX)); - error = EINVAL; - goto out; - } - } - } - /* don't allow non-printing characters (like my sweet umlauts.. snif) */ - args->pa_typename[sizeof(args->pa_typename)-1] = '\0'; - for (p = args->pa_typename; *p; p++) - if (*p < ' ' || *p > '~') - *p = '.'; - - args->pa_mntfromname[sizeof(args->pa_mntfromname)-1] = '\0'; - for (p = args->pa_mntfromname; *p; p++) - if (*p < ' ' || *p > '~') - *p = '.'; + /* nuke spy bits */ + args->pa_flags &= PUFFS_KFLAG_MASK; /* build real name */ - (void)strlcpy(fstype, PUFFS_TYPEPREFIX, sizeof(fstype)); - (void)strlcat(fstype, args->pa_typename, sizeof(fstype)); + (void)strlcpy(namebuf, PUFFS_NAMEPREFIX, sizeof(namebuf)); + (void)strlcat(namebuf, args->pa_name, sizeof(namebuf)); /* inform user server if it got the max request size it wanted */ - if (args->pa_maxmsglen == 0 || args->pa_maxmsglen > PUFFS_MSG_MAXSIZE) - args->pa_maxmsglen = PUFFS_MSG_MAXSIZE; - else if (args->pa_maxmsglen < 2*PUFFS_MSGSTRUCT_MAX) - args->pa_maxmsglen = 2*PUFFS_MSGSTRUCT_MAX; - - (void)strlcpy(args->pa_typename, fstype, sizeof(args->pa_typename)); - - if (args->pa_nhashbuckets == 0) - args->pa_nhashbuckets = puffs_pnodebuckets_default; - if (args->pa_nhashbuckets < 1) - args->pa_nhashbuckets = 1; - if (args->pa_nhashbuckets > PUFFS_MAXPNODEBUCKETS) { - args->pa_nhashbuckets = puffs_maxpnodebuckets; - printf("puffs_mount: using %d hash buckets. " - "adjust puffs_maxpnodebuckets for more\n", - puffs_maxpnodebuckets); - } + if (args->pa_maxreqlen == 0 || args->pa_maxreqlen > PUFFS_REQ_MAXSIZE) + args->pa_maxreqlen = PUFFS_REQ_MAXSIZE; + else if (args->pa_maxreqlen < PUFFS_REQSTRUCT_MAX) + args->pa_maxreqlen = PUFFS_REQSTRUCT_MAX; + (void)strlcpy(args->pa_name, namebuf, sizeof(args->pa_name)); - error = set_statvfs_info(path, UIO_USERSPACE, args->pa_mntfromname, - UIO_SYSSPACE, fstype, mp, l); + error = copyout(args, data, sizeof(struct puffs_args)); if (error) goto out; - mp->mnt_stat.f_iosize = DEV_BSIZE; - /* - * We can't handle the VFS_STATVFS() mount_domount() does - * after VFS_MOUNT() because we'd deadlock, so handle it - * here already. - */ - copy_statvfs_info(&args->pa_svfsb, mp); - (void)memcpy(&mp->mnt_stat, &args->pa_svfsb, sizeof(mp->mnt_stat)); + error = set_statvfs_info(path, UIO_USERSPACE, namebuf, + UIO_SYSSPACE, mp, l); + if (error) + goto out; + mp->mnt_stat.f_iosize = DEV_BSIZE; MALLOC(pmp, struct puffs_mount *, sizeof(struct puffs_mount), M_PUFFS, M_WAITOK | M_ZERO); @@ -212,17 +134,22 @@ puffs_mount(struct mount *mp, const char mp->mnt_iflag |= IMNT_HAS_TRANS; pmp->pmp_status = PUFFSTAT_MOUNTING; + pmp->pmp_nextreq = 0; pmp->pmp_mp = mp; - pmp->pmp_msg_maxsize = args->pa_maxmsglen; + pmp->pmp_req_maxsize = args->pa_maxreqlen; pmp->pmp_args = *args; - pmp->pmp_npnodehash = args->pa_nhashbuckets; + /* puffs_node hash buckets */ + pmp->pmp_npnodehash = puffs_pnodebuckets; + if (pmp->pmp_npnodehash < 1) + pmp->pmp_npnodehash = 1; + if (pmp->pmp_npnodehash > PUFFS_MAXPNODEBUCKETS) + pmp->pmp_npnodehash = PUFFS_MAXPNODEBUCKETS; pmp->pmp_pnodehash = malloc (sizeof(struct puffs_pnode_hashlist *) * pmp->pmp_npnodehash, M_PUFFS, M_WAITOK); for (i = 0; i < pmp->pmp_npnodehash; i++) LIST_INIT(&pmp->pmp_pnodehash[i]); - LIST_INIT(&pmp->pmp_newcookie); /* * Inform the fileops processing code that we have a mountpoint. @@ -234,18 +161,10 @@ puffs_mount(struct mount *mp, const char goto out; } - /* XXX: check parameters */ - pmp->pmp_root_cookie = args->pa_root_cookie; - pmp->pmp_root_vtype = args->pa_root_vtype; - pmp->pmp_root_vsize = args->pa_root_vsize; - pmp->pmp_root_rdev = args->pa_root_rdev; - - mutex_init(&pmp->pmp_lock, MUTEX_DEFAULT, IPL_NONE); - cv_init(&pmp->pmp_msg_waiter_cv, "puffsget"); - cv_init(&pmp->pmp_refcount_cv, "puffsref"); - cv_init(&pmp->pmp_unmounting_cv, "puffsum"); - TAILQ_INIT(&pmp->pmp_msg_touser); - TAILQ_INIT(&pmp->pmp_msg_replywait); + simple_lock_init(&pmp->pmp_lock); + TAILQ_INIT(&pmp->pmp_req_touser); + TAILQ_INIT(&pmp->pmp_req_replywait); + TAILQ_INIT(&pmp->pmp_req_sizepark); DPRINTF(("puffs_mount: mount point at %p, puffs specific at %p\n", mp, MPTOPUFFSMP(mp))); @@ -261,24 +180,67 @@ puffs_mount(struct mount *mp, const char return error; } +/* + * This is called from the first "Hello, I'm alive" ioctl + * from userspace. + */ int -puffs_start(struct mount *mp, int flags, struct lwp *l) +puffs_start2(struct puffs_mount *pmp, struct puffs_startreq *sreq) { - struct puffs_mount *pmp = MPTOPUFFSMP(mp); + struct puffs_node *pn; + struct mount *mp; - KASSERT(pmp->pmp_status == PUFFSTAT_MOUNTING); + mp = PMPTOMP(pmp); + + simple_lock(&pmp->pmp_lock); + + /* + * if someone has issued a VFS_ROOT() already, fill in the + * vnode cookie. + */ + pn = NULL; + if (pmp->pmp_root) { + pn = VPTOPP(pmp->pmp_root); + pn->pn_cookie = sreq->psr_cookie; + } + + /* We're good to fly */ + pmp->pmp_rootcookie = sreq->psr_cookie; pmp->pmp_status = PUFFSTAT_RUNNING; + simple_unlock(&pmp->pmp_lock); + + /* do the VFS_STATVFS() we missed out on in sys_mount() */ + copy_statvfs_info(&sreq->psr_sb, mp); + (void)memcpy(&mp->mnt_stat, &sreq->psr_sb, sizeof(mp->mnt_stat)); + mp->mnt_stat.f_iosize = DEV_BSIZE; + + DPRINTF(("puffs_start2: root vp %p, cur root pnode %p, cookie %p\n", + pmp->pmp_root, pn, sreq->psr_cookie)); + + return 0; +} + +int +puffs_start(struct mount *mp, int flags, struct lwp *l) +{ + /* + * This cannot travel to userspace, as this is called from + * the kernel context of the process doing mount(2). But + * it's probably a safe bet that the process doing mount(2) + * realizes it needs to start the filesystem also... + */ return 0; } int puffs_unmount(struct mount *mp, int mntflags, struct lwp *l) { - PUFFS_MSG_VARS(vfs, unmount); struct puffs_mount *pmp; int error, force; + PUFFS_VFSREQ(unmount); + error = 0; force = mntflags & MNT_FORCE; pmp = MPTOPUFFSMP(mp); @@ -302,24 +264,21 @@ puffs_unmount(struct mount *mp, int mntf * If we are not DYING, we should ask userspace's opinion * about the situation */ - mutex_enter(&pmp->pmp_lock); + simple_lock(&pmp->pmp_lock); if (pmp->pmp_status != PUFFSTAT_DYING) { pmp->pmp_unmounting = 1; - mutex_exit(&pmp->pmp_lock); - - PUFFS_MSG_ALLOC(vfs, unmount); - unmount_msg->pvfsr_flags = mntflags; - puffs_cidcvt(&unmount_msg->pvfsr_cid, l); + simple_unlock(&pmp->pmp_lock); - error = puffs_msg_vfs(pmp, park_unmount, PUFFS_VFS_UNMOUNT); - PUFFS_MSG_RELEASE(unmount); + unmount_arg.pvfsr_flags = mntflags; + unmount_arg.pvfsr_pid = puffs_lwp2pid(l); - error = checkerr(pmp, error, __func__); + error = puffs_vfstouser(pmp, PUFFS_VFS_UNMOUNT, + &unmount_arg, sizeof(unmount_arg)); DPRINTF(("puffs_unmount: error %d force %d\n", error, force)); - mutex_enter(&pmp->pmp_lock); + simple_lock(&pmp->pmp_lock); pmp->pmp_unmounting = 0; - cv_broadcast(&pmp->pmp_unmounting_cv); + wakeup(&pmp->pmp_unmounting); } /* @@ -332,28 +291,24 @@ puffs_unmount(struct mount *mp, int mntf puffs_nukebypmp(pmp); /* - * Wait until there are no more users for the mount resource. - * Notice that this is hooked against transport_close - * and return from touser. In an ideal world, it would - * be hooked against final return from all operations. - * But currently it works well enough, since nobody - * does weird blocking voodoo after return from touser(). + * Sink waiters. This is still not perfect, since the + * draining is done after userret, not when they really + * exit the file system. It will probably work as almost + * no call will block and therefore cause a context switch + * and therefore will protected by the biglock after + * exiting userspace. But ... it's an imperfect world. */ - while (pmp->pmp_refcount != 0) - cv_wait(&pmp->pmp_refcount_cv, &pmp->pmp_lock); - mutex_exit(&pmp->pmp_lock); + while (pmp->pmp_req_touser_waiters != 0) + ltsleep(&pmp->pmp_req_touser_waiters, PVFS, + "puffsink", 0, &pmp->pmp_lock); + simple_unlock(&pmp->pmp_lock); /* free resources now that we hopefully have no waiters left */ - cv_destroy(&pmp->pmp_unmounting_cv); - cv_destroy(&pmp->pmp_refcount_cv); - cv_destroy(&pmp->pmp_msg_waiter_cv); - mutex_destroy(&pmp->pmp_lock); - free(pmp->pmp_pnodehash, M_PUFFS); FREE(pmp, M_PUFFS); error = 0; } else { - mutex_exit(&pmp->pmp_lock); + simple_unlock(&pmp->pmp_lock); } out: @@ -367,18 +322,75 @@ puffs_unmount(struct mount *mp, int mntf int puffs_root(struct mount *mp, struct vnode **vpp) { - struct puffs_mount *pmp = MPTOPUFFSMP(mp); - int rv; + struct puffs_mount *pmp; + struct puffs_node *pn; + struct vnode *vp; + + pmp = MPTOPUFFSMP(mp); + + /* + * pmp_lock must be held if vref()'ing or vrele()'ing the + * root vnode. the latter is controlled by puffs_inactive(). + */ + simple_lock(&pmp->pmp_lock); + vp = pmp->pmp_root; + if (vp) { + simple_lock(&vp->v_interlock); + simple_unlock(&pmp->pmp_lock); + pn = VPTOPP(vp); + if (vget(vp, LK_EXCLUSIVE | LK_RETRY | LK_INTERLOCK)) + goto grabnew; + *vpp = vp; + return 0; + } else + simple_unlock(&pmp->pmp_lock); + + /* XXX: this is wrong, so FIXME */ + grabnew: + + /* + * So, didn't have the magic root vnode available. + * No matter, grab another an stuff it with the cookie. + */ + if (puffs_getvnode(mp, pmp->pmp_rootcookie, VDIR, 0, 0, &vp)) + panic("sloppy programming"); + + simple_lock(&pmp->pmp_lock); + /* + * check if by mysterious force someone else created a root + * vnode while we were executing. + */ + if (pmp->pmp_root) { + vref(pmp->pmp_root); + simple_unlock(&pmp->pmp_lock); + puffs_putvnode(vp); + vn_lock(pmp->pmp_root, LK_EXCLUSIVE | LK_RETRY); + *vpp = pmp->pmp_root; + return 0; + } - rv = puffs_cookie2vnode(pmp, pmp->pmp_root_cookie, 1, 1, vpp); - KASSERT(rv != PUFFS_NOSUCHCOOKIE); - return rv; + /* store cache */ + vp->v_flag = VROOT; + pmp->pmp_root = vp; + simple_unlock(&pmp->pmp_lock); + + vn_lock(pmp->pmp_root, LK_EXCLUSIVE | LK_RETRY); + + *vpp = vp; + return 0; +} + +int +puffs_quotactl(struct mount *mp, int cmd, uid_t uid, void *arg, struct lwp *l) +{ + + return EOPNOTSUPP; } int puffs_statvfs(struct mount *mp, struct statvfs *sbp, struct lwp *l) { - PUFFS_MSG_VARS(vfs, statvfs); + struct puffs_vfsreq_statvfs *statvfs_arg; /* too big for stack */ struct puffs_mount *pmp; int error = 0; @@ -393,12 +405,14 @@ puffs_statvfs(struct mount *mp, struct s if (pmp->pmp_status == PUFFSTAT_MOUNTING) return EINPROGRESS; - PUFFS_MSG_ALLOC(vfs, statvfs); - puffs_cidcvt(&statvfs_msg->pvfsr_cid, l); - - error = puffs_msg_vfs(pmp, park_statvfs, PUFFS_VFS_STATVFS); - error = checkerr(pmp, error, __func__); - statvfs_msg->pvfsr_sb.f_iosize = DEV_BSIZE; + /* too big for stack */ + MALLOC(statvfs_arg, struct puffs_vfsreq_statvfs *, + sizeof(struct puffs_vfsreq_statvfs), M_PUFFS, M_WAITOK | M_ZERO); + statvfs_arg->pvfsr_pid = puffs_lwp2pid(l); + + error = puffs_vfstouser(pmp, PUFFS_VFS_STATVFS, + statvfs_arg, sizeof(*statvfs_arg)); + statvfs_arg->pvfsr_sb.f_iosize = DEV_BSIZE; /* * Try to produce a sensible result even in the event @@ -407,24 +421,23 @@ puffs_statvfs(struct mount *mp, struct s * XXX: cache the copy in non-error case */ if (!error) { - copy_statvfs_info(&statvfs_msg->pvfsr_sb, mp); - (void)memcpy(sbp, &statvfs_msg->pvfsr_sb, + copy_statvfs_info(&statvfs_arg->pvfsr_sb, mp); + (void)memcpy(sbp, &statvfs_arg->pvfsr_sb, sizeof(struct statvfs)); } else { copy_statvfs_info(sbp, mp); } - PUFFS_MSG_RELEASE(statvfs); + FREE(statvfs_arg, M_PUFFS); return error; } static int -pageflush(struct mount *mp, kauth_cred_t cred, - int waitfor, int suspending, struct lwp *l) +pageflush(struct mount *mp, int waitfor, int suspending) { struct puffs_node *pn; - struct vnode *vp, *mvp; - int error, rv; + struct vnode *vp, *nvp; + int error, rv, ppflags; KASSERT(((waitfor == MNT_WAIT) && suspending) == 0); KASSERT((suspending == 0) @@ -432,10 +445,9 @@ pageflush(struct mount *mp, kauth_cred_t && fstrans_getstate(mp) == FSTRANS_SUSPENDING)); error = 0; - - /* Allocate a marker vnode. */ - if ((mvp = valloc(mp)) == NULL) - return ENOMEM; + ppflags = PGO_CLEANIT | PGO_ALLPAGES; + if (waitfor == MNT_WAIT) + ppflags |= PGO_SYNCIO; /* * Sync all cached data from regular vnodes (which are not @@ -443,21 +455,23 @@ pageflush(struct mount *mp, kauth_cred_t * for the fs server, which should handle data and metadata for * all the nodes it knows to exist. */ - mutex_enter(&mntvnode_lock); + simple_lock(&mntvnode_slock); loop: - for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = vunmark(mvp)) { - vmark(mvp, vp); - if (vp->v_mount != mp || vismarker(vp)) - continue; + for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = nvp) { + /* check if we're on the right list */ + if (vp->v_mount != mp) + goto loop; - mutex_enter(&vp->v_interlock); + simple_lock(&vp->v_interlock); pn = VPTOPP(vp); + nvp = TAILQ_NEXT(vp, v_mntvnodes); + if (vp->v_type != VREG || UVM_OBJ_IS_CLEAN(&vp->v_uobj)) { - mutex_exit(&vp->v_interlock); + simple_unlock(&vp->v_interlock); continue; } - mutex_exit(&mntvnode_lock); + simple_unlock(&mntvnode_slock); /* * Here we try to get a reference to the vnode and to @@ -479,11 +493,9 @@ pageflush(struct mount *mp, kauth_cred_t */ rv = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK); if (rv) { - mutex_enter(&mntvnode_lock); - if (rv == ENOENT) { - (void)vunmark(mvp); + simple_lock(&mntvnode_slock); + if (rv == ENOENT) goto loop; - } continue; } @@ -508,24 +520,21 @@ pageflush(struct mount *mp, kauth_cred_t * storage. * TODO: Maybe also hint the user server of this twist? */ - if (suspending || waitfor == MNT_LAZY) { - mutex_enter(&vp->v_interlock); + simple_lock(&vp->v_interlock); + if (suspending || waitfor == MNT_LAZY) pn->pn_stat |= PNODE_SUSPEND; - mutex_exit(&vp->v_interlock); - } - rv = VOP_FSYNC(vp, cred, waitfor, 0, 0, l); + rv = VOP_PUTPAGES(vp, 0, 0, ppflags); if (suspending || waitfor == MNT_LAZY) { - mutex_enter(&vp->v_interlock); + simple_lock(&vp->v_interlock); pn->pn_stat &= ~PNODE_SUSPEND; - mutex_exit(&vp->v_interlock); + simple_unlock(&vp->v_interlock); } if (rv) error = rv; vput(vp); - mutex_enter(&mntvnode_lock); + simple_lock(&mntvnode_slock); } - mutex_exit(&mntvnode_lock); - vfree(mvp); + simple_unlock(&mntvnode_slock); return error; } @@ -534,184 +543,73 @@ int puffs_sync(struct mount *mp, int waitfor, struct kauth_cred *cred, struct lwp *l) { - PUFFS_MSG_VARS(vfs, sync); - struct puffs_mount *pmp = MPTOPUFFSMP(mp); int error, rv; - error = pageflush(mp, cred, waitfor, 0, l); + PUFFS_VFSREQ(sync); + + error = pageflush(mp, waitfor, 0); /* sync fs */ - PUFFS_MSG_ALLOC(vfs, sync); - sync_msg->pvfsr_waitfor = waitfor; - puffs_credcvt(&sync_msg->pvfsr_cred, cred); - puffs_cidcvt(&sync_msg->pvfsr_cid, l); + sync_arg.pvfsr_waitfor = waitfor; + puffs_credcvt(&sync_arg.pvfsr_cred, cred); + sync_arg.pvfsr_pid = puffs_lwp2pid(l); - rv = puffs_msg_vfs(pmp, park_sync, PUFFS_VFS_SYNC); - rv = checkerr(pmp, rv, __func__); + rv = puffs_vfstouser(MPTOPUFFSMP(mp), PUFFS_VFS_SYNC, + &sync_arg, sizeof(sync_arg)); if (rv) error = rv; - PUFFS_MSG_RELEASE(sync); return error; } int -puffs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) +puffs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) { - PUFFS_MSG_VARS(vfs, fhtonode); - struct puffs_mount *pmp = MPTOPUFFSMP(mp); - struct vnode *vp; - void *fhdata; - size_t argsize, fhlen; - int error; - - if (pmp->pmp_args.pa_fhsize == 0) - return EOPNOTSUPP; - - if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) { - fhlen = fhp->fid_len; - fhdata = fhp; - } else { - fhlen = PUFFS_FROMFHSIZE(fhp->fid_len); - fhdata = fhp->fid_data; - - if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_DYNAMIC) { - if (pmp->pmp_args.pa_fhsize < fhlen) - return EINVAL; - } else { - if (pmp->pmp_args.pa_fhsize != fhlen) - return EINVAL; - } - } - - argsize = sizeof(struct puffs_vfsmsg_fhtonode) + fhlen; - puffs_msgmem_alloc(argsize, &park_fhtonode, (void **)&fhtonode_msg, 1); - fhtonode_msg->pvfsr_dsize = fhlen; - memcpy(fhtonode_msg->pvfsr_data, fhdata, fhlen); - - error = puffs_msg_vfs(pmp, park_fhtonode, PUFFS_VFS_FHTOVP); - error = checkerr(pmp, error, __func__); - if (error) - goto out; - - error = puffs_cookie2vnode(pmp, fhtonode_msg->pvfsr_fhcookie, 1,1,&vp); - DPRINTF(("puffs_fhtovp: got cookie %p, existing vnode %p\n", - fhtonode_msg->pvfsr_fhcookie, vp)); - if (error == PUFFS_NOSUCHCOOKIE) { - error = puffs_getvnode(mp, fhtonode_msg->pvfsr_fhcookie, - fhtonode_msg->pvfsr_vtype, fhtonode_msg->pvfsr_size, - fhtonode_msg->pvfsr_rdev, &vp); - if (error) - goto out; - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); - } else if (error) { - goto out; - } - *vpp = vp; - out: - puffs_msgmem_release(park_fhtonode); - return error; + return EOPNOTSUPP; } +#if 0 +/*ARGSUSED*/ int -puffs_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size) +puffs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) { - PUFFS_MSG_VARS(vfs, nodetofh); - struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); - size_t argsize, fhlen; - int error; - - if (pmp->pmp_args.pa_fhsize == 0) - return EOPNOTSUPP; - - /* if file handles are static len, we can test len immediately */ - if (((pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_DYNAMIC) == 0) - && ((pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) == 0) - && (PUFFS_FROMFHSIZE(*fh_size) < pmp->pmp_args.pa_fhsize)) { - *fh_size = PUFFS_TOFHSIZE(pmp->pmp_args.pa_fhsize); - return E2BIG; - } - if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) - fhlen = *fh_size; - else - fhlen = PUFFS_FROMFHSIZE(*fh_size); - - argsize = sizeof(struct puffs_vfsmsg_nodetofh) + fhlen; - puffs_msgmem_alloc(argsize, &park_nodetofh, (void **)&nodetofh_msg, 1); - nodetofh_msg->pvfsr_fhcookie = VPTOPNC(vp); - nodetofh_msg->pvfsr_dsize = fhlen; - - error = puffs_msg_vfs(pmp, park_nodetofh, PUFFS_VFS_VPTOFH); - error = checkerr(pmp, error, __func__); - - if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) - fhlen = nodetofh_msg->pvfsr_dsize; - else if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_DYNAMIC) - fhlen = PUFFS_TOFHSIZE(nodetofh_msg->pvfsr_dsize); - else - fhlen = PUFFS_TOFHSIZE(pmp->pmp_args.pa_fhsize); - - if (error) { - if (error == E2BIG) - *fh_size = fhlen; - goto out; - } - - if (fhlen > FHANDLE_SIZE_MAX) { - puffs_msg_errnotify(pmp, PUFFS_ERR_VPTOFH, E2BIG, - "file handle too big", VPTOPNC(vp)); - error = EPROTO; - goto out; - } - - if (*fh_size < fhlen) { - *fh_size = fhlen; - error = E2BIG; - goto out; - } - *fh_size = fhlen; + return EOPNOTSUPP; +} - if (fhp) { - if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) { - memcpy(fhp, nodetofh_msg->pvfsr_data, fhlen); - } else { - fhp->fid_len = *fh_size; - memcpy(fhp->fid_data, nodetofh_msg->pvfsr_data, - nodetofh_msg->pvfsr_dsize); - } - } +/*ARGSUSED*/ +int +puffs_vptofh(struct vnode *vp, struct fid *fhp) +{ - out: - puffs_msgmem_release(park_nodetofh); - return error; + return EOPNOTSUPP; } +#endif void puffs_init() { - /* some checks depend on this */ - KASSERT(VNOVAL == VSIZENOTSET); - +#ifdef _LKM malloc_type_attach(M_PUFFS); - pool_init(&puffs_pnpool, sizeof(struct puffs_node), 0, 0, 0, - "puffpnpl", &pool_allocator_nointr, IPL_NONE); - puffs_transport_init(); - puffs_msgif_init(); + "puffspnpl", &pool_allocator_nointr, IPL_NONE); +#endif + + return; } void puffs_done() { - puffs_msgif_destroy(); - puffs_transport_destroy(); +#ifdef _LKM pool_destroy(&puffs_pnpool); - malloc_type_detach(M_PUFFS); +#endif + + return; } int @@ -724,7 +622,6 @@ puffs_snapshot(struct mount *mp, struct int puffs_suspendctl(struct mount *mp, int cmd) { - PUFFS_MSG_VARS(vfs, suspend); struct puffs_mount *pmp; int error; @@ -734,31 +631,19 @@ puffs_suspendctl(struct mount *mp, int c DPRINTF(("puffs_suspendctl: suspending\n")); if ((error = fstrans_setstate(mp, FSTRANS_SUSPENDING)) != 0) break; - PUFFS_MSG_ALLOC(vfs, suspend); - puffs_msg_setfaf(park_suspend); - suspend_msg->pvfsr_status = PUFFS_SUSPEND_START; - puffs_msg_vfs(pmp, park_suspend, PUFFS_VFS_SUSPEND); - PUFFS_MSG_RELEASE(suspend); + puffs_suspendtouser(pmp, PUFFS_SUSPEND_START); - error = pageflush(mp, FSCRED, 0, 1, curlwp); + error = pageflush(mp, 0, 1); if (error == 0) error = fstrans_setstate(mp, FSTRANS_SUSPENDED); if (error != 0) { - PUFFS_MSG_ALLOC(vfs, suspend); - puffs_msg_setfaf(park_suspend); - suspend_msg->pvfsr_status = PUFFS_SUSPEND_ERROR; - puffs_msg_vfs(pmp, park_suspend, PUFFS_VFS_SUSPEND); - PUFFS_MSG_RELEASE(suspend); + puffs_suspendtouser(pmp, PUFFS_SUSPEND_ERROR); (void) fstrans_setstate(mp, FSTRANS_NORMAL); break; } - PUFFS_MSG_ALLOC(vfs, suspend); - puffs_msg_setfaf(park_suspend); - suspend_msg->pvfsr_status = PUFFS_SUSPEND_SUSPENDED; - puffs_msg_vfs(pmp, park_suspend, PUFFS_VFS_SUSPEND); - PUFFS_MSG_RELEASE(suspend); + puffs_suspendtouser(pmp, PUFFS_SUSPEND_SUSPENDED); break; @@ -766,11 +651,7 @@ puffs_suspendctl(struct mount *mp, int c DPRINTF(("puffs_suspendctl: resume\n")); error = 0; (void) fstrans_setstate(mp, FSTRANS_NORMAL); - PUFFS_MSG_ALLOC(vfs, suspend); - puffs_msg_setfaf(park_suspend); - suspend_msg->pvfsr_status = PUFFS_SUSPEND_RESUME; - puffs_msg_vfs(pmp, park_suspend, PUFFS_VFS_SUSPEND); - PUFFS_MSG_RELEASE(suspend); + puffs_suspendtouser(pmp, PUFFS_SUSPEND_RESUME); break; default: @@ -792,17 +673,16 @@ const struct vnodeopv_desc * const puffs struct vfsops puffs_vfsops = { MOUNT_PUFFS, - sizeof (struct puffs_kargs), puffs_mount, /* mount */ puffs_start, /* start */ puffs_unmount, /* unmount */ puffs_root, /* root */ - (void *)eopnotsupp, /* quotactl */ + puffs_quotactl, /* quotactl */ puffs_statvfs, /* statvfs */ puffs_sync, /* sync */ - (void *)eopnotsupp, /* vget */ - puffs_fhtovp, /* fhtovp */ - puffs_vptofh, /* vptofh */ + puffs_vget, /* vget */ + (void *)eopnotsupp, /* fhtovp */ + (void *)eopnotsupp, /* vptofh */ puffs_init, /* init */ NULL, /* reinit */ puffs_done, /* done */