Fri Jan 7 16:02:32 2011 UTC ()
Make P2K_WIZARDUID require a valid integer instead of defaulting to root.


(pooka)
diff -r1.9 -r1.10 src/lib/libp2k/p2k.3
diff -r1.53 -r1.54 src/lib/libp2k/p2k.c

cvs diff -r1.9 -r1.10 src/lib/libp2k/p2k.3 (switch to unified diff)

--- src/lib/libp2k/p2k.3 2011/01/07 15:50:40 1.9
+++ src/lib/libp2k/p2k.3 2011/01/07 16:02:32 1.10
@@ -1,143 +1,141 @@ @@ -1,143 +1,141 @@
1.\" $NetBSD: p2k.3,v 1.9 2011/01/07 15:50:40 pooka Exp $ 1.\" $NetBSD: p2k.3,v 1.10 2011/01/07 16:02:32 pooka Exp $
2.\" 2.\"
3.\" Copyright (c) 2008 Antti Kantee. All rights reserved. 3.\" Copyright (c) 2008 Antti Kantee. All rights reserved.
4.\" 4.\"
5.\" Redistribution and use in source and binary forms, with or without 5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions 6.\" modification, are permitted provided that the following conditions
7.\" are met: 7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright 8.\" 1. Redistributions of source code must retain the above copyright
9.\" notice, this list of conditions and the following disclaimer. 9.\" notice, this list of conditions and the following disclaimer.
10.\" 2. Redistributions in binary form must reproduce the above copyright 10.\" 2. Redistributions in binary form must reproduce the above copyright
11.\" notice, this list of conditions and the following disclaimer in the 11.\" notice, this list of conditions and the following disclaimer in the
12.\" documentation and/or other materials provided with the distribution. 12.\" documentation and/or other materials provided with the distribution.
13.\" 13.\"
14.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24.\" SUCH DAMAGE. 24.\" SUCH DAMAGE.
25.\" 25.\"
26.Dd January 7, 2011 26.Dd January 7, 2011
27.Dt P2K 3 27.Dt P2K 3
28.Os 28.Os
29.Sh NAME 29.Sh NAME
30.Nm p2k 30.Nm p2k
31.Nd puffs to kernel vfs translation library 31.Nd puffs to kernel vfs translation library
32.Sh LIBRARY 32.Sh LIBRARY
33p2k Library (libp2k, \-lp2k) 33p2k Library (libp2k, \-lp2k)
34.Sh SYNOPSIS 34.Sh SYNOPSIS
35.In rump/p2k.h 35.In rump/p2k.h
36.Ft struct p2k_mount * 36.Ft struct p2k_mount *
37.Fn p2k_init "uint32_t puffs_flags" 37.Fn p2k_init "uint32_t puffs_flags"
38.Ft void 38.Ft void
39.Fn p2k_cancel "struct p2k_mount *p2m" "int error" 39.Fn p2k_cancel "struct p2k_mount *p2m" "int error"
40.Ft int 40.Ft int
41.Fo p2k_setup_fs 41.Fo p2k_setup_fs
42.Fa "struct p2k_mount *p2m" "const char *vfsname" "const char *devpath" 42.Fa "struct p2k_mount *p2m" "const char *vfsname" "const char *devpath"
43.Fa "const char *mountpath" "int mntflags" "void *arg" "size_t alen" 43.Fa "const char *mountpath" "int mntflags" "void *arg" "size_t alen"
44.Fc 44.Fc
45.Fo p2k_setup_diskfs 45.Fo p2k_setup_diskfs
46.Fa "struct p2k_mount *p2m" "const char *vfsname" "const char *devpath" 46.Fa "struct p2k_mount *p2m" "const char *vfsname" "const char *devpath"
47.Fa "int partition" "const char *mountpath" "int mntflags" 47.Fa "int partition" "const char *mountpath" "int mntflags"
48.Fa "void *arg" "size_t alen" 48.Fa "void *arg" "size_t alen"
49.Fc 49.Fc
50.Ft int 50.Ft int
51.Fn p2k_mainloop "struct p2k_mount *p2m" 51.Fn p2k_mainloop "struct p2k_mount *p2m"
52.Ft int 52.Ft int
53.Fo p2k_run_fs 53.Fo p2k_run_fs
54.Fa "const char *vfsname" "const char *devpath" "const char *mountpath" 54.Fa "const char *vfsname" "const char *devpath" "const char *mountpath"
55.Fa "int mntflags" "void *arg" "size_t alen" "uint32_t puffs_flags" 55.Fa "int mntflags" "void *arg" "size_t alen" "uint32_t puffs_flags"
56.Fc 56.Fc
57.Ft int 57.Ft int
58.Fo p2k_run_diskfs 58.Fo p2k_run_diskfs
59.Fa "const char *vfsname" "const char *devpath" "int partition" 59.Fa "const char *vfsname" "const char *devpath" "int partition"
60.Fa "const char *mountpath" "int mntflags" "void *arg" "size_t alen" 60.Fa "const char *mountpath" "int mntflags" "void *arg" "size_t alen"
61.Fa "uint32_t puffs_flags" 61.Fa "uint32_t puffs_flags"
62.Fc 62.Fc
63.Sh DESCRIPTION 63.Sh DESCRIPTION
64The 64The
65.Nm 65.Nm
66library translates the puffs protocol to the kernel 66library translates the puffs protocol to the kernel
67.Xr vfs 9 67.Xr vfs 9
68protocol and back again. 68protocol and back again.
69It can therefore be used to mount and run kernel file system code as 69It can therefore be used to mount and run kernel file system code as
70a userspace daemon. 70a userspace daemon.
71.Pp 71.Pp
72Calling the library interface function mounts the file system and, 72Calling the library interface function mounts the file system and,
73if succesful, starts handling requests. 73if succesful, starts handling requests.
74The parameters are handled by 74The parameters are handled by
75.Fn ukfs_mount 75.Fn ukfs_mount
76(see 76(see
77.Xr ukfs 3 ) , 77.Xr ukfs 3 ) ,
78with the exception that 78with the exception that
79.Fa mountpath 79.Fa mountpath
80and 80and
81.Fa puffs_flags 81.Fa puffs_flags
82are handled by 82are handled by
83.Xr puffs 3 . 83.Xr puffs 3 .
84The "run_fs" variants of the interfaces are provided as a convenience 84The "run_fs" variants of the interfaces are provided as a convenience
85for the common case. 85for the common case.
86They execute all of init, setup and mainloop in one call. 86They execute all of init, setup and mainloop in one call.
87.Sh ENVIRONMENT 87.Sh ENVIRONMENT
88The following environment variables affect the behaviour of 88The following environment variables affect the behaviour of
89.Nm . 89.Nm .
90They are useful mostly for debugging purposes. 90They are useful mostly for debugging purposes.
91The flags are environment variables because typically the command line 91The flags are environment variables because typically the command line
92arguments to 92arguments to
93.Nm 93.Nm
94utilities are parsed using versions not aware of 94utilities are parsed using versions not aware of
95.Nm 95.Nm
96options; for example, the 96options; for example, the
97.Xr rump_cd9660 8 97.Xr rump_cd9660 8
98arguments are really parsed by 98arguments are really parsed by
99.Xr mount_cd9660 8 . 99.Xr mount_cd9660 8 .
100.Bl -tag -width "XP2K_NOCACHE_PAGE" -offset 2n 100.Bl -tag -width "XP2K_NOCACHE_PAGE" -offset 2n
101.It Dv P2K_DEBUG 101.It Dv P2K_DEBUG
102Do not detach from tty and print information about each puffs operation. 102Do not detach from tty and print information about each puffs operation.
103In case the daemon receives 103In case the daemon receives
104.Dv SIGINFO 104.Dv SIGINFO
105(typically from ctrl-T), it dumps out the status of the mount point. 105(typically from ctrl-T), it dumps out the status of the mount point.
106Sending 106Sending
107.Dv SIGUSR1 107.Dv SIGUSR1
108causes a dump of all the vnodes (verbose). 108causes a dump of all the vnodes (verbose).
109.It Dv P2K_NODETACH 109.It Dv P2K_NODETACH
110Do not detach from tty. 110Do not detach from tty.
111.It Dv P2K_NOCACHE_PAGE 111.It Dv P2K_NOCACHE_PAGE
112Do not use the puffs page cache. 112Do not use the puffs page cache.
113.It Dv P2K_NOCACHE_NAME 113.It Dv P2K_NOCACHE_NAME
114Do not use the puffs name cache. 114Do not use the puffs name cache.
115.It Dv P2K_NOCACHE 115.It Dv P2K_NOCACHE
116Do not use the puffs page or name cache. 116Do not use the puffs page or name cache.
117.It Dv P2K_WIZARDUID 117.It Dv P2K_WIZARDUID
118If set, use the value of the variable to determine the UID of the 118If set, use the value of the variable to determine the UID of the
119caller of each operation instead of the actual caller supplied by 119caller of each operation instead of the actual caller supplied by
120.Xr puffs 3 . 120.Xr puffs 3 .
121This can be used for example to simplify modifying an OS installations 121This can be used for example to simplify modifying an OS installation's
122root image as a non-root user. 122root image as a non-root user.
123If the variable is set but does not contain an integer value, 0 
124(root) is used. 
125.El 123.El
126.Sh SEE ALSO 124.Sh SEE ALSO
127.Xr puffs 3 , 125.Xr puffs 3 ,
128.Xr rump 3 , 126.Xr rump 3 ,
129.Xr ukfs 3 , 127.Xr ukfs 3 ,
130.Xr rump_cd9660 8 , 128.Xr rump_cd9660 8 ,
131.Xr rump_efs 8 , 129.Xr rump_efs 8 ,
132.Xr rump_ext2fs 8 , 130.Xr rump_ext2fs 8 ,
133.Xr rump_ffs 8 , 131.Xr rump_ffs 8 ,
134.Xr rump_hfs 8 , 132.Xr rump_hfs 8 ,
135.Xr rump_lfs 8 , 133.Xr rump_lfs 8 ,
136.Xr rump_msdos 8 , 134.Xr rump_msdos 8 ,
137.Xr rump_nfs 8 , 135.Xr rump_nfs 8 ,
138.Xr rump_ntfs 8 , 136.Xr rump_ntfs 8 ,
139.Xr rump_smbfs 8 , 137.Xr rump_smbfs 8 ,
140.Xr rump_syspuffs 8 , 138.Xr rump_syspuffs 8 ,
141.Xr rump_sysvbfs 8 , 139.Xr rump_sysvbfs 8 ,
142.Xr rump_tmpfs 8 , 140.Xr rump_tmpfs 8 ,
143.Xr rump_udf 8 141.Xr rump_udf 8

cvs diff -r1.53 -r1.54 src/lib/libp2k/p2k.c (switch to unified diff)

--- src/lib/libp2k/p2k.c 2011/01/07 15:47:14 1.53
+++ src/lib/libp2k/p2k.c 2011/01/07 16:02:32 1.54
@@ -1,1349 +1,1356 @@ @@ -1,1349 +1,1356 @@
1/* $NetBSD: p2k.c,v 1.53 2011/01/07 15:47:14 pooka Exp $ */ 1/* $NetBSD: p2k.c,v 1.54 2011/01/07 16:02:32 pooka Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2007, 2008, 2009 Antti Kantee. All Rights Reserved. 4 * Copyright (c) 2007, 2008, 2009 Antti Kantee. All Rights Reserved.
5 * 5 *
6 * Development of this software was supported by the 6 * Development of this software was supported by the
7 * Finnish Cultural Foundation. 7 * Finnish Cultural Foundation.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE. 28 * SUCH DAMAGE.
29 */ 29 */
30 30
31/* 31/*
32 * puffs 2k, i.e. puffs 2 kernel. Converts the puffs protocol to 32 * puffs 2k, i.e. puffs 2 kernel. Converts the puffs protocol to
33 * the kernel vfs protocol and vice versa. 33 * the kernel vfs protocol and vice versa.
34 * 34 *
35 * A word about reference counting: puffs in the kernel is the king of 35 * A word about reference counting: puffs in the kernel is the king of
36 * reference counting. We must maintain a vnode alive and kicking 36 * reference counting. We must maintain a vnode alive and kicking
37 * until the kernel tells us to reclaim it. Therefore we make sure 37 * until the kernel tells us to reclaim it. Therefore we make sure
38 * we never accidentally lose a vnode. Before calling operations which 38 * we never accidentally lose a vnode. Before calling operations which
39 * decrease the refcount we always bump the refcount up to compensate. 39 * decrease the refcount we always bump the refcount up to compensate.
40 * Come inactive, if the file system thinks that the vnode should be 40 * Come inactive, if the file system thinks that the vnode should be
41 * put out of its misery, it will set the recycle flag. We use this 41 * put out of its misery, it will set the recycle flag. We use this
42 * to tell the kernel to reclaim the vnode. Only in reclaim do we 42 * to tell the kernel to reclaim the vnode. Only in reclaim do we
43 * really nuke the last reference. 43 * really nuke the last reference.
44 */ 44 */
45 45
46#include <sys/cdefs.h> 46#include <sys/cdefs.h>
47#include <sys/mount.h> 47#include <sys/mount.h>
48#include <sys/param.h> 48#include <sys/param.h>
49#include <sys/vnode.h> 49#include <sys/vnode.h>
50#include <sys/lock.h> 50#include <sys/lock.h>
51#include <sys/namei.h> 51#include <sys/namei.h>
52#include <sys/dirent.h> 52#include <sys/dirent.h>
53#include <sys/hash.h> 53#include <sys/hash.h>
54 54
55#include <assert.h> 55#include <assert.h>
56#include <errno.h> 56#include <errno.h>
57#include <puffs.h> 57#include <puffs.h>
58#include <stdlib.h> 58#include <stdlib.h>
59#include <stdio.h> 59#include <stdio.h>
60 60
61#include <rump/rump.h> 61#include <rump/rump.h>
62#include <rump/p2k.h> 62#include <rump/p2k.h>
63#include <rump/ukfs.h> 63#include <rump/ukfs.h>
64 64
65/* NetBSD-5 compat */ 65/* NetBSD-5 compat */
66#ifndef MOUNT_RUMPFS 66#ifndef MOUNT_RUMPFS
67#define MOUNT_RUMPFS "rumpfs" 67#define MOUNT_RUMPFS "rumpfs"
68#endif 68#endif
69 69
70PUFFSOP_PROTOS(p2k) 70PUFFSOP_PROTOS(p2k)
71 71
72LIST_HEAD(p2k_vp_hash, p2k_node); 72LIST_HEAD(p2k_vp_hash, p2k_node);
73#define NHASHBUCK (1<<16) 73#define NHASHBUCK (1<<16)
74struct p2k_mount { 74struct p2k_mount {
75 struct vnode *p2m_rvp; 75 struct vnode *p2m_rvp;
76 struct puffs_usermount *p2m_pu; 76 struct puffs_usermount *p2m_pu;
77 struct ukfs *p2m_ukfs; 77 struct ukfs *p2m_ukfs;
78 struct p2k_vp_hash p2m_vphash[NHASHBUCK]; 78 struct p2k_vp_hash p2m_vphash[NHASHBUCK];
79 struct mount *p2m_mp; 79 struct mount *p2m_mp;
80 int p2m_nvnodes; 80 int p2m_nvnodes;
81 int p2m_imtmpfsman; 81 int p2m_imtmpfsman;
82 bool p2m_hasdebug; 82 bool p2m_hasdebug;
83}; 83};
84 84
85struct p2k_node { 85struct p2k_node {
86 struct vnode *p2n_vp; 86 struct vnode *p2n_vp;
87 87
88 LIST_ENTRY(p2k_node) p2n_entries; 88 LIST_ENTRY(p2k_node) p2n_entries;
89}; 89};
90 90
91#define OPC2VP(opc) (((struct p2k_node *)opc)->p2n_vp) 91#define OPC2VP(opc) (((struct p2k_node *)opc)->p2n_vp)
92 92
93static int haswizard; 93static int haswizard;
94static uid_t wizarduid; 94static uid_t wizarduid;
95 95
96static struct kauth_cred * 96static struct kauth_cred *
97cred_create(const struct puffs_cred *pcr) 97cred_create(const struct puffs_cred *pcr)
98{ 98{
99 gid_t groups[NGROUPS]; 99 gid_t groups[NGROUPS];
100 uid_t uid; 100 uid_t uid;
101 gid_t gid; 101 gid_t gid;
102 short ngroups = __arraycount(groups); 102 short ngroups = __arraycount(groups);
103 103
104 if (haswizard) { 104 if (haswizard) {
105 uid = wizarduid; 105 uid = wizarduid;
106 } else { 106 } else {
107 if (puffs_cred_getuid(pcr, &uid) == -1) 107 if (puffs_cred_getuid(pcr, &uid) == -1)
108 uid = 0; 108 uid = 0;
109 } 109 }
110 if (puffs_cred_getgid(pcr, &gid) == -1) 110 if (puffs_cred_getgid(pcr, &gid) == -1)
111 gid = 0; 111 gid = 0;
112 puffs_cred_getgroups(pcr, groups, &ngroups); 112 puffs_cred_getgroups(pcr, groups, &ngroups);
113 113
114 /* LINTED: ngroups is ok */ 114 /* LINTED: ngroups is ok */
115 return rump_pub_cred_create(uid, gid, ngroups, groups); 115 return rump_pub_cred_create(uid, gid, ngroups, groups);
116} 116}
117 117
118static __inline void 118static __inline void
119cred_destroy(struct kauth_cred *cred) 119cred_destroy(struct kauth_cred *cred)
120{ 120{
121 121
122 rump_pub_cred_put(cred); 122 rump_pub_cred_put(cred);
123} 123}
124 124
125static struct componentname * 125static struct componentname *
126makecn(const struct puffs_cn *pcn) 126makecn(const struct puffs_cn *pcn)
127{ 127{
128 struct kauth_cred *cred; 128 struct kauth_cred *cred;
129 129
130 cred = cred_create(pcn->pcn_cred); 130 cred = cred_create(pcn->pcn_cred);
131 /* LINTED: prehistoric types in first two args */ 131 /* LINTED: prehistoric types in first two args */
132 return rump_pub_makecn(pcn->pcn_nameiop, pcn->pcn_flags, 132 return rump_pub_makecn(pcn->pcn_nameiop, pcn->pcn_flags,
133 pcn->pcn_name, pcn->pcn_namelen, cred, rump_pub_lwproc_curlwp()); 133 pcn->pcn_name, pcn->pcn_namelen, cred, rump_pub_lwproc_curlwp());
134} 134}
135 135
136static __inline void 136static __inline void
137freecn(struct componentname *cnp) 137freecn(struct componentname *cnp)
138{ 138{
139 139
140 rump_pub_freecn(cnp, RUMPCN_FREECRED); 140 rump_pub_freecn(cnp, RUMPCN_FREECRED);
141} 141}
142 142
143static void 143static void
144makelwp(struct puffs_usermount *pu) 144makelwp(struct puffs_usermount *pu)
145{ 145{
146 pid_t pid; 146 pid_t pid;
147 lwpid_t lid; 147 lwpid_t lid;
148 148
149 puffs_cc_getcaller(puffs_cc_getcc(pu), &pid, &lid); 149 puffs_cc_getcaller(puffs_cc_getcc(pu), &pid, &lid);
150 rump_pub_allbetsareoff_setid(pid, lid); 150 rump_pub_allbetsareoff_setid(pid, lid);
151} 151}
152 152
153static volatile sig_atomic_t dodump; 153static volatile sig_atomic_t dodump;
154static void 154static void
155dumpmp(struct puffs_usermount *pu) 155dumpmp(struct puffs_usermount *pu)
156{ 156{
157 struct statvfs svfsb; 157 struct statvfs svfsb;
158 158
159 if (dodump && p2k_fs_statvfs(pu, &svfsb) == 0) { 159 if (dodump && p2k_fs_statvfs(pu, &svfsb) == 0) {
160 rump_pub_vfs_mount_print(svfsb.f_mntonname, dodump-1); 160 rump_pub_vfs_mount_print(svfsb.f_mntonname, dodump-1);
161 } 161 }
162 162
163 dodump = 0; 163 dodump = 0;
164} 164}
165 165
166static void 166static void
167sighand(int sig) 167sighand(int sig)
168{ 168{
169 169
170 if (sig == SIGINFO) 170 if (sig == SIGINFO)
171 dodump = 1; 171 dodump = 1;
172 else if (sig == SIGUSR1) 172 else if (sig == SIGUSR1)
173 dodump = 2; 173 dodump = 2;
174} 174}
175 175
176static __inline struct p2k_vp_hash * 176static __inline struct p2k_vp_hash *
177gethash(struct p2k_mount *p2m, struct vnode *vp) 177gethash(struct p2k_mount *p2m, struct vnode *vp)
178{ 178{
179 uint32_t hash; 179 uint32_t hash;
180 180
181 hash = hash32_buf(&vp, sizeof(vp), HASH32_BUF_INIT); 181 hash = hash32_buf(&vp, sizeof(vp), HASH32_BUF_INIT);
182 return &p2m->p2m_vphash[hash % NHASHBUCK]; 182 return &p2m->p2m_vphash[hash % NHASHBUCK];
183} 183}
184 184
185/* 185/*
186 * Find node based on hash of vnode pointer. If vnode is found, 186 * Find node based on hash of vnode pointer. If vnode is found,
187 * releases one reference to vnode based on the fact that we just 187 * releases one reference to vnode based on the fact that we just
188 * performed a lookup for it. 188 * performed a lookup for it.
189 * 189 *
190 * If the optinal p2n_storage parameter is passed, it is used instead 190 * If the optinal p2n_storage parameter is passed, it is used instead
191 * of allocating more memory. This allows for easier error recovery. 191 * of allocating more memory. This allows for easier error recovery.
192 */ 192 */
193static struct p2k_node * 193static struct p2k_node *
194getp2n(struct p2k_mount *p2m, struct vnode *vp, bool initial, 194getp2n(struct p2k_mount *p2m, struct vnode *vp, bool initial,
195 struct p2k_node *p2n_storage) 195 struct p2k_node *p2n_storage)
196{ 196{
197 struct p2k_vp_hash *hl; 197 struct p2k_vp_hash *hl;
198 struct p2k_node *p2n = NULL; 198 struct p2k_node *p2n = NULL;
199 199
200 /* p2n_storage => initial */ 200 /* p2n_storage => initial */
201 assert(!p2n_storage || initial); 201 assert(!p2n_storage || initial);
202 202
203 hl = gethash(p2m, vp); 203 hl = gethash(p2m, vp);
204 if (!initial) 204 if (!initial)
205 LIST_FOREACH(p2n, hl, p2n_entries) 205 LIST_FOREACH(p2n, hl, p2n_entries)
206 if (p2n->p2n_vp == vp) 206 if (p2n->p2n_vp == vp)
207 break; 207 break;
208 208
209 hl = gethash(p2m, vp); 209 hl = gethash(p2m, vp);
210 if (p2n) { 210 if (p2n) {
211 rump_pub_vp_rele(vp); 211 rump_pub_vp_rele(vp);
212 } else { 212 } else {
213 if (p2n_storage) 213 if (p2n_storage)
214 p2n = p2n_storage; 214 p2n = p2n_storage;
215 else 215 else
216 p2n = malloc(sizeof(*p2n)); 216 p2n = malloc(sizeof(*p2n));
217 if (!p2n) { 217 if (!p2n) {
218 rump_pub_vp_rele(vp); 218 rump_pub_vp_rele(vp);
219 return NULL; 219 return NULL;
220 } 220 }
221 memset(p2n, 0, sizeof(*p2n)); 221 memset(p2n, 0, sizeof(*p2n));
222 LIST_INSERT_HEAD(hl, p2n, p2n_entries); 222 LIST_INSERT_HEAD(hl, p2n, p2n_entries);
223 p2n->p2n_vp = vp; 223 p2n->p2n_vp = vp;
224 } 224 }
225 return p2n; 225 return p2n;
226} 226}
227 227
228static void 228static void
229freep2n(struct p2k_node *p2n) 229freep2n(struct p2k_node *p2n)
230{ 230{
231 231
232 assert(p2n->p2n_vp == NULL); 232 assert(p2n->p2n_vp == NULL);
233 LIST_REMOVE(p2n, p2n_entries); 233 LIST_REMOVE(p2n, p2n_entries);
234 free(p2n); 234 free(p2n);
235} 235}
236 236
237/*ARGSUSED*/ 237/*ARGSUSED*/
238static void 238static void
239p2k_errcatcher(struct puffs_usermount *pu, uint8_t type, int error, 239p2k_errcatcher(struct puffs_usermount *pu, uint8_t type, int error,
240 const char *str, puffs_cookie_t cook) 240 const char *str, puffs_cookie_t cook)
241{ 241{
242 242
243 fprintf(stderr, "type %d, error %d, cookie %p (%s)\n", 243 fprintf(stderr, "type %d, error %d, cookie %p (%s)\n",
244 type, error, cook, str); 244 type, error, cook, str);
245 245
246 /* 246 /*
247 * Trap all EINVAL responses to lookup. It most likely means 247 * Trap all EINVAL responses to lookup. It most likely means
248 * that we supplied VNON/VBAD as the type. The real kernel 248 * that we supplied VNON/VBAD as the type. The real kernel
249 * doesn't panic from this either, but just handles it. 249 * doesn't panic from this either, but just handles it.
250 */ 250 */
251 if (type != PUFFS_VN_LOOKUP && error == EINVAL) 251 if (type != PUFFS_VN_LOOKUP && error == EINVAL)
252 abort(); 252 abort();
253} 253}
254 254
255/* just to avoid annoying loop when singlestepping */ 255/* just to avoid annoying loop when singlestepping */
256static struct p2k_mount * 256static struct p2k_mount *
257allocp2m(void) 257allocp2m(void)
258{ 258{
259 struct p2k_mount *p2m; 259 struct p2k_mount *p2m;
260 int i; 260 int i;
261 261
262 p2m = malloc(sizeof(*p2m)); 262 p2m = malloc(sizeof(*p2m));
263 if (p2m == NULL) 263 if (p2m == NULL)
264 return NULL; 264 return NULL;
265 memset(p2m, 0, sizeof(*p2m)); 265 memset(p2m, 0, sizeof(*p2m));
266 266
267 for (i = 0; i < NHASHBUCK; i++) 267 for (i = 0; i < NHASHBUCK; i++)
268 LIST_INIT(&p2m->p2m_vphash[i]); 268 LIST_INIT(&p2m->p2m_vphash[i]);
269 269
270 return p2m; 270 return p2m;
271} 271}
272 272
273struct p2k_mount * 273struct p2k_mount *
274p2k_init(uint32_t puffs_flags) 274p2k_init(uint32_t puffs_flags)
275{ 275{
276 struct puffs_ops *pops; 276 struct puffs_ops *pops;
277 struct p2k_mount *p2m; 277 struct p2k_mount *p2m;
278 char *envbuf; 278 char *envbuf;
279 bool dodaemon; 279 bool dodaemon;
280 bool hasdebug; 280 bool hasdebug;
281 281
282 PUFFSOP_INIT(pops); 282 PUFFSOP_INIT(pops);
283 283
284 PUFFSOP_SET(pops, p2k, fs, statvfs); 284 PUFFSOP_SET(pops, p2k, fs, statvfs);
285 PUFFSOP_SET(pops, p2k, fs, unmount); 285 PUFFSOP_SET(pops, p2k, fs, unmount);
286 PUFFSOP_SET(pops, p2k, fs, sync); 286 PUFFSOP_SET(pops, p2k, fs, sync);
287 PUFFSOP_SET(pops, p2k, fs, fhtonode); 287 PUFFSOP_SET(pops, p2k, fs, fhtonode);
288 PUFFSOP_SET(pops, p2k, fs, nodetofh); 288 PUFFSOP_SET(pops, p2k, fs, nodetofh);
289 PUFFSOP_SET(pops, p2k, fs, extattrctl); 289 PUFFSOP_SET(pops, p2k, fs, extattrctl);
290 290
291 PUFFSOP_SET(pops, p2k, node, lookup); 291 PUFFSOP_SET(pops, p2k, node, lookup);
292 PUFFSOP_SET(pops, p2k, node, create); 292 PUFFSOP_SET(pops, p2k, node, create);
293 PUFFSOP_SET(pops, p2k, node, mknod); 293 PUFFSOP_SET(pops, p2k, node, mknod);
294 PUFFSOP_SET(pops, p2k, node, open); 294 PUFFSOP_SET(pops, p2k, node, open);
295 PUFFSOP_SET(pops, p2k, node, close); 295 PUFFSOP_SET(pops, p2k, node, close);
296 PUFFSOP_SET(pops, p2k, node, access); 296 PUFFSOP_SET(pops, p2k, node, access);
297 PUFFSOP_SET(pops, p2k, node, getattr); 297 PUFFSOP_SET(pops, p2k, node, getattr);
298 PUFFSOP_SET(pops, p2k, node, setattr); 298 PUFFSOP_SET(pops, p2k, node, setattr);
299#if 0 299#if 0
300 PUFFSOP_SET(pops, p2k, node, poll); 300 PUFFSOP_SET(pops, p2k, node, poll);
301#endif 301#endif
302 PUFFSOP_SET(pops, p2k, node, mmap); 302 PUFFSOP_SET(pops, p2k, node, mmap);
303 PUFFSOP_SET(pops, p2k, node, fsync); 303 PUFFSOP_SET(pops, p2k, node, fsync);
304 PUFFSOP_SET(pops, p2k, node, seek); 304 PUFFSOP_SET(pops, p2k, node, seek);
305 PUFFSOP_SET(pops, p2k, node, remove); 305 PUFFSOP_SET(pops, p2k, node, remove);
306 PUFFSOP_SET(pops, p2k, node, link); 306 PUFFSOP_SET(pops, p2k, node, link);
307 PUFFSOP_SET(pops, p2k, node, rename); 307 PUFFSOP_SET(pops, p2k, node, rename);
308 PUFFSOP_SET(pops, p2k, node, mkdir); 308 PUFFSOP_SET(pops, p2k, node, mkdir);
309 PUFFSOP_SET(pops, p2k, node, rmdir); 309 PUFFSOP_SET(pops, p2k, node, rmdir);
310 PUFFSOP_SET(pops, p2k, node, symlink); 310 PUFFSOP_SET(pops, p2k, node, symlink);
311 PUFFSOP_SET(pops, p2k, node, readdir); 311 PUFFSOP_SET(pops, p2k, node, readdir);
312 PUFFSOP_SET(pops, p2k, node, readlink); 312 PUFFSOP_SET(pops, p2k, node, readlink);
313 PUFFSOP_SET(pops, p2k, node, read); 313 PUFFSOP_SET(pops, p2k, node, read);
314 PUFFSOP_SET(pops, p2k, node, write); 314 PUFFSOP_SET(pops, p2k, node, write);
315 315
316 PUFFSOP_SET(pops, p2k, node, pathconf); 316 PUFFSOP_SET(pops, p2k, node, pathconf);
317 317
318 PUFFSOP_SET(pops, p2k, node, inactive); 318 PUFFSOP_SET(pops, p2k, node, inactive);
319 PUFFSOP_SET(pops, p2k, node, reclaim); 319 PUFFSOP_SET(pops, p2k, node, reclaim);
320 320
321 PUFFSOP_SET(pops, p2k, node, getextattr); 321 PUFFSOP_SET(pops, p2k, node, getextattr);
322 PUFFSOP_SET(pops, p2k, node, setextattr); 322 PUFFSOP_SET(pops, p2k, node, setextattr);
323 PUFFSOP_SET(pops, p2k, node, listextattr); 323 PUFFSOP_SET(pops, p2k, node, listextattr);
324 PUFFSOP_SET(pops, p2k, node, deleteextattr); 324 PUFFSOP_SET(pops, p2k, node, deleteextattr);
325 325
326 dodaemon = true; 326 dodaemon = true;
327 hasdebug = false; 327 hasdebug = false;
328 328
329 if (getenv("P2K_DEBUG") != NULL) { 329 if (getenv("P2K_DEBUG") != NULL) {
330 puffs_flags |= PUFFS_FLAG_OPDUMP; 330 puffs_flags |= PUFFS_FLAG_OPDUMP;
331 dodaemon = false; 331 dodaemon = false;
332 hasdebug = true; 332 hasdebug = true;
333 } 333 }
334 if (getenv("P2K_NODETACH") != NULL) { 334 if (getenv("P2K_NODETACH") != NULL) {
335 dodaemon = false; 335 dodaemon = false;
336 } 336 }
337 if (getenv("P2K_NOCACHE_PAGE") != NULL) { 337 if (getenv("P2K_NOCACHE_PAGE") != NULL) {
338 puffs_flags |= PUFFS_KFLAG_NOCACHE_PAGE; 338 puffs_flags |= PUFFS_KFLAG_NOCACHE_PAGE;
339 } 339 }
340 if (getenv("P2K_NOCACHE_NAME") != NULL) { 340 if (getenv("P2K_NOCACHE_NAME") != NULL) {
341 puffs_flags |= PUFFS_KFLAG_NOCACHE_NAME; 341 puffs_flags |= PUFFS_KFLAG_NOCACHE_NAME;
342 } 342 }
343 if (getenv("P2K_NOCACHE") != NULL) { 343 if (getenv("P2K_NOCACHE") != NULL) {
344 puffs_flags |= PUFFS_KFLAG_NOCACHE; 344 puffs_flags |= PUFFS_KFLAG_NOCACHE;
345 } 345 }
346 if ((envbuf = getenv("P2K_WIZARDUID")) != NULL) { 346 if ((envbuf = getenv("P2K_WIZARDUID")) != NULL) {
347 /* default to 0 in error cases */ 347 char *ep;
348 wizarduid = atoi(envbuf); 348
349 haswizard = 1; 349 wizarduid = strtoul(envbuf, &ep, 10);
350 printf("P2K WIZARD MODE: using uid %d\n", wizarduid); 350 if (envbuf[0] == '\0' || *ep != '\0') {
 351 printf("P2K_WIZARDUID: invalid uid %s\n", envbuf);
 352 } else if (wizarduid > UID_MAX) {
 353 printf("P2K_WIZARDUID: uid %s out-of-range\n", envbuf);
 354 } else {
 355 haswizard = 1;
 356 printf("P2K WIZARD MODE: using uid %d\n", wizarduid);
 357 }
351 } 358 }
352 359
353 p2m = allocp2m(); 360 p2m = allocp2m();
354 if (p2m == NULL) 361 if (p2m == NULL)
355 return NULL; 362 return NULL;
356 p2m->p2m_pu = puffs_init(pops, PUFFS_DEFER, PUFFS_DEFER, 363 p2m->p2m_pu = puffs_init(pops, PUFFS_DEFER, PUFFS_DEFER,
357 PUFFS_DEFER, puffs_flags); 364 PUFFS_DEFER, puffs_flags);
358 if (p2m->p2m_pu == NULL) { 365 if (p2m->p2m_pu == NULL) {
359 int sverrno = errno; 366 int sverrno = errno;
360 free(p2m); 367 free(p2m);
361 errno = sverrno; 368 errno = sverrno;
362 return NULL; 369 return NULL;
363 } 370 }
364 p2m->p2m_hasdebug = hasdebug; 371 p2m->p2m_hasdebug = hasdebug;
365 372
366 if (dodaemon) { 373 if (dodaemon) {
367 if (puffs_daemon(p2m->p2m_pu, 1, 1) == -1) { 374 if (puffs_daemon(p2m->p2m_pu, 1, 1) == -1) {
368 int sverrno = errno; 375 int sverrno = errno;
369 p2k_cancel(p2m, sverrno); 376 p2k_cancel(p2m, sverrno);
370 errno = sverrno; 377 errno = sverrno;
371 p2m = NULL; 378 p2m = NULL;
372 } 379 }
373 } 380 }
374 if (p2m) 381 if (p2m)
375 rump_init(); 382 rump_init();
376 383
377 rump_pub_lwproc_rfork(RUMP_RFCFDG); 384 rump_pub_lwproc_rfork(RUMP_RFCFDG);
378 385
379 return p2m; 386 return p2m;
380} 387}
381 388
382void 389void
383p2k_cancel(struct p2k_mount *p2m, int error) 390p2k_cancel(struct p2k_mount *p2m, int error)
384{ 391{
385 392
386 puffs_cancel(p2m->p2m_pu, error); 393 puffs_cancel(p2m->p2m_pu, error);
387 free(p2m); 394 free(p2m);
388} 395}
389 396
390static int 397static int
391setupfs(struct p2k_mount *p2m, const char *vfsname, const char *devpath, 398setupfs(struct p2k_mount *p2m, const char *vfsname, const char *devpath,
392 struct ukfs_part *part, const char *mountpath, int mntflags, 399 struct ukfs_part *part, const char *mountpath, int mntflags,
393 void *arg, size_t alen) 400 void *arg, size_t alen)
394{ 401{
395 char partpath[UKFS_DEVICE_MAXPATHLEN]; 402 char partpath[UKFS_DEVICE_MAXPATHLEN];
396 char partbuf[UKFS_DEVICE_MAXSTR]; 403 char partbuf[UKFS_DEVICE_MAXSTR];
397 char typebuf[PUFFS_TYPELEN]; 404 char typebuf[PUFFS_TYPELEN];
398 struct puffs_usermount *pu = p2m->p2m_pu; 405 struct puffs_usermount *pu = p2m->p2m_pu;
399 struct p2k_node *p2n_root; 406 struct p2k_node *p2n_root;
400 struct ukfs *ukfs = NULL; 407 struct ukfs *ukfs = NULL;
401 extern int puffs_fakecc; 408 extern int puffs_fakecc;
402 int rv = -1, sverrno; 409 int rv = -1, sverrno;
403 410
404 strcpy(typebuf, "p2k|"); 411 strcpy(typebuf, "p2k|");
405 if (strcmp(vfsname, "puffs") == 0) { /* XXX */ 412 if (strcmp(vfsname, "puffs") == 0) { /* XXX */
406 struct puffs_kargs *args = arg; 413 struct puffs_kargs *args = arg;
407 strlcat(typebuf, args->pa_typename, sizeof(typebuf)); 414 strlcat(typebuf, args->pa_typename, sizeof(typebuf));
408 } else { 415 } else {
409 strlcat(typebuf, vfsname, sizeof(typebuf)); 416 strlcat(typebuf, vfsname, sizeof(typebuf));
410 } 417 }
411 418
412 strlcpy(partpath, devpath, sizeof(partpath)); 419 strlcpy(partpath, devpath, sizeof(partpath));
413 if (ukfs_part_tostring(part, partbuf, sizeof(partbuf))) { 420 if (ukfs_part_tostring(part, partbuf, sizeof(partbuf))) {
414 strlcat(partpath, partbuf, sizeof(partpath)); 421 strlcat(partpath, partbuf, sizeof(partpath));
415 } 422 }
416 puffs_setmntinfo(pu, partpath, typebuf); 423 puffs_setmntinfo(pu, partpath, typebuf);
417 424
418 if (ukfs_init() == -1) 425 if (ukfs_init() == -1)
419 goto out; 426 goto out;
420 427
421 /*  428 /*
422 * If we're mounting rumpfs, actually do no mount and redirect 429 * If we're mounting rumpfs, actually do no mount and redirect
423 * requests to rump fs namespace root. Strictly speaking, this 430 * requests to rump fs namespace root. Strictly speaking, this
424 * is not correct, but I don't think anyone will notice. 431 * is not correct, but I don't think anyone will notice.
425 * After all, we're mostly interested in things which reside 432 * After all, we're mostly interested in things which reside
426 * specifically on the rootfs, namely the contents of /dev 433 * specifically on the rootfs, namely the contents of /dev
427 */ 434 */
428 if (strcmp(vfsname, MOUNT_RUMPFS) == 0) { 435 if (strcmp(vfsname, MOUNT_RUMPFS) == 0) {
429 if ((rv = rump_pub_vfs_getmp("/", &p2m->p2m_mp)) != 0) { 436 if ((rv = rump_pub_vfs_getmp("/", &p2m->p2m_mp)) != 0) {
430 errno = rv; 437 errno = rv;
431 rv = -1; 438 rv = -1;
432 goto out; 439 goto out;
433 } 440 }
434 } else { 441 } else {
435 if (part != ukfs_part_na) 442 if (part != ukfs_part_na)
436 ukfs = ukfs_mount_disk(vfsname, devpath, part, 443 ukfs = ukfs_mount_disk(vfsname, devpath, part,
437 mountpath, mntflags, arg, alen); 444 mountpath, mntflags, arg, alen);
438 else 445 else
439 ukfs = ukfs_mount(vfsname, devpath, mountpath, mntflags, 446 ukfs = ukfs_mount(vfsname, devpath, mountpath, mntflags,
440 arg, alen); 447 arg, alen);
441 if (ukfs == NULL) 448 if (ukfs == NULL)
442 goto out; 449 goto out;
443 ukfs_setspecific(ukfs, p2m); 450 ukfs_setspecific(ukfs, p2m);
444 p2m->p2m_ukfs = ukfs; 451 p2m->p2m_ukfs = ukfs;
445 p2m->p2m_mp = ukfs_getmp(ukfs); 452 p2m->p2m_mp = ukfs_getmp(ukfs);
446 } 453 }
447 if ((rv = rump_pub_vfs_root(p2m->p2m_mp, &p2m->p2m_rvp, 0)) != 0) { 454 if ((rv = rump_pub_vfs_root(p2m->p2m_mp, &p2m->p2m_rvp, 0)) != 0) {
448 errno = rv; 455 errno = rv;
449 rv = -1; 456 rv = -1;
450 goto out; 457 goto out;
451 } 458 }
452 459
453 p2m->p2m_pu = pu; 460 p2m->p2m_pu = pu;
454 461
455 /* 462 /*
456 * Detect tmpfs. XXX: this is a kludge. See inactive(). 463 * Detect tmpfs. XXX: this is a kludge. See inactive().
457 * 464 *
458 * In reality we'd want "does file system use anon objects 465 * In reality we'd want "does file system use anon objects
459 * for storage?". But since tmpfs hides the anon object from 466 * for storage?". But since tmpfs hides the anon object from
460 * the public interface, we can't actually detect it sanely. 467 * the public interface, we can't actually detect it sanely.
461 * Therefore, use this kludge. 468 * Therefore, use this kludge.
462 */ 469 */
463 p2m->p2m_imtmpfsman = strcmp(vfsname, MOUNT_TMPFS) == 0; 470 p2m->p2m_imtmpfsman = strcmp(vfsname, MOUNT_TMPFS) == 0;
464 471
465 p2n_root = getp2n(p2m, p2m->p2m_rvp, true, NULL); 472 p2n_root = getp2n(p2m, p2m->p2m_rvp, true, NULL);
466 puffs_setfhsize(pu, 0, PUFFS_FHFLAG_PASSTHROUGH); 473 puffs_setfhsize(pu, 0, PUFFS_FHFLAG_PASSTHROUGH);
467 puffs_setstacksize(pu, PUFFS_STACKSIZE_MIN); 474 puffs_setstacksize(pu, PUFFS_STACKSIZE_MIN);
468 puffs_fakecc = 1; 475 puffs_fakecc = 1;
469 puffs_set_prepost(pu, makelwp, NULL); 476 puffs_set_prepost(pu, makelwp, NULL);
470 477
471 if (p2m->p2m_hasdebug) { 478 if (p2m->p2m_hasdebug) {
472 struct timespec ts; 479 struct timespec ts;
473 480
474 signal(SIGINFO, sighand); 481 signal(SIGINFO, sighand);
475 signal(SIGUSR1, sighand); 482 signal(SIGUSR1, sighand);
476 483
477 ts.tv_sec = 0; 484 ts.tv_sec = 0;
478 ts.tv_nsec = 1000*1000*10; /* 10ms */ 485 ts.tv_nsec = 1000*1000*10; /* 10ms */
479 puffs_ml_setloopfn(pu, dumpmp); 486 puffs_ml_setloopfn(pu, dumpmp);
480 puffs_ml_settimeout(pu, &ts); 487 puffs_ml_settimeout(pu, &ts);
481 } 488 }
482 puffs_set_errnotify(pu, p2k_errcatcher); 489 puffs_set_errnotify(pu, p2k_errcatcher);
483 490
484 puffs_setspecific(pu, p2m); 491 puffs_setspecific(pu, p2m);
485 rv = puffs_mount(pu, mountpath, mntflags, p2n_root); 492 rv = puffs_mount(pu, mountpath, mntflags, p2n_root);
486 493
487 out: 494 out:
488 if (rv == -1) { 495 if (rv == -1) {
489 sverrno = errno; 496 sverrno = errno;
490 puffs_cancel(pu, sverrno); 497 puffs_cancel(pu, sverrno);
491 if (ukfs) 498 if (ukfs)
492 ukfs_release(p2m->p2m_ukfs, UKFS_RELFLAG_FORCE); 499 ukfs_release(p2m->p2m_ukfs, UKFS_RELFLAG_FORCE);
493 free(p2m); 500 free(p2m);
494 errno = sverrno; 501 errno = sverrno;
495 } 502 }
496 503
497 return rv; 504 return rv;
498} 505}
499 506
500int 507int
501p2k_mainloop(struct p2k_mount *p2m) 508p2k_mainloop(struct p2k_mount *p2m)
502{ 509{
503 int rv, sverrno; 510 int rv, sverrno;
504 511
505 rv = puffs_mainloop(p2m->p2m_pu); 512 rv = puffs_mainloop(p2m->p2m_pu);
506 sverrno = errno; 513 sverrno = errno;
507 puffs_exit(p2m->p2m_pu, 1); 514 puffs_exit(p2m->p2m_pu, 1);
508 if (p2m->p2m_ukfs) 515 if (p2m->p2m_ukfs)
509 ukfs_release(p2m->p2m_ukfs, UKFS_RELFLAG_FORCE); 516 ukfs_release(p2m->p2m_ukfs, UKFS_RELFLAG_FORCE);
510 free(p2m); 517 free(p2m);
511 518
512 if (rv == -1) 519 if (rv == -1)
513 errno = sverrno; 520 errno = sverrno;
514 return rv; 521 return rv;
515} 522}
516 523
517int 524int
518p2k_run_fs(const char *vfsname, const char *devpath, const char *mountpath, 525p2k_run_fs(const char *vfsname, const char *devpath, const char *mountpath,
519 int mntflags, void *arg, size_t alen, uint32_t puffs_flags) 526 int mntflags, void *arg, size_t alen, uint32_t puffs_flags)
520{ 527{
521 struct p2k_mount *p2m; 528 struct p2k_mount *p2m;
522 int rv; 529 int rv;
523 530
524 p2m = p2k_init(puffs_flags); 531 p2m = p2k_init(puffs_flags);
525 if (p2m == NULL) 532 if (p2m == NULL)
526 return -1; 533 return -1;
527 rv = setupfs(p2m, vfsname, devpath, ukfs_part_na, mountpath, 534 rv = setupfs(p2m, vfsname, devpath, ukfs_part_na, mountpath,
528 mntflags, arg, alen); 535 mntflags, arg, alen);
529 if (rv == -1) 536 if (rv == -1)
530 return rv; 537 return rv;
531 return p2k_mainloop(p2m); 538 return p2k_mainloop(p2m);
532} 539}
533 540
534int 541int
535p2k_run_diskfs(const char *vfsname, const char *devpath, struct ukfs_part *part, 542p2k_run_diskfs(const char *vfsname, const char *devpath, struct ukfs_part *part,
536 const char *mountpath, int mntflags, void *arg, size_t alen, 543 const char *mountpath, int mntflags, void *arg, size_t alen,
537 uint32_t puffs_flags) 544 uint32_t puffs_flags)
538{ 545{
539 struct p2k_mount *p2m; 546 struct p2k_mount *p2m;
540 int rv; 547 int rv;
541 548
542 p2m = p2k_init(puffs_flags); 549 p2m = p2k_init(puffs_flags);
543 if (p2m == NULL) 550 if (p2m == NULL)
544 return -1; 551 return -1;
545 rv = setupfs(p2m, vfsname, devpath, part, mountpath, mntflags, 552 rv = setupfs(p2m, vfsname, devpath, part, mountpath, mntflags,
546 arg, alen); 553 arg, alen);
547 if (rv == -1) 554 if (rv == -1)
548 return rv; 555 return rv;
549 return p2k_mainloop(p2m); 556 return p2k_mainloop(p2m);
550} 557}
551 558
552int 559int
553p2k_setup_fs(struct p2k_mount *p2m, const char *vfsname, const char *devpath, 560p2k_setup_fs(struct p2k_mount *p2m, const char *vfsname, const char *devpath,
554 const char *mountpath, int mntflags, void *arg, size_t alen) 561 const char *mountpath, int mntflags, void *arg, size_t alen)
555{ 562{
556 563
557 return setupfs(p2m, vfsname, devpath, ukfs_part_na, mountpath, 564 return setupfs(p2m, vfsname, devpath, ukfs_part_na, mountpath,
558 mntflags, arg, alen); 565 mntflags, arg, alen);
559} 566}
560 567
561int 568int
562p2k_setup_diskfs(struct p2k_mount *p2m, const char *vfsname, 569p2k_setup_diskfs(struct p2k_mount *p2m, const char *vfsname,
563 const char *devpath, struct ukfs_part *part, const char *mountpath, 570 const char *devpath, struct ukfs_part *part, const char *mountpath,
564 int mntflags, void *arg, size_t alen) 571 int mntflags, void *arg, size_t alen)
565{ 572{
566 573
567 return setupfs(p2m, vfsname, devpath, part, mountpath, mntflags, 574 return setupfs(p2m, vfsname, devpath, part, mountpath, mntflags,
568 arg, alen); 575 arg, alen);
569} 576}
570 577
571int 578int
572p2k_fs_statvfs(struct puffs_usermount *pu, struct statvfs *sbp) 579p2k_fs_statvfs(struct puffs_usermount *pu, struct statvfs *sbp)
573{ 580{
574 struct p2k_mount *p2m = puffs_getspecific(pu); 581 struct p2k_mount *p2m = puffs_getspecific(pu);
575 struct mount *mp = p2m->p2m_mp; 582 struct mount *mp = p2m->p2m_mp;
576 583
577 return rump_pub_vfs_statvfs(mp, sbp); 584 return rump_pub_vfs_statvfs(mp, sbp);
578} 585}
579 586
580/*ARGSUSED*/ 587/*ARGSUSED*/
581int 588int
582p2k_fs_unmount(struct puffs_usermount *pu, int flags) 589p2k_fs_unmount(struct puffs_usermount *pu, int flags)
583{ 590{
584 struct p2k_mount *p2m = puffs_getspecific(pu); 591 struct p2k_mount *p2m = puffs_getspecific(pu);
585 struct ukfs *fs = p2m->p2m_ukfs; 592 struct ukfs *fs = p2m->p2m_ukfs;
586 int error = 0; 593 int error = 0;
587 594
588 rump_pub_vp_rele(p2m->p2m_rvp); 595 rump_pub_vp_rele(p2m->p2m_rvp);
589 596
590 if (fs) { 597 if (fs) {
591 if (ukfs_release(fs, 0) != 0) { 598 if (ukfs_release(fs, 0) != 0) {
592 struct statvfs svfsb; 599 struct statvfs svfsb;
593 600
594 if (p2m->p2m_hasdebug 601 if (p2m->p2m_hasdebug
595 && p2k_fs_statvfs(pu, &svfsb) == 0) { 602 && p2k_fs_statvfs(pu, &svfsb) == 0) {
596 printf("\nSOFT UNMOUNT FAILED, MP INFO DUMP\n"); 603 printf("\nSOFT UNMOUNT FAILED, MP INFO DUMP\n");
597 rump_pub_vfs_mount_print(svfsb.f_mntonname, 1); 604 rump_pub_vfs_mount_print(svfsb.f_mntonname, 1);
598 } 605 }
599 ukfs_release(fs, UKFS_RELFLAG_FORCE); 606 ukfs_release(fs, UKFS_RELFLAG_FORCE);
600 error = 0; 607 error = 0;
601 } 608 }
602 } 609 }
603 p2m->p2m_ukfs = NULL; 610 p2m->p2m_ukfs = NULL;
604 611
605 if (p2m->p2m_hasdebug) { 612 if (p2m->p2m_hasdebug) {
606 printf("-- rump kernel event counters --\n"); 613 printf("-- rump kernel event counters --\n");
607 rump_printevcnts(); 614 rump_printevcnts();
608 printf("-- end of event counters --\n"); 615 printf("-- end of event counters --\n");
609 } 616 }
610 617
611 return error; 618 return error;
612} 619}
613 620
614int 621int
615p2k_fs_sync(struct puffs_usermount *pu, int waitfor, 622p2k_fs_sync(struct puffs_usermount *pu, int waitfor,
616 const struct puffs_cred *pcr) 623 const struct puffs_cred *pcr)
617{ 624{
618 struct p2k_mount *p2m = puffs_getspecific(pu); 625 struct p2k_mount *p2m = puffs_getspecific(pu);
619 struct mount *mp = p2m->p2m_mp; 626 struct mount *mp = p2m->p2m_mp;
620 struct kauth_cred *cred; 627 struct kauth_cred *cred;
621 int rv; 628 int rv;
622 629
623 cred = cred_create(pcr); 630 cred = cred_create(pcr);
624 rv = rump_pub_vfs_sync(mp, waitfor, cred); 631 rv = rump_pub_vfs_sync(mp, waitfor, cred);
625 cred_destroy(cred); 632 cred_destroy(cred);
626 633
627 return rv; 634 return rv;
628} 635}
629 636
630/*ARGSUSED*/ 637/*ARGSUSED*/
631int 638int
632p2k_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize, 639p2k_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize,
633 struct puffs_newinfo *pni) 640 struct puffs_newinfo *pni)
634{ 641{
635 struct p2k_mount *p2m = puffs_getspecific(pu); 642 struct p2k_mount *p2m = puffs_getspecific(pu);
636 struct mount *mp = p2m->p2m_mp; 643 struct mount *mp = p2m->p2m_mp;
637 struct p2k_node *p2n; 644 struct p2k_node *p2n;
638 struct vnode *vp; 645 struct vnode *vp;
639 enum vtype vtype; 646 enum vtype vtype;
640 voff_t vsize; 647 voff_t vsize;
641 uint64_t rdev; /* XXX: allows running this on NetBSD 5.0 */ 648 uint64_t rdev; /* XXX: allows running this on NetBSD 5.0 */
642 int rv; 649 int rv;
643 650
644 rv = rump_pub_vfs_fhtovp(mp, fid, &vp); 651 rv = rump_pub_vfs_fhtovp(mp, fid, &vp);
645 if (rv) 652 if (rv)
646 return rv; 653 return rv;
647 RUMP_VOP_UNLOCK(vp); 654 RUMP_VOP_UNLOCK(vp);
648 655
649 p2n = getp2n(p2m, vp, false, NULL); 656 p2n = getp2n(p2m, vp, false, NULL);
650 if (p2n == NULL) 657 if (p2n == NULL)
651 return ENOMEM; 658 return ENOMEM;
652 659
653 puffs_newinfo_setcookie(pni, p2n); 660 puffs_newinfo_setcookie(pni, p2n);
654 rump_pub_getvninfo(vp, &vtype, &vsize, (void *)&rdev); 661 rump_pub_getvninfo(vp, &vtype, &vsize, (void *)&rdev);
655 puffs_newinfo_setvtype(pni, vtype); 662 puffs_newinfo_setvtype(pni, vtype);
656 puffs_newinfo_setsize(pni, vsize); 663 puffs_newinfo_setsize(pni, vsize);
657 /* LINTED: yea, it'll lose accuracy, but that's life */ 664 /* LINTED: yea, it'll lose accuracy, but that's life */
658 puffs_newinfo_setrdev(pni, rdev); 665 puffs_newinfo_setrdev(pni, rdev);
659 666
660 return 0; 667 return 0;
661} 668}
662 669
663/*ARGSUSED*/ 670/*ARGSUSED*/
664int 671int
665p2k_fs_nodetofh(struct puffs_usermount *pu, puffs_cookie_t cookie, void *fid, 672p2k_fs_nodetofh(struct puffs_usermount *pu, puffs_cookie_t cookie, void *fid,
666 size_t *fidsize) 673 size_t *fidsize)
667{ 674{
668 struct vnode *vp = OPC2VP(cookie); 675 struct vnode *vp = OPC2VP(cookie);
669 676
670 return rump_pub_vfs_vptofh(vp, fid, fidsize); 677 return rump_pub_vfs_vptofh(vp, fid, fidsize);
671} 678}
672 679
673int 680int
674p2k_fs_extattrctl(struct puffs_usermount *pu, int cmd, 681p2k_fs_extattrctl(struct puffs_usermount *pu, int cmd,
675 puffs_cookie_t cookie, int flags, 682 puffs_cookie_t cookie, int flags,
676 int attrnamespace, const char *attrname) 683 int attrnamespace, const char *attrname)
677{ 684{
678 struct p2k_mount *p2m = puffs_getspecific(pu); 685 struct p2k_mount *p2m = puffs_getspecific(pu);
679 struct mount *mp = p2m->p2m_mp; 686 struct mount *mp = p2m->p2m_mp;
680 struct vnode *vp; 687 struct vnode *vp;
681 688
682 if (flags & PUFFS_EXTATTRCTL_HASNODE) { 689 if (flags & PUFFS_EXTATTRCTL_HASNODE) {
683 vp = OPC2VP(cookie); 690 vp = OPC2VP(cookie);
684 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY); 691 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY);
685 } else { 692 } else {
686 vp = NULL; 693 vp = NULL;
687 } 694 }
688 695
689 /* vfsop unlocks (but doesn't release) vnode, so we're done here */ 696 /* vfsop unlocks (but doesn't release) vnode, so we're done here */
690 return rump_pub_vfs_extattrctl(mp, cmd, vp, attrnamespace, attrname); 697 return rump_pub_vfs_extattrctl(mp, cmd, vp, attrnamespace, attrname);
691} 698}
692 699
693/*ARGSUSED*/ 700/*ARGSUSED*/
694int 701int
695p2k_node_lookup(struct puffs_usermount *pu, puffs_cookie_t opc, 702p2k_node_lookup(struct puffs_usermount *pu, puffs_cookie_t opc,
696 struct puffs_newinfo *pni, const struct puffs_cn *pcn) 703 struct puffs_newinfo *pni, const struct puffs_cn *pcn)
697{ 704{
698 struct p2k_mount *p2m = puffs_getspecific(pu); 705 struct p2k_mount *p2m = puffs_getspecific(pu);
699 struct p2k_node *p2n_dir = opc, *p2n; 706 struct p2k_node *p2n_dir = opc, *p2n;
700 struct componentname *cn; 707 struct componentname *cn;
701 struct vnode *dvp = p2n_dir->p2n_vp, *vp; 708 struct vnode *dvp = p2n_dir->p2n_vp, *vp;
702 enum vtype vtype; 709 enum vtype vtype;
703 voff_t vsize; 710 voff_t vsize;
704 uint64_t rdev; /* XXX: uint64_t because of stack overwrite in compat */ 711 uint64_t rdev; /* XXX: uint64_t because of stack overwrite in compat */
705 int rv; 712 int rv;
706 713
707 cn = makecn(pcn); 714 cn = makecn(pcn);
708 RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE); 715 RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE);
709 rv = RUMP_VOP_LOOKUP(dvp, &vp, cn); 716 rv = RUMP_VOP_LOOKUP(dvp, &vp, cn);
710 RUMP_VOP_UNLOCK(dvp); 717 RUMP_VOP_UNLOCK(dvp);
711 freecn(cn); 718 freecn(cn);
712 719
713 if (rv) { 720 if (rv) {
714 if (rv == EJUSTRETURN) { 721 if (rv == EJUSTRETURN) {
715 rv = ENOENT; 722 rv = ENOENT;
716 } 723 }
717 return rv; 724 return rv;
718 } 725 }
719 RUMP_VOP_UNLOCK(vp); 726 RUMP_VOP_UNLOCK(vp);
720 727
721 p2n = getp2n(p2m, vp, false, NULL); 728 p2n = getp2n(p2m, vp, false, NULL);
722 if (p2n == NULL) { 729 if (p2n == NULL) {
723 return ENOMEM; 730 return ENOMEM;
724 } 731 }
725 732
726 puffs_newinfo_setcookie(pni, p2n); 733 puffs_newinfo_setcookie(pni, p2n);
727 rump_pub_getvninfo(vp, &vtype, &vsize, (void *)&rdev); 734 rump_pub_getvninfo(vp, &vtype, &vsize, (void *)&rdev);
728 puffs_newinfo_setvtype(pni, vtype); 735 puffs_newinfo_setvtype(pni, vtype);
729 puffs_newinfo_setsize(pni, vsize); 736 puffs_newinfo_setsize(pni, vsize);
730 /* LINTED: yea, it'll lose accuracy, but that's life */ 737 /* LINTED: yea, it'll lose accuracy, but that's life */
731 puffs_newinfo_setrdev(pni, rdev); 738 puffs_newinfo_setrdev(pni, rdev);
732 739
733 return 0; 740 return 0;
734} 741}
735 742
736#define VERS_TIMECHANGE 599000700 743#define VERS_TIMECHANGE 599000700
737static int 744static int
738needcompat(void) 745needcompat(void)
739{ 746{
740 747
741 /*LINTED*/ 748 /*LINTED*/
742 return __NetBSD_Version__ < VERS_TIMECHANGE 749 return __NetBSD_Version__ < VERS_TIMECHANGE
743 && rump_pub_getversion() >= VERS_TIMECHANGE; 750 && rump_pub_getversion() >= VERS_TIMECHANGE;
744} 751}
745 752
746#define DOCOMPAT(va, va_compat) \ 753#define DOCOMPAT(va, va_compat) \
747do { \ 754do { \
748 if (needcompat()) { \ 755 if (needcompat()) { \
749 va_compat = rump_pub_vattr_init(); \ 756 va_compat = rump_pub_vattr_init(); \
750 rump_pub_vattr50_to_vattr(va, va_compat); \ 757 rump_pub_vattr50_to_vattr(va, va_compat); \
751 } else { \ 758 } else { \
752 va_compat = __UNCONST(va); \ 759 va_compat = __UNCONST(va); \
753 } \ 760 } \
754} while (/*CONSTCOND*/0) 761} while (/*CONSTCOND*/0)
755 762
756#define UNDOCOMPAT(va_compat) \ 763#define UNDOCOMPAT(va_compat) \
757do { \ 764do { \
758 if (needcompat()) \ 765 if (needcompat()) \
759 rump_pub_vattr_free(va_compat); \ 766 rump_pub_vattr_free(va_compat); \
760} while (/*CONSTCOND*/0) 767} while (/*CONSTCOND*/0)
761 768
762static int 769static int
763do_makenode(struct puffs_usermount *pu, struct p2k_node *p2n_dir, 770do_makenode(struct puffs_usermount *pu, struct p2k_node *p2n_dir,
764 struct puffs_newinfo *pni, const struct puffs_cn *pcn, 771 struct puffs_newinfo *pni, const struct puffs_cn *pcn,
765 const struct vattr *vap, char *link_target, 772 const struct vattr *vap, char *link_target,
766 int (*makefn)(struct vnode *, struct vnode **, struct componentname *, 773 int (*makefn)(struct vnode *, struct vnode **, struct componentname *,
767 struct vattr *), 774 struct vattr *),
768 int (*symfn)(struct vnode *, struct vnode **, struct componentname *, 775 int (*symfn)(struct vnode *, struct vnode **, struct componentname *,
769 struct vattr *, char *)) 776 struct vattr *, char *))
770{ 777{
771 struct p2k_mount *p2m = puffs_getspecific(pu); 778 struct p2k_mount *p2m = puffs_getspecific(pu);
772 struct vnode *dvp = p2n_dir->p2n_vp; 779 struct vnode *dvp = p2n_dir->p2n_vp;
773 struct p2k_node *p2n; 780 struct p2k_node *p2n;
774 struct componentname *cn; 781 struct componentname *cn;
775 struct vattr *va_x; 782 struct vattr *va_x;
776 struct vnode *vp; 783 struct vnode *vp;
777 int rv; 784 int rv;
778 785
779 p2n = malloc(sizeof(*p2n)); 786 p2n = malloc(sizeof(*p2n));
780 if (p2n == NULL) 787 if (p2n == NULL)
781 return ENOMEM; 788 return ENOMEM;
782 DOCOMPAT(vap, va_x); 789 DOCOMPAT(vap, va_x);
783 790
784 cn = makecn(pcn); 791 cn = makecn(pcn);
785 RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE); 792 RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE);
786 rump_pub_vp_incref(dvp); 793 rump_pub_vp_incref(dvp);
787 if (makefn) { 794 if (makefn) {
788 rv = makefn(dvp, &vp, cn, va_x); 795 rv = makefn(dvp, &vp, cn, va_x);
789 } else { 796 } else {
790 rv = symfn(dvp, &vp, cn, va_x, link_target); 797 rv = symfn(dvp, &vp, cn, va_x, link_target);
791 } 798 }
792 assert(RUMP_VOP_ISLOCKED(dvp) == 0); 799 assert(RUMP_VOP_ISLOCKED(dvp) == 0);
793 freecn(cn); 800 freecn(cn);
794 801
795 if (rv == 0) { 802 if (rv == 0) {
796 RUMP_VOP_UNLOCK(vp); 803 RUMP_VOP_UNLOCK(vp);
797 p2n = getp2n(p2m, vp, true, p2n); 804 p2n = getp2n(p2m, vp, true, p2n);
798 puffs_newinfo_setcookie(pni, p2n); 805 puffs_newinfo_setcookie(pni, p2n);
799 } else { 806 } else {
800 free(p2n); 807 free(p2n);
801 } 808 }
802 809
803 UNDOCOMPAT(va_x); 810 UNDOCOMPAT(va_x);
804 811
805 return rv; 812 return rv;
806 813
807} 814}
808 815
809/*ARGSUSED*/ 816/*ARGSUSED*/
810int 817int
811p2k_node_create(struct puffs_usermount *pu, puffs_cookie_t opc, 818p2k_node_create(struct puffs_usermount *pu, puffs_cookie_t opc,
812 struct puffs_newinfo *pni, const struct puffs_cn *pcn, 819 struct puffs_newinfo *pni, const struct puffs_cn *pcn,
813 const struct vattr *vap) 820 const struct vattr *vap)
814{ 821{
815 822
816 return do_makenode(pu, opc, pni, pcn, vap, NULL, RUMP_VOP_CREATE, NULL); 823 return do_makenode(pu, opc, pni, pcn, vap, NULL, RUMP_VOP_CREATE, NULL);
817} 824}
818 825
819/*ARGSUSED*/ 826/*ARGSUSED*/
820int 827int
821p2k_node_mknod(struct puffs_usermount *pu, puffs_cookie_t opc, 828p2k_node_mknod(struct puffs_usermount *pu, puffs_cookie_t opc,
822 struct puffs_newinfo *pni, const struct puffs_cn *pcn, 829 struct puffs_newinfo *pni, const struct puffs_cn *pcn,
823 const struct vattr *vap) 830 const struct vattr *vap)
824{ 831{
825 832
826 return do_makenode(pu, opc, pni, pcn, vap, NULL, RUMP_VOP_MKNOD, NULL); 833 return do_makenode(pu, opc, pni, pcn, vap, NULL, RUMP_VOP_MKNOD, NULL);
827} 834}
828 835
829/*ARGSUSED*/ 836/*ARGSUSED*/
830int 837int
831p2k_node_open(struct puffs_usermount *pu, puffs_cookie_t opc, int mode, 838p2k_node_open(struct puffs_usermount *pu, puffs_cookie_t opc, int mode,
832 const struct puffs_cred *pcr) 839 const struct puffs_cred *pcr)
833{ 840{
834 struct vnode *vp = OPC2VP(opc); 841 struct vnode *vp = OPC2VP(opc);
835 struct kauth_cred *cred; 842 struct kauth_cred *cred;
836 int rv; 843 int rv;
837 844
838 cred = cred_create(pcr); 845 cred = cred_create(pcr);
839 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 846 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
840 rv = RUMP_VOP_OPEN(vp, mode, cred); 847 rv = RUMP_VOP_OPEN(vp, mode, cred);
841 RUMP_VOP_UNLOCK(vp); 848 RUMP_VOP_UNLOCK(vp);
842 cred_destroy(cred); 849 cred_destroy(cred);
843 850
844 return rv; 851 return rv;
845} 852}
846 853
847/*ARGSUSED*/ 854/*ARGSUSED*/
848int 855int
849p2k_node_close(struct puffs_usermount *pu, puffs_cookie_t opc, int flags, 856p2k_node_close(struct puffs_usermount *pu, puffs_cookie_t opc, int flags,
850 const struct puffs_cred *pcr) 857 const struct puffs_cred *pcr)
851{ 858{
852 struct vnode *vp = OPC2VP(opc); 859 struct vnode *vp = OPC2VP(opc);
853 struct kauth_cred *cred; 860 struct kauth_cred *cred;
854 861
855 cred = cred_create(pcr); 862 cred = cred_create(pcr);
856 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 863 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
857 RUMP_VOP_CLOSE(vp, flags, cred); 864 RUMP_VOP_CLOSE(vp, flags, cred);
858 RUMP_VOP_UNLOCK(vp); 865 RUMP_VOP_UNLOCK(vp);
859 cred_destroy(cred); 866 cred_destroy(cred);
860 867
861 return 0; 868 return 0;
862} 869}
863 870
864/*ARGSUSED*/ 871/*ARGSUSED*/
865int 872int
866p2k_node_access(struct puffs_usermount *pu, puffs_cookie_t opc, int mode, 873p2k_node_access(struct puffs_usermount *pu, puffs_cookie_t opc, int mode,
867 const struct puffs_cred *pcr) 874 const struct puffs_cred *pcr)
868{ 875{
869 struct vnode *vp = OPC2VP(opc); 876 struct vnode *vp = OPC2VP(opc);
870 struct kauth_cred *cred; 877 struct kauth_cred *cred;
871 int rv; 878 int rv;
872 879
873 cred = cred_create(pcr); 880 cred = cred_create(pcr);
874 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 881 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
875 rv = RUMP_VOP_ACCESS(vp, mode, cred); 882 rv = RUMP_VOP_ACCESS(vp, mode, cred);
876 RUMP_VOP_UNLOCK(vp); 883 RUMP_VOP_UNLOCK(vp);
877 cred_destroy(cred); 884 cred_destroy(cred);
878 885
879 return rv; 886 return rv;
880} 887}
881 888
882/*ARGSUSED*/ 889/*ARGSUSED*/
883int 890int
884p2k_node_getattr(struct puffs_usermount *pu, puffs_cookie_t opc, 891p2k_node_getattr(struct puffs_usermount *pu, puffs_cookie_t opc,
885 struct vattr *vap, const struct puffs_cred *pcr) 892 struct vattr *vap, const struct puffs_cred *pcr)
886{ 893{
887 struct vnode *vp = OPC2VP(opc); 894 struct vnode *vp = OPC2VP(opc);
888 struct kauth_cred *cred; 895 struct kauth_cred *cred;
889 struct vattr *va_x; 896 struct vattr *va_x;
890 int rv; 897 int rv;
891 898
892 /* "deadfs" */ 899 /* "deadfs" */
893 if (!vp) 900 if (!vp)
894 return 0; 901 return 0;
895 902
896 if (needcompat()) { 903 if (needcompat()) {
897 va_x = rump_pub_vattr_init(); 904 va_x = rump_pub_vattr_init();
898 } else { 905 } else {
899 va_x = vap; 906 va_x = vap;
900 } 907 }
901 908
902 cred = cred_create(pcr); 909 cred = cred_create(pcr);
903 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 910 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
904 rv = RUMP_VOP_GETATTR(vp, va_x, cred); 911 rv = RUMP_VOP_GETATTR(vp, va_x, cred);
905 RUMP_VOP_UNLOCK(vp); 912 RUMP_VOP_UNLOCK(vp);
906 cred_destroy(cred); 913 cred_destroy(cred);
907 914
908 if (needcompat()) { 915 if (needcompat()) {
909 rump_pub_vattr_to_vattr50(va_x, vap); 916 rump_pub_vattr_to_vattr50(va_x, vap);
910 rump_pub_vattr_free(va_x); 917 rump_pub_vattr_free(va_x);
911 } 918 }
912 919
913 return rv; 920 return rv;
914} 921}
915 922
916/*ARGSUSED*/ 923/*ARGSUSED*/
917int 924int
918p2k_node_setattr(struct puffs_usermount *pu, puffs_cookie_t opc, 925p2k_node_setattr(struct puffs_usermount *pu, puffs_cookie_t opc,
919 const struct vattr *vap, const struct puffs_cred *pcr) 926 const struct vattr *vap, const struct puffs_cred *pcr)
920{ 927{
921 struct vnode *vp = OPC2VP(opc); 928 struct vnode *vp = OPC2VP(opc);
922 struct kauth_cred *cred; 929 struct kauth_cred *cred;
923 struct vattr *va_x; 930 struct vattr *va_x;
924 int rv; 931 int rv;
925 932
926 /* "deadfs" */ 933 /* "deadfs" */
927 if (!vp) 934 if (!vp)
928 return 0; 935 return 0;
929 936
930 DOCOMPAT(vap, va_x); 937 DOCOMPAT(vap, va_x);
931 938
932 cred = cred_create(pcr); 939 cred = cred_create(pcr);
933 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 940 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
934 rv = RUMP_VOP_SETATTR(vp, va_x, cred); 941 rv = RUMP_VOP_SETATTR(vp, va_x, cred);
935 RUMP_VOP_UNLOCK(vp); 942 RUMP_VOP_UNLOCK(vp);
936 cred_destroy(cred); 943 cred_destroy(cred);
937 944
938 UNDOCOMPAT(va_x); 945 UNDOCOMPAT(va_x);
939 946
940 return rv; 947 return rv;
941} 948}
942 949
943/*ARGSUSED*/ 950/*ARGSUSED*/
944int 951int
945p2k_node_fsync(struct puffs_usermount *pu, puffs_cookie_t opc, 952p2k_node_fsync(struct puffs_usermount *pu, puffs_cookie_t opc,
946 const struct puffs_cred *pcr, int flags, off_t offlo, off_t offhi) 953 const struct puffs_cred *pcr, int flags, off_t offlo, off_t offhi)
947{ 954{
948 struct vnode *vp = OPC2VP(opc); 955 struct vnode *vp = OPC2VP(opc);
949 struct kauth_cred *cred; 956 struct kauth_cred *cred;
950 int rv; 957 int rv;
951 958
952 /* "deadfs" */ 959 /* "deadfs" */
953 if (!vp) 960 if (!vp)
954 return 0; 961 return 0;
955 962
956 cred = cred_create(pcr); 963 cred = cred_create(pcr);
957 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 964 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
958 rv = RUMP_VOP_FSYNC(vp, cred, flags, offlo, offhi); 965 rv = RUMP_VOP_FSYNC(vp, cred, flags, offlo, offhi);
959 RUMP_VOP_UNLOCK(vp); 966 RUMP_VOP_UNLOCK(vp);
960 cred_destroy(cred); 967 cred_destroy(cred);
961 968
962 return rv; 969 return rv;
963} 970}
964 971
965/*ARGSUSED*/ 972/*ARGSUSED*/
966int 973int
967p2k_node_mmap(struct puffs_usermount *pu, puffs_cookie_t opc, vm_prot_t flags, 974p2k_node_mmap(struct puffs_usermount *pu, puffs_cookie_t opc, vm_prot_t flags,
968 const struct puffs_cred *pcr) 975 const struct puffs_cred *pcr)
969{ 976{
970 struct kauth_cred *cred; 977 struct kauth_cred *cred;
971 int rv; 978 int rv;
972 979
973 cred = cred_create(pcr); 980 cred = cred_create(pcr);
974 rv = RUMP_VOP_MMAP(OPC2VP(opc), flags, cred); 981 rv = RUMP_VOP_MMAP(OPC2VP(opc), flags, cred);
975 cred_destroy(cred); 982 cred_destroy(cred);
976 983
977 return rv; 984 return rv;
978} 985}
979 986
980/*ARGSUSED*/ 987/*ARGSUSED*/
981int 988int
982p2k_node_seek(struct puffs_usermount *pu, puffs_cookie_t opc, 989p2k_node_seek(struct puffs_usermount *pu, puffs_cookie_t opc,
983 off_t oldoff, off_t newoff, const struct puffs_cred *pcr) 990 off_t oldoff, off_t newoff, const struct puffs_cred *pcr)
984{ 991{
985 struct vnode *vp = OPC2VP(opc); 992 struct vnode *vp = OPC2VP(opc);
986 struct kauth_cred *cred; 993 struct kauth_cred *cred;
987 int rv; 994 int rv;
988 995
989 cred = cred_create(pcr); 996 cred = cred_create(pcr);
990 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 997 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
991 rv = RUMP_VOP_SEEK(vp, oldoff, newoff, cred); 998 rv = RUMP_VOP_SEEK(vp, oldoff, newoff, cred);
992 RUMP_VOP_UNLOCK(vp); 999 RUMP_VOP_UNLOCK(vp);
993 cred_destroy(cred); 1000 cred_destroy(cred);
994 1001
995 return rv; 1002 return rv;
996} 1003}
997 1004
998static int 1005static int
999do_nukenode(struct p2k_node *p2n_dir, struct p2k_node *p2n, 1006do_nukenode(struct p2k_node *p2n_dir, struct p2k_node *p2n,
1000 const struct puffs_cn *pcn, 1007 const struct puffs_cn *pcn,
1001 int (*nukefn)(struct vnode *, struct vnode *, struct componentname *)) 1008 int (*nukefn)(struct vnode *, struct vnode *, struct componentname *))
1002{ 1009{
1003 struct vnode *dvp = p2n_dir->p2n_vp, *vp = p2n->p2n_vp; 1010 struct vnode *dvp = p2n_dir->p2n_vp, *vp = p2n->p2n_vp;
1004 struct componentname *cn; 1011 struct componentname *cn;
1005 int rv; 1012 int rv;
1006 1013
1007 cn = makecn(pcn); 1014 cn = makecn(pcn);
1008 RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE); 1015 RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE);
1009 rump_pub_vp_incref(dvp); 1016 rump_pub_vp_incref(dvp);
1010 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 1017 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
1011 rump_pub_vp_incref(vp); 1018 rump_pub_vp_incref(vp);
1012 rv = nukefn(dvp, vp, cn); 1019 rv = nukefn(dvp, vp, cn);
1013 assert(RUMP_VOP_ISLOCKED(dvp) == 0); 1020 assert(RUMP_VOP_ISLOCKED(dvp) == 0);
1014 assert(RUMP_VOP_ISLOCKED(vp) == 0); 1021 assert(RUMP_VOP_ISLOCKED(vp) == 0);
1015 freecn(cn); 1022 freecn(cn);
1016 1023
1017 return rv; 1024 return rv;
1018 1025
1019} 1026}
1020 1027
1021/*ARGSUSED*/ 1028/*ARGSUSED*/
1022int 1029int
1023p2k_node_remove(struct puffs_usermount *pu, puffs_cookie_t opc, 1030p2k_node_remove(struct puffs_usermount *pu, puffs_cookie_t opc,
1024 puffs_cookie_t targ, const struct puffs_cn *pcn) 1031 puffs_cookie_t targ, const struct puffs_cn *pcn)
1025{ 1032{
1026 1033
1027 return do_nukenode(opc, targ, pcn, RUMP_VOP_REMOVE); 1034 return do_nukenode(opc, targ, pcn, RUMP_VOP_REMOVE);
1028} 1035}
1029 1036
1030/*ARGSUSED*/ 1037/*ARGSUSED*/
1031int 1038int
1032p2k_node_link(struct puffs_usermount *pu, puffs_cookie_t opc, 1039p2k_node_link(struct puffs_usermount *pu, puffs_cookie_t opc,
1033 puffs_cookie_t targ, const struct puffs_cn *pcn) 1040 puffs_cookie_t targ, const struct puffs_cn *pcn)
1034{ 1041{
1035 struct vnode *dvp = OPC2VP(opc); 1042 struct vnode *dvp = OPC2VP(opc);
1036 struct componentname *cn; 1043 struct componentname *cn;
1037 int rv; 1044 int rv;
1038 1045
1039 cn = makecn(pcn); 1046 cn = makecn(pcn);
1040 RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE); 1047 RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE);
1041 rump_pub_vp_incref(dvp); 1048 rump_pub_vp_incref(dvp);
1042 rv = RUMP_VOP_LINK(dvp, OPC2VP(targ), cn); 1049 rv = RUMP_VOP_LINK(dvp, OPC2VP(targ), cn);
1043 freecn(cn); 1050 freecn(cn);
1044 1051
1045 return rv; 1052 return rv;
1046} 1053}
1047 1054
1048/*ARGSUSED*/ 1055/*ARGSUSED*/
1049int 1056int
1050p2k_node_rename(struct puffs_usermount *pu, 1057p2k_node_rename(struct puffs_usermount *pu,
1051 puffs_cookie_t src_dir, puffs_cookie_t src, 1058 puffs_cookie_t src_dir, puffs_cookie_t src,
1052 const struct puffs_cn *pcn_src, 1059 const struct puffs_cn *pcn_src,
1053 puffs_cookie_t targ_dir, puffs_cookie_t targ, 1060 puffs_cookie_t targ_dir, puffs_cookie_t targ,
1054 const struct puffs_cn *pcn_targ) 1061 const struct puffs_cn *pcn_targ)
1055{ 1062{
1056 struct vnode *dvp, *vp, *tdvp, *tvp = NULL; 1063 struct vnode *dvp, *vp, *tdvp, *tvp = NULL;
1057 struct componentname *cn_src, *cn_targ; 1064 struct componentname *cn_src, *cn_targ;
1058 int rv; 1065 int rv;
1059 1066
1060 cn_src = makecn(pcn_src); 1067 cn_src = makecn(pcn_src);
1061 cn_targ = makecn(pcn_targ); 1068 cn_targ = makecn(pcn_targ);
1062 1069
1063 dvp = OPC2VP(src_dir); 1070 dvp = OPC2VP(src_dir);
1064 vp = OPC2VP(src); 1071 vp = OPC2VP(src);
1065 tdvp = OPC2VP(targ_dir); 1072 tdvp = OPC2VP(targ_dir);
1066 if (targ) { 1073 if (targ) {
1067 tvp = OPC2VP(targ); 1074 tvp = OPC2VP(targ);
1068 } 1075 }
1069 1076
1070 rump_pub_vp_incref(dvp); 1077 rump_pub_vp_incref(dvp);
1071 rump_pub_vp_incref(vp); 1078 rump_pub_vp_incref(vp);
1072 RUMP_VOP_LOCK(tdvp, LK_EXCLUSIVE); 1079 RUMP_VOP_LOCK(tdvp, LK_EXCLUSIVE);
1073 rump_pub_vp_incref(tdvp); 1080 rump_pub_vp_incref(tdvp);
1074 if (tvp) { 1081 if (tvp) {
1075 RUMP_VOP_LOCK(tvp, LK_EXCLUSIVE); 1082 RUMP_VOP_LOCK(tvp, LK_EXCLUSIVE);
1076 rump_pub_vp_incref(tvp); 1083 rump_pub_vp_incref(tvp);
1077 } 1084 }
1078 rv = RUMP_VOP_RENAME(dvp, vp, cn_src, tdvp, tvp, cn_targ); 1085 rv = RUMP_VOP_RENAME(dvp, vp, cn_src, tdvp, tvp, cn_targ);
1079 assert(RUMP_VOP_ISLOCKED(tdvp) == 0); 1086 assert(RUMP_VOP_ISLOCKED(tdvp) == 0);
1080 if (tvp) { 1087 if (tvp) {
1081 assert(RUMP_VOP_ISLOCKED(tvp) == 0); 1088 assert(RUMP_VOP_ISLOCKED(tvp) == 0);
1082 } 1089 }
1083 freecn(cn_src); 1090 freecn(cn_src);
1084 freecn(cn_targ); 1091 freecn(cn_targ);
1085 1092
1086 return rv; 1093 return rv;
1087} 1094}
1088 1095
1089/*ARGSUSED*/ 1096/*ARGSUSED*/
1090int 1097int
1091p2k_node_mkdir(struct puffs_usermount *pu, puffs_cookie_t opc, 1098p2k_node_mkdir(struct puffs_usermount *pu, puffs_cookie_t opc,
1092 struct puffs_newinfo *pni, const struct puffs_cn *pcn, 1099 struct puffs_newinfo *pni, const struct puffs_cn *pcn,
1093 const struct vattr *vap) 1100 const struct vattr *vap)
1094{ 1101{
1095 1102
1096 return do_makenode(pu, opc, pni, pcn, vap, NULL, RUMP_VOP_MKDIR, NULL); 1103 return do_makenode(pu, opc, pni, pcn, vap, NULL, RUMP_VOP_MKDIR, NULL);
1097} 1104}
1098 1105
1099/*ARGSUSED*/ 1106/*ARGSUSED*/
1100int 1107int
1101p2k_node_rmdir(struct puffs_usermount *pu, puffs_cookie_t opc, 1108p2k_node_rmdir(struct puffs_usermount *pu, puffs_cookie_t opc,
1102 puffs_cookie_t targ, const struct puffs_cn *pcn) 1109 puffs_cookie_t targ, const struct puffs_cn *pcn)
1103{ 1110{
1104 1111
1105 return do_nukenode(opc, targ, pcn, RUMP_VOP_RMDIR); 1112 return do_nukenode(opc, targ, pcn, RUMP_VOP_RMDIR);
1106} 1113}
1107 1114
1108/*ARGSUSED*/ 1115/*ARGSUSED*/
1109int 1116int
1110p2k_node_symlink(struct puffs_usermount *pu, puffs_cookie_t opc, 1117p2k_node_symlink(struct puffs_usermount *pu, puffs_cookie_t opc,
1111 struct puffs_newinfo *pni, const struct puffs_cn *pcn, 1118 struct puffs_newinfo *pni, const struct puffs_cn *pcn,
1112 const struct vattr *vap, const char *link_target) 1119 const struct vattr *vap, const char *link_target)
1113{ 1120{
1114 1121
1115 return do_makenode(pu, opc, pni, pcn, vap, 1122 return do_makenode(pu, opc, pni, pcn, vap,
1116 __UNCONST(link_target), NULL, RUMP_VOP_SYMLINK); 1123 __UNCONST(link_target), NULL, RUMP_VOP_SYMLINK);
1117} 1124}
1118 1125
1119/*ARGSUSED*/ 1126/*ARGSUSED*/
1120int 1127int
1121p2k_node_readdir(struct puffs_usermount *pu, puffs_cookie_t opc, 1128p2k_node_readdir(struct puffs_usermount *pu, puffs_cookie_t opc,
1122 struct dirent *dent, off_t *readoff, size_t *reslen, 1129 struct dirent *dent, off_t *readoff, size_t *reslen,
1123 const struct puffs_cred *pcr, int *eofflag, 1130 const struct puffs_cred *pcr, int *eofflag,
1124 off_t *cookies, size_t *ncookies) 1131 off_t *cookies, size_t *ncookies)
1125{ 1132{
1126 struct vnode *vp = OPC2VP(opc); 1133 struct vnode *vp = OPC2VP(opc);
1127 struct kauth_cred *cred; 1134 struct kauth_cred *cred;
1128 struct uio *uio; 1135 struct uio *uio;
1129 off_t *vop_cookies; 1136 off_t *vop_cookies;
1130 int vop_ncookies; 1137 int vop_ncookies;
1131 int rv; 1138 int rv;
1132 1139
1133 cred = cred_create(pcr); 1140 cred = cred_create(pcr);
1134 uio = rump_pub_uio_setup(dent, *reslen, *readoff, RUMPUIO_READ); 1141 uio = rump_pub_uio_setup(dent, *reslen, *readoff, RUMPUIO_READ);
1135 RUMP_VOP_LOCK(vp, LK_SHARED); 1142 RUMP_VOP_LOCK(vp, LK_SHARED);
1136 if (cookies) { 1143 if (cookies) {
1137 rv = RUMP_VOP_READDIR(vp, uio, cred, eofflag, 1144 rv = RUMP_VOP_READDIR(vp, uio, cred, eofflag,
1138 &vop_cookies, &vop_ncookies); 1145 &vop_cookies, &vop_ncookies);
1139 memcpy(cookies, vop_cookies, vop_ncookies * sizeof(*cookies)); 1146 memcpy(cookies, vop_cookies, vop_ncookies * sizeof(*cookies));
1140 *ncookies = vop_ncookies; 1147 *ncookies = vop_ncookies;
1141 free(vop_cookies); 1148 free(vop_cookies);
1142 } else { 1149 } else {
1143 rv = RUMP_VOP_READDIR(vp, uio, cred, eofflag, NULL, NULL); 1150 rv = RUMP_VOP_READDIR(vp, uio, cred, eofflag, NULL, NULL);
1144 } 1151 }
1145 RUMP_VOP_UNLOCK(vp); 1152 RUMP_VOP_UNLOCK(vp);
1146 if (rv == 0) { 1153 if (rv == 0) {
1147 *reslen = rump_pub_uio_getresid(uio); 1154 *reslen = rump_pub_uio_getresid(uio);
1148 *readoff = rump_pub_uio_getoff(uio); 1155 *readoff = rump_pub_uio_getoff(uio);
1149 } 1156 }
1150 rump_pub_uio_free(uio); 1157 rump_pub_uio_free(uio);
1151 cred_destroy(cred); 1158 cred_destroy(cred);
1152 1159
1153 return rv; 1160 return rv;
1154} 1161}
1155 1162
1156/*ARGSUSED*/ 1163/*ARGSUSED*/
1157int 1164int
1158p2k_node_readlink(struct puffs_usermount *pu, puffs_cookie_t opc, 1165p2k_node_readlink(struct puffs_usermount *pu, puffs_cookie_t opc,
1159 const struct puffs_cred *pcr, char *linkname, size_t *linklen) 1166 const struct puffs_cred *pcr, char *linkname, size_t *linklen)
1160{ 1167{
1161 struct vnode *vp = OPC2VP(opc); 1168 struct vnode *vp = OPC2VP(opc);
1162 struct kauth_cred *cred; 1169 struct kauth_cred *cred;
1163 struct uio *uio; 1170 struct uio *uio;
1164 int rv; 1171 int rv;
1165 1172
1166 cred = cred_create(pcr); 1173 cred = cred_create(pcr);
1167 uio = rump_pub_uio_setup(linkname, *linklen, 0, RUMPUIO_READ); 1174 uio = rump_pub_uio_setup(linkname, *linklen, 0, RUMPUIO_READ);
1168 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 1175 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
1169 rv = RUMP_VOP_READLINK(vp, uio, cred); 1176 rv = RUMP_VOP_READLINK(vp, uio, cred);
1170 RUMP_VOP_UNLOCK(vp); 1177 RUMP_VOP_UNLOCK(vp);
1171 *linklen -= rump_pub_uio_free(uio); 1178 *linklen -= rump_pub_uio_free(uio);
1172 cred_destroy(cred); 1179 cred_destroy(cred);
1173 1180
1174 return rv; 1181 return rv;
1175} 1182}
1176 1183
1177/*ARGSUSED*/ 1184/*ARGSUSED*/
1178int 1185int
1179p2k_node_read(struct puffs_usermount *pu, puffs_cookie_t opc, 1186p2k_node_read(struct puffs_usermount *pu, puffs_cookie_t opc,
1180 uint8_t *buf, off_t offset, size_t *resid, 1187 uint8_t *buf, off_t offset, size_t *resid,
1181 const struct puffs_cred *pcr, int ioflag) 1188 const struct puffs_cred *pcr, int ioflag)
1182{ 1189{
1183 struct vnode *vp = OPC2VP(opc); 1190 struct vnode *vp = OPC2VP(opc);
1184 struct kauth_cred *cred; 1191 struct kauth_cred *cred;
1185 struct uio *uio; 1192 struct uio *uio;
1186 int rv; 1193 int rv;
1187 1194
1188 cred = cred_create(pcr); 1195 cred = cred_create(pcr);
1189 uio = rump_pub_uio_setup(buf, *resid, offset, RUMPUIO_READ); 1196 uio = rump_pub_uio_setup(buf, *resid, offset, RUMPUIO_READ);
1190 RUMP_VOP_LOCK(vp, LK_SHARED); 1197 RUMP_VOP_LOCK(vp, LK_SHARED);
1191 rv = RUMP_VOP_READ(vp, uio, ioflag, cred); 1198 rv = RUMP_VOP_READ(vp, uio, ioflag, cred);
1192 RUMP_VOP_UNLOCK(vp); 1199 RUMP_VOP_UNLOCK(vp);
1193 *resid = rump_pub_uio_free(uio); 1200 *resid = rump_pub_uio_free(uio);
1194 cred_destroy(cred); 1201 cred_destroy(cred);
1195 1202
1196 return rv; 1203 return rv;
1197} 1204}
1198 1205
1199/*ARGSUSED*/ 1206/*ARGSUSED*/
1200int 1207int
1201p2k_node_write(struct puffs_usermount *pu, puffs_cookie_t opc, 1208p2k_node_write(struct puffs_usermount *pu, puffs_cookie_t opc,
1202 uint8_t *buf, off_t offset, size_t *resid, 1209 uint8_t *buf, off_t offset, size_t *resid,
1203 const struct puffs_cred *pcr, int ioflag) 1210 const struct puffs_cred *pcr, int ioflag)
1204{ 1211{
1205 struct vnode *vp = OPC2VP(opc); 1212 struct vnode *vp = OPC2VP(opc);
1206 struct kauth_cred *cred; 1213 struct kauth_cred *cred;
1207 struct uio *uio; 1214 struct uio *uio;
1208 int rv; 1215 int rv;
1209 1216
1210 /* "deadfs" */ 1217 /* "deadfs" */
1211 if (!vp) 1218 if (!vp)
1212 return 0; 1219 return 0;
1213 1220
1214 cred = cred_create(pcr); 1221 cred = cred_create(pcr);
1215 uio = rump_pub_uio_setup(buf, *resid, offset, RUMPUIO_WRITE); 1222 uio = rump_pub_uio_setup(buf, *resid, offset, RUMPUIO_WRITE);
1216 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 1223 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
1217 rv = RUMP_VOP_WRITE(vp, uio, ioflag, cred); 1224 rv = RUMP_VOP_WRITE(vp, uio, ioflag, cred);
1218 RUMP_VOP_UNLOCK(vp); 1225 RUMP_VOP_UNLOCK(vp);
1219 *resid = rump_pub_uio_free(uio); 1226 *resid = rump_pub_uio_free(uio);
1220 cred_destroy(cred); 1227 cred_destroy(cred);
1221 1228
1222 return rv; 1229 return rv;
1223} 1230}
1224 1231
1225/*ARGSUSED*/ 1232/*ARGSUSED*/
1226int 1233int
1227p2k_node_pathconf(struct puffs_usermount *pu, puffs_cookie_t opc, 1234p2k_node_pathconf(struct puffs_usermount *pu, puffs_cookie_t opc,
1228 int name, register_t *retval) 1235 int name, register_t *retval)
1229{ 1236{
1230 struct vnode *vp = OPC2VP(opc); 1237 struct vnode *vp = OPC2VP(opc);
1231 int rv; 1238 int rv;
1232 1239
1233 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 1240 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
1234 rv = RUMP_VOP_PATHCONF(vp, name, retval); 1241 rv = RUMP_VOP_PATHCONF(vp, name, retval);
1235 RUMP_VOP_UNLOCK(vp); 1242 RUMP_VOP_UNLOCK(vp);
1236 1243
1237 return rv; 1244 return rv;
1238} 1245}
1239 1246
1240/*ARGSUSED*/ 1247/*ARGSUSED*/
1241int 1248int
1242p2k_node_getextattr(struct puffs_usermount *pu, puffs_cookie_t opc, 1249p2k_node_getextattr(struct puffs_usermount *pu, puffs_cookie_t opc,
1243 int attrnamespace, const char *attrname, size_t *attrsize, 1250 int attrnamespace, const char *attrname, size_t *attrsize,
1244 uint8_t *attr, size_t *resid, const struct puffs_cred *pcr) 1251 uint8_t *attr, size_t *resid, const struct puffs_cred *pcr)
1245{ 1252{
1246 struct vnode *vp = OPC2VP(opc); 1253 struct vnode *vp = OPC2VP(opc);
1247 struct kauth_cred *cred; 1254 struct kauth_cred *cred;
1248 struct uio *uio; 1255 struct uio *uio;
1249 int rv; 1256 int rv;
1250 1257
1251 if (attr) 1258 if (attr)
1252 uio = rump_pub_uio_setup(attr, *resid, 0, RUMPUIO_READ); 1259 uio = rump_pub_uio_setup(attr, *resid, 0, RUMPUIO_READ);
1253 else 1260 else
1254 uio = NULL; 1261 uio = NULL;
1255 1262
1256 cred = cred_create(pcr); 1263 cred = cred_create(pcr);
1257 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 1264 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
1258 rv = RUMP_VOP_GETEXTATTR(vp, attrnamespace, attrname, uio, 1265 rv = RUMP_VOP_GETEXTATTR(vp, attrnamespace, attrname, uio,
1259 attrsize, cred); 1266 attrsize, cred);
1260 RUMP_VOP_UNLOCK(vp); 1267 RUMP_VOP_UNLOCK(vp);
1261 cred_destroy(cred); 1268 cred_destroy(cred);
1262 1269
1263 if (uio) 1270 if (uio)
1264 *resid = rump_pub_uio_free(uio); 1271 *resid = rump_pub_uio_free(uio);
1265 1272
1266 return rv; 1273 return rv;
1267} 1274}
1268 1275
1269/*ARGSUSED*/ 1276/*ARGSUSED*/
1270int 1277int
1271p2k_node_setextattr(struct puffs_usermount *pu, puffs_cookie_t opc, 1278p2k_node_setextattr(struct puffs_usermount *pu, puffs_cookie_t opc,
1272 int attrnamespace, const char *attrname, 1279 int attrnamespace, const char *attrname,
1273 uint8_t *attr, size_t *resid, const struct puffs_cred *pcr) 1280 uint8_t *attr, size_t *resid, const struct puffs_cred *pcr)
1274{ 1281{
1275 struct vnode *vp = OPC2VP(opc); 1282 struct vnode *vp = OPC2VP(opc);
1276 struct kauth_cred *cred; 1283 struct kauth_cred *cred;
1277 struct uio *uio; 1284 struct uio *uio;
1278 int rv; 1285 int rv;
1279 1286
1280 if (attr) 1287 if (attr)
1281 uio = rump_pub_uio_setup(attr, *resid, 0, RUMPUIO_READ); 1288 uio = rump_pub_uio_setup(attr, *resid, 0, RUMPUIO_READ);
1282 else 1289 else
1283 uio = NULL; 1290 uio = NULL;
1284 1291
1285 cred = cred_create(pcr); 1292 cred = cred_create(pcr);
1286 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 1293 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
1287 rv = RUMP_VOP_SETEXTATTR(vp, attrnamespace, attrname, uio, cred); 1294 rv = RUMP_VOP_SETEXTATTR(vp, attrnamespace, attrname, uio, cred);
1288 RUMP_VOP_UNLOCK(vp); 1295 RUMP_VOP_UNLOCK(vp);
1289 cred_destroy(cred); 1296 cred_destroy(cred);
1290 1297
1291 if (uio) 1298 if (uio)
1292 *resid = rump_pub_uio_free(uio); 1299 *resid = rump_pub_uio_free(uio);
1293 1300
1294 return rv; 1301 return rv;
1295} 1302}
1296 1303
1297/*ARGSUSED*/ 1304/*ARGSUSED*/
1298int 1305int
1299p2k_node_listextattr(struct puffs_usermount *pu, puffs_cookie_t opc, 1306p2k_node_listextattr(struct puffs_usermount *pu, puffs_cookie_t opc,
1300 int attrnamespace, size_t *attrsize, 1307 int attrnamespace, size_t *attrsize,
1301 uint8_t *attrs, size_t *resid, const struct puffs_cred *pcr) 1308 uint8_t *attrs, size_t *resid, const struct puffs_cred *pcr)
1302{ 1309{
1303 struct vnode *vp = OPC2VP(opc); 1310 struct vnode *vp = OPC2VP(opc);
1304 struct kauth_cred *cred; 1311 struct kauth_cred *cred;
1305 struct uio *uio; 1312 struct uio *uio;
1306 int rv; 1313 int rv;
1307 1314
1308 if (attrs) 1315 if (attrs)
1309 uio = rump_pub_uio_setup(attrs, *resid, 0, RUMPUIO_READ); 1316 uio = rump_pub_uio_setup(attrs, *resid, 0, RUMPUIO_READ);
1310 else 1317 else
1311 uio = NULL; 1318 uio = NULL;
1312 1319
1313 cred = cred_create(pcr); 1320 cred = cred_create(pcr);
1314 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 1321 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
1315 rv = RUMP_VOP_LISTEXTATTR(vp, attrnamespace, uio, attrsize, cred); 1322 rv = RUMP_VOP_LISTEXTATTR(vp, attrnamespace, uio, attrsize, cred);
1316 RUMP_VOP_UNLOCK(vp); 1323 RUMP_VOP_UNLOCK(vp);
1317 cred_destroy(cred); 1324 cred_destroy(cred);
1318 1325
1319 if (uio) 1326 if (uio)
1320 *resid = rump_pub_uio_free(uio); 1327 *resid = rump_pub_uio_free(uio);
1321 1328
1322 return rv; 1329 return rv;
1323} 1330}
1324 1331
1325/*ARGSUSED*/ 1332/*ARGSUSED*/
1326int 1333int
1327p2k_node_deleteextattr(struct puffs_usermount *pu, puffs_cookie_t opc, 1334p2k_node_deleteextattr(struct puffs_usermount *pu, puffs_cookie_t opc,
1328 int attrnamespace, const char *attrname, const struct puffs_cred *pcr) 1335 int attrnamespace, const char *attrname, const struct puffs_cred *pcr)
1329{ 1336{
1330 struct vnode *vp = OPC2VP(opc); 1337 struct vnode *vp = OPC2VP(opc);
1331 struct kauth_cred *cred; 1338 struct kauth_cred *cred;
1332 int rv; 1339 int rv;
1333 1340
1334 cred = cred_create(pcr); 1341 cred = cred_create(pcr);
1335 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 1342 RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
1336 rv = RUMP_VOP_DELETEEXTATTR(vp, attrnamespace, attrname, cred); 1343 rv = RUMP_VOP_DELETEEXTATTR(vp, attrnamespace, attrname, cred);
1337 RUMP_VOP_UNLOCK(vp); 1344 RUMP_VOP_UNLOCK(vp);
1338 cred_destroy(cred); 1345 cred_destroy(cred);
1339 1346
1340 return rv; 1347 return rv;
1341} 1348}
1342 1349
1343/* the kernel releases its last reference here */  1350/* the kernel releases its last reference here */
1344int 1351int
1345p2k_node_inactive(struct puffs_usermount *pu, puffs_cookie_t opc) 1352p2k_node_inactive(struct puffs_usermount *pu, puffs_cookie_t opc)
1346{ 1353{
1347 struct p2k_mount *p2m = puffs_getspecific(pu); 1354 struct p2k_mount *p2m = puffs_getspecific(pu);
1348 struct p2k_node *p2n = opc; 1355 struct p2k_node *p2n = opc;
1349 struct vnode *vp = OPC2VP(opc); 1356 struct vnode *vp = OPC2VP(opc);