| @@ -1,587 +1,604 @@ | | | @@ -1,587 +1,604 @@ |
1 | /* $NetBSD: rump_vfs.c,v 1.18 2009/05/01 11:01:34 pooka Exp $ */ | | 1 | /* $NetBSD: rump_vfs.c,v 1.19 2009/05/03 16:01:44 pooka Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2008 Antti Kantee. All Rights Reserved. | | 4 | * Copyright (c) 2008 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 | #include <sys/cdefs.h> | | 31 | #include <sys/cdefs.h> |
32 | __KERNEL_RCSID(0, "$NetBSD"); | | 32 | __KERNEL_RCSID(0, "$NetBSD"); |
33 | | | 33 | |
34 | #include <sys/param.h> | | 34 | #include <sys/param.h> |
35 | #include <sys/buf.h> | | 35 | #include <sys/buf.h> |
36 | #include <sys/conf.h> | | 36 | #include <sys/conf.h> |
37 | #include <sys/evcnt.h> | | 37 | #include <sys/evcnt.h> |
38 | #include <sys/filedesc.h> | | 38 | #include <sys/filedesc.h> |
39 | #include <sys/lockf.h> | | 39 | #include <sys/lockf.h> |
40 | #include <sys/kthread.h> | | 40 | #include <sys/kthread.h> |
41 | #include <sys/module.h> | | 41 | #include <sys/module.h> |
42 | #include <sys/namei.h> | | 42 | #include <sys/namei.h> |
43 | #include <sys/queue.h> | | 43 | #include <sys/queue.h> |
44 | #include <sys/vfs_syscalls.h> | | 44 | #include <sys/vfs_syscalls.h> |
45 | #include <sys/vnode.h> | | 45 | #include <sys/vnode.h> |
46 | #include <sys/wapbl.h> | | 46 | #include <sys/wapbl.h> |
47 | | | 47 | |
48 | #include <miscfs/specfs/specdev.h> | | 48 | #include <miscfs/specfs/specdev.h> |
49 | #include <miscfs/syncfs/syncfs.h> | | 49 | #include <miscfs/syncfs/syncfs.h> |
50 | | | 50 | |
51 | #include <rump/rump.h> | | 51 | #include <rump/rump.h> |
52 | #include <rump/rumpuser.h> | | 52 | #include <rump/rumpuser.h> |
53 | | | 53 | |
54 | #include "rump_private.h" | | 54 | #include "rump_private.h" |
55 | #include "rump_vfs_private.h" | | 55 | #include "rump_vfs_private.h" |
56 | | | 56 | |
57 | struct fakeblk { | | 57 | struct fakeblk { |
58 | char path[MAXPATHLEN]; | | 58 | char path[MAXPATHLEN]; |
59 | LIST_ENTRY(fakeblk) entries; | | 59 | LIST_ENTRY(fakeblk) entries; |
60 | }; | | 60 | }; |
61 | static LIST_HEAD(, fakeblk) fakeblks = LIST_HEAD_INITIALIZER(fakeblks); | | 61 | static LIST_HEAD(, fakeblk) fakeblks = LIST_HEAD_INITIALIZER(fakeblks); |
62 | | | 62 | |
63 | static struct cwdinfo rump_cwdi; | | 63 | static struct cwdinfo rump_cwdi; |
64 | | | 64 | |
65 | static void rump_rcvp_lwpset(struct vnode *, struct vnode *, struct lwp *); | | 65 | static void rump_rcvp_lwpset(struct vnode *, struct vnode *, struct lwp *); |
66 | | | 66 | |
67 | static void | | 67 | static void |
68 | pvfs_init(struct proc *p) | | 68 | pvfs_init(struct proc *p) |
69 | { | | 69 | { |
70 | | | 70 | |
71 | p->p_cwdi = cwdinit(); | | 71 | p->p_cwdi = cwdinit(); |
72 | } | | 72 | } |
73 | | | 73 | |
74 | static void | | 74 | static void |
75 | pvfs_rele(struct proc *p) | | 75 | pvfs_rele(struct proc *p) |
76 | { | | 76 | { |
77 | | | 77 | |
78 | cwdfree(p->p_cwdi); | | 78 | cwdfree(p->p_cwdi); |
79 | } | | 79 | } |
80 | | | 80 | |
81 | void | | 81 | void |
82 | rump_vfs_init(void) | | 82 | rump_vfs_init(void) |
83 | { | | 83 | { |
84 | char buf[64]; | | 84 | char buf[64]; |
85 | int error; | | 85 | int error; |
86 | | | 86 | |
87 | dovfsusermount = 1; | | 87 | dovfsusermount = 1; |
88 | | | 88 | |
89 | if (rumpuser_getenv("RUMP_NVNODES", buf, sizeof(buf), &error) == 0) { | | 89 | if (rumpuser_getenv("RUMP_NVNODES", buf, sizeof(buf), &error) == 0) { |
90 | desiredvnodes = strtoul(buf, NULL, 10); | | 90 | desiredvnodes = strtoul(buf, NULL, 10); |
91 | } else { | | 91 | } else { |
92 | desiredvnodes = 1<<16; | | 92 | desiredvnodes = 1<<16; |
93 | } | | 93 | } |
94 | | | 94 | |
95 | rumpblk_init(); | | 95 | rumpblk_init(); |
96 | | | 96 | |
97 | cache_cpu_init(&rump_cpu); | | 97 | cache_cpu_init(&rump_cpu); |
98 | vfsinit(); | | 98 | vfsinit(); |
99 | bufinit(); | | 99 | bufinit(); |
100 | wapbl_init(); | | 100 | wapbl_init(); |
101 | cwd_sys_init(); | | 101 | cwd_sys_init(); |
102 | lf_init(); | | 102 | lf_init(); |
103 | | | 103 | |
104 | rumpuser_bioinit(rump_biodone); | | 104 | rumpuser_bioinit(rump_biodone); |
105 | rumpfs_init(); | | 105 | rumpfs_init(); |
106 | | | 106 | |
107 | rump_proc_vfs_init = pvfs_init; | | 107 | rump_proc_vfs_init = pvfs_init; |
108 | rump_proc_vfs_release = pvfs_rele; | | 108 | rump_proc_vfs_release = pvfs_rele; |
109 | | | 109 | |
110 | /* bootstrap cwdi */ | | 110 | /* bootstrap cwdi */ |
111 | rw_init(&rump_cwdi.cwdi_lock); | | 111 | rw_init(&rump_cwdi.cwdi_lock); |
112 | rump_cwdi.cwdi_cdir = rootvnode; | | 112 | rump_cwdi.cwdi_cdir = rootvnode; |
113 | vref(rump_cwdi.cwdi_cdir); | | 113 | vref(rump_cwdi.cwdi_cdir); |
114 | proc0.p_cwdi = &rump_cwdi; | | 114 | proc0.p_cwdi = &rump_cwdi; |
115 | proc0.p_cwdi = cwdinit(); | | 115 | proc0.p_cwdi = cwdinit(); |
116 | | | 116 | |
117 | if (rump_threads) { | | 117 | if (rump_threads) { |
118 | int rv; | | 118 | int rv; |
119 | | | 119 | |
120 | if ((rv = kthread_create(PRI_IOFLUSH, KTHREAD_MPSAFE, NULL, | | 120 | if ((rv = kthread_create(PRI_IOFLUSH, KTHREAD_MPSAFE, NULL, |
121 | sched_sync, NULL, NULL, "ioflush")) != 0) | | 121 | sched_sync, NULL, NULL, "ioflush")) != 0) |
122 | panic("syncer thread create failed: %d", rv); | | 122 | panic("syncer thread create failed: %d", rv); |
123 | } else { | | 123 | } else { |
124 | syncdelay = 0; | | 124 | syncdelay = 0; |
125 | } | | 125 | } |
126 | } | | 126 | } |
127 | | | 127 | |
128 | struct mount * | | 128 | struct mount * |
129 | rump_mnt_init(struct vfsops *vfsops, int mntflags) | | 129 | rump_mnt_init(struct vfsops *vfsops, int mntflags) |
130 | { | | 130 | { |
131 | struct mount *mp; | | 131 | struct mount *mp; |
132 | | | 132 | |
133 | mp = kmem_zalloc(sizeof(struct mount), KM_SLEEP); | | 133 | mp = kmem_zalloc(sizeof(struct mount), KM_SLEEP); |
134 | | | 134 | |
135 | mp->mnt_op = vfsops; | | 135 | mp->mnt_op = vfsops; |
136 | mp->mnt_flag = mntflags; | | 136 | mp->mnt_flag = mntflags; |
137 | TAILQ_INIT(&mp->mnt_vnodelist); | | 137 | TAILQ_INIT(&mp->mnt_vnodelist); |
138 | rw_init(&mp->mnt_unmounting); | | 138 | rw_init(&mp->mnt_unmounting); |
139 | mutex_init(&mp->mnt_updating, MUTEX_DEFAULT, IPL_NONE); | | 139 | mutex_init(&mp->mnt_updating, MUTEX_DEFAULT, IPL_NONE); |
140 | mutex_init(&mp->mnt_renamelock, MUTEX_DEFAULT, IPL_NONE); | | 140 | mutex_init(&mp->mnt_renamelock, MUTEX_DEFAULT, IPL_NONE); |
141 | mp->mnt_refcnt = 1; | | 141 | mp->mnt_refcnt = 1; |
142 | mp->mnt_vnodecovered = rootvnode; | | 142 | mp->mnt_vnodecovered = rootvnode; |
143 | | | 143 | |
144 | mount_initspecific(mp); | | 144 | mount_initspecific(mp); |
145 | | | 145 | |
146 | return mp; | | 146 | return mp; |
147 | } | | 147 | } |
148 | | | 148 | |
149 | int | | 149 | int |
150 | rump_mnt_mount(struct mount *mp, const char *path, void *data, size_t *dlen) | | 150 | rump_mnt_mount(struct mount *mp, const char *path, void *data, size_t *dlen) |
151 | { | | 151 | { |
152 | struct vnode *rvp; | | 152 | struct vnode *rvp; |
153 | int rv; | | 153 | int rv; |
154 | | | 154 | |
155 | rv = VFS_MOUNT(mp, path, data, dlen); | | 155 | rv = VFS_MOUNT(mp, path, data, dlen); |
156 | if (rv) | | 156 | if (rv) |
157 | return rv; | | 157 | return rv; |
158 | | | 158 | |
159 | (void) VFS_STATVFS(mp, &mp->mnt_stat); | | 159 | (void) VFS_STATVFS(mp, &mp->mnt_stat); |
160 | rv = VFS_START(mp, 0); | | 160 | rv = VFS_START(mp, 0); |
161 | if (rv) { | | 161 | if (rv) { |
162 | VFS_UNMOUNT(mp, MNT_FORCE); | | 162 | VFS_UNMOUNT(mp, MNT_FORCE); |
163 | return rv; | | 163 | return rv; |
164 | } | | 164 | } |
165 | | | 165 | |
166 | /* | | 166 | /* |
167 | * XXX: set a root for lwp0. This is strictly not correct, | | 167 | * XXX: set a root for lwp0. This is strictly not correct, |
168 | * but makes things work for single fs case without having | | 168 | * but makes things work for single fs case without having |
169 | * to manually call rump_rcvp_set(). | | 169 | * to manually call rump_rcvp_set(). |
170 | */ | | 170 | */ |
171 | VFS_ROOT(mp, &rvp); | | 171 | VFS_ROOT(mp, &rvp); |
172 | rump_rcvp_lwpset(rvp, rvp, &lwp0); | | 172 | rump_rcvp_lwpset(rvp, rvp, &lwp0); |
173 | vput(rvp); | | 173 | vput(rvp); |
174 | | | 174 | |
175 | return rv; | | 175 | return rv; |
176 | } | | 176 | } |
177 | | | 177 | |
178 | void | | 178 | void |
179 | rump_mnt_destroy(struct mount *mp) | | 179 | rump_mnt_destroy(struct mount *mp) |
180 | { | | 180 | { |
181 | | | 181 | |
182 | /* See rcvp XXX above */ | | 182 | /* See rcvp XXX above */ |
183 | rump_cwdi.cwdi_rdir = NULL; | | 183 | rump_cwdi.cwdi_rdir = NULL; |
184 | vref(rootvnode); | | 184 | vref(rootvnode); |
185 | rump_cwdi.cwdi_cdir = rootvnode; | | 185 | rump_cwdi.cwdi_cdir = rootvnode; |
186 | | | 186 | |
187 | mount_finispecific(mp); | | 187 | mount_finispecific(mp); |
188 | kmem_free(mp, sizeof(*mp)); | | 188 | kmem_free(mp, sizeof(*mp)); |
189 | } | | 189 | } |
190 | | | 190 | |
191 | struct componentname * | | 191 | struct componentname * |
192 | rump_makecn(u_long nameiop, u_long flags, const char *name, size_t namelen, | | 192 | rump_makecn(u_long nameiop, u_long flags, const char *name, size_t namelen, |
193 | kauth_cred_t creds, struct lwp *l) | | 193 | kauth_cred_t creds, struct lwp *l) |
194 | { | | 194 | { |
195 | struct componentname *cnp; | | 195 | struct componentname *cnp; |
196 | const char *cp = NULL; | | 196 | const char *cp = NULL; |
197 | | | 197 | |
198 | cnp = kmem_zalloc(sizeof(struct componentname), KM_SLEEP); | | 198 | cnp = kmem_zalloc(sizeof(struct componentname), KM_SLEEP); |
199 | | | 199 | |
200 | cnp->cn_nameiop = nameiop; | | 200 | cnp->cn_nameiop = nameiop; |
201 | cnp->cn_flags = flags | HASBUF; | | 201 | cnp->cn_flags = flags | HASBUF; |
202 | | | 202 | |
203 | cnp->cn_pnbuf = PNBUF_GET(); | | 203 | cnp->cn_pnbuf = PNBUF_GET(); |
204 | strcpy(cnp->cn_pnbuf, name); | | 204 | strcpy(cnp->cn_pnbuf, name); |
205 | cnp->cn_nameptr = cnp->cn_pnbuf; | | 205 | cnp->cn_nameptr = cnp->cn_pnbuf; |
206 | cnp->cn_namelen = namelen; | | 206 | cnp->cn_namelen = namelen; |
207 | cnp->cn_hash = namei_hash(name, &cp); | | 207 | cnp->cn_hash = namei_hash(name, &cp); |
208 | | | 208 | |
209 | cnp->cn_cred = creds; | | 209 | cnp->cn_cred = creds; |
210 | | | 210 | |
211 | return cnp; | | 211 | return cnp; |
212 | } | | 212 | } |
213 | | | 213 | |
214 | void | | 214 | void |
215 | rump_freecn(struct componentname *cnp, int flags) | | 215 | rump_freecn(struct componentname *cnp, int flags) |
216 | { | | 216 | { |
217 | | | 217 | |
218 | if (flags & RUMPCN_FREECRED) | | 218 | if (flags & RUMPCN_FREECRED) |
219 | rump_cred_destroy(cnp->cn_cred); | | 219 | rump_cred_destroy(cnp->cn_cred); |
220 | | | 220 | |
221 | if ((flags & RUMPCN_HASNTBUF) == 0) { | | 221 | if ((flags & RUMPCN_HASNTBUF) == 0) { |
222 | if (cnp->cn_flags & SAVENAME) { | | 222 | if (cnp->cn_flags & SAVENAME) { |
223 | if (flags & RUMPCN_ISLOOKUP ||cnp->cn_flags & SAVESTART) | | 223 | if (flags & RUMPCN_ISLOOKUP ||cnp->cn_flags & SAVESTART) |
224 | PNBUF_PUT(cnp->cn_pnbuf); | | 224 | PNBUF_PUT(cnp->cn_pnbuf); |
225 | } else { | | 225 | } else { |
226 | PNBUF_PUT(cnp->cn_pnbuf); | | 226 | PNBUF_PUT(cnp->cn_pnbuf); |
227 | } | | 227 | } |
228 | } | | 228 | } |
229 | kmem_free(cnp, sizeof(*cnp)); | | 229 | kmem_free(cnp, sizeof(*cnp)); |
230 | } | | 230 | } |
231 | | | 231 | |
232 | /* hey baby, what's your namei? */ | | 232 | /* hey baby, what's your namei? */ |
233 | int | | 233 | int |
234 | rump_namei(uint32_t op, uint32_t flags, const char *namep, | | 234 | rump_namei(uint32_t op, uint32_t flags, const char *namep, |
235 | struct vnode **dvpp, struct vnode **vpp, struct componentname **cnpp) | | 235 | struct vnode **dvpp, struct vnode **vpp, struct componentname **cnpp) |
236 | { | | 236 | { |
237 | struct nameidata nd; | | 237 | struct nameidata nd; |
238 | int rv; | | 238 | int rv; |
239 | | | 239 | |
240 | NDINIT(&nd, op, flags, UIO_SYSSPACE, namep); | | 240 | NDINIT(&nd, op, flags, UIO_SYSSPACE, namep); |
241 | rv = namei(&nd); | | 241 | rv = namei(&nd); |
242 | if (rv) | | 242 | if (rv) |
243 | return rv; | | 243 | return rv; |
244 | | | 244 | |
245 | if (dvpp) { | | 245 | if (dvpp) { |
246 | KASSERT(flags & LOCKPARENT); | | 246 | KASSERT(flags & LOCKPARENT); |
247 | *dvpp = nd.ni_dvp; | | 247 | *dvpp = nd.ni_dvp; |
248 | } else { | | 248 | } else { |
249 | KASSERT((flags & LOCKPARENT) == 0); | | 249 | KASSERT((flags & LOCKPARENT) == 0); |
250 | } | | 250 | } |
251 | | | 251 | |
252 | if (vpp) { | | 252 | if (vpp) { |
253 | *vpp = nd.ni_vp; | | 253 | *vpp = nd.ni_vp; |
254 | } else { | | 254 | } else { |
255 | if (nd.ni_vp) { | | 255 | if (nd.ni_vp) { |
256 | if (flags & LOCKLEAF) | | 256 | if (flags & LOCKLEAF) |
257 | vput(nd.ni_vp); | | 257 | vput(nd.ni_vp); |
258 | else | | 258 | else |
259 | vrele(nd.ni_vp); | | 259 | vrele(nd.ni_vp); |
260 | } | | 260 | } |
261 | } | | 261 | } |
262 | | | 262 | |
263 | if (cnpp) { | | 263 | if (cnpp) { |
264 | struct componentname *cnp; | | 264 | struct componentname *cnp; |
265 | | | 265 | |
266 | cnp = kmem_alloc(sizeof(*cnp), KM_SLEEP); | | 266 | cnp = kmem_alloc(sizeof(*cnp), KM_SLEEP); |
267 | memcpy(cnp, &nd.ni_cnd, sizeof(*cnp)); | | 267 | memcpy(cnp, &nd.ni_cnd, sizeof(*cnp)); |
268 | *cnpp = cnp; | | 268 | *cnpp = cnp; |
269 | } else if (nd.ni_cnd.cn_flags & HASBUF) { | | 269 | } else if (nd.ni_cnd.cn_flags & HASBUF) { |
270 | panic("%s: pathbuf mismatch", __func__); | | 270 | panic("%s: pathbuf mismatch", __func__); |
271 | } | | 271 | } |
272 | | | 272 | |
273 | return rv; | | 273 | return rv; |
274 | } | | 274 | } |
275 | | | 275 | |
276 | static struct fakeblk * | | 276 | static struct fakeblk * |
277 | _rump_fakeblk_find(const char *path) | | 277 | _rump_fakeblk_find(const char *path) |
278 | { | | 278 | { |
279 | char buf[MAXPATHLEN]; | | 279 | char buf[MAXPATHLEN]; |
280 | struct fakeblk *fblk; | | 280 | struct fakeblk *fblk; |
281 | int error; | | 281 | int error; |
282 | | | 282 | |
283 | if (rumpuser_realpath(path, buf, &error) == NULL) | | 283 | if (rumpuser_realpath(path, buf, &error) == NULL) |
284 | return NULL; | | 284 | return NULL; |
285 | | | 285 | |
286 | LIST_FOREACH(fblk, &fakeblks, entries) | | 286 | LIST_FOREACH(fblk, &fakeblks, entries) |
287 | if (strcmp(fblk->path, buf) == 0) | | 287 | if (strcmp(fblk->path, buf) == 0) |
288 | return fblk; | | 288 | return fblk; |
289 | | | 289 | |
290 | return NULL; | | 290 | return NULL; |
291 | } | | 291 | } |
292 | | | 292 | |
293 | int | | 293 | int |
294 | rump_fakeblk_register(const char *path) | | 294 | rump_fakeblk_register(const char *path) |
295 | { | | 295 | { |
296 | char buf[MAXPATHLEN]; | | 296 | char buf[MAXPATHLEN]; |
297 | struct fakeblk *fblk; | | 297 | struct fakeblk *fblk; |
298 | int error; | | 298 | int error; |
299 | | | 299 | |
300 | if (_rump_fakeblk_find(path)) | | 300 | if (_rump_fakeblk_find(path)) |
301 | return EEXIST; | | 301 | return EEXIST; |
302 | | | 302 | |
303 | if (rumpuser_realpath(path, buf, &error) == NULL) | | 303 | if (rumpuser_realpath(path, buf, &error) == NULL) |
304 | return error; | | 304 | return error; |
305 | | | 305 | |
306 | fblk = kmem_alloc(sizeof(struct fakeblk), KM_NOSLEEP); | | 306 | fblk = kmem_alloc(sizeof(struct fakeblk), KM_NOSLEEP); |
307 | if (fblk == NULL) | | 307 | if (fblk == NULL) |
308 | return ENOMEM; | | 308 | return ENOMEM; |
309 | | | 309 | |
310 | strlcpy(fblk->path, buf, MAXPATHLEN); | | 310 | strlcpy(fblk->path, buf, MAXPATHLEN); |
311 | LIST_INSERT_HEAD(&fakeblks, fblk, entries); | | 311 | LIST_INSERT_HEAD(&fakeblks, fblk, entries); |
312 | | | 312 | |
313 | return 0; | | 313 | return 0; |
314 | } | | 314 | } |
315 | | | 315 | |
316 | int | | 316 | int |
317 | rump_fakeblk_find(const char *path) | | 317 | rump_fakeblk_find(const char *path) |
318 | { | | 318 | { |
319 | | | 319 | |
320 | return _rump_fakeblk_find(path) != NULL; | | 320 | return _rump_fakeblk_find(path) != NULL; |
321 | } | | 321 | } |
322 | | | 322 | |
323 | void | | 323 | void |
324 | rump_fakeblk_deregister(const char *path) | | 324 | rump_fakeblk_deregister(const char *path) |
325 | { | | 325 | { |
326 | struct fakeblk *fblk; | | 326 | struct fakeblk *fblk; |
327 | | | 327 | |
328 | fblk = _rump_fakeblk_find(path); | | 328 | fblk = _rump_fakeblk_find(path); |
329 | if (fblk == NULL) | | 329 | if (fblk == NULL) |
330 | return; | | 330 | return; |
331 | | | 331 | |
332 | LIST_REMOVE(fblk, entries); | | 332 | LIST_REMOVE(fblk, entries); |
333 | kmem_free(fblk, sizeof(*fblk)); | | 333 | kmem_free(fblk, sizeof(*fblk)); |
334 | } | | 334 | } |
335 | | | 335 | |
336 | void | | 336 | void |
337 | rump_getvninfo(struct vnode *vp, enum vtype *vtype, voff_t *vsize, dev_t *vdev) | | 337 | rump_getvninfo(struct vnode *vp, enum vtype *vtype, voff_t *vsize, dev_t *vdev) |
338 | { | | 338 | { |
339 | | | 339 | |
340 | *vtype = vp->v_type; | | 340 | *vtype = vp->v_type; |
341 | *vsize = vp->v_size; | | 341 | *vsize = vp->v_size; |
342 | if (vp->v_specnode) | | 342 | if (vp->v_specnode) |
343 | *vdev = vp->v_rdev; | | 343 | *vdev = vp->v_rdev; |
344 | else | | 344 | else |
345 | *vdev = 0; | | 345 | *vdev = 0; |
346 | } | | 346 | } |
347 | | | 347 | |
348 | struct vfsops * | | 348 | struct vfsops * |
349 | rump_vfslist_iterate(struct vfsops *ops) | | 349 | rump_vfslist_iterate(struct vfsops *ops) |
350 | { | | 350 | { |
351 | | | 351 | |
352 | if (ops == NULL) | | 352 | if (ops == NULL) |
353 | return LIST_FIRST(&vfs_list); | | 353 | return LIST_FIRST(&vfs_list); |
354 | else | | 354 | else |
355 | return LIST_NEXT(ops, vfs_list); | | 355 | return LIST_NEXT(ops, vfs_list); |
356 | } | | 356 | } |
357 | | | 357 | |
358 | struct vfsops * | | 358 | struct vfsops * |
359 | rump_vfs_getopsbyname(const char *name) | | 359 | rump_vfs_getopsbyname(const char *name) |
360 | { | | 360 | { |
361 | | | 361 | |
362 | return vfs_getopsbyname(name); | | 362 | return vfs_getopsbyname(name); |
363 | } | | 363 | } |
364 | | | 364 | |
| | | 365 | int |
| | | 366 | rump_vfs_getmp(const char *path, struct mount **mpp) |
| | | 367 | { |
| | | 368 | struct nameidata nd; |
| | | 369 | struct vnode *vp; |
| | | 370 | int rv; |
| | | 371 | |
| | | 372 | NDINIT(&nd, LOOKUP, FOLLOW | TRYEMULROOT, UIO_USERSPACE, path); |
| | | 373 | if ((rv = namei(&nd)) != 0) |
| | | 374 | return rv; |
| | | 375 | vp = nd.ni_vp; |
| | | 376 | |
| | | 377 | *mpp = vp->v_mount; |
| | | 378 | vrele(vp); |
| | | 379 | return 0; |
| | | 380 | } |
| | | 381 | |
365 | struct vattr* | | 382 | struct vattr* |
366 | rump_vattr_init(void) | | 383 | rump_vattr_init(void) |
367 | { | | 384 | { |
368 | struct vattr *vap; | | 385 | struct vattr *vap; |
369 | | | 386 | |
370 | vap = kmem_alloc(sizeof(struct vattr), KM_SLEEP); | | 387 | vap = kmem_alloc(sizeof(struct vattr), KM_SLEEP); |
371 | vattr_null(vap); | | 388 | vattr_null(vap); |
372 | | | 389 | |
373 | return vap; | | 390 | return vap; |
374 | } | | 391 | } |
375 | | | 392 | |
376 | void | | 393 | void |
377 | rump_vattr_settype(struct vattr *vap, enum vtype vt) | | 394 | rump_vattr_settype(struct vattr *vap, enum vtype vt) |
378 | { | | 395 | { |
379 | | | 396 | |
380 | vap->va_type = vt; | | 397 | vap->va_type = vt; |
381 | } | | 398 | } |
382 | | | 399 | |
383 | void | | 400 | void |
384 | rump_vattr_setmode(struct vattr *vap, mode_t mode) | | 401 | rump_vattr_setmode(struct vattr *vap, mode_t mode) |
385 | { | | 402 | { |
386 | | | 403 | |
387 | vap->va_mode = mode; | | 404 | vap->va_mode = mode; |
388 | } | | 405 | } |
389 | | | 406 | |
390 | void | | 407 | void |
391 | rump_vattr_setrdev(struct vattr *vap, dev_t dev) | | 408 | rump_vattr_setrdev(struct vattr *vap, dev_t dev) |
392 | { | | 409 | { |
393 | | | 410 | |
394 | vap->va_rdev = dev; | | 411 | vap->va_rdev = dev; |
395 | } | | 412 | } |
396 | | | 413 | |
397 | void | | 414 | void |
398 | rump_vattr_free(struct vattr *vap) | | 415 | rump_vattr_free(struct vattr *vap) |
399 | { | | 416 | { |
400 | | | 417 | |
401 | kmem_free(vap, sizeof(*vap)); | | 418 | kmem_free(vap, sizeof(*vap)); |
402 | } | | 419 | } |
403 | | | 420 | |
404 | void | | 421 | void |
405 | rump_vp_incref(struct vnode *vp) | | 422 | rump_vp_incref(struct vnode *vp) |
406 | { | | 423 | { |
407 | | | 424 | |
408 | mutex_enter(&vp->v_interlock); | | 425 | mutex_enter(&vp->v_interlock); |
409 | ++vp->v_usecount; | | 426 | ++vp->v_usecount; |
410 | mutex_exit(&vp->v_interlock); | | 427 | mutex_exit(&vp->v_interlock); |
411 | } | | 428 | } |
412 | | | 429 | |
413 | int | | 430 | int |
414 | rump_vp_getref(struct vnode *vp) | | 431 | rump_vp_getref(struct vnode *vp) |
415 | { | | 432 | { |
416 | | | 433 | |
417 | return vp->v_usecount; | | 434 | return vp->v_usecount; |
418 | } | | 435 | } |
419 | | | 436 | |
420 | void | | 437 | void |
421 | rump_vp_decref(struct vnode *vp) | | 438 | rump_vp_decref(struct vnode *vp) |
422 | { | | 439 | { |
423 | | | 440 | |
424 | mutex_enter(&vp->v_interlock); | | 441 | mutex_enter(&vp->v_interlock); |
425 | --vp->v_usecount; | | 442 | --vp->v_usecount; |
426 | mutex_exit(&vp->v_interlock); | | 443 | mutex_exit(&vp->v_interlock); |
427 | } | | 444 | } |
428 | | | 445 | |
429 | /* | | 446 | /* |
430 | * Really really recycle with a cherry on top. We should be | | 447 | * Really really recycle with a cherry on top. We should be |
431 | * extra-sure we can do this. For example with p2k there is | | 448 | * extra-sure we can do this. For example with p2k there is |
432 | * no problem, since puffs in the kernel takes care of refcounting | | 449 | * no problem, since puffs in the kernel takes care of refcounting |
433 | * for us. | | 450 | * for us. |
434 | */ | | 451 | */ |
435 | void | | 452 | void |
436 | rump_vp_recycle_nokidding(struct vnode *vp) | | 453 | rump_vp_recycle_nokidding(struct vnode *vp) |
437 | { | | 454 | { |
438 | | | 455 | |
439 | mutex_enter(&vp->v_interlock); | | 456 | mutex_enter(&vp->v_interlock); |
440 | vp->v_usecount = 1; | | 457 | vp->v_usecount = 1; |
441 | /* | | 458 | /* |
442 | * XXX: NFS holds a reference to the root vnode, so don't clean | | 459 | * XXX: NFS holds a reference to the root vnode, so don't clean |
443 | * it out. This is very wrong, but fixing it properly would | | 460 | * it out. This is very wrong, but fixing it properly would |
444 | * take too much effort for now | | 461 | * take too much effort for now |
445 | */ | | 462 | */ |
446 | if (vp->v_tag == VT_NFS && vp->v_vflag & VV_ROOT) { | | 463 | if (vp->v_tag == VT_NFS && vp->v_vflag & VV_ROOT) { |
447 | mutex_exit(&vp->v_interlock); | | 464 | mutex_exit(&vp->v_interlock); |
448 | return; | | 465 | return; |
449 | } | | 466 | } |
450 | vclean(vp, DOCLOSE); | | 467 | vclean(vp, DOCLOSE); |
451 | vrelel(vp, 0); | | 468 | vrelel(vp, 0); |
452 | } | | 469 | } |
453 | | | 470 | |
454 | void | | 471 | void |
455 | rump_vp_rele(struct vnode *vp) | | 472 | rump_vp_rele(struct vnode *vp) |
456 | { | | 473 | { |
457 | | | 474 | |
458 | vrele(vp); | | 475 | vrele(vp); |
459 | } | | 476 | } |
460 | | | 477 | |
461 | void | | 478 | void |
462 | rump_vp_interlock(struct vnode *vp) | | 479 | rump_vp_interlock(struct vnode *vp) |
463 | { | | 480 | { |
464 | | | 481 | |
465 | mutex_enter(&vp->v_interlock); | | 482 | mutex_enter(&vp->v_interlock); |
466 | } | | 483 | } |
467 | | | 484 | |
468 | int | | 485 | int |
469 | rump_vfs_unmount(struct mount *mp, int mntflags) | | 486 | rump_vfs_unmount(struct mount *mp, int mntflags) |
470 | { | | 487 | { |
471 | #if 0 | | 488 | #if 0 |
472 | struct evcnt *ev; | | 489 | struct evcnt *ev; |
473 | | | 490 | |
474 | printf("event counters:\n"); | | 491 | printf("event counters:\n"); |
475 | TAILQ_FOREACH(ev, &allevents, ev_list) | | 492 | TAILQ_FOREACH(ev, &allevents, ev_list) |
476 | printf("%s: %llu\n", ev->ev_name, ev->ev_count); | | 493 | printf("%s: %llu\n", ev->ev_name, ev->ev_count); |
477 | #endif | | 494 | #endif |
478 | | | 495 | |
479 | return VFS_UNMOUNT(mp, mntflags); | | 496 | return VFS_UNMOUNT(mp, mntflags); |
480 | } | | 497 | } |
481 | | | 498 | |
482 | int | | 499 | int |
483 | rump_vfs_root(struct mount *mp, struct vnode **vpp, int lock) | | 500 | rump_vfs_root(struct mount *mp, struct vnode **vpp, int lock) |
484 | { | | 501 | { |
485 | int rv; | | 502 | int rv; |
486 | | | 503 | |
487 | rv = VFS_ROOT(mp, vpp); | | 504 | rv = VFS_ROOT(mp, vpp); |
488 | if (rv) | | 505 | if (rv) |
489 | return rv; | | 506 | return rv; |
490 | | | 507 | |
491 | if (!lock) | | 508 | if (!lock) |
492 | VOP_UNLOCK(*vpp, 0); | | 509 | VOP_UNLOCK(*vpp, 0); |
493 | | | 510 | |
494 | return 0; | | 511 | return 0; |
495 | } | | 512 | } |
496 | | | 513 | |
497 | int | | 514 | int |
498 | rump_vfs_statvfs(struct mount *mp, struct statvfs *sbp) | | 515 | rump_vfs_statvfs(struct mount *mp, struct statvfs *sbp) |
499 | { | | 516 | { |
500 | | | 517 | |
501 | return VFS_STATVFS(mp, sbp); | | 518 | return VFS_STATVFS(mp, sbp); |
502 | } | | 519 | } |
503 | | | 520 | |
504 | int | | 521 | int |
505 | rump_vfs_sync(struct mount *mp, int wait, kauth_cred_t cred) | | 522 | rump_vfs_sync(struct mount *mp, int wait, kauth_cred_t cred) |
506 | { | | 523 | { |
507 | | | 524 | |
508 | return VFS_SYNC(mp, wait ? MNT_WAIT : MNT_NOWAIT, cred); | | 525 | return VFS_SYNC(mp, wait ? MNT_WAIT : MNT_NOWAIT, cred); |
509 | } | | 526 | } |
510 | | | 527 | |
511 | int | | 528 | int |
512 | rump_vfs_fhtovp(struct mount *mp, struct fid *fid, struct vnode **vpp) | | 529 | rump_vfs_fhtovp(struct mount *mp, struct fid *fid, struct vnode **vpp) |
513 | { | | 530 | { |
514 | | | 531 | |
515 | return VFS_FHTOVP(mp, fid, vpp); | | 532 | return VFS_FHTOVP(mp, fid, vpp); |
516 | } | | 533 | } |
517 | | | 534 | |
518 | int | | 535 | int |
519 | rump_vfs_vptofh(struct vnode *vp, struct fid *fid, size_t *fidsize) | | 536 | rump_vfs_vptofh(struct vnode *vp, struct fid *fid, size_t *fidsize) |
520 | { | | 537 | { |
521 | | | 538 | |
522 | return VFS_VPTOFH(vp, fid, fidsize); | | 539 | return VFS_VPTOFH(vp, fid, fidsize); |
523 | } | | 540 | } |
524 | | | 541 | |
525 | /*ARGSUSED*/ | | 542 | /*ARGSUSED*/ |
526 | void | | 543 | void |
527 | rump_vfs_syncwait(struct mount *mp) | | 544 | rump_vfs_syncwait(struct mount *mp) |
528 | { | | 545 | { |
529 | int n; | | 546 | int n; |
530 | | | 547 | |
531 | n = buf_syncwait(); | | 548 | n = buf_syncwait(); |
532 | if (n) | | 549 | if (n) |
533 | printf("syncwait: unsynced buffers: %d\n", n); | | 550 | printf("syncwait: unsynced buffers: %d\n", n); |
534 | } | | 551 | } |
535 | | | 552 | |
536 | void | | 553 | void |
537 | rump_biodone(void *arg, size_t count, int error) | | 554 | rump_biodone(void *arg, size_t count, int error) |
538 | { | | 555 | { |
539 | struct buf *bp = arg; | | 556 | struct buf *bp = arg; |
540 | | | 557 | |
541 | bp->b_resid = bp->b_bcount - count; | | 558 | bp->b_resid = bp->b_bcount - count; |
542 | KASSERT(bp->b_resid >= 0); | | 559 | KASSERT(bp->b_resid >= 0); |
543 | bp->b_error = error; | | 560 | bp->b_error = error; |
544 | | | 561 | |
545 | biodone(bp); | | 562 | biodone(bp); |
546 | } | | 563 | } |
547 | | | 564 | |
548 | static void | | 565 | static void |
549 | rump_rcvp_lwpset(struct vnode *rvp, struct vnode *cvp, struct lwp *l) | | 566 | rump_rcvp_lwpset(struct vnode *rvp, struct vnode *cvp, struct lwp *l) |
550 | { | | 567 | { |
551 | struct cwdinfo *cwdi = l->l_proc->p_cwdi; | | 568 | struct cwdinfo *cwdi = l->l_proc->p_cwdi; |
552 | | | 569 | |
553 | KASSERT(cvp); | | 570 | KASSERT(cvp); |
554 | | | 571 | |
555 | rw_enter(&cwdi->cwdi_lock, RW_WRITER); | | 572 | rw_enter(&cwdi->cwdi_lock, RW_WRITER); |
556 | if (cwdi->cwdi_rdir) | | 573 | if (cwdi->cwdi_rdir) |
557 | vrele(cwdi->cwdi_rdir); | | 574 | vrele(cwdi->cwdi_rdir); |
558 | if (rvp) | | 575 | if (rvp) |
559 | vref(rvp); | | 576 | vref(rvp); |
560 | cwdi->cwdi_rdir = rvp; | | 577 | cwdi->cwdi_rdir = rvp; |
561 | | | 578 | |
562 | vrele(cwdi->cwdi_cdir); | | 579 | vrele(cwdi->cwdi_cdir); |
563 | vref(cvp); | | 580 | vref(cvp); |
564 | cwdi->cwdi_cdir = cvp; | | 581 | cwdi->cwdi_cdir = cvp; |
565 | rw_exit(&cwdi->cwdi_lock); | | 582 | rw_exit(&cwdi->cwdi_lock); |
566 | } | | 583 | } |
567 | | | 584 | |
568 | void | | 585 | void |
569 | rump_rcvp_set(struct vnode *rvp, struct vnode *cvp) | | 586 | rump_rcvp_set(struct vnode *rvp, struct vnode *cvp) |
570 | { | | 587 | { |
571 | | | 588 | |
572 | rump_rcvp_lwpset(rvp, cvp, curlwp); | | 589 | rump_rcvp_lwpset(rvp, cvp, curlwp); |
573 | } | | 590 | } |
574 | | | 591 | |
575 | struct vnode * | | 592 | struct vnode * |
576 | rump_cdir_get(void) | | 593 | rump_cdir_get(void) |
577 | { | | 594 | { |
578 | struct vnode *vp; | | 595 | struct vnode *vp; |
579 | struct cwdinfo *cwdi = curlwp->l_proc->p_cwdi; | | 596 | struct cwdinfo *cwdi = curlwp->l_proc->p_cwdi; |
580 | | | 597 | |
581 | rw_enter(&cwdi->cwdi_lock, RW_READER); | | 598 | rw_enter(&cwdi->cwdi_lock, RW_READER); |
582 | vp = cwdi->cwdi_cdir; | | 599 | vp = cwdi->cwdi_cdir; |
583 | rw_exit(&cwdi->cwdi_lock); | | 600 | rw_exit(&cwdi->cwdi_lock); |
584 | vref(vp); | | 601 | vref(vp); |
585 | | | 602 | |
586 | return vp; | | 603 | return vp; |
587 | } | | 604 | } |