154947Sheideman /*
2*63248Sbostic  * Copyright (c) 1992, 1993
3*63248Sbostic  *	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*63248Sbostic  *	@(#)umap_vfsops.c	8.1 (Berkeley) 06/10/93
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 	int i;
4354947Sheideman 	int error = 0;
4454947Sheideman 	struct umap_args args;
4554947Sheideman 	struct vnode *lowerrootvp, *vp;
4654947Sheideman 	struct vnode *umapm_rootvp;
4754947Sheideman 	struct umap_mount *amp;
4854947Sheideman 	u_int size;
4954947Sheideman 
5054947Sheideman #ifdef UMAPFS_DIAGNOSTIC
5154947Sheideman 	printf("umapfs_mount(mp = %x)\n", mp);
5254947Sheideman #endif
5354947Sheideman 
5454947Sheideman 	/*
5554947Sheideman 	 * Update is a no-op
5654947Sheideman 	 */
5754947Sheideman 	if (mp->mnt_flag & MNT_UPDATE) {
5854947Sheideman 		return (EOPNOTSUPP);
5954947Sheideman 		/* return VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, p);*/
6054947Sheideman 	}
6154947Sheideman 
6254947Sheideman 	/*
6354947Sheideman 	 * Get argument
6454947Sheideman 	 */
6554947Sheideman 	if (error = copyin(data, (caddr_t)&args, sizeof(struct umap_args)))
6654947Sheideman 		return (error);
6754947Sheideman 
6854947Sheideman 	/*
6954959Sheideman 	 * Find lower node
7054947Sheideman 	 */
7154947Sheideman 	NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF,
7254947Sheideman 		UIO_USERSPACE, args.target, p);
7354947Sheideman 	if (error = namei(ndp))
7454947Sheideman 		return (error);
7554947Sheideman 
7654947Sheideman 	/*
7754959Sheideman 	 * Sanity check on lower vnode
7854947Sheideman 	 */
7954947Sheideman 	lowerrootvp = ndp->ni_vp;
8054947Sheideman #ifdef UMAPFS_DIAGNOSTIC
8154947Sheideman 	printf("vp = %x, check for VDIR...\n", lowerrootvp);
8254947Sheideman #endif
8354947Sheideman 	vrele(ndp->ni_dvp);
8454947Sheideman 	ndp->ni_dvp = 0;
8554947Sheideman 
8654947Sheideman 	if (lowerrootvp->v_type != VDIR) {
8754947Sheideman 		vput(lowerrootvp);
8854947Sheideman 		return (EINVAL);
8954947Sheideman 	}
9054947Sheideman 
9154947Sheideman #ifdef UMAPFS_DIAGNOSTIC
9254947Sheideman 	printf("mp = %x\n", mp);
9354947Sheideman #endif
9454947Sheideman 
9554947Sheideman 	amp = (struct umap_mount *) malloc(sizeof(struct umap_mount),
9654947Sheideman 				M_UFSMNT, M_WAITOK);	/* XXX */
9754947Sheideman 
9854947Sheideman 	/*
9954959Sheideman 	 * Save reference to underlying FS
10054947Sheideman 	 */
10154947Sheideman 	amp->umapm_vfs = lowerrootvp->v_mount;
10254947Sheideman 
10354947Sheideman 	/*
10454947Sheideman 	 * Now copy in the number of entries and maps for umap mapping.
10554947Sheideman 	 */
10654947Sheideman 	amp->info_nentries = args.nentries;
10754947Sheideman 	amp->info_gnentries = args.gnentries;
10854947Sheideman 	error = copyin(args.mapdata, (caddr_t)amp->info_mapdata,
10954959Sheideman 	    2*sizeof(int)*args.nentries);
11054947Sheideman 	if (error) 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,
12054959Sheideman 	    2*sizeof(int)*args.nentries);
12154947Sheideman 	if (error) return (error);
12254959Sheideman 
12354959Sheideman #ifdef UMAP_DIAGNOSTIC
12454947Sheideman 	printf("umap_mount:gnentries %d\n",args.gnentries);
12554959Sheideman 	for (i = 0; i < args.gnentries; i++)
12654947Sheideman 		printf("	group %d maps to %d\n",
12754947Sheideman 		    amp->info_gmapdata[i][0],
12854947Sheideman 	 	    amp->info_gmapdata[i][1]);
12954959Sheideman #endif
13054947Sheideman 
13154947Sheideman 
13254947Sheideman 	/*
13354947Sheideman 	 * Save reference.  Each mount also holds
13454947Sheideman 	 * a reference on the root vnode.
13554947Sheideman 	 */
13654947Sheideman 	error = umap_node_create(mp, lowerrootvp, &vp);
13754947Sheideman 	/*
13854959Sheideman 	 * Unlock the node (either the lower or the alias)
13954947Sheideman 	 */
14054947Sheideman 	VOP_UNLOCK(vp);
14154947Sheideman 	/*
14254947Sheideman 	 * Make sure the node alias worked
14354947Sheideman 	 */
14454947Sheideman 	if (error) {
14554947Sheideman 		vrele(lowerrootvp);
14654947Sheideman 		free(amp, M_UFSMNT);	/* XXX */
14754947Sheideman 		return (error);
14854947Sheideman 	}
14954947Sheideman 
15054947Sheideman 	/*
15154947Sheideman 	 * Keep a held reference to the root vnode.
15254947Sheideman 	 * It is vrele'd in umapfs_unmount.
15354947Sheideman 	 */
15454947Sheideman 	umapm_rootvp = vp;
15554947Sheideman 	umapm_rootvp->v_flag |= VROOT;
15654947Sheideman 	amp->umapm_rootvp = umapm_rootvp;
15754947Sheideman 	if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
15854947Sheideman 		mp->mnt_flag |= MNT_LOCAL;
15954947Sheideman 	mp->mnt_data = (qaddr_t) amp;
16054947Sheideman 	getnewfsid(mp, MOUNT_LOFS);
16154947Sheideman 
16254947Sheideman 	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
16354947Sheideman 	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
16454947Sheideman 	(void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
16554947Sheideman 	    &size);
16654947Sheideman 	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
16754947Sheideman #ifdef UMAPFS_DIAGNOSTIC
16854959Sheideman 	printf("umapfs_mount: lower %s, alias at %s\n",
16954947Sheideman 		mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
17054947Sheideman #endif
17154947Sheideman 	return (0);
17254947Sheideman }
17354947Sheideman 
17454947Sheideman /*
17554947Sheideman  * VFS start.  Nothing needed here - the start routine
17654947Sheideman  * on the underlying filesystem will have been called
17754947Sheideman  * when that filesystem was mounted.
17854947Sheideman  */
17954947Sheideman int
18054947Sheideman umapfs_start(mp, flags, p)
18154947Sheideman 	struct mount *mp;
18254947Sheideman 	int flags;
18354947Sheideman 	struct proc *p;
18454947Sheideman {
18554947Sheideman 	return (0);
18654947Sheideman 	/* return VFS_START(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, flags, p); */
18754947Sheideman }
18854947Sheideman 
18954947Sheideman /*
19054947Sheideman  * Free reference to umap layer
19154947Sheideman  */
19254947Sheideman int
19354947Sheideman umapfs_unmount(mp, mntflags, p)
19454947Sheideman 	struct mount *mp;
19554947Sheideman 	int mntflags;
19654947Sheideman 	struct proc *p;
19754947Sheideman {
19854947Sheideman 	struct vnode *umapm_rootvp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
19954947Sheideman 	int error;
20054947Sheideman 	int flags = 0;
20154947Sheideman 	extern int doforce;
20254947Sheideman 
20354947Sheideman #ifdef UMAPFS_DIAGNOSTIC
20454947Sheideman 	printf("umapfs_unmount(mp = %x)\n", mp);
20554947Sheideman #endif
20654947Sheideman 
20754947Sheideman 	if (mntflags & MNT_FORCE) {
20854947Sheideman 		/* lofs can never be rootfs so don't check for it */
20954947Sheideman 		if (!doforce)
21054947Sheideman 			return (EINVAL);
21154947Sheideman 		flags |= FORCECLOSE;
21254947Sheideman 	}
21354947Sheideman 
21454947Sheideman 	/*
21554947Sheideman 	 * Clear out buffer cache.  I don't think we
21654947Sheideman 	 * ever get anything cached at this level at the
21754947Sheideman 	 * moment, but who knows...
21854947Sheideman 	 */
21955031Smckusick #ifdef notyet
22054947Sheideman 	mntflushbuf(mp, 0);
22154947Sheideman 	if (mntinvalbuf(mp, 1))
22254947Sheideman 		return (EBUSY);
22354947Sheideman #endif
22454947Sheideman 	if (umapm_rootvp->v_usecount > 1)
22554947Sheideman 		return (EBUSY);
22654947Sheideman 	if (error = vflush(mp, umapm_rootvp, flags))
22754947Sheideman 		return (error);
22854947Sheideman 
22954947Sheideman #ifdef UMAPFS_DIAGNOSTIC
23054959Sheideman 	vprint("alias root of lower", umapm_rootvp);
23154947Sheideman #endif
23254947Sheideman 	/*
23354947Sheideman 	 * Release reference on underlying root vnode
23454947Sheideman 	 */
23554947Sheideman 	vrele(umapm_rootvp);
23654947Sheideman 	/*
23754947Sheideman 	 * And blow it away for future re-use
23854947Sheideman 	 */
23954947Sheideman 	vgone(umapm_rootvp);
24054947Sheideman 	/*
24154947Sheideman 	 * Finally, throw away the umap_mount structure
24254947Sheideman 	 */
24354947Sheideman 	free(mp->mnt_data, M_UFSMNT);	/* XXX */
24454947Sheideman 	mp->mnt_data = 0;
24554947Sheideman 	return 0;
24654947Sheideman }
24754947Sheideman 
24854947Sheideman int
24954947Sheideman umapfs_root(mp, vpp)
25054947Sheideman 	struct mount *mp;
25154947Sheideman 	struct vnode **vpp;
25254947Sheideman {
25354947Sheideman 	struct vnode *vp;
25454947Sheideman 
25554947Sheideman #ifdef UMAPFS_DIAGNOSTIC
25654947Sheideman 	printf("umapfs_root(mp = %x, vp = %x->%x)\n", mp,
25754947Sheideman 			MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
25854947Sheideman 			UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp)
25954947Sheideman 			);
26054947Sheideman #endif
26154947Sheideman 
26254947Sheideman 	/*
26354947Sheideman 	 * Return locked reference to root.
26454947Sheideman 	 */
26554947Sheideman 	vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
26654947Sheideman 	VREF(vp);
26754947Sheideman 	VOP_LOCK(vp);
26854947Sheideman 	*vpp = vp;
26954947Sheideman 	return 0;
27054947Sheideman }
27154947Sheideman 
27254947Sheideman int
27354947Sheideman umapfs_quotactl(mp, cmd, uid, arg, p)
27454947Sheideman 	struct mount *mp;
27554947Sheideman 	int cmd;
27654947Sheideman 	uid_t uid;
27754947Sheideman 	caddr_t arg;
27854947Sheideman 	struct proc *p;
27954947Sheideman {
28054947Sheideman 	return VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p);
28154947Sheideman }
28254947Sheideman 
28354947Sheideman int
28454947Sheideman umapfs_statfs(mp, sbp, p)
28554947Sheideman 	struct mount *mp;
28654947Sheideman 	struct statfs *sbp;
28754947Sheideman 	struct proc *p;
28854947Sheideman {
28954947Sheideman 	int error;
29054947Sheideman 	struct statfs mstat;
29154947Sheideman 
29254947Sheideman #ifdef UMAPFS_DIAGNOSTIC
29354947Sheideman 	printf("umapfs_statfs(mp = %x, vp = %x->%x)\n", mp,
29454947Sheideman 			MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
29554947Sheideman 			UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp)
29654947Sheideman 			);
29754947Sheideman #endif
29854947Sheideman 
29954947Sheideman 	bzero(&mstat, sizeof(mstat));
30054947Sheideman 
30154947Sheideman 	error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p);
30254947Sheideman 	if (error)
30354947Sheideman 		return (error);
30454947Sheideman 
30554947Sheideman 	/* now copy across the "interesting" information and fake the rest */
30654947Sheideman 	sbp->f_type = mstat.f_type;
30754947Sheideman 	sbp->f_flags = mstat.f_flags;
30854947Sheideman 	sbp->f_bsize = mstat.f_bsize;
30954947Sheideman 	sbp->f_iosize = mstat.f_iosize;
31054947Sheideman 	sbp->f_blocks = mstat.f_blocks;
31154947Sheideman 	sbp->f_bfree = mstat.f_bfree;
31254947Sheideman 	sbp->f_bavail = mstat.f_bavail;
31354947Sheideman 	sbp->f_files = mstat.f_files;
31454947Sheideman 	sbp->f_ffree = mstat.f_ffree;
31554947Sheideman 	if (sbp != &mp->mnt_stat) {
31654947Sheideman 		bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
31754947Sheideman 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
31854947Sheideman 		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
31954947Sheideman 	}
32054947Sheideman 	return (0);
32154947Sheideman }
32254947Sheideman 
32354947Sheideman int
32454947Sheideman umapfs_sync(mp, waitfor, cred, p)
32554947Sheideman 	struct mount *mp;
32654947Sheideman 	int waitfor;
32754947Sheideman 	struct ucred *cred;
32854947Sheideman 	struct proc *p;
32954947Sheideman {
33054947Sheideman 	/*
33154947Sheideman 	 * XXX - Assumes no data cached at umap layer.
33254947Sheideman 	 */
33354947Sheideman 	return (0);
33454947Sheideman }
33554947Sheideman 
33654947Sheideman int
33754947Sheideman umapfs_vget(mp, ino, vpp)
33854947Sheideman 	struct mount *mp;
33954947Sheideman 	ino_t ino;
34054947Sheideman 	struct vnode **vpp;
34154947Sheideman {
34254947Sheideman 
34354947Sheideman 	return VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp);
34454947Sheideman }
34554947Sheideman 
34654947Sheideman int
34754947Sheideman umapfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp)
34854947Sheideman 	struct mount *mp;
34954947Sheideman 	struct fid *fidp;
35054947Sheideman 	struct mbuf *nam;
35154947Sheideman 	struct vnode **vpp;
35254947Sheideman 	int *exflagsp;
35354947Sheideman 	struct ucred**credanonp;
35454947Sheideman {
35554947Sheideman 
35654947Sheideman 	return VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, nam, vpp, exflagsp,credanonp);
35754947Sheideman }
35854947Sheideman 
35954947Sheideman int
36054947Sheideman umapfs_vptofh(vp, fhp)
36154947Sheideman 	struct vnode *vp;
36254947Sheideman 	struct fid *fhp;
36354947Sheideman {
36454947Sheideman 	return VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp);
36554947Sheideman }
36654947Sheideman 
36754947Sheideman int umapfs_init __P((void));
36854947Sheideman 
36954947Sheideman struct vfsops umap_vfsops = {
37054947Sheideman 	umapfs_mount,
37154947Sheideman 	umapfs_start,
37254947Sheideman 	umapfs_unmount,
37354947Sheideman 	umapfs_root,
37454947Sheideman 	umapfs_quotactl,
37554947Sheideman 	umapfs_statfs,
37654947Sheideman 	umapfs_sync,
37754947Sheideman 	umapfs_vget,
37854947Sheideman 	umapfs_fhtovp,
37954947Sheideman 	umapfs_vptofh,
38054947Sheideman 	umapfs_init,
38154947Sheideman };
382