154947Sheideman /*
269363Spendry  * Copyright (c) 1992, 1993, 1995
363248Sbostic  *	The Regents of the University of California.  All rights reserved.
454947Sheideman  *
554947Sheideman  * This code is derived from software donated to Berkeley by
654959Sheideman  * the UCLA Ficus project.
754947Sheideman  *
854947Sheideman  * %sccs.include.redist.c%
954947Sheideman  *
10*69446Smckusick  *	@(#)umap_vfsops.c	8.8 (Berkeley) 05/14/95
1154947Sheideman  *
1254959Sheideman  * @(#)null_vfsops.c       1.5 (Berkeley) 7/10/92
1354947Sheideman  */
1454947Sheideman 
1554947Sheideman /*
1654959Sheideman  * Umap Layer
1755053Spendry  * (See mount_umap(8) for a description of this layer.)
1854947Sheideman  */
1954947Sheideman 
2054947Sheideman #include <sys/param.h>
2154947Sheideman #include <sys/systm.h>
22*69446Smckusick #include <sys/proc.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
umapfs_mount(mp,path,data,ndp,p)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;
4765726Sbostic 	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);
5865726Sbostic 		/* 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,
10865726Sbostic 	    2*sizeof(u_long)*args.nentries);
10965726Sbostic 	if (error)
11065726Sbostic 		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,
12065726Sbostic 	    2*sizeof(u_long)*args.nentries);
12165726Sbostic 	if (error)
12265726Sbostic 		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 	 */
141*69446Smckusick 	VOP_UNLOCK(vp, 0, p);
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;
16168624Smckusick 	vfs_getnewfsid(mp);
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
umapfs_start(mp,flags,p)18154947Sheideman umapfs_start(mp, flags, p)
18254947Sheideman 	struct mount *mp;
18354947Sheideman 	int flags;
18454947Sheideman 	struct proc *p;
18554947Sheideman {
18654947Sheideman 	return (0);
18765726Sbostic 	/* return (VFS_START(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, flags, p)); */
18854947Sheideman }
18954947Sheideman 
19054947Sheideman /*
19154947Sheideman  * Free reference to umap layer
19254947Sheideman  */
19354947Sheideman int
umapfs_unmount(mp,mntflags,p)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 
20354947Sheideman #ifdef UMAPFS_DIAGNOSTIC
20454947Sheideman 	printf("umapfs_unmount(mp = %x)\n", mp);
20554947Sheideman #endif
20654947Sheideman 
20769340Smckusick 	if (mntflags & MNT_FORCE)
20854947Sheideman 		flags |= FORCECLOSE;
20954947Sheideman 
21054947Sheideman 	/*
21154947Sheideman 	 * Clear out buffer cache.  I don't think we
21254947Sheideman 	 * ever get anything cached at this level at the
21354947Sheideman 	 * moment, but who knows...
21454947Sheideman 	 */
21555031Smckusick #ifdef notyet
21654947Sheideman 	mntflushbuf(mp, 0);
21754947Sheideman 	if (mntinvalbuf(mp, 1))
21854947Sheideman 		return (EBUSY);
21954947Sheideman #endif
22054947Sheideman 	if (umapm_rootvp->v_usecount > 1)
22154947Sheideman 		return (EBUSY);
22254947Sheideman 	if (error = vflush(mp, umapm_rootvp, flags))
22354947Sheideman 		return (error);
22454947Sheideman 
22554947Sheideman #ifdef UMAPFS_DIAGNOSTIC
22654959Sheideman 	vprint("alias root of lower", umapm_rootvp);
22754947Sheideman #endif
22854947Sheideman 	/*
22954947Sheideman 	 * Release reference on underlying root vnode
23054947Sheideman 	 */
23154947Sheideman 	vrele(umapm_rootvp);
23254947Sheideman 	/*
23354947Sheideman 	 * And blow it away for future re-use
23454947Sheideman 	 */
23569363Spendry 	vgone(umapm_rootvp);
23654947Sheideman 	/*
23754947Sheideman 	 * Finally, throw away the umap_mount structure
23854947Sheideman 	 */
23954947Sheideman 	free(mp->mnt_data, M_UFSMNT);	/* XXX */
24054947Sheideman 	mp->mnt_data = 0;
24165726Sbostic 	return (0);
24254947Sheideman }
24354947Sheideman 
24454947Sheideman int
umapfs_root(mp,vpp)24554947Sheideman umapfs_root(mp, vpp)
24654947Sheideman 	struct mount *mp;
24754947Sheideman 	struct vnode **vpp;
24854947Sheideman {
249*69446Smckusick 	struct proc *p = curproc;	/* XXX */
25054947Sheideman 	struct vnode *vp;
25154947Sheideman 
25254947Sheideman #ifdef UMAPFS_DIAGNOSTIC
25354947Sheideman 	printf("umapfs_root(mp = %x, vp = %x->%x)\n", mp,
25454947Sheideman 			MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
25554947Sheideman 			UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp)
25654947Sheideman 			);
25754947Sheideman #endif
25854947Sheideman 
25954947Sheideman 	/*
26054947Sheideman 	 * Return locked reference to root.
26154947Sheideman 	 */
26254947Sheideman 	vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
26354947Sheideman 	VREF(vp);
264*69446Smckusick 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
26554947Sheideman 	*vpp = vp;
26665726Sbostic 	return (0);
26754947Sheideman }
26854947Sheideman 
26954947Sheideman int
umapfs_quotactl(mp,cmd,uid,arg,p)27054947Sheideman umapfs_quotactl(mp, cmd, uid, arg, p)
27154947Sheideman 	struct mount *mp;
27254947Sheideman 	int cmd;
27354947Sheideman 	uid_t uid;
27454947Sheideman 	caddr_t arg;
27554947Sheideman 	struct proc *p;
27654947Sheideman {
27765726Sbostic 	return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p));
27854947Sheideman }
27954947Sheideman 
28054947Sheideman int
umapfs_statfs(mp,sbp,p)28154947Sheideman umapfs_statfs(mp, sbp, p)
28254947Sheideman 	struct mount *mp;
28354947Sheideman 	struct statfs *sbp;
28454947Sheideman 	struct proc *p;
28554947Sheideman {
28654947Sheideman 	int error;
28754947Sheideman 	struct statfs mstat;
28854947Sheideman 
28954947Sheideman #ifdef UMAPFS_DIAGNOSTIC
29054947Sheideman 	printf("umapfs_statfs(mp = %x, vp = %x->%x)\n", mp,
29154947Sheideman 			MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
29254947Sheideman 			UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp)
29354947Sheideman 			);
29454947Sheideman #endif
29554947Sheideman 
29654947Sheideman 	bzero(&mstat, sizeof(mstat));
29754947Sheideman 
29854947Sheideman 	error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p);
29954947Sheideman 	if (error)
30054947Sheideman 		return (error);
30154947Sheideman 
30254947Sheideman 	/* now copy across the "interesting" information and fake the rest */
30354947Sheideman 	sbp->f_type = mstat.f_type;
30454947Sheideman 	sbp->f_flags = mstat.f_flags;
30554947Sheideman 	sbp->f_bsize = mstat.f_bsize;
30654947Sheideman 	sbp->f_iosize = mstat.f_iosize;
30754947Sheideman 	sbp->f_blocks = mstat.f_blocks;
30854947Sheideman 	sbp->f_bfree = mstat.f_bfree;
30954947Sheideman 	sbp->f_bavail = mstat.f_bavail;
31054947Sheideman 	sbp->f_files = mstat.f_files;
31154947Sheideman 	sbp->f_ffree = mstat.f_ffree;
31254947Sheideman 	if (sbp != &mp->mnt_stat) {
31354947Sheideman 		bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
31454947Sheideman 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
31554947Sheideman 		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
31654947Sheideman 	}
31754947Sheideman 	return (0);
31854947Sheideman }
31954947Sheideman 
32054947Sheideman int
umapfs_sync(mp,waitfor,cred,p)32154947Sheideman umapfs_sync(mp, waitfor, cred, p)
32254947Sheideman 	struct mount *mp;
32354947Sheideman 	int waitfor;
32454947Sheideman 	struct ucred *cred;
32554947Sheideman 	struct proc *p;
32654947Sheideman {
32754947Sheideman 	/*
32854947Sheideman 	 * XXX - Assumes no data cached at umap layer.
32954947Sheideman 	 */
33054947Sheideman 	return (0);
33154947Sheideman }
33254947Sheideman 
33354947Sheideman int
umapfs_vget(mp,ino,vpp)33454947Sheideman umapfs_vget(mp, ino, vpp)
33554947Sheideman 	struct mount *mp;
33654947Sheideman 	ino_t ino;
33754947Sheideman 	struct vnode **vpp;
33854947Sheideman {
33954947Sheideman 
34065726Sbostic 	return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp));
34154947Sheideman }
34254947Sheideman 
34354947Sheideman int
umapfs_fhtovp(mp,fidp,nam,vpp,exflagsp,credanonp)34454947Sheideman umapfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp)
34554947Sheideman 	struct mount *mp;
34654947Sheideman 	struct fid *fidp;
34754947Sheideman 	struct mbuf *nam;
34854947Sheideman 	struct vnode **vpp;
34954947Sheideman 	int *exflagsp;
35054947Sheideman 	struct ucred**credanonp;
35154947Sheideman {
35254947Sheideman 
35365726Sbostic 	return (VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, nam, vpp, exflagsp,credanonp));
35454947Sheideman }
35554947Sheideman 
35654947Sheideman int
umapfs_vptofh(vp,fhp)35754947Sheideman umapfs_vptofh(vp, fhp)
35854947Sheideman 	struct vnode *vp;
35954947Sheideman 	struct fid *fhp;
36054947Sheideman {
36165726Sbostic 	return (VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp));
36254947Sheideman }
36354947Sheideman 
36468624Smckusick int umapfs_init __P((struct vfsconf *));
36568624Smckusick #define umapfs_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
36668624Smckusick 	    size_t, struct proc *)))eopnotsupp)
36754947Sheideman 
36854947Sheideman struct vfsops umap_vfsops = {
36954947Sheideman 	umapfs_mount,
37054947Sheideman 	umapfs_start,
37154947Sheideman 	umapfs_unmount,
37254947Sheideman 	umapfs_root,
37354947Sheideman 	umapfs_quotactl,
37454947Sheideman 	umapfs_statfs,
37554947Sheideman 	umapfs_sync,
37654947Sheideman 	umapfs_vget,
37754947Sheideman 	umapfs_fhtovp,
37854947Sheideman 	umapfs_vptofh,
37954947Sheideman 	umapfs_init,
38068624Smckusick 	umapfs_sysctl,
38154947Sheideman };
382