1 /*
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  * All rights reserved.
5  *
6  * This code is derived from software donated to Berkeley by
7  * Jan-Simon Pendry.
8  *
9  * %sccs.include.redist.c%
10  *
11  *	@(#)kernfs_vfsops.c	8.3 (Berkeley) 01/04/94
12  */
13 
14 /*
15  * Kernel params Filesystem
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/conf.h>
21 #include <sys/types.h>
22 #include <sys/proc.h>
23 #include <sys/vnode.h>
24 #include <sys/mount.h>
25 #include <sys/namei.h>
26 #include <sys/malloc.h>
27 
28 #include <miscfs/specfs/specdev.h>
29 #include <miscfs/kernfs/kernfs.h>
30 
31 struct vnode *rrootvp;
32 
33 /*
34  * Create a vnode for a character device.
35  */
36 int
37 cdevvp(dev, vpp)
38 	dev_t dev;
39 	struct vnode **vpp;
40 {
41 	register struct vnode *vp;
42 	struct vnode *nvp;
43 	int error;
44 
45 	if (dev == NODEV)
46 		return (0);
47 	error = getnewvnode(VT_NON, (struct mount *)0, spec_vnodeop_p, &nvp);
48 	if (error) {
49 		*vpp = 0;
50 		return (error);
51 	}
52 	vp = nvp;
53 	vp->v_type = VCHR;
54 	if (nvp = checkalias(vp, dev, (struct mount *)0)) {
55 		vput(vp);
56 		vp = nvp;
57 	}
58 	*vpp = vp;
59 	return (0);
60 }
61 
62 kernfs_init()
63 {
64 	int cmaj;
65 	int bmaj = major(rootdev);
66 	int error = ENXIO;
67 
68 #ifdef KERNFS_DIAGNOSTIC
69 	printf("kernfs_init\n");		/* printed during system boot */
70 #endif
71 
72 	for (cmaj = 0; cmaj < nchrdev; cmaj++) {
73 		if (cdevsw[cmaj].d_open == bdevsw[bmaj].d_open) {
74 			dev_t cdev = makedev(cmaj, minor(rootdev));
75 			error = cdevvp(cdev, &rrootvp);
76 			if (error == 0)
77 				break;
78 		}
79 	}
80 
81 	if (error) {
82 		printf("kernfs: no raw boot device\n");
83 		rrootvp = 0;
84 	}
85 }
86 
87 /*
88  * Mount the Kernel params filesystem
89  */
90 kernfs_mount(mp, path, data, ndp, p)
91 	struct mount *mp;
92 	char *path;
93 	caddr_t data;
94 	struct nameidata *ndp;
95 	struct proc *p;
96 {
97 	int error = 0;
98 	u_int size;
99 	struct kernfs_mount *fmp;
100 	struct vnode *rvp;
101 
102 #ifdef KERNFS_DIAGNOSTIC
103 	printf("kernfs_mount(mp = %x)\n", mp);
104 #endif
105 
106 	/*
107 	 * Update is a no-op
108 	 */
109 	if (mp->mnt_flag & MNT_UPDATE)
110 		return (EOPNOTSUPP);
111 
112 	error = getnewvnode(VT_KERNFS, mp, kernfs_vnodeop_p, &rvp);	/* XXX */
113 	if (error)
114 		return (error);
115 
116 	MALLOC(fmp, struct kernfs_mount *, sizeof(struct kernfs_mount),
117 				M_UFSMNT, M_WAITOK);	/* XXX */
118 	rvp->v_type = VDIR;
119 	rvp->v_flag |= VROOT;
120 #ifdef KERNFS_DIAGNOSTIC
121 	printf("kernfs_mount: root vp = %x\n", rvp);
122 #endif
123 	fmp->kf_root = rvp;
124 	mp->mnt_flag |= MNT_LOCAL;
125 	mp->mnt_data = (qaddr_t) fmp;
126 	getnewfsid(mp, MOUNT_KERNFS);
127 
128 	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
129 	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
130 	bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
131 	bcopy("kernfs", mp->mnt_stat.f_mntfromname, sizeof("kernfs"));
132 #ifdef KERNFS_DIAGNOSTIC
133 	printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname);
134 #endif
135 	return (0);
136 }
137 
138 kernfs_start(mp, flags, p)
139 	struct mount *mp;
140 	int flags;
141 	struct proc *p;
142 {
143 	return (0);
144 }
145 
146 kernfs_unmount(mp, mntflags, p)
147 	struct mount *mp;
148 	int mntflags;
149 	struct proc *p;
150 {
151 	int error;
152 	int flags = 0;
153 	extern int doforce;
154 	struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root;
155 
156 #ifdef KERNFS_DIAGNOSTIC
157 	printf("kernfs_unmount(mp = %x)\n", mp);
158 #endif
159 
160 	if (mntflags & MNT_FORCE) {
161 		/* kernfs can never be rootfs so don't check for it */
162 		if (!doforce)
163 			return (EINVAL);
164 		flags |= FORCECLOSE;
165 	}
166 
167 	/*
168 	 * Clear out buffer cache.  I don't think we
169 	 * ever get anything cached at this level at the
170 	 * moment, but who knows...
171 	 */
172 	if (rootvp->v_usecount > 1)
173 		return (EBUSY);
174 #ifdef KERNFS_DIAGNOSTIC
175 	printf("kernfs_unmount: calling vflush\n");
176 #endif
177 	if (error = vflush(mp, rootvp, flags))
178 		return (error);
179 
180 #ifdef KERNFS_DIAGNOSTIC
181 	vprint("kernfs root", rootvp);
182 #endif
183 	/*
184 	 * Release reference on underlying root vnode
185 	 */
186 	vrele(rootvp);
187 	/*
188 	 * And blow it away for future re-use
189 	 */
190 	vgone(rootvp);
191 	/*
192 	 * Finally, throw away the kernfs_mount structure
193 	 */
194 	free(mp->mnt_data, M_UFSMNT);	/* XXX */
195 	mp->mnt_data = 0;
196 	return 0;
197 }
198 
199 kernfs_root(mp, vpp)
200 	struct mount *mp;
201 	struct vnode **vpp;
202 {
203 	struct vnode *vp;
204 
205 #ifdef KERNFS_DIAGNOSTIC
206 	printf("kernfs_root(mp = %x)\n", mp);
207 #endif
208 
209 	/*
210 	 * Return locked reference to root.
211 	 */
212 	vp = VFSTOKERNFS(mp)->kf_root;
213 	VREF(vp);
214 	VOP_LOCK(vp);
215 	*vpp = vp;
216 	return (0);
217 }
218 
219 kernfs_quotactl(mp, cmd, uid, arg, p)
220 	struct mount *mp;
221 	int cmd;
222 	uid_t uid;
223 	caddr_t arg;
224 	struct proc *p;
225 {
226 	return (EOPNOTSUPP);
227 }
228 
229 kernfs_statfs(mp, sbp, p)
230 	struct mount *mp;
231 	struct statfs *sbp;
232 	struct proc *p;
233 {
234 #ifdef KERNFS_DIAGNOSTIC
235 	printf("kernfs_statfs(mp = %x)\n", mp);
236 #endif
237 
238 	sbp->f_type = MOUNT_KERNFS;
239 	sbp->f_flags = 0;
240 	sbp->f_bsize = DEV_BSIZE;
241 	sbp->f_iosize = DEV_BSIZE;
242 	sbp->f_blocks = 2;		/* 1K to keep df happy */
243 	sbp->f_bfree = 0;
244 	sbp->f_bavail = 0;
245 	sbp->f_files = 0;
246 	sbp->f_ffree = 0;
247 	if (sbp != &mp->mnt_stat) {
248 		bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
249 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
250 		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
251 	}
252 	return (0);
253 }
254 
255 kernfs_sync(mp, waitfor)
256 	struct mount *mp;
257 	int waitfor;
258 {
259 	return (0);
260 }
261 
262 /*
263  * Kernfs flat namespace lookup.
264  * Currently unsupported.
265  */
266 kernfs_vget(mp, ino, vpp)
267 	struct mount *mp;
268 	ino_t ino;
269 	struct vnode **vpp;
270 {
271 
272 	return (EOPNOTSUPP);
273 }
274 
275 
276 kernfs_fhtovp(mp, fhp, setgen, vpp)
277 	struct mount *mp;
278 	struct fid *fhp;
279 	int setgen;
280 	struct vnode **vpp;
281 {
282 	return (EOPNOTSUPP);
283 }
284 
285 kernfs_vptofh(vp, fhp)
286 	struct vnode *vp;
287 	struct fid *fhp;
288 {
289 	return (EOPNOTSUPP);
290 }
291 
292 struct vfsops kernfs_vfsops = {
293 	kernfs_mount,
294 	kernfs_start,
295 	kernfs_unmount,
296 	kernfs_root,
297 	kernfs_quotactl,
298 	kernfs_statfs,
299 	kernfs_sync,
300 	kernfs_vget,
301 	kernfs_fhtovp,
302 	kernfs_vptofh,
303 	kernfs_init,
304 };
305