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  * %sccs.include.redist.c%
10  *
11  *	@(#)kernfs_vfsops.c	7.1 (Berkeley) 07/18/92
12  */
13 
14 /*
15  * Kernel params Filesystem
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/time.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 #include <miscfs/kernfs/kernfs.h>
28 
29 kernfs_init()
30 {
31 #ifdef KERNFS_DIAGNOSTIC
32 	printf("kernfs_init\n");		/* printed during system boot */
33 #endif
34 }
35 
36 /*
37  * Mount the Kernel params filesystem
38  */
39 kernfs_mount(mp, path, data, ndp, p)
40 	struct mount *mp;
41 	char *path;
42 	caddr_t data;
43 	struct nameidata *ndp;
44 	struct proc *p;
45 {
46 	int error = 0;
47 	u_int size;
48 	struct kernfs_mount *fmp;
49 	struct vnode *rvp;
50 
51 #ifdef KERNFS_DIAGNOSTIC
52 	printf("kernfs_mount(mp = %x)\n", mp);
53 #endif
54 
55 	/*
56 	 * Update is a no-op
57 	 */
58 	if (mp->mnt_flag & MNT_UPDATE)
59 		return (EOPNOTSUPP);
60 
61 	error = getnewvnode(VT_UFS, mp, kernfs_vnodeop_p, &rvp);	/* XXX */
62 	if (error)
63 		return (error);
64 
65 	MALLOC(fmp, struct kernfs_mount *, sizeof(struct kernfs_mount),
66 				M_UFSMNT, M_WAITOK);	/* XXX */
67 	rvp->v_type = VDIR;
68 	rvp->v_flag |= VROOT;
69 #ifdef KERNFS_DIAGNOSTIC
70 	printf("kernfs_mount: root vp = %x\n", rvp);
71 #endif
72 	fmp->kf_root = rvp;
73 	mp->mnt_flag |= MNT_LOCAL;
74 	mp->mnt_data = (qaddr_t) fmp;
75 	getnewfsid(mp, MOUNT_KERNFS);
76 
77 	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
78 	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
79 	bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
80 	bcopy("kernfs", mp->mnt_stat.f_mntfromname, sizeof("kernfs"));
81 #ifdef KERNFS_DIAGNOSTIC
82 	printf("kernfs_mount: at %s\n", mp->mnt_stat.f_mntonname);
83 #endif
84 	return (0);
85 }
86 
87 kernfs_start(mp, flags, p)
88 	struct mount *mp;
89 	int flags;
90 	struct proc *p;
91 {
92 	return (0);
93 }
94 
95 kernfs_unmount(mp, mntflags, p)
96 	struct mount *mp;
97 	int mntflags;
98 	struct proc *p;
99 {
100 	int error;
101 	int flags = 0;
102 	extern int doforce;
103 	struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root;
104 
105 #ifdef KERNFS_DIAGNOSTIC
106 	printf("kernfs_unmount(mp = %x)\n", mp);
107 #endif
108 
109 	if (mntflags & MNT_FORCE) {
110 		/* kernfs can never be rootfs so don't check for it */
111 		if (!doforce)
112 			return (EINVAL);
113 		flags |= FORCECLOSE;
114 	}
115 
116 	/*
117 	 * Clear out buffer cache.  I don't think we
118 	 * ever get anything cached at this level at the
119 	 * moment, but who knows...
120 	 */
121 #if 0
122 #ifdef KERNFS_DIAGNOSTIC
123 	printf("kernfs_unmount: calling mntflushbuf\n");
124 #endif
125 	mntflushbuf(mp, 0);
126 #ifdef KERNFS_DIAGNOSTIC
127 	printf("kernfs_unmount: calling mntinvalbuf\n");
128 #endif
129 	if (mntinvalbuf(mp, 1))
130 		return (EBUSY);
131 #endif
132 	if (rootvp->v_usecount > 1)
133 		return (EBUSY);
134 #ifdef KERNFS_DIAGNOSTIC
135 	printf("kernfs_unmount: calling vflush\n");
136 #endif
137 	if (error = vflush(mp, rootvp, flags))
138 		return (error);
139 
140 #ifdef KERNFS_DIAGNOSTIC
141 	vprint("kernfs root", rootvp);
142 #endif
143 	/*
144 	 * Release reference on underlying root vnode
145 	 */
146 	vrele(rootvp);
147 	/*
148 	 * And blow it away for future re-use
149 	 */
150 	vgone(rootvp);
151 	/*
152 	 * Finally, throw away the kernfs_mount structure
153 	 */
154 	free(mp->mnt_data, M_UFSMNT);	/* XXX */
155 	mp->mnt_data = 0;
156 	return 0;
157 }
158 
159 kernfs_root(mp, vpp)
160 	struct mount *mp;
161 	struct vnode **vpp;
162 {
163 	struct vnode *vp;
164 	int error;
165 
166 #ifdef KERNFS_DIAGNOSTIC
167 	printf("kernfs_root(mp = %x)\n", mp);
168 #endif
169 
170 	/*
171 	 * Return locked reference to root.
172 	 */
173 	vp = VFSTOKERNFS(mp)->kf_root;
174 	VREF(vp);
175 	VOP_LOCK(vp);
176 	*vpp = vp;
177 	return (0);
178 }
179 
180 kernfs_quotactl(mp, cmd, uid, arg, p)
181 	struct mount *mp;
182 	int cmd;
183 	uid_t uid;
184 	caddr_t arg;
185 	struct proc *p;
186 {
187 	return (EOPNOTSUPP);
188 }
189 
190 kernfs_statfs(mp, sbp, p)
191 	struct mount *mp;
192 	struct statfs *sbp;
193 	struct proc *p;
194 {
195 #ifdef KERNFS_DIAGNOSTIC
196 	printf("kernfs_statfs(mp = %x)\n", mp);
197 #endif
198 
199 	sbp->f_type = MOUNT_KERNFS;
200 	sbp->f_flags = 0;
201 	sbp->f_bsize = DEV_BSIZE;
202 	sbp->f_iosize = DEV_BSIZE;
203 	sbp->f_blocks = 2;		/* 1K to keep df happy */
204 	sbp->f_bfree = 0;
205 	sbp->f_bavail = 0;
206 	sbp->f_files = 0;		/* Allow for "." */
207 	sbp->f_ffree = 0;		/* See comments above */
208 	if (sbp != &mp->mnt_stat) {
209 		bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
210 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
211 		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
212 	}
213 	return (0);
214 }
215 
216 kernfs_sync(mp, waitfor)
217 	struct mount *mp;
218 	int waitfor;
219 {
220 	return (0);
221 }
222 
223 /*
224  * Fdesc flat namespace lookup.
225  * Currently unsupported.
226  */
227 kernfs_vget(mp, ino, vpp)
228 	struct mount *mp;
229 	ino_t ino;
230 	struct vnode **vpp;
231 {
232 
233 	return (EOPNOTSUPP);
234 }
235 
236 
237 kernfs_fhtovp(mp, fhp, setgen, vpp)
238 	struct mount *mp;
239 	struct fid *fhp;
240 	int setgen;
241 	struct vnode **vpp;
242 {
243 	return (EOPNOTSUPP);
244 }
245 
246 kernfs_vptofh(vp, fhp)
247 	struct vnode *vp;
248 	struct fid *fhp;
249 {
250 	return (EOPNOTSUPP);
251 }
252 
253 struct vfsops kernfs_vfsops = {
254 	kernfs_mount,
255 	kernfs_start,
256 	kernfs_unmount,
257 	kernfs_root,
258 	kernfs_quotactl,
259 	kernfs_statfs,
260 	kernfs_sync,
261 	kernfs_vget,
262 	kernfs_fhtovp,
263 	kernfs_vptofh,
264 	kernfs_init,
265 };
266