rumpfs.c revision 1.6.4.2 1 1.6.4.2 skrll /* $NetBSD: rumpfs.c,v 1.6.4.2 2009/01/19 13:20:27 skrll Exp $ */
2 1.6.4.2 skrll
3 1.6.4.2 skrll /*
4 1.6.4.2 skrll * Copyright (c) 2007 Antti Kantee. All Rights Reserved.
5 1.6.4.2 skrll *
6 1.6.4.2 skrll * Development of this software was supported by Google Summer of Code.
7 1.6.4.2 skrll *
8 1.6.4.2 skrll * Redistribution and use in source and binary forms, with or without
9 1.6.4.2 skrll * modification, are permitted provided that the following conditions
10 1.6.4.2 skrll * are met:
11 1.6.4.2 skrll * 1. Redistributions of source code must retain the above copyright
12 1.6.4.2 skrll * notice, this list of conditions and the following disclaimer.
13 1.6.4.2 skrll * 2. Redistributions in binary form must reproduce the above copyright
14 1.6.4.2 skrll * notice, this list of conditions and the following disclaimer in the
15 1.6.4.2 skrll * documentation and/or other materials provided with the distribution.
16 1.6.4.2 skrll *
17 1.6.4.2 skrll * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
18 1.6.4.2 skrll * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 1.6.4.2 skrll * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 1.6.4.2 skrll * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 1.6.4.2 skrll * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 1.6.4.2 skrll * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 1.6.4.2 skrll * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 1.6.4.2 skrll * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 1.6.4.2 skrll * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 1.6.4.2 skrll * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 1.6.4.2 skrll * SUCH DAMAGE.
28 1.6.4.2 skrll */
29 1.6.4.2 skrll
30 1.6.4.2 skrll #include <sys/cdefs.h>
31 1.6.4.2 skrll __KERNEL_RCSID(0, "$NetBSD: rumpfs.c,v 1.6.4.2 2009/01/19 13:20:27 skrll Exp $");
32 1.6.4.2 skrll
33 1.6.4.2 skrll #include <sys/param.h>
34 1.6.4.2 skrll #include <sys/mount.h>
35 1.6.4.2 skrll #include <sys/vnode.h>
36 1.6.4.2 skrll #include <sys/errno.h>
37 1.6.4.2 skrll #include <sys/kauth.h>
38 1.6.4.2 skrll #include <sys/lock.h>
39 1.6.4.2 skrll #include <sys/lockf.h>
40 1.6.4.2 skrll #include <sys/stat.h>
41 1.6.4.2 skrll #include <sys/namei.h>
42 1.6.4.2 skrll #include <sys/queue.h>
43 1.6.4.2 skrll #include <sys/filedesc.h>
44 1.6.4.2 skrll #include <sys/syscallargs.h>
45 1.6.4.2 skrll
46 1.6.4.2 skrll #include <miscfs/fifofs/fifo.h>
47 1.6.4.2 skrll #include <miscfs/specfs/specdev.h>
48 1.6.4.2 skrll #include <miscfs/syncfs/syncfs.h>
49 1.6.4.2 skrll #include <miscfs/genfs/genfs.h>
50 1.6.4.2 skrll
51 1.6.4.2 skrll #include <rump/rumpuser.h>
52 1.6.4.2 skrll
53 1.6.4.2 skrll #include "rump_private.h"
54 1.6.4.2 skrll #include "rump_vfs_private.h"
55 1.6.4.2 skrll
56 1.6.4.2 skrll static int rump_vop_lookup(void *);
57 1.6.4.2 skrll
58 1.6.4.2 skrll int (**dead_vnodeop_p)(void *);
59 1.6.4.2 skrll const struct vnodeopv_entry_desc dead_vnodeop_entries[] = {
60 1.6.4.2 skrll { &vop_default_desc, vn_default_error },
61 1.6.4.2 skrll { NULL, NULL }
62 1.6.4.2 skrll };
63 1.6.4.2 skrll const struct vnodeopv_desc dead_vnodeop_opv_desc =
64 1.6.4.2 skrll { &dead_vnodeop_p, dead_vnodeop_entries };
65 1.6.4.2 skrll
66 1.6.4.2 skrll int (**sync_vnodeop_p)(void *);
67 1.6.4.2 skrll const struct vnodeopv_entry_desc sync_vnodeop_entries[] = {
68 1.6.4.2 skrll { &vop_default_desc, vn_default_error },
69 1.6.4.2 skrll { NULL, NULL }
70 1.6.4.2 skrll };
71 1.6.4.2 skrll const struct vnodeopv_desc sync_vnodeop_opv_desc =
72 1.6.4.2 skrll { &sync_vnodeop_p, sync_vnodeop_entries };
73 1.6.4.2 skrll
74 1.6.4.2 skrll int (**fifo_vnodeop_p)(void *);
75 1.6.4.2 skrll const struct vnodeopv_entry_desc fifo_vnodeop_entries[] = {
76 1.6.4.2 skrll { &vop_default_desc, vn_default_error },
77 1.6.4.2 skrll { NULL, NULL }
78 1.6.4.2 skrll };
79 1.6.4.2 skrll const struct vnodeopv_desc fifo_vnodeop_opv_desc =
80 1.6.4.2 skrll { &fifo_vnodeop_p, fifo_vnodeop_entries };
81 1.6.4.2 skrll
82 1.6.4.2 skrll int (**rump_vnodeop_p)(void *);
83 1.6.4.2 skrll const struct vnodeopv_entry_desc rump_vnodeop_entries[] = {
84 1.6.4.2 skrll { &vop_default_desc, vn_default_error },
85 1.6.4.2 skrll { &vop_lookup_desc, rump_vop_lookup },
86 1.6.4.2 skrll { &vop_lock_desc, genfs_lock },
87 1.6.4.2 skrll { &vop_unlock_desc, genfs_unlock },
88 1.6.4.2 skrll { NULL, NULL }
89 1.6.4.2 skrll };
90 1.6.4.2 skrll const struct vnodeopv_desc rump_vnodeop_opv_desc =
91 1.6.4.2 skrll { &rump_vnodeop_p, rump_vnodeop_entries };
92 1.6.4.2 skrll const struct vnodeopv_desc * const rump_opv_descs[] = {
93 1.6.4.2 skrll &rump_vnodeop_opv_desc,
94 1.6.4.2 skrll NULL
95 1.6.4.2 skrll };
96 1.6.4.2 skrll
97 1.6.4.2 skrll static struct mount mnt_dummy;
98 1.6.4.2 skrll
99 1.6.4.2 skrll static int
100 1.6.4.2 skrll rump_makevnode(const char *path, size_t size, enum vtype vt, struct vnode **vpp)
101 1.6.4.2 skrll {
102 1.6.4.2 skrll struct vnode *vp;
103 1.6.4.2 skrll int rv;
104 1.6.4.2 skrll
105 1.6.4.2 skrll vp = kmem_alloc(sizeof(struct vnode), KM_SLEEP);
106 1.6.4.2 skrll vp->v_size = vp->v_writesize = size;
107 1.6.4.2 skrll vp->v_type = vt;
108 1.6.4.2 skrll if (vp->v_type != VBLK)
109 1.6.4.2 skrll if (rump_fakeblk_find(path))
110 1.6.4.2 skrll vp->v_type = VBLK;
111 1.6.4.2 skrll
112 1.6.4.2 skrll if (vp->v_type != VBLK && vp->v_type != VDIR)
113 1.6.4.2 skrll panic("rump_makevnode: only VBLK/VDIR vnodes supported");
114 1.6.4.2 skrll
115 1.6.4.2 skrll if (vp->v_type == VBLK) {
116 1.6.4.2 skrll rv = rumpblk_register(path);
117 1.6.4.2 skrll if (rv == -1) {
118 1.6.4.2 skrll rv = EINVAL;
119 1.6.4.2 skrll goto bad;
120 1.6.4.2 skrll }
121 1.6.4.2 skrll spec_node_init(vp, makedev(RUMPBLK, rv));
122 1.6.4.2 skrll vp->v_op = spec_vnodeop_p;
123 1.6.4.2 skrll } else {
124 1.6.4.2 skrll vp->v_op = rump_vnodeop_p;
125 1.6.4.2 skrll }
126 1.6.4.2 skrll vp->v_mount = &mnt_dummy;
127 1.6.4.2 skrll vp->v_vnlock = &vp->v_lock;
128 1.6.4.2 skrll vp->v_usecount = 1;
129 1.6.4.2 skrll mutex_init(&vp->v_interlock, MUTEX_DEFAULT, IPL_NONE);
130 1.6.4.2 skrll memset(&vp->v_lock, 0, sizeof(vp->v_lock));
131 1.6.4.2 skrll rw_init(&vp->v_lock.vl_lock);
132 1.6.4.2 skrll cv_init(&vp->v_cv, "vnode");
133 1.6.4.2 skrll *vpp = vp;
134 1.6.4.2 skrll
135 1.6.4.2 skrll return 0;
136 1.6.4.2 skrll
137 1.6.4.2 skrll bad:
138 1.6.4.2 skrll kmem_free(vp, sizeof(*vp));
139 1.6.4.2 skrll return rv;
140 1.6.4.2 skrll }
141 1.6.4.2 skrll
142 1.6.4.2 skrll /* from libpuffs, but let's decouple this from that */
143 1.6.4.2 skrll static enum vtype
144 1.6.4.2 skrll mode2vt(mode_t mode)
145 1.6.4.2 skrll {
146 1.6.4.2 skrll
147 1.6.4.2 skrll switch (mode & S_IFMT) {
148 1.6.4.2 skrll case S_IFIFO:
149 1.6.4.2 skrll return VFIFO;
150 1.6.4.2 skrll case S_IFCHR:
151 1.6.4.2 skrll return VCHR;
152 1.6.4.2 skrll case S_IFDIR:
153 1.6.4.2 skrll return VDIR;
154 1.6.4.2 skrll case S_IFBLK:
155 1.6.4.2 skrll return VBLK;
156 1.6.4.2 skrll case S_IFREG:
157 1.6.4.2 skrll return VREG;
158 1.6.4.2 skrll case S_IFLNK:
159 1.6.4.2 skrll return VLNK;
160 1.6.4.2 skrll case S_IFSOCK:
161 1.6.4.2 skrll return VSOCK;
162 1.6.4.2 skrll default:
163 1.6.4.2 skrll return VBAD; /* XXX: not really true, but ... */
164 1.6.4.2 skrll }
165 1.6.4.2 skrll }
166 1.6.4.2 skrll
167 1.6.4.2 skrll /*
168 1.6.4.2 skrll * Simple lookup for faking lookup of device entry for rump file systems
169 1.6.4.2 skrll */
170 1.6.4.2 skrll static int
171 1.6.4.2 skrll rump_vop_lookup(void *v)
172 1.6.4.2 skrll {
173 1.6.4.2 skrll struct vop_lookup_args /* {
174 1.6.4.2 skrll struct vnode *a_dvp;
175 1.6.4.2 skrll struct vnode **a_vpp;
176 1.6.4.2 skrll struct componentname *a_cnp;
177 1.6.4.2 skrll }; */ *ap = v;
178 1.6.4.2 skrll struct componentname *cnp = ap->a_cnp;
179 1.6.4.2 skrll struct stat sb_node;
180 1.6.4.2 skrll int rv, error;
181 1.6.4.2 skrll
182 1.6.4.2 skrll /* we handle only some "non-special" cases */
183 1.6.4.2 skrll KASSERT(cnp->cn_nameiop == LOOKUP);
184 1.6.4.2 skrll KASSERT((cnp->cn_flags & ISDOTDOT) == 0);
185 1.6.4.2 skrll KASSERT(cnp->cn_namelen != 0 && cnp->cn_pnbuf[0] != '.');
186 1.6.4.2 skrll
187 1.6.4.2 skrll if (cnp->cn_flags & FOLLOW)
188 1.6.4.2 skrll rv = rumpuser_stat(cnp->cn_pnbuf, &sb_node, &error);
189 1.6.4.2 skrll else
190 1.6.4.2 skrll rv = rumpuser_lstat(cnp->cn_pnbuf, &sb_node, &error);
191 1.6.4.2 skrll if (rv)
192 1.6.4.2 skrll return error;
193 1.6.4.2 skrll
194 1.6.4.2 skrll error = rump_makevnode(cnp->cn_pnbuf, sb_node.st_size,
195 1.6.4.2 skrll mode2vt(sb_node.st_mode), ap->a_vpp);
196 1.6.4.2 skrll if (error)
197 1.6.4.2 skrll return error;
198 1.6.4.2 skrll
199 1.6.4.2 skrll vn_lock(*ap->a_vpp, LK_RETRY | LK_EXCLUSIVE);
200 1.6.4.2 skrll cnp->cn_consume = strlen(cnp->cn_nameptr + cnp->cn_namelen);
201 1.6.4.2 skrll cnp->cn_flags &= ~REQUIREDIR;
202 1.6.4.2 skrll
203 1.6.4.2 skrll return 0;
204 1.6.4.2 skrll }
205 1.6.4.2 skrll
206 1.6.4.2 skrll void
207 1.6.4.2 skrll rumpfs_init()
208 1.6.4.2 skrll {
209 1.6.4.2 skrll int rv;
210 1.6.4.2 skrll
211 1.6.4.2 skrll vfs_opv_init(rump_opv_descs);
212 1.6.4.2 skrll rv = rump_makevnode("/", 0, VDIR, &rootvnode);
213 1.6.4.2 skrll if (rv)
214 1.6.4.2 skrll panic("could not create root vnode: %d", rv);
215 1.6.4.2 skrll rootvnode->v_vflag |= VV_ROOT;
216 1.6.4.2 skrll }
217