xref: /netbsd-src/sys/miscfs/kernfs/kernfs_vfsops.c (revision 0b9f50897e9a9c6709320fafb4c3787fddcc0a45)
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.8 1993/08/23 05:02:14 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