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