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