kernfs_vfsops.c revision 1.3 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.3 1993/03/27 00:37:09 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 struct vnode *rrootdevvp;
56
57 kernfs_init()
58 {
59 int error, bmaj, cmaj;
60
61 #ifdef KERNFS_DIAGNOSTIC
62 printf("kernfs_init\n"); /* printed during system boot */
63 #endif
64
65 bmaj = major(rootdev);
66
67 /* hunt for the raw root device by looking in cdevsw for a matching
68 * open routine...
69 */
70 for (cmaj = 0; cmaj < nchrdev; cmaj++) {
71 if (cdevsw[cmaj].d_open == bdevsw[bmaj].d_open) {
72 dev_t cdev = makedev(cmaj, minor(rootdev));
73 error = cdevvp(cdev, &rrootdevvp);
74 if (error == 0)
75 break;
76 }
77 }
78
79 /* this isn't fatal... */
80 if (error) {
81 printf("kernfs: no raw boot device\n");
82 rrootdevvp = 0;
83 }
84 }
85
86 /*
87 * Mount the kernel parameter filesystem
88 */
89 kernfs_mount(mp, path, data, ndp, p)
90 struct mount *mp;
91 char *path;
92 caddr_t data;
93 struct nameidata *ndp;
94 struct proc *p;
95 {
96 int error = 0;
97 u_int size;
98 struct kernfs_mount *fmp;
99 struct vnode *rvp;
100
101 #ifdef KERNFS_DIAGNOSTIC
102 printf("kernfs_mount(mp = %x)\n", mp);
103 #endif
104
105 /*
106 * Update is a no-op
107 */
108 if (mp->mnt_flag & MNT_UPDATE)
109 return (EOPNOTSUPP);
110
111 error = getnewvnode(VT_UFS, mp, &kernfs_vnodeops, &rvp); /* XXX */
112 if (error)
113 return (error);
114
115 fmp = (struct kernfs_mount *) malloc(sizeof(struct kernfs_mount),
116 M_UFSMNT, M_WAITOK); /* XXX */
117 rvp->v_type = VDIR;
118 rvp->v_flag |= VROOT;
119 #ifdef KERNFS_DIAGNOSTIC
120 printf("kernfs_mount: root vp = %x\n", rvp);
121 #endif
122 fmp->kf_root = rvp;
123 mp->mnt_flag |= MNT_LOCAL;
124 mp->mnt_data = (qaddr_t) fmp;
125 getnewfsid(mp, MOUNT_KERNFS);
126
127 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
128 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
129 bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
130 bcopy("kernfs", mp->mnt_stat.f_mntfromname, sizeof("kernfs"));
131 #ifdef KERNFS_DIAGNOSTIC
132 printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname);
133 #endif
134 return (0);
135 }
136
137 kernfs_start(mp, flags, p)
138 struct mount *mp;
139 int flags;
140 struct proc *p;
141 {
142 return (0);
143 }
144
145 kernfs_unmount(mp, mntflags, p)
146 struct mount *mp;
147 int mntflags;
148 struct proc *p;
149 {
150 int error;
151 int flags = 0;
152 extern int doforce;
153 struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root;
154
155 #ifdef KERNFS_DIAGNOSTIC
156 printf("kernfs_unmount(mp = %x)\n", mp);
157 #endif
158
159 if (mntflags & MNT_FORCE) {
160 /* kernfs can never be rootfs so don't check for it */
161 if (!doforce)
162 return (EINVAL);
163 flags |= FORCECLOSE;
164 }
165
166 /*
167 * Clear out buffer cache. I don't think we
168 * ever get anything cached at this level at the
169 * moment, but who knows...
170 */
171 #ifdef KERNFS_DIAGNOSTIC
172 printf("kernfs_unmount: calling mntflushbuf\n");
173 #endif
174 mntflushbuf(mp, 0);
175 #ifdef KERNFS_DIAGNOSTIC
176 printf("kernfs_unmount: calling mntinvalbuf\n");
177 #endif
178 if (mntinvalbuf(mp, 1))
179 return (EBUSY);
180 if (rootvp->v_usecount > 1)
181 return (EBUSY);
182 #ifdef KERNFS_DIAGNOSTIC
183 printf("kernfs_unmount: calling vflush\n");
184 #endif
185 if (error = vflush(mp, rootvp, flags))
186 return (error);
187
188 #ifdef KERNFS_DIAGNOSTIC
189 vprint("kernfs root", rootvp);
190 #endif
191 /*
192 * Release reference on underlying root vnode
193 */
194 vrele(rootvp);
195 /*
196 * And blow it away for future re-use
197 */
198 vgone(rootvp);
199 /*
200 * Finally, throw away the kernfs_mount structure
201 */
202 free(mp->mnt_data, M_UFSMNT); /* XXX */
203 mp->mnt_data = 0;
204 return 0;
205 }
206
207 kernfs_root(mp, vpp)
208 struct mount *mp;
209 struct vnode **vpp;
210 {
211 struct vnode *vp;
212 int error;
213
214 #ifdef KERNFS_DIAGNOSTIC
215 printf("kernfs_root(mp = %x)\n", mp);
216 #endif
217
218 /*
219 * Return locked reference to root.
220 */
221 vp = VFSTOKERNFS(mp)->kf_root;
222 VREF(vp);
223 VOP_LOCK(vp);
224 *vpp = vp;
225 return (0);
226 }
227
228 kernfs_quotactl(mp, cmd, uid, arg, p)
229 struct mount *mp;
230 int cmd;
231 uid_t uid;
232 caddr_t arg;
233 struct proc *p;
234 {
235 return (EOPNOTSUPP);
236 }
237
238 kernfs_statfs(mp, sbp, p)
239 struct mount *mp;
240 struct statfs *sbp;
241 struct proc *p;
242 {
243 struct filedesc *fdp;
244 int lim;
245 int i;
246 int last;
247 int freefd;
248
249 #ifdef KERNFS_DIAGNOSTIC
250 printf("kernfs_statfs(mp = %x)\n", mp);
251 #endif
252
253 sbp->f_type = MOUNT_KERNFS;
254 sbp->f_flags = 0;
255 sbp->f_fsize = DEV_BSIZE;
256 sbp->f_bsize = DEV_BSIZE;
257 sbp->f_blocks = 2; /* 1K to keep df happy */
258 sbp->f_bfree = 0;
259 sbp->f_bavail = 0;
260 sbp->f_files = 0; /* Allow for "." */
261 sbp->f_ffree = 0; /* See comments above */
262 if (sbp != &mp->mnt_stat) {
263 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
264 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
265 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
266 }
267 return (0);
268 }
269
270 kernfs_sync(mp, waitfor)
271 struct mount *mp;
272 int waitfor;
273 {
274 return (0);
275 }
276
277 kernfs_fhtovp(mp, fhp, vpp)
278 struct mount *mp;
279 struct fid *fhp;
280 struct vnode **vpp;
281 {
282 return (EOPNOTSUPP);
283 }
284
285 kernfs_vptofh(vp, fhp)
286 struct vnode *vp;
287 struct fid *fhp;
288 {
289 return (EOPNOTSUPP);
290 }
291
292 struct vfsops kernfs_vfsops = {
293 kernfs_mount,
294 kernfs_start,
295 kernfs_unmount,
296 kernfs_root,
297 kernfs_quotactl,
298 kernfs_statfs,
299 kernfs_sync,
300 kernfs_fhtovp,
301 kernfs_vptofh,
302 kernfs_init,
303 };
304