154947Sheideman /*
263248Sbostic  * Copyright (c) 1992, 1993
363248Sbostic  *	The Regents of the University of California.  All rights reserved.
454947Sheideman  * All rights reserved.
554947Sheideman  *
654947Sheideman  * This code is derived from software donated to Berkeley by
754959Sheideman  * the UCLA Ficus project.
854947Sheideman  *
954947Sheideman  * %sccs.include.redist.c%
1054947Sheideman  *
11*65726Sbostic  *	@(#)umap_vfsops.c	8.2 (Berkeley) 01/13/94
1254947Sheideman  *
1354959Sheideman  * @(#)null_vfsops.c       1.5 (Berkeley) 7/10/92
1454947Sheideman  */
1554947Sheideman 
1654947Sheideman /*
1754959Sheideman  * Umap Layer
1855053Spendry  * (See mount_umap(8) for a description of this layer.)
1954947Sheideman  */
2054947Sheideman 
2154947Sheideman #include <sys/param.h>
2254947Sheideman #include <sys/systm.h>
2354947Sheideman #include <sys/time.h>
2454947Sheideman #include <sys/types.h>
2554947Sheideman #include <sys/vnode.h>
2654947Sheideman #include <sys/mount.h>
2754947Sheideman #include <sys/namei.h>
2854947Sheideman #include <sys/malloc.h>
2955053Spendry #include <miscfs/umapfs/umap.h>
3054947Sheideman 
3154947Sheideman /*
3254947Sheideman  * Mount umap layer
3354947Sheideman  */
3454947Sheideman int
3554947Sheideman umapfs_mount(mp, path, data, ndp, p)
3654947Sheideman 	struct mount *mp;
3754947Sheideman 	char *path;
3854947Sheideman 	caddr_t data;
3954947Sheideman 	struct nameidata *ndp;
4054947Sheideman 	struct proc *p;
4154947Sheideman {
4254947Sheideman 	struct umap_args args;
4354947Sheideman 	struct vnode *lowerrootvp, *vp;
4454947Sheideman 	struct vnode *umapm_rootvp;
4554947Sheideman 	struct umap_mount *amp;
4654947Sheideman 	u_int size;
47*65726Sbostic 	int error;
4854947Sheideman 
4954947Sheideman #ifdef UMAPFS_DIAGNOSTIC
5054947Sheideman 	printf("umapfs_mount(mp = %x)\n", mp);
5154947Sheideman #endif
5254947Sheideman 
5354947Sheideman 	/*
5454947Sheideman 	 * Update is a no-op
5554947Sheideman 	 */
5654947Sheideman 	if (mp->mnt_flag & MNT_UPDATE) {
5754947Sheideman 		return (EOPNOTSUPP);
58*65726Sbostic 		/* return (VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, p));*/
5954947Sheideman 	}
6054947Sheideman 
6154947Sheideman 	/*
6254947Sheideman 	 * Get argument
6354947Sheideman 	 */
6454947Sheideman 	if (error = copyin(data, (caddr_t)&args, sizeof(struct umap_args)))
6554947Sheideman 		return (error);
6654947Sheideman 
6754947Sheideman 	/*
6854959Sheideman 	 * Find lower node
6954947Sheideman 	 */
7054947Sheideman 	NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF,
7154947Sheideman 		UIO_USERSPACE, args.target, p);
7254947Sheideman 	if (error = namei(ndp))
7354947Sheideman 		return (error);
7454947Sheideman 
7554947Sheideman 	/*
7654959Sheideman 	 * Sanity check on lower vnode
7754947Sheideman 	 */
7854947Sheideman 	lowerrootvp = ndp->ni_vp;
7954947Sheideman #ifdef UMAPFS_DIAGNOSTIC
8054947Sheideman 	printf("vp = %x, check for VDIR...\n", lowerrootvp);
8154947Sheideman #endif
8254947Sheideman 	vrele(ndp->ni_dvp);
8354947Sheideman 	ndp->ni_dvp = 0;
8454947Sheideman 
8554947Sheideman 	if (lowerrootvp->v_type != VDIR) {
8654947Sheideman 		vput(lowerrootvp);
8754947Sheideman 		return (EINVAL);
8854947Sheideman 	}
8954947Sheideman 
9054947Sheideman #ifdef UMAPFS_DIAGNOSTIC
9154947Sheideman 	printf("mp = %x\n", mp);
9254947Sheideman #endif
9354947Sheideman 
9454947Sheideman 	amp = (struct umap_mount *) malloc(sizeof(struct umap_mount),
9554947Sheideman 				M_UFSMNT, M_WAITOK);	/* XXX */
9654947Sheideman 
9754947Sheideman 	/*
9854959Sheideman 	 * Save reference to underlying FS
9954947Sheideman 	 */
10054947Sheideman 	amp->umapm_vfs = lowerrootvp->v_mount;
10154947Sheideman 
10254947Sheideman 	/*
10354947Sheideman 	 * Now copy in the number of entries and maps for umap mapping.
10454947Sheideman 	 */
10554947Sheideman 	amp->info_nentries = args.nentries;
10654947Sheideman 	amp->info_gnentries = args.gnentries;
10754947Sheideman 	error = copyin(args.mapdata, (caddr_t)amp->info_mapdata,
108*65726Sbostic 	    2*sizeof(u_long)*args.nentries);
109*65726Sbostic 	if (error)
110*65726Sbostic 		return (error);
11154959Sheideman 
11254959Sheideman #ifdef UMAP_DIAGNOSTIC
11354947Sheideman 	printf("umap_mount:nentries %d\n",args.nentries);
11454959Sheideman 	for (i = 0; i < args.nentries; i++)
11554947Sheideman 		printf("   %d maps to %d\n", amp->info_mapdata[i][0],
11654947Sheideman 	 	    amp->info_mapdata[i][1]);
11754959Sheideman #endif
11854947Sheideman 
11954947Sheideman 	error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata,
120*65726Sbostic 	    2*sizeof(u_long)*args.nentries);
121*65726Sbostic 	if (error)
122*65726Sbostic 		return (error);
12354959Sheideman 
12454959Sheideman #ifdef UMAP_DIAGNOSTIC
12554947Sheideman 	printf("umap_mount:gnentries %d\n",args.gnentries);
12654959Sheideman 	for (i = 0; i < args.gnentries; i++)
12754947Sheideman 		printf("	group %d maps to %d\n",
12854947Sheideman 		    amp->info_gmapdata[i][0],
12954947Sheideman 	 	    amp->info_gmapdata[i][1]);
13054959Sheideman #endif
13154947Sheideman 
13254947Sheideman 
13354947Sheideman 	/*
13454947Sheideman 	 * Save reference.  Each mount also holds
13554947Sheideman 	 * a reference on the root vnode.
13654947Sheideman 	 */
13754947Sheideman 	error = umap_node_create(mp, lowerrootvp, &vp);
13854947Sheideman 	/*
13954959Sheideman 	 * Unlock the node (either the lower or the alias)
14054947Sheideman 	 */
14154947Sheideman 	VOP_UNLOCK(vp);
14254947Sheideman 	/*
14354947Sheideman 	 * Make sure the node alias worked
14454947Sheideman 	 */
14554947Sheideman 	if (error) {
14654947Sheideman 		vrele(lowerrootvp);
14754947Sheideman 		free(amp, M_UFSMNT);	/* XXX */
14854947Sheideman 		return (error);
14954947Sheideman 	}
15054947Sheideman 
15154947Sheideman 	/*
15254947Sheideman 	 * Keep a held reference to the root vnode.
15354947Sheideman 	 * It is vrele'd in umapfs_unmount.
15454947Sheideman 	 */
15554947Sheideman 	umapm_rootvp = vp;
15654947Sheideman 	umapm_rootvp->v_flag |= VROOT;
15754947Sheideman 	amp->umapm_rootvp = umapm_rootvp;
15854947Sheideman 	if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
15954947Sheideman 		mp->mnt_flag |= MNT_LOCAL;
16054947Sheideman 	mp->mnt_data = (qaddr_t) amp;
16154947Sheideman 	getnewfsid(mp, MOUNT_LOFS);
16254947Sheideman 
16354947Sheideman 	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
16454947Sheideman 	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
16554947Sheideman 	(void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
16654947Sheideman 	    &size);
16754947Sheideman 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
16854947Sheideman #ifdef UMAPFS_DIAGNOSTIC
16954959Sheideman 	printf("umapfs_mount: lower %s, alias at %s\n",
17054947Sheideman 		mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
17154947Sheideman #endif
17254947Sheideman 	return (0);
17354947Sheideman }
17454947Sheideman 
17554947Sheideman /*
17654947Sheideman  * VFS start.  Nothing needed here - the start routine
17754947Sheideman  * on the underlying filesystem will have been called
17854947Sheideman  * when that filesystem was mounted.
17954947Sheideman  */
18054947Sheideman int
18154947Sheideman umapfs_start(mp, flags, p)
18254947Sheideman 	struct mount *mp;
18354947Sheideman 	int flags;
18454947Sheideman 	struct proc *p;
18554947Sheideman {
18654947Sheideman 	return (0);
187*65726Sbostic 	/* return (VFS_START(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, flags, p)); */
18854947Sheideman }
18954947Sheideman 
19054947Sheideman /*
19154947Sheideman  * Free reference to umap layer
19254947Sheideman  */
19354947Sheideman int
19454947Sheideman umapfs_unmount(mp, mntflags, p)
19554947Sheideman 	struct mount *mp;
19654947Sheideman 	int mntflags;
19754947Sheideman 	struct proc *p;
19854947Sheideman {
19954947Sheideman 	struct vnode *umapm_rootvp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
20054947Sheideman 	int error;
20154947Sheideman 	int flags = 0;
20254947Sheideman 	extern int doforce;
20354947Sheideman 
20454947Sheideman #ifdef UMAPFS_DIAGNOSTIC
20554947Sheideman 	printf("umapfs_unmount(mp = %x)\n", mp);
20654947Sheideman #endif
20754947Sheideman 
20854947Sheideman 	if (mntflags & MNT_FORCE) {
20954947Sheideman 		/* lofs can never be rootfs so don't check for it */
21054947Sheideman 		if (!doforce)
21154947Sheideman 			return (EINVAL);
21254947Sheideman 		flags |= FORCECLOSE;
21354947Sheideman 	}
21454947Sheideman 
21554947Sheideman 	/*
21654947Sheideman 	 * Clear out buffer cache.  I don't think we
21754947Sheideman 	 * ever get anything cached at this level at the
21854947Sheideman 	 * moment, but who knows...
21954947Sheideman 	 */
22055031Smckusick #ifdef notyet
22154947Sheideman 	mntflushbuf(mp, 0);
22254947Sheideman 	if (mntinvalbuf(mp, 1))
22354947Sheideman 		return (EBUSY);
22454947Sheideman #endif
22554947Sheideman 	if (umapm_rootvp->v_usecount > 1)
22654947Sheideman 		return (EBUSY);
22754947Sheideman 	if (error = vflush(mp, umapm_rootvp, flags))
22854947Sheideman 		return (error);
22954947Sheideman 
23054947Sheideman #ifdef UMAPFS_DIAGNOSTIC
23154959Sheideman 	vprint("alias root of lower", umapm_rootvp);
23254947Sheideman #endif
23354947Sheideman 	/*
23454947Sheideman 	 * Release reference on underlying root vnode
23554947Sheideman 	 */
23654947Sheideman 	vrele(umapm_rootvp);
23754947Sheideman 	/*
23854947Sheideman 	 * And blow it away for future re-use
23954947Sheideman 	 */
24054947Sheideman 	vgone(umapm_rootvp);
24154947Sheideman 	/*
24254947Sheideman 	 * Finally, throw away the umap_mount structure
24354947Sheideman 	 */
24454947Sheideman 	free(mp->mnt_data, M_UFSMNT);	/* XXX */
24554947Sheideman 	mp->mnt_data = 0;
246*65726Sbostic 	return (0);
24754947Sheideman }
24854947Sheideman 
24954947Sheideman int
25054947Sheideman umapfs_root(mp, vpp)
25154947Sheideman 	struct mount *mp;
25254947Sheideman 	struct vnode **vpp;
25354947Sheideman {
25454947Sheideman 	struct vnode *vp;
25554947Sheideman 
25654947Sheideman #ifdef UMAPFS_DIAGNOSTIC
25754947Sheideman 	printf("umapfs_root(mp = %x, vp = %x->%x)\n", mp,
25854947Sheideman 			MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
25954947Sheideman 			UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp)
26054947Sheideman 			);
26154947Sheideman #endif
26254947Sheideman 
26354947Sheideman 	/*
26454947Sheideman 	 * Return locked reference to root.
26554947Sheideman 	 */
26654947Sheideman 	vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
26754947Sheideman 	VREF(vp);
26854947Sheideman 	VOP_LOCK(vp);
26954947Sheideman 	*vpp = vp;
270*65726Sbostic 	return (0);
27154947Sheideman }
27254947Sheideman 
27354947Sheideman int
27454947Sheideman umapfs_quotactl(mp, cmd, uid, arg, p)
27554947Sheideman 	struct mount *mp;
27654947Sheideman 	int cmd;
27754947Sheideman 	uid_t uid;
27854947Sheideman 	caddr_t arg;
27954947Sheideman 	struct proc *p;
28054947Sheideman {
281*65726Sbostic 	return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p));
28254947Sheideman }
28354947Sheideman 
28454947Sheideman int
28554947Sheideman umapfs_statfs(mp, sbp, p)
28654947Sheideman 	struct mount *mp;
28754947Sheideman 	struct statfs *sbp;
28854947Sheideman 	struct proc *p;
28954947Sheideman {
29054947Sheideman 	int error;
29154947Sheideman 	struct statfs mstat;
29254947Sheideman 
29354947Sheideman #ifdef UMAPFS_DIAGNOSTIC
29454947Sheideman 	printf("umapfs_statfs(mp = %x, vp = %x->%x)\n", mp,
29554947Sheideman 			MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
29654947Sheideman 			UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp)
29754947Sheideman 			);
29854947Sheideman #endif
29954947Sheideman 
30054947Sheideman 	bzero(&mstat, sizeof(mstat));
30154947Sheideman 
30254947Sheideman 	error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p);
30354947Sheideman 	if (error)
30454947Sheideman 		return (error);
30554947Sheideman 
30654947Sheideman 	/* now copy across the "interesting" information and fake the rest */
30754947Sheideman 	sbp->f_type = mstat.f_type;
30854947Sheideman 	sbp->f_flags = mstat.f_flags;
30954947Sheideman 	sbp->f_bsize = mstat.f_bsize;
31054947Sheideman 	sbp->f_iosize = mstat.f_iosize;
31154947Sheideman 	sbp->f_blocks = mstat.f_blocks;
31254947Sheideman 	sbp->f_bfree = mstat.f_bfree;
31354947Sheideman 	sbp->f_bavail = mstat.f_bavail;
31454947Sheideman 	sbp->f_files = mstat.f_files;
31554947Sheideman 	sbp->f_ffree = mstat.f_ffree;
31654947Sheideman 	if (sbp != &mp->mnt_stat) {
31754947Sheideman 		bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
31854947Sheideman 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
31954947Sheideman 		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
32054947Sheideman 	}
32154947Sheideman 	return (0);
32254947Sheideman }
32354947Sheideman 
32454947Sheideman int
32554947Sheideman umapfs_sync(mp, waitfor, cred, p)
32654947Sheideman 	struct mount *mp;
32754947Sheideman 	int waitfor;
32854947Sheideman 	struct ucred *cred;
32954947Sheideman 	struct proc *p;
33054947Sheideman {
33154947Sheideman 	/*
33254947Sheideman 	 * XXX - Assumes no data cached at umap layer.
33354947Sheideman 	 */
33454947Sheideman 	return (0);
33554947Sheideman }
33654947Sheideman 
33754947Sheideman int
33854947Sheideman umapfs_vget(mp, ino, vpp)
33954947Sheideman 	struct mount *mp;
34054947Sheideman 	ino_t ino;
34154947Sheideman 	struct vnode **vpp;
34254947Sheideman {
34354947Sheideman 
344*65726Sbostic 	return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp));
34554947Sheideman }
34654947Sheideman 
34754947Sheideman int
34854947Sheideman umapfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp)
34954947Sheideman 	struct mount *mp;
35054947Sheideman 	struct fid *fidp;
35154947Sheideman 	struct mbuf *nam;
35254947Sheideman 	struct vnode **vpp;
35354947Sheideman 	int *exflagsp;
35454947Sheideman 	struct ucred**credanonp;
35554947Sheideman {
35654947Sheideman 
357*65726Sbostic 	return (VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, nam, vpp, exflagsp,credanonp));
35854947Sheideman }
35954947Sheideman 
36054947Sheideman int
36154947Sheideman umapfs_vptofh(vp, fhp)
36254947Sheideman 	struct vnode *vp;
36354947Sheideman 	struct fid *fhp;
36454947Sheideman {
365*65726Sbostic 	return (VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp));
36654947Sheideman }
36754947Sheideman 
36854947Sheideman int umapfs_init __P((void));
36954947Sheideman 
37054947Sheideman struct vfsops umap_vfsops = {
37154947Sheideman 	umapfs_mount,
37254947Sheideman 	umapfs_start,
37354947Sheideman 	umapfs_unmount,
37454947Sheideman 	umapfs_root,
37554947Sheideman 	umapfs_quotactl,
37654947Sheideman 	umapfs_statfs,
37754947Sheideman 	umapfs_sync,
37854947Sheideman 	umapfs_vget,
37954947Sheideman 	umapfs_fhtovp,
38054947Sheideman 	umapfs_vptofh,
38154947Sheideman 	umapfs_init,
38254947Sheideman };
383