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  *	@(#)umap_vfsops.c	1.1 (Berkeley) 07/11/92
12  *
13  * @(#)lofs_vfsops.c	1.2 (Berkeley) 6/18/92
14  * $Id: lofs_vfsops.c,v 1.9 1992/05/30 10:26:24 jsp Exp jsp $
15  */
16 
17 /*
18  * Null Layer
19  * (See umap_vnops.c for a description of what this does.)
20  */
21 
22 #include <sys/param.h>
23 #include <sys/systm.h>
24 #include <sys/time.h>
25 #include <sys/types.h>
26 #include <sys/vnode.h>
27 #include <sys/mount.h>
28 #include <sys/namei.h>
29 #include <sys/malloc.h>
30 #include <umapfs/umap.h>
31 
32 /*
33  * Mount umap layer
34  */
35 int
36 umapfs_mount(mp, path, data, ndp, p)
37 	struct mount *mp;
38 	char *path;
39 	caddr_t data;
40 	struct nameidata *ndp;
41 	struct proc *p;
42 {
43 	int i;
44 	int error = 0;
45 	struct umap_args args;
46 	struct vnode *lowerrootvp, *vp;
47 	struct vnode *umapm_rootvp;
48 	struct umap_mount *amp;
49 	u_int size;
50 
51 #ifdef UMAPFS_DIAGNOSTIC
52 	printf("umapfs_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 		/* return VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, p);*/
61 	}
62 
63 	/*
64 	 * Get argument
65 	 */
66 	if (error = copyin(data, (caddr_t)&args, sizeof(struct umap_args)))
67 		return (error);
68 
69 	/*
70 	 * Find target node
71 	 */
72 	NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF,
73 		UIO_USERSPACE, args.target, p);
74 	if (error = namei(ndp))
75 		return (error);
76 
77 	/*
78 	 * Sanity check on target vnode
79 	 */
80 	lowerrootvp = ndp->ni_vp;
81 #ifdef UMAPFS_DIAGNOSTIC
82 	printf("vp = %x, check for VDIR...\n", lowerrootvp);
83 #endif
84 	vrele(ndp->ni_dvp);
85 	ndp->ni_dvp = 0;
86 
87 	/*
88 	 * NEEDSWORK: Is this really bad, or just not
89 	 * the way it's been?
90 	 */
91 	if (lowerrootvp->v_type != VDIR) {
92 		vput(lowerrootvp);
93 		return (EINVAL);
94 	}
95 
96 #ifdef UMAPFS_DIAGNOSTIC
97 	printf("mp = %x\n", mp);
98 #endif
99 
100 	amp = (struct umap_mount *) malloc(sizeof(struct umap_mount),
101 				M_UFSMNT, M_WAITOK);	/* XXX */
102 
103 	/*
104 	 * Save reference to underlying target FS
105 	 */
106 	amp->umapm_vfs = lowerrootvp->v_mount;
107 
108 	/*
109 	 * Now copy in the number of entries and maps for umap mapping.
110 	 */
111 
112 	amp->info_nentries = args.nentries;
113 	amp->info_gnentries = args.gnentries;
114 	error = copyin(args.mapdata, (caddr_t)amp->info_mapdata,
115 	    8*args.nentries);
116 	if (error) return (error);
117 	printf("umap_mount:nentries %d\n",args.nentries);
118 	for (i=0; i<args.nentries;i++)
119 		printf("   %d maps to %d\n", amp->info_mapdata[i][0],
120 	 	    amp->info_mapdata[i][1]);
121 
122 	error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata,
123 	    8*args.nentries);
124 	if (error) return (error);
125 	printf("umap_mount:gnentries %d\n",args.gnentries);
126 	for (i=0; i<args.gnentries;i++)
127 		printf("	group %d maps to %d\n",
128 		    amp->info_gmapdata[i][0],
129 	 	    amp->info_gmapdata[i][1]);
130 
131 
132 	/*
133 	 * Save reference.  Each mount also holds
134 	 * a reference on the root vnode.
135 	 */
136 	error = umap_node_create(mp, lowerrootvp, &vp);
137 	/*
138 	 * Unlock the node (either the target or the alias)
139 	 */
140 	VOP_UNLOCK(vp);
141 	/*
142 	 * Make sure the node alias worked
143 	 */
144 	if (error) {
145 		vrele(lowerrootvp);
146 		free(amp, M_UFSMNT);	/* XXX */
147 		return (error);
148 	}
149 
150 	/*
151 	 * Keep a held reference to the root vnode.
152 	 * It is vrele'd in umapfs_unmount.
153 	 */
154 	umapm_rootvp = vp;
155 	umapm_rootvp->v_flag |= VROOT;
156 	amp->umapm_rootvp = umapm_rootvp;
157 	if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
158 		mp->mnt_flag |= MNT_LOCAL;
159 	mp->mnt_data = (qaddr_t) amp;
160 	getnewfsid(mp, MOUNT_LOFS);
161 
162 	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
163 	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
164 	(void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
165 	    &size);
166 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
167 #ifdef UMAPFS_DIAGNOSTIC
168 	printf("umapfs_mount: target %s, alias at %s\n",
169 		mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
170 #endif
171 	return (0);
172 }
173 
174 /*
175  * VFS start.  Nothing needed here - the start routine
176  * on the underlying filesystem will have been called
177  * when that filesystem was mounted.
178  */
179 int
180 umapfs_start(mp, flags, p)
181 	struct mount *mp;
182 	int flags;
183 	struct proc *p;
184 {
185 	return (0);
186 	/* return VFS_START(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, flags, p); */
187 }
188 
189 /*
190  * Free reference to umap layer
191  */
192 int
193 umapfs_unmount(mp, mntflags, p)
194 	struct mount *mp;
195 	int mntflags;
196 	struct proc *p;
197 {
198 	struct vnode *umapm_rootvp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
199 	int error;
200 	int flags = 0;
201 	extern int doforce;
202 
203 #ifdef UMAPFS_DIAGNOSTIC
204 	printf("umapfs_unmount(mp = %x)\n", mp);
205 #endif
206 
207 	if (mntflags & MNT_FORCE) {
208 		/* lofs can never be rootfs so don't check for it */
209 		if (!doforce)
210 			return (EINVAL);
211 		flags |= FORCECLOSE;
212 	}
213 
214 	/*
215 	 * Clear out buffer cache.  I don't think we
216 	 * ever get anything cached at this level at the
217 	 * moment, but who knows...
218 	 */
219 #if 0
220 	mntflushbuf(mp, 0);
221 	if (mntinvalbuf(mp, 1))
222 		return (EBUSY);
223 #endif
224 	if (umapm_rootvp->v_usecount > 1)
225 		return (EBUSY);
226 	if (error = vflush(mp, umapm_rootvp, flags))
227 		return (error);
228 
229 #ifdef UMAPFS_DIAGNOSTIC
230 	/*
231 	 * Flush any remaining vnode references
232 	 */
233 	umap_node_flushmp (mp);
234 #endif
235 
236 #ifdef UMAPFS_DIAGNOSTIC
237 	vprint("alias root of target", umapm_rootvp);
238 #endif
239 	/*
240 	 * Release reference on underlying root vnode
241 	 */
242 	vrele(umapm_rootvp);
243 	/*
244 	 * And blow it away for future re-use
245 	 */
246 	vgone(umapm_rootvp);
247 	/*
248 	 * Finally, throw away the umap_mount structure
249 	 */
250 	free(mp->mnt_data, M_UFSMNT);	/* XXX */
251 	mp->mnt_data = 0;
252 	return 0;
253 }
254 
255 int
256 umapfs_root(mp, vpp)
257 	struct mount *mp;
258 	struct vnode **vpp;
259 {
260 	struct vnode *vp;
261 
262 #ifdef UMAPFS_DIAGNOSTIC
263 	printf("umapfs_root(mp = %x, vp = %x->%x)\n", mp,
264 			MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
265 			UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp)
266 			);
267 #endif
268 
269 	/*
270 	 * Return locked reference to root.
271 	 */
272 	vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
273 	VREF(vp);
274 	VOP_LOCK(vp);
275 	*vpp = vp;
276 	return 0;
277 }
278 
279 int
280 umapfs_quotactl(mp, cmd, uid, arg, p)
281 	struct mount *mp;
282 	int cmd;
283 	uid_t uid;
284 	caddr_t arg;
285 	struct proc *p;
286 {
287 	return VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p);
288 }
289 
290 int
291 umapfs_statfs(mp, sbp, p)
292 	struct mount *mp;
293 	struct statfs *sbp;
294 	struct proc *p;
295 {
296 	int error;
297 	struct statfs mstat;
298 
299 #ifdef UMAPFS_DIAGNOSTIC
300 	printf("umapfs_statfs(mp = %x, vp = %x->%x)\n", mp,
301 			MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
302 			UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp)
303 			);
304 #endif
305 
306 	bzero(&mstat, sizeof(mstat));
307 
308 	error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p);
309 	if (error)
310 		return (error);
311 
312 	/* now copy across the "interesting" information and fake the rest */
313 	sbp->f_type = mstat.f_type;
314 	sbp->f_flags = mstat.f_flags;
315 	sbp->f_bsize = mstat.f_bsize;
316 	sbp->f_iosize = mstat.f_iosize;
317 	sbp->f_blocks = mstat.f_blocks;
318 	sbp->f_bfree = mstat.f_bfree;
319 	sbp->f_bavail = mstat.f_bavail;
320 	sbp->f_files = mstat.f_files;
321 	sbp->f_ffree = mstat.f_ffree;
322 	if (sbp != &mp->mnt_stat) {
323 		bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
324 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
325 		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
326 	}
327 	return (0);
328 }
329 
330 int
331 umapfs_sync(mp, waitfor, cred, p)
332 	struct mount *mp;
333 	int waitfor;
334 	struct ucred *cred;
335 	struct proc *p;
336 {
337 	/*
338 	 * XXX - Assumes no data cached at umap layer.
339 	 */
340 	return (0);
341 }
342 
343 int
344 umapfs_vget(mp, ino, vpp)
345 	struct mount *mp;
346 	ino_t ino;
347 	struct vnode **vpp;
348 {
349 
350 	return VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp);
351 }
352 
353 int
354 umapfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp)
355 	struct mount *mp;
356 	struct fid *fidp;
357 	struct mbuf *nam;
358 	struct vnode **vpp;
359 	int *exflagsp;
360 	struct ucred**credanonp;
361 {
362 
363 	return VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, nam, vpp, exflagsp,credanonp);
364 }
365 
366 int
367 umapfs_vptofh(vp, fhp)
368 	struct vnode *vp;
369 	struct fid *fhp;
370 {
371 	return VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp);
372 }
373 
374 int umapfs_init __P((void));
375 
376 struct vfsops umap_vfsops = {
377 	umapfs_mount,
378 	umapfs_start,
379 	umapfs_unmount,
380 	umapfs_root,
381 	umapfs_quotactl,
382 	umapfs_statfs,
383 	umapfs_sync,
384 	umapfs_vget,
385 	umapfs_fhtovp,
386 	umapfs_vptofh,
387 	umapfs_init,
388 };
389