Module Name: src
Committed By: pooka
Date: Tue Jul 6 13:47:47 UTC 2010
Modified Files:
src/sys/fs/puffs: puffs_msgif.c puffs_msgif.h puffs_sys.h
puffs_vfsops.c
Added Files:
src/sys/fs/puffs: puffs_compat.c
Log Message:
Add compat to enable running puffs in a 64bit time_t kernel against
a server which runs in 32bit time_t namespace.
To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 src/sys/fs/puffs/puffs_compat.c
cvs rdiff -u -r1.80 -r1.81 src/sys/fs/puffs/puffs_msgif.c
cvs rdiff -u -r1.74 -r1.75 src/sys/fs/puffs/puffs_msgif.h
cvs rdiff -u -r1.75 -r1.76 src/sys/fs/puffs/puffs_sys.h
cvs rdiff -u -r1.92 -r1.93 src/sys/fs/puffs/puffs_vfsops.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/fs/puffs/puffs_msgif.c
diff -u src/sys/fs/puffs/puffs_msgif.c:1.80 src/sys/fs/puffs/puffs_msgif.c:1.81
--- src/sys/fs/puffs/puffs_msgif.c:1.80 Thu Jan 14 19:50:07 2010
+++ src/sys/fs/puffs/puffs_msgif.c Tue Jul 6 13:47:47 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: puffs_msgif.c,v 1.80 2010/01/14 19:50:07 pooka Exp $ */
+/* $NetBSD: puffs_msgif.c,v 1.81 2010/07/06 13:47:47 pooka Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: puffs_msgif.c,v 1.80 2010/01/14 19:50:07 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: puffs_msgif.c,v 1.81 2010/07/06 13:47:47 pooka Exp $");
#include <sys/param.h>
#include <sys/atomic.h>
@@ -65,6 +65,9 @@
size_t park_copylen; /* userspace copylength */
size_t park_maxlen; /* max size in comeback */
+ struct puffs_req *park_creq; /* non-compat preq */
+ size_t park_creqlen; /* non-compat preq len */
+
parkdone_fn park_done; /* "biodone" a'la puffs */
void *park_donearg;
@@ -136,7 +139,7 @@
return park;
park->park_refcount = 1;
- park->park_preq = NULL;
+ park->park_preq = park->park_creq = NULL;
park->park_flags = PARKFLAG_WANTREPLY;
#ifdef PUFFSDEBUG
@@ -161,6 +164,7 @@
puffs_msgpark_release1(struct puffs_msgpark *park, int howmany)
{
struct puffs_req *preq = park->park_preq;
+ struct puffs_req *creq = park->park_creq;
int refcnt;
KASSERT(mutex_owned(&park->park_mtx));
@@ -173,6 +177,10 @@
alloced--;
if (preq)
kmem_free(preq, park->park_maxlen);
+#if 1
+ if (creq)
+ kmem_free(creq, park->park_creqlen);
+#endif
pool_cache_put(parkpc, park);
#ifdef PUFFSDEBUG
@@ -324,10 +332,24 @@
{
struct lwp *l = curlwp;
struct mount *mp;
- struct puffs_req *preq;
+ struct puffs_req *preq, *creq;
+ ssize_t delta;
mp = PMPTOMP(pmp);
preq = park->park_preq;
+
+#if 1
+ /* check if we do compat adjustments */
+ if (pmp->pmp_docompat && puffs_compat_outgoing(preq, &creq, &delta)) {
+ park->park_creq = park->park_preq;
+ park->park_creqlen = park->park_maxlen;
+
+ park->park_maxlen += delta;
+ park->park_copylen += delta;
+ park->park_preq = preq = creq;
+ }
+#endif
+
preq->preq_buflen = park->park_maxlen;
KASSERT(preq->preq_id == 0
|| (preq->preq_opclass & PUFFSOPFLAG_ISRESPONSE));
@@ -732,13 +754,31 @@
DPRINTF(("puffsop_msg: bad service - waiter gone for "
"park %p\n", park));
} else {
+#if 1
+ if (park->park_creq) {
+ struct puffs_req *creq;
+ size_t csize;
+
+ KASSERT(pmp->pmp_docompat);
+ puffs_compat_incoming(preq, park->park_creq);
+ creq = park->park_creq;
+ csize = park->park_creqlen;
+ park->park_creq = park->park_preq;
+ park->park_creqlen = park->park_maxlen;
+
+ park->park_preq = creq;
+ park->park_maxlen = csize;
+
+ memcpy(park->park_creq, preq, pth->pth_framelen);
+ } else {
+#endif
+ memcpy(park->park_preq, preq, pth->pth_framelen);
+ }
+
if (park->park_flags & PARKFLAG_CALL) {
DPRINTF(("puffsop_msg: call for %p, arg %p\n",
park->park_preq, park->park_donearg));
park->park_done(pmp, preq, park->park_donearg);
- } else {
- /* XXX: yes, I know */
- memcpy(park->park_preq, preq, pth->pth_framelen);
}
}
Index: src/sys/fs/puffs/puffs_msgif.h
diff -u src/sys/fs/puffs/puffs_msgif.h:1.74 src/sys/fs/puffs/puffs_msgif.h:1.75
--- src/sys/fs/puffs/puffs_msgif.h:1.74 Mon Jun 7 11:21:31 2010
+++ src/sys/fs/puffs/puffs_msgif.h Tue Jul 6 13:47:47 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: puffs_msgif.h,v 1.74 2010/06/07 11:21:31 pooka Exp $ */
+/* $NetBSD: puffs_msgif.h,v 1.75 2010/07/06 13:47:47 pooka Exp $ */
/*
* Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
@@ -146,7 +146,9 @@
struct statvfs pa_svfsb;
- uint32_t pa_spare[128];
+ uint32_t pa_time32;
+
+ uint32_t pa_spare[127];
};
#define pa_root_rdev devunion.dev
Index: src/sys/fs/puffs/puffs_sys.h
diff -u src/sys/fs/puffs/puffs_sys.h:1.75 src/sys/fs/puffs/puffs_sys.h:1.76
--- src/sys/fs/puffs/puffs_sys.h:1.75 Thu Jan 7 23:02:34 2010
+++ src/sys/fs/puffs/puffs_sys.h Tue Jul 6 13:47:47 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: puffs_sys.h,v 1.75 2010/01/07 23:02:34 pooka Exp $ */
+/* $NetBSD: puffs_sys.h,v 1.76 2010/07/06 13:47:47 pooka Exp $ */
/*
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
@@ -166,6 +166,7 @@
kcondvar_t pmp_sopcv;
int pmp_sopthrcount;
TAILQ_HEAD(, puffs_sopreq) pmp_sopreqs;
+ bool pmp_docompat;
};
#define PUFFSTAT_BEFOREINIT 0
@@ -263,6 +264,9 @@
void puffs_senderr(struct puffs_mount *, int, int, const char *,
puffs_cookie_t);
+bool puffs_compat_outgoing(struct puffs_req *, struct puffs_req**, ssize_t*);
+void puffs_compat_incoming(struct puffs_req *, struct puffs_req *);
+
void puffs_updatenode(struct puffs_node *, int, voff_t);
#define PUFFS_UPDATEATIME 0x01
#define PUFFS_UPDATECTIME 0x02
Index: src/sys/fs/puffs/puffs_vfsops.c
diff -u src/sys/fs/puffs/puffs_vfsops.c:1.92 src/sys/fs/puffs/puffs_vfsops.c:1.93
--- src/sys/fs/puffs/puffs_vfsops.c:1.92 Tue Jul 6 12:28:40 2010
+++ src/sys/fs/puffs/puffs_vfsops.c Tue Jul 6 13:47:47 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: puffs_vfsops.c,v 1.92 2010/07/06 12:28:40 pooka Exp $ */
+/* $NetBSD: puffs_vfsops.c,v 1.93 2010/07/06 13:47:47 pooka Exp $ */
/*
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.92 2010/07/06 12:28:40 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.93 2010/07/06 13:47:47 pooka Exp $");
#include <sys/param.h>
#include <sys/mount.h>
@@ -292,6 +292,7 @@
pmp->pmp_root_vtype = args->pa_root_vtype;
pmp->pmp_root_vsize = args->pa_root_vsize;
pmp->pmp_root_rdev = args->pa_root_rdev;
+ pmp->pmp_docompat = args->pa_time32;
mutex_init(&pmp->pmp_lock, MUTEX_DEFAULT, IPL_NONE);
mutex_init(&pmp->pmp_sopmtx, MUTEX_DEFAULT, IPL_NONE);
Added files:
Index: src/sys/fs/puffs/puffs_compat.c
diff -u /dev/null src/sys/fs/puffs/puffs_compat.c:1.1
--- /dev/null Tue Jul 6 13:47:47 2010
+++ src/sys/fs/puffs/puffs_compat.c Tue Jul 6 13:47:47 2010
@@ -0,0 +1,434 @@
+/* $NetBSD: puffs_compat.c,v 1.1 2010/07/06 13:47:47 pooka Exp $ */
+
+/*
+ * Copyright (c) 2010 Antti Kantee. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This file handles puffs PDUs so that they are compatible between
+ * 32bit<->64bit time_t/dev_t. It enables running a -current kernel
+ * against a 5.0 userland (assuming the protocol otherwise matches!).
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: puffs_compat.c,v 1.1 2010/07/06 13:47:47 pooka Exp $");
+
+#include <sys/param.h>
+#include <sys/atomic.h>
+#include <sys/kmem.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include <sys/atomic.h>
+
+#include <dev/putter/putter_sys.h>
+
+#include <fs/puffs/puffs_msgif.h>
+#include <fs/puffs/puffs_sys.h>
+
+#include <compat/sys/time.h>
+
+/*
+ * compat types
+ */
+struct vattr50 {
+ enum vtype va_type;
+ mode_t va_mode;
+ nlink_t va_nlink;
+ uid_t va_uid;
+ gid_t va_gid;
+ uint32_t va_fsid;
+ ino_t va_fileid;
+ u_quad_t va_size;
+ long va_blocksize;
+ struct timespec50 va_atime;
+ struct timespec50 va_mtime;
+ struct timespec50 va_ctime;
+ struct timespec50 va_birthtime;
+ u_long va_gen;
+ u_long va_flags;
+ uint32_t va_rdev;
+ u_quad_t va_bytes;
+ u_quad_t va_filerev;
+ u_int va_vaflags;
+ long va_spare;
+};
+
+struct puffs50_vfsmsg_fhtonode {
+ struct puffs_req pvfsr_pr;
+
+ void *pvfsr_fhcookie; /* IN */
+ enum vtype pvfsr_vtype; /* IN */
+ voff_t pvfsr_size; /* IN */
+ uint32_t pvfsr_rdev; /* IN */
+
+ size_t pvfsr_dsize; /* OUT */
+ uint8_t pvfsr_data[0] /* OUT, XXX */
+ __aligned(ALIGNBYTES+1);
+};
+
+struct puffs50_vnmsg_lookup {
+ struct puffs_req pvn_pr;
+
+ struct puffs_kcn pvnr_cn; /* OUT */
+ struct puffs_kcred pvnr_cn_cred; /* OUT */
+
+ puffs_cookie_t pvnr_newnode; /* IN */
+ enum vtype pvnr_vtype; /* IN */
+ voff_t pvnr_size; /* IN */
+ uint32_t pvnr_rdev; /* IN */
+};
+
+struct puffs50_vnmsg_create {
+ struct puffs_req pvn_pr;
+
+ struct puffs_kcn pvnr_cn; /* OUT */
+ struct puffs_kcred pvnr_cn_cred; /* OUT */
+
+ struct vattr50 pvnr_va; /* OUT */
+ puffs_cookie_t pvnr_newnode; /* IN */
+};
+
+struct puffs50_vnmsg_mknod {
+ struct puffs_req pvn_pr;
+
+ struct puffs_kcn pvnr_cn; /* OUT */
+ struct puffs_kcred pvnr_cn_cred; /* OUT */
+
+ struct vattr50 pvnr_va; /* OUT */
+ puffs_cookie_t pvnr_newnode; /* IN */
+};
+
+#define puffs50_vnmsg_setattr puffs50_vnmsg_setgetattr
+#define puffs50_vnmsg_getattr puffs50_vnmsg_setgetattr
+struct puffs50_vnmsg_setgetattr {
+ struct puffs_req pvn_pr;
+
+ struct puffs_kcred pvnr_cred; /* OUT */
+ struct vattr50 pvnr_va; /* IN/OUT (op depend) */
+};
+
+struct puffs50_vnmsg_mkdir {
+ struct puffs_req pvn_pr;
+
+ struct puffs_kcn pvnr_cn; /* OUT */
+ struct puffs_kcred pvnr_cn_cred; /* OUT */
+
+ struct vattr50 pvnr_va; /* OUT */
+ puffs_cookie_t pvnr_newnode; /* IN */
+};
+
+struct puffs50_vnmsg_symlink {
+ struct puffs_req pvn_pr;
+
+ struct puffs_kcn pvnr_cn; /* OUT */
+ struct puffs_kcred pvnr_cn_cred; /* OUT */
+
+ struct vattr50 pvnr_va; /* OUT */
+ puffs_cookie_t pvnr_newnode; /* IN */
+ char pvnr_link[MAXPATHLEN]; /* OUT */
+};
+
+/*
+ * vattr translation routines
+ */
+
+static void
+vattr_to_50(const struct vattr *va, struct vattr50 *va50)
+{
+
+ va50->va_type = va->va_type;
+ va50->va_mode = va->va_mode;
+ va50->va_nlink = va->va_nlink;
+ va50->va_uid = va->va_uid;
+ va50->va_gid = va->va_gid;
+ va50->va_fsid = (uint64_t)va->va_fsid;
+ va50->va_fileid = va->va_fileid;
+ va50->va_size = va->va_size;
+ va50->va_blocksize = va->va_blocksize;
+ timespec_to_timespec50(&va->va_atime, &va50->va_atime);
+ timespec_to_timespec50(&va->va_ctime, &va50->va_ctime);
+ timespec_to_timespec50(&va->va_mtime, &va50->va_mtime);
+ timespec_to_timespec50(&va->va_birthtime, &va50->va_birthtime);
+ va50->va_gen = va->va_gen;
+ va50->va_flags = va->va_flags;
+ va50->va_rdev = (int32_t)va->va_rdev;
+ va50->va_bytes = va->va_bytes;
+ va50->va_filerev = va->va_filerev;
+ va50->va_vaflags = va->va_flags;
+}
+
+static void
+vattr_from_50(const struct vattr50 *va50, struct vattr *va)
+{
+
+ va->va_type = va50->va_type;
+ va->va_mode = va50->va_mode;
+ va->va_nlink = va50->va_nlink;
+ va->va_uid = va50->va_uid;
+ va->va_gid = va50->va_gid;
+ va->va_fsid = (uint32_t)va50->va_fsid;
+ va->va_fileid = va50->va_fileid;
+ va->va_size = va50->va_size;
+ va->va_blocksize = va50->va_blocksize;
+ timespec50_to_timespec(&va50->va_atime, &va->va_atime);
+ timespec50_to_timespec(&va50->va_ctime, &va->va_ctime);
+ timespec50_to_timespec(&va50->va_mtime, &va->va_mtime);
+ timespec50_to_timespec(&va50->va_birthtime, &va->va_birthtime);
+ va->va_gen = va50->va_gen;
+ va->va_flags = va50->va_flags;
+ va->va_rdev = (uint32_t)va50->va_rdev;
+ va->va_bytes = va50->va_bytes;
+ va->va_filerev = va50->va_filerev;
+ va->va_vaflags = va50->va_flags;
+}
+
+/*
+ * XXX: cannot assert that sleeping is possible
+ * (this always a valid assumption for now)
+ */
+#define INIT(name) \
+ struct puffs50_##name *cmsg; \
+ struct puffs_##name *omsg; \
+ creq = kmem_zalloc(sizeof(struct puffs50_##name), KM_SLEEP); \
+ cmsg = (struct puffs50_##name *)creq; \
+ omsg = (struct puffs_##name *)oreq; \
+ delta = sizeof(struct puffs50_##name)-sizeof(struct puffs_##name);
+#define ASSIGN(field) \
+ cmsg->field = omsg->field;
+
+bool
+puffs_compat_outgoing(struct puffs_req *oreq,
+ struct puffs_req **creqp, ssize_t *deltap)
+{
+ struct puffs_req *creq = NULL;
+ ssize_t delta = 0;
+ bool rv = false;
+
+ if (PUFFSOP_OPCLASS(oreq->preq_opclass == PUFFSOP_VFS)) {
+ INIT(vfsmsg_fhtonode);
+
+ ASSIGN(pvfsr_pr);
+ ASSIGN(pvfsr_dsize);
+ memcpy(cmsg->pvfsr_data, omsg->pvfsr_data, cmsg->pvfsr_dsize);
+ } else if (PUFFSOP_OPCLASS(oreq->preq_opclass) == PUFFSOP_VN) {
+ switch (oreq->preq_optype) {
+ case PUFFS_VN_LOOKUP:
+ {
+ INIT(vnmsg_lookup);
+
+ ASSIGN(pvn_pr);
+ ASSIGN(pvnr_cn);
+ ASSIGN(pvnr_cn_cred);
+
+ break;
+ }
+
+ case PUFFS_VN_CREATE:
+ {
+ INIT(vnmsg_create);
+
+ ASSIGN(pvn_pr);
+ ASSIGN(pvnr_cn);
+ ASSIGN(pvnr_cn_cred);
+ vattr_to_50(&omsg->pvnr_va, &cmsg->pvnr_va);
+
+ break;
+ }
+
+ case PUFFS_VN_MKNOD:
+ {
+ INIT(vnmsg_mknod);
+
+ ASSIGN(pvn_pr);
+ ASSIGN(pvnr_cn);
+ ASSIGN(pvnr_cn_cred);
+ vattr_to_50(&omsg->pvnr_va, &cmsg->pvnr_va);
+
+ break;
+ }
+
+ case PUFFS_VN_MKDIR:
+ {
+ INIT(vnmsg_mkdir);
+
+ ASSIGN(pvn_pr);
+ ASSIGN(pvnr_cn);
+ ASSIGN(pvnr_cn_cred);
+ vattr_to_50(&omsg->pvnr_va, &cmsg->pvnr_va);
+
+ break;
+ }
+
+ case PUFFS_VN_SYMLINK:
+ {
+ INIT(vnmsg_symlink);
+
+ ASSIGN(pvn_pr);
+ ASSIGN(pvnr_cn);
+ ASSIGN(pvnr_cn_cred);
+ vattr_to_50(&omsg->pvnr_va, &cmsg->pvnr_va);
+ memcpy(cmsg->pvnr_link, omsg->pvnr_link,
+ sizeof(cmsg->pvnr_link));
+
+ break;
+ }
+
+ case PUFFS_VN_SETATTR:
+ {
+ INIT(vnmsg_setattr);
+
+ ASSIGN(pvn_pr);
+ ASSIGN(pvnr_cred);
+ vattr_to_50(&omsg->pvnr_va, &cmsg->pvnr_va);
+
+ break;
+ }
+ case PUFFS_VN_GETATTR:
+ {
+ INIT(vnmsg_getattr);
+
+ ASSIGN(pvn_pr);
+ ASSIGN(pvnr_cred);
+
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ if (creq) {
+ *creqp = creq;
+ *deltap = delta;
+ rv = true;
+ }
+
+ return rv;
+}
+#undef INIT
+#undef ASSIGN
+
+#define INIT(name) \
+ struct puffs50_##name *cmsg = (void *)preq; \
+ struct puffs_##name *omsg = (void *)creq;
+#define ASSIGN(field) \
+ omsg->field = cmsg->field;
+
+void
+puffs_compat_incoming(struct puffs_req *preq, struct puffs_req *creq)
+{
+
+ if (PUFFSOP_OPCLASS(preq->preq_opclass == PUFFSOP_VFS)) {
+ INIT(vfsmsg_fhtonode);
+
+ ASSIGN(pvfsr_pr);
+
+ ASSIGN(pvfsr_fhcookie);
+ ASSIGN(pvfsr_vtype);
+ ASSIGN(pvfsr_size);
+ ASSIGN(pvfsr_rdev);
+ } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) {
+ switch (preq->preq_optype) {
+ case PUFFS_VN_LOOKUP:
+ {
+ INIT(vnmsg_lookup);
+
+ ASSIGN(pvn_pr);
+ ASSIGN(pvnr_newnode);
+ ASSIGN(pvnr_vtype);
+ ASSIGN(pvnr_size);
+ ASSIGN(pvnr_rdev);
+
+ break;
+ }
+
+ case PUFFS_VN_CREATE:
+ {
+ INIT(vnmsg_create);
+
+ ASSIGN(pvn_pr);
+ ASSIGN(pvnr_newnode);
+
+ break;
+ }
+
+ case PUFFS_VN_MKNOD:
+ {
+ INIT(vnmsg_mknod);
+
+ ASSIGN(pvn_pr);
+ ASSIGN(pvnr_newnode);
+
+ break;
+ }
+
+ case PUFFS_VN_MKDIR:
+ {
+ INIT(vnmsg_mkdir);
+
+ ASSIGN(pvn_pr);
+ ASSIGN(pvnr_newnode);
+
+ break;
+ }
+
+ case PUFFS_VN_SYMLINK:
+ {
+ INIT(vnmsg_symlink);
+
+ ASSIGN(pvn_pr);
+ ASSIGN(pvnr_newnode);
+
+ break;
+ }
+
+ case PUFFS_VN_SETATTR:
+ {
+ INIT(vnmsg_setattr);
+
+ ASSIGN(pvn_pr);
+
+ break;
+ }
+ case PUFFS_VN_GETATTR:
+ {
+ INIT(vnmsg_getattr);
+
+ ASSIGN(pvn_pr);
+ vattr_from_50(&cmsg->pvnr_va, &omsg->pvnr_va);
+
+ break;
+ }
+
+ default:
+ panic("puffs compat ops come in pairs");
+ }
+ }
+}