kernfs_vfsops.c revision 1.37 1 /* $NetBSD: kernfs_vfsops.c,v 1.37 2000/06/10 18:27:03 assar Exp $ */
2
3 /*
4 * Copyright (c) 1992, 1993, 1995
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software donated to Berkeley by
8 * Jan-Simon Pendry.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)kernfs_vfsops.c 8.10 (Berkeley) 5/14/95
39 */
40
41 /*
42 * Kernel params Filesystem
43 */
44
45 #if defined(_KERNEL) && !defined(_LKM)
46 #include "opt_compat_netbsd.h"
47 #endif
48
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/conf.h>
52 #include <sys/types.h>
53 #include <sys/proc.h>
54 #include <sys/vnode.h>
55 #include <sys/mount.h>
56 #include <sys/namei.h>
57 #include <sys/malloc.h>
58
59 #include <miscfs/specfs/specdev.h>
60 #include <miscfs/kernfs/kernfs.h>
61
62 dev_t rrootdev = NODEV;
63
64 void kernfs_init __P((void));
65 void kernfs_done __P((void));
66 void kernfs_get_rrootdev __P((void));
67 int kernfs_mount __P((struct mount *, const char *, void *,
68 struct nameidata *, struct proc *));
69 int kernfs_start __P((struct mount *, int, struct proc *));
70 int kernfs_unmount __P((struct mount *, int, struct proc *));
71 int kernfs_root __P((struct mount *, struct vnode **));
72 int kernfs_statfs __P((struct mount *, struct statfs *, struct proc *));
73 int kernfs_quotactl __P((struct mount *, int, uid_t, caddr_t,
74 struct proc *));
75 int kernfs_sync __P((struct mount *, int, struct ucred *, struct proc *));
76 int kernfs_vget __P((struct mount *, ino_t, struct vnode **));
77 int kernfs_fhtovp __P((struct mount *, struct fid *, struct vnode **));
78 int kernfs_checkexp __P((struct mount *, struct mbuf *, int *,
79 struct ucred **));
80 int kernfs_vptofh __P((struct vnode *, struct fid *));
81 int kernfs_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
82 struct proc *));
83
84 void
85 kernfs_init()
86 {
87 }
88
89 void
90 kernfs_done()
91 {
92 }
93
94 void
95 kernfs_get_rrootdev()
96 {
97 static int tried = 0;
98 int cmaj;
99
100 if (tried) {
101 /* Already did it once. */
102 return;
103 }
104 tried = 1;
105
106 if (rootdev == NODEV)
107 return;
108 for (cmaj = 0; cmaj < nchrdev; cmaj++) {
109 rrootdev = makedev(cmaj, minor(rootdev));
110 if (chrtoblk(rrootdev) == rootdev)
111 return;
112 }
113 rrootdev = NODEV;
114 printf("kernfs_get_rrootdev: no raw root device\n");
115 }
116
117 /*
118 * Mount the Kernel params filesystem
119 */
120 int
121 kernfs_mount(mp, path, data, ndp, p)
122 struct mount *mp;
123 const char *path;
124 void *data;
125 struct nameidata *ndp;
126 struct proc *p;
127 {
128 int error = 0;
129 size_t size;
130 struct kernfs_mount *fmp;
131 struct vnode *rvp;
132
133 #ifdef KERNFS_DIAGNOSTIC
134 printf("kernfs_mount(mp = %p)\n", mp);
135 #endif
136
137 /*
138 * Update is a no-op
139 */
140 if (mp->mnt_flag & MNT_UPDATE)
141 return (EOPNOTSUPP);
142
143 error = getnewvnode(VT_KERNFS, mp, kernfs_vnodeop_p, &rvp);
144 if (error)
145 return (error);
146
147 MALLOC(fmp, struct kernfs_mount *, sizeof(struct kernfs_mount),
148 M_MISCFSMNT, M_WAITOK);
149 rvp->v_type = VDIR;
150 rvp->v_flag |= VROOT;
151 #ifdef KERNFS_DIAGNOSTIC
152 printf("kernfs_mount: root vp = %p\n", rvp);
153 #endif
154 fmp->kf_root = rvp;
155 mp->mnt_flag |= MNT_LOCAL;
156 mp->mnt_data = (qaddr_t)fmp;
157 vfs_getnewfsid(mp);
158
159 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
160 memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
161 memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
162 memcpy(mp->mnt_stat.f_mntfromname, "kernfs", sizeof("kernfs"));
163 #ifdef KERNFS_DIAGNOSTIC
164 printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname);
165 #endif
166
167 kernfs_get_rrootdev();
168 return (0);
169 }
170
171 int
172 kernfs_start(mp, flags, p)
173 struct mount *mp;
174 int flags;
175 struct proc *p;
176 {
177
178 return (0);
179 }
180
181 int
182 kernfs_unmount(mp, mntflags, p)
183 struct mount *mp;
184 int mntflags;
185 struct proc *p;
186 {
187 int error;
188 int flags = 0;
189 struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root;
190
191 #ifdef KERNFS_DIAGNOSTIC
192 printf("kernfs_unmount(mp = %p)\n", mp);
193 #endif
194
195 if (mntflags & MNT_FORCE)
196 flags |= FORCECLOSE;
197
198 /*
199 * Clear out buffer cache. I don't think we
200 * ever get anything cached at this level at the
201 * moment, but who knows...
202 */
203 if (rootvp->v_usecount > 1)
204 return (EBUSY);
205 #ifdef KERNFS_DIAGNOSTIC
206 printf("kernfs_unmount: calling vflush\n");
207 #endif
208 if ((error = vflush(mp, rootvp, flags)) != 0)
209 return (error);
210
211 #ifdef KERNFS_DIAGNOSTIC
212 vprint("kernfs root", rootvp);
213 #endif
214 /*
215 * Clean out the old root vnode for reuse.
216 */
217 vrele(rootvp);
218 vgone(rootvp);
219 /*
220 * Finally, throw away the kernfs_mount structure
221 */
222 free(mp->mnt_data, M_MISCFSMNT);
223 mp->mnt_data = 0;
224 return (0);
225 }
226
227 int
228 kernfs_root(mp, vpp)
229 struct mount *mp;
230 struct vnode **vpp;
231 {
232 struct vnode *vp;
233
234 #ifdef KERNFS_DIAGNOSTIC
235 printf("kernfs_root(mp = %p)\n", mp);
236 #endif
237
238 /*
239 * Return locked reference to root.
240 */
241 vp = VFSTOKERNFS(mp)->kf_root;
242 VREF(vp);
243 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
244 *vpp = vp;
245 return (0);
246 }
247
248 int
249 kernfs_quotactl(mp, cmd, uid, arg, p)
250 struct mount *mp;
251 int cmd;
252 uid_t uid;
253 caddr_t arg;
254 struct proc *p;
255 {
256
257 return (EOPNOTSUPP);
258 }
259
260 int
261 kernfs_statfs(mp, sbp, p)
262 struct mount *mp;
263 struct statfs *sbp;
264 struct proc *p;
265 {
266
267 #ifdef KERNFS_DIAGNOSTIC
268 printf("kernfs_statfs(mp = %p)\n", mp);
269 #endif
270
271 sbp->f_bsize = DEV_BSIZE;
272 sbp->f_iosize = DEV_BSIZE;
273 sbp->f_blocks = 2; /* 1K to keep df happy */
274 sbp->f_bfree = 0;
275 sbp->f_bavail = 0;
276 sbp->f_files = 0;
277 sbp->f_ffree = 0;
278 #ifdef COMPAT_09
279 sbp->f_type = 7;
280 #else
281 sbp->f_type = 0;
282 #endif
283 if (sbp != &mp->mnt_stat) {
284 memcpy(&sbp->f_fsid, &mp->mnt_stat.f_fsid, sizeof(sbp->f_fsid));
285 memcpy(sbp->f_mntonname, mp->mnt_stat.f_mntonname, MNAMELEN);
286 memcpy(sbp->f_mntfromname, mp->mnt_stat.f_mntfromname, MNAMELEN);
287 }
288 strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN);
289 return (0);
290 }
291
292 /*ARGSUSED*/
293 int
294 kernfs_sync(mp, waitfor, uc, p)
295 struct mount *mp;
296 int waitfor;
297 struct ucred *uc;
298 struct proc *p;
299 {
300
301 return (0);
302 }
303
304 /*
305 * Kernfs flat namespace lookup.
306 * Currently unsupported.
307 */
308 int
309 kernfs_vget(mp, ino, vpp)
310 struct mount *mp;
311 ino_t ino;
312 struct vnode **vpp;
313 {
314
315 return (EOPNOTSUPP);
316 }
317
318 /*ARGSUSED*/
319 int
320 kernfs_fhtovp(mp, fhp, vpp)
321 struct mount *mp;
322 struct fid *fhp;
323 struct vnode **vpp;
324 {
325
326 return (EOPNOTSUPP);
327 }
328
329 /*ARGSUSED*/
330 int
331 kernfs_checkexp(mp, mb, what, anon)
332 struct mount *mp;
333 struct mbuf *mb;
334 int *what;
335 struct ucred **anon;
336 {
337
338 return (EOPNOTSUPP);
339 }
340
341 /*ARGSUSED*/
342 int
343 kernfs_vptofh(vp, fhp)
344 struct vnode *vp;
345 struct fid *fhp;
346 {
347
348 return (EOPNOTSUPP);
349 }
350
351 int
352 kernfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
353 int *name;
354 u_int namelen;
355 void *oldp;
356 size_t *oldlenp;
357 void *newp;
358 size_t newlen;
359 struct proc *p;
360 {
361 return (EOPNOTSUPP);
362 }
363
364 extern struct vnodeopv_desc kernfs_vnodeop_opv_desc;
365
366 struct vnodeopv_desc *kernfs_vnodeopv_descs[] = {
367 &kernfs_vnodeop_opv_desc,
368 NULL,
369 };
370
371 struct vfsops kernfs_vfsops = {
372 MOUNT_KERNFS,
373 kernfs_mount,
374 kernfs_start,
375 kernfs_unmount,
376 kernfs_root,
377 kernfs_quotactl,
378 kernfs_statfs,
379 kernfs_sync,
380 kernfs_vget,
381 kernfs_fhtovp,
382 kernfs_vptofh,
383 kernfs_init,
384 kernfs_done,
385 kernfs_sysctl,
386 NULL, /* vfs_mountroot */
387 kernfs_checkexp,
388 kernfs_vnodeopv_descs,
389 };
390