xref: /netbsd-src/sys/miscfs/kernfs/kernfs_vfsops.c (revision cda4f8f6ee55684e8d311b86c99ea59191e6b74f)
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 1993/06/07 05:25:24 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 root 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_KERNFS, mp, &kernfs_vnodeops, &rvp);
147 	if (error)
148 		return (error);
149 
150 	fmp = (struct kernfs_mount *) malloc(sizeof(struct kernfs_mount),
151 				 M_MISCFSMNT, M_WAITOK);
152 	rvp->v_type = VDIR;
153 	rvp->v_flag |= VROOT;
154 	VTOKERN(rvp)->kf_kt = &kernfs_targets[KERNFS_TARGET_ROOT];
155 #ifdef KERNFS_DIAGNOSTIC
156 	printf("kernfs_mount: root vp = %x\n", rvp);
157 #endif
158 	fmp->kf_root = rvp;
159 	mp->mnt_flag |= MNT_LOCAL;
160 	mp->mnt_data = (qaddr_t) fmp;
161 	getnewfsid(mp, MOUNT_KERNFS);
162 
163 	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
164 	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
165 	bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
166 	bcopy("kernfs", mp->mnt_stat.f_mntfromname, sizeof("kernfs"));
167 #ifdef KERNFS_DIAGNOSTIC
168 	printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname);
169 #endif
170 	return (0);
171 }
172 
173 kernfs_start(mp, flags, p)
174 	struct mount *mp;
175 	int flags;
176 	struct proc *p;
177 {
178 	return (0);
179 }
180 
181 kernfs_unmount(mp, mntflags, p)
182 	struct mount *mp;
183 	int mntflags;
184 	struct proc *p;
185 {
186 	int error;
187 	int flags = 0;
188 	extern int doforce;
189 	struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root;
190 
191 #ifdef KERNFS_DIAGNOSTIC
192 	printf("kernfs_unmount(mp = %x)\n", mp);
193 #endif
194 
195 	if (mntflags & MNT_FORCE) {
196 		/* kernfs can never be rootfs so don't check for it */
197 		if (!doforce)
198 			return (EINVAL);
199 		flags |= FORCECLOSE;
200 	}
201 
202 	/*
203 	 * Clear out buffer cache.  I don't think we
204 	 * ever get anything cached at this level at the
205 	 * moment, but who knows...
206 	 */
207 #ifdef KERNFS_DIAGNOSTIC
208 	printf("kernfs_unmount: calling mntflushbuf\n");
209 #endif
210 	mntflushbuf(mp, 0);
211 #ifdef KERNFS_DIAGNOSTIC
212 	printf("kernfs_unmount: calling mntinvalbuf\n");
213 #endif
214 	if (mntinvalbuf(mp, 1))
215 		return (EBUSY);
216 	if (rootvp->v_usecount > 1)
217 		return (EBUSY);
218 #ifdef KERNFS_DIAGNOSTIC
219 	printf("kernfs_unmount: calling vflush\n");
220 #endif
221 	if (error = vflush(mp, rootvp, flags))
222 		return (error);
223 
224 #ifdef KERNFS_DIAGNOSTIC
225 	vprint("kernfs root", rootvp);
226 #endif
227 	/*
228 	 * Release reference on underlying root vnode
229 	 */
230 	vrele(rootvp);
231 	/*
232 	 * And blow it away for future re-use
233 	 */
234 	vgone(rootvp);
235 	/*
236 	 * Finally, throw away the kernfs_mount structure
237 	 */
238 	free(mp->mnt_data, M_MISCFSMNT);
239 	mp->mnt_data = 0;
240 	return 0;
241 }
242 
243 kernfs_root(mp, vpp)
244 	struct mount *mp;
245 	struct vnode **vpp;
246 {
247 	struct vnode *vp;
248 	int error;
249 
250 #ifdef KERNFS_DIAGNOSTIC
251 	printf("kernfs_root(mp = %x)\n", mp);
252 #endif
253 
254 	/*
255 	 * Return locked reference to root.
256 	 */
257 	vp = VFSTOKERNFS(mp)->kf_root;
258 	VREF(vp);
259 	VOP_LOCK(vp);
260 	*vpp = vp;
261 	return (0);
262 }
263 
264 kernfs_quotactl(mp, cmd, uid, arg, p)
265 	struct mount *mp;
266 	int cmd;
267 	uid_t uid;
268 	caddr_t arg;
269 	struct proc *p;
270 {
271 	return (EOPNOTSUPP);
272 }
273 
274 kernfs_statfs(mp, sbp, p)
275 	struct mount *mp;
276 	struct statfs *sbp;
277 	struct proc *p;
278 {
279 	struct filedesc *fdp;
280 	int lim;
281 	int i;
282 	int last;
283 	int freefd;
284 
285 #ifdef KERNFS_DIAGNOSTIC
286 	printf("kernfs_statfs(mp = %x)\n", mp);
287 #endif
288 
289 	sbp->f_type = MOUNT_KERNFS;
290 	sbp->f_flags = 0;
291 	sbp->f_fsize = DEV_BSIZE;
292 	sbp->f_bsize = DEV_BSIZE;
293 	sbp->f_blocks = 2;		/* 1K to keep df happy */
294 	sbp->f_bfree = 0;
295 	sbp->f_bavail = 0;
296 	sbp->f_files = 0;		/* Allow for "." */
297 	sbp->f_ffree = 0;		/* See comments above */
298 	if (sbp != &mp->mnt_stat) {
299 		bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
300 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
301 		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
302 	}
303 	return (0);
304 }
305 
306 kernfs_sync(mp, waitfor)
307 	struct mount *mp;
308 	int waitfor;
309 {
310 	return (0);
311 }
312 
313 kernfs_fhtovp(mp, fhp, vpp)
314 	struct mount *mp;
315 	struct fid *fhp;
316 	struct vnode **vpp;
317 {
318 	return (EOPNOTSUPP);
319 }
320 
321 kernfs_vptofh(vp, fhp)
322 	struct vnode *vp;
323 	struct fid *fhp;
324 {
325 	return (EOPNOTSUPP);
326 }
327 
328 struct vfsops kernfs_vfsops = {
329 	kernfs_mount,
330 	kernfs_start,
331 	kernfs_unmount,
332 	kernfs_root,
333 	kernfs_quotactl,
334 	kernfs_statfs,
335 	kernfs_sync,
336 	kernfs_fhtovp,
337 	kernfs_vptofh,
338 	kernfs_init,
339 };
340