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