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