kernfs_vfsops.c revision 1.4 1 /*
2 * Copyright (c) 1990, 1992 Jan-Simon Pendry
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Jan-Simon Pendry.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * $Id: kernfs_vfsops.c,v 1.4 1993/03/27 02:00:45 cgd Exp $
37 */
38
39 /*
40 * Kernel params Filesystem
41 */
42
43 #include "param.h"
44 #include "systm.h"
45 #include "time.h"
46 #include "types.h"
47 #include "proc.h"
48 #include "vnode.h"
49 #include "mount.h"
50 #include "namei.h"
51 #include "malloc.h"
52 #include "conf.h"
53 #include "miscfs/kernfs/kernfs.h"
54
55 /* bring in the spec vnodeops for cdevvp */
56 extern struct vnodeops spec_vnodeops;
57
58 struct vnode *rrootdevvp;
59
60 /*
61 * cdevvp:
62 * get a character device node.
63 * this is used a few places in the miscfs routines.
64 *
65 * copied from the bdevvp in kern/vfs_subr.c
66 */
67 cdevvp(dev, vpp)
68 dev_t dev;
69 struct vnode **vpp;
70 {
71 register struct vnode *vp;
72 struct vnode *nvp;
73 int error;
74
75 if (dev == NODEV)
76 return (0);
77 error = getnewvnode(VT_NON, (struct mount *)0, &spec_vnodeops, &nvp);
78 if (error) {
79 *vpp = 0;
80 return (error);
81 }
82 vp = nvp;
83 vp->v_type = VCHR;
84 if (nvp = checkalias(vp, dev, (struct mount *)0)) {
85 vput(vp);
86 vp = nvp;
87 }
88 *vpp = vp;
89 return (0);
90 }
91
92 kernfs_init()
93 {
94 int error, bmaj, cmaj;
95
96 #ifdef KERNFS_DIAGNOSTIC
97 printf("kernfs_init\n"); /* printed during system boot */
98 #endif
99
100 bmaj = major(rootdev);
101
102 /* hunt for the raw root device by looking in cdevsw for a matching
103 * open routine...
104 */
105 for (cmaj = 0; cmaj < nchrdev; cmaj++) {
106 if (cdevsw[cmaj].d_open == bdevsw[bmaj].d_open) {
107 dev_t cdev = makedev(cmaj, minor(rootdev));
108 error = cdevvp(cdev, &rrootdevvp);
109 if (error == 0)
110 break;
111 }
112 }
113
114 /* this isn't fatal... */
115 if (error) {
116 printf("kernfs: no raw boot device\n");
117 rrootdevvp = 0;
118 }
119 }
120
121 /*
122 * Mount the kernel parameter filesystem
123 */
124 kernfs_mount(mp, path, data, ndp, p)
125 struct mount *mp;
126 char *path;
127 caddr_t data;
128 struct nameidata *ndp;
129 struct proc *p;
130 {
131 int error = 0;
132 u_int size;
133 struct kernfs_mount *fmp;
134 struct vnode *rvp;
135
136 #ifdef KERNFS_DIAGNOSTIC
137 printf("kernfs_mount(mp = %x)\n", mp);
138 #endif
139
140 /*
141 * Update is a no-op
142 */
143 if (mp->mnt_flag & MNT_UPDATE)
144 return (EOPNOTSUPP);
145
146 error = getnewvnode(VT_UFS, mp, &kernfs_vnodeops, &rvp); /* XXX */
147 if (error)
148 return (error);
149
150 fmp = (struct kernfs_mount *) malloc(sizeof(struct kernfs_mount),
151 M_UFSMNT, M_WAITOK); /* XXX */
152 rvp->v_type = VDIR;
153 rvp->v_flag |= VROOT;
154 #ifdef KERNFS_DIAGNOSTIC
155 printf("kernfs_mount: root vp = %x\n", rvp);
156 #endif
157 fmp->kf_root = rvp;
158 mp->mnt_flag |= MNT_LOCAL;
159 mp->mnt_data = (qaddr_t) fmp;
160 getnewfsid(mp, MOUNT_KERNFS);
161
162 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
163 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
164 bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
165 bcopy("kernfs", mp->mnt_stat.f_mntfromname, sizeof("kernfs"));
166 #ifdef KERNFS_DIAGNOSTIC
167 printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname);
168 #endif
169 return (0);
170 }
171
172 kernfs_start(mp, flags, p)
173 struct mount *mp;
174 int flags;
175 struct proc *p;
176 {
177 return (0);
178 }
179
180 kernfs_unmount(mp, mntflags, p)
181 struct mount *mp;
182 int mntflags;
183 struct proc *p;
184 {
185 int error;
186 int flags = 0;
187 extern int doforce;
188 struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root;
189
190 #ifdef KERNFS_DIAGNOSTIC
191 printf("kernfs_unmount(mp = %x)\n", mp);
192 #endif
193
194 if (mntflags & MNT_FORCE) {
195 /* kernfs can never be rootfs so don't check for it */
196 if (!doforce)
197 return (EINVAL);
198 flags |= FORCECLOSE;
199 }
200
201 /*
202 * Clear out buffer cache. I don't think we
203 * ever get anything cached at this level at the
204 * moment, but who knows...
205 */
206 #ifdef KERNFS_DIAGNOSTIC
207 printf("kernfs_unmount: calling mntflushbuf\n");
208 #endif
209 mntflushbuf(mp, 0);
210 #ifdef KERNFS_DIAGNOSTIC
211 printf("kernfs_unmount: calling mntinvalbuf\n");
212 #endif
213 if (mntinvalbuf(mp, 1))
214 return (EBUSY);
215 if (rootvp->v_usecount > 1)
216 return (EBUSY);
217 #ifdef KERNFS_DIAGNOSTIC
218 printf("kernfs_unmount: calling vflush\n");
219 #endif
220 if (error = vflush(mp, rootvp, flags))
221 return (error);
222
223 #ifdef KERNFS_DIAGNOSTIC
224 vprint("kernfs root", rootvp);
225 #endif
226 /*
227 * Release reference on underlying root vnode
228 */
229 vrele(rootvp);
230 /*
231 * And blow it away for future re-use
232 */
233 vgone(rootvp);
234 /*
235 * Finally, throw away the kernfs_mount structure
236 */
237 free(mp->mnt_data, M_UFSMNT); /* XXX */
238 mp->mnt_data = 0;
239 return 0;
240 }
241
242 kernfs_root(mp, vpp)
243 struct mount *mp;
244 struct vnode **vpp;
245 {
246 struct vnode *vp;
247 int error;
248
249 #ifdef KERNFS_DIAGNOSTIC
250 printf("kernfs_root(mp = %x)\n", mp);
251 #endif
252
253 /*
254 * Return locked reference to root.
255 */
256 vp = VFSTOKERNFS(mp)->kf_root;
257 VREF(vp);
258 VOP_LOCK(vp);
259 *vpp = vp;
260 return (0);
261 }
262
263 kernfs_quotactl(mp, cmd, uid, arg, p)
264 struct mount *mp;
265 int cmd;
266 uid_t uid;
267 caddr_t arg;
268 struct proc *p;
269 {
270 return (EOPNOTSUPP);
271 }
272
273 kernfs_statfs(mp, sbp, p)
274 struct mount *mp;
275 struct statfs *sbp;
276 struct proc *p;
277 {
278 struct filedesc *fdp;
279 int lim;
280 int i;
281 int last;
282 int freefd;
283
284 #ifdef KERNFS_DIAGNOSTIC
285 printf("kernfs_statfs(mp = %x)\n", mp);
286 #endif
287
288 sbp->f_type = MOUNT_KERNFS;
289 sbp->f_flags = 0;
290 sbp->f_fsize = DEV_BSIZE;
291 sbp->f_bsize = DEV_BSIZE;
292 sbp->f_blocks = 2; /* 1K to keep df happy */
293 sbp->f_bfree = 0;
294 sbp->f_bavail = 0;
295 sbp->f_files = 0; /* Allow for "." */
296 sbp->f_ffree = 0; /* See comments above */
297 if (sbp != &mp->mnt_stat) {
298 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
299 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
300 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
301 }
302 return (0);
303 }
304
305 kernfs_sync(mp, waitfor)
306 struct mount *mp;
307 int waitfor;
308 {
309 return (0);
310 }
311
312 kernfs_fhtovp(mp, fhp, vpp)
313 struct mount *mp;
314 struct fid *fhp;
315 struct vnode **vpp;
316 {
317 return (EOPNOTSUPP);
318 }
319
320 kernfs_vptofh(vp, fhp)
321 struct vnode *vp;
322 struct fid *fhp;
323 {
324 return (EOPNOTSUPP);
325 }
326
327 struct vfsops kernfs_vfsops = {
328 kernfs_mount,
329 kernfs_start,
330 kernfs_unmount,
331 kernfs_root,
332 kernfs_quotactl,
333 kernfs_statfs,
334 kernfs_sync,
335 kernfs_fhtovp,
336 kernfs_vptofh,
337 kernfs_init,
338 };
339