154947Sheideman /* 2*69363Spendry * 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*69363Spendry * @(#)umap_vfsops.c 8.7 (Berkeley) 05/10/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> 2254947Sheideman #include <sys/time.h> 2354947Sheideman #include <sys/types.h> 2454947Sheideman #include <sys/vnode.h> 2554947Sheideman #include <sys/mount.h> 2654947Sheideman #include <sys/namei.h> 2754947Sheideman #include <sys/malloc.h> 2855053Spendry #include <miscfs/umapfs/umap.h> 2954947Sheideman 3054947Sheideman /* 3154947Sheideman * Mount umap layer 3254947Sheideman */ 3354947Sheideman int 3454947Sheideman umapfs_mount(mp, path, data, ndp, p) 3554947Sheideman struct mount *mp; 3654947Sheideman char *path; 3754947Sheideman caddr_t data; 3854947Sheideman struct nameidata *ndp; 3954947Sheideman struct proc *p; 4054947Sheideman { 4154947Sheideman struct umap_args args; 4254947Sheideman struct vnode *lowerrootvp, *vp; 4354947Sheideman struct vnode *umapm_rootvp; 4454947Sheideman struct umap_mount *amp; 4554947Sheideman u_int size; 4665726Sbostic int error; 4754947Sheideman 4854947Sheideman #ifdef UMAPFS_DIAGNOSTIC 4954947Sheideman printf("umapfs_mount(mp = %x)\n", mp); 5054947Sheideman #endif 5154947Sheideman 5254947Sheideman /* 5354947Sheideman * Update is a no-op 5454947Sheideman */ 5554947Sheideman if (mp->mnt_flag & MNT_UPDATE) { 5654947Sheideman return (EOPNOTSUPP); 5765726Sbostic /* return (VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, p));*/ 5854947Sheideman } 5954947Sheideman 6054947Sheideman /* 6154947Sheideman * Get argument 6254947Sheideman */ 6354947Sheideman if (error = copyin(data, (caddr_t)&args, sizeof(struct umap_args))) 6454947Sheideman return (error); 6554947Sheideman 6654947Sheideman /* 6754959Sheideman * Find lower node 6854947Sheideman */ 6954947Sheideman NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF, 7054947Sheideman UIO_USERSPACE, args.target, p); 7154947Sheideman if (error = namei(ndp)) 7254947Sheideman return (error); 7354947Sheideman 7454947Sheideman /* 7554959Sheideman * Sanity check on lower vnode 7654947Sheideman */ 7754947Sheideman lowerrootvp = ndp->ni_vp; 7854947Sheideman #ifdef UMAPFS_DIAGNOSTIC 7954947Sheideman printf("vp = %x, check for VDIR...\n", lowerrootvp); 8054947Sheideman #endif 8154947Sheideman vrele(ndp->ni_dvp); 8254947Sheideman ndp->ni_dvp = 0; 8354947Sheideman 8454947Sheideman if (lowerrootvp->v_type != VDIR) { 8554947Sheideman vput(lowerrootvp); 8654947Sheideman return (EINVAL); 8754947Sheideman } 8854947Sheideman 8954947Sheideman #ifdef UMAPFS_DIAGNOSTIC 9054947Sheideman printf("mp = %x\n", mp); 9154947Sheideman #endif 9254947Sheideman 9354947Sheideman amp = (struct umap_mount *) malloc(sizeof(struct umap_mount), 9454947Sheideman M_UFSMNT, M_WAITOK); /* XXX */ 9554947Sheideman 9654947Sheideman /* 9754959Sheideman * Save reference to underlying FS 9854947Sheideman */ 9954947Sheideman amp->umapm_vfs = lowerrootvp->v_mount; 10054947Sheideman 10154947Sheideman /* 10254947Sheideman * Now copy in the number of entries and maps for umap mapping. 10354947Sheideman */ 10454947Sheideman amp->info_nentries = args.nentries; 10554947Sheideman amp->info_gnentries = args.gnentries; 10654947Sheideman error = copyin(args.mapdata, (caddr_t)amp->info_mapdata, 10765726Sbostic 2*sizeof(u_long)*args.nentries); 10865726Sbostic if (error) 10965726Sbostic return (error); 11054959Sheideman 11154959Sheideman #ifdef UMAP_DIAGNOSTIC 11254947Sheideman printf("umap_mount:nentries %d\n",args.nentries); 11354959Sheideman for (i = 0; i < args.nentries; i++) 11454947Sheideman printf(" %d maps to %d\n", amp->info_mapdata[i][0], 11554947Sheideman amp->info_mapdata[i][1]); 11654959Sheideman #endif 11754947Sheideman 11854947Sheideman error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata, 11965726Sbostic 2*sizeof(u_long)*args.nentries); 12065726Sbostic if (error) 12165726Sbostic 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; 16068624Smckusick vfs_getnewfsid(mp); 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); 18665726Sbostic /* 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 20254947Sheideman #ifdef UMAPFS_DIAGNOSTIC 20354947Sheideman printf("umapfs_unmount(mp = %x)\n", mp); 20454947Sheideman #endif 20554947Sheideman 20669340Smckusick if (mntflags & MNT_FORCE) 20754947Sheideman flags |= FORCECLOSE; 20854947Sheideman 20954947Sheideman /* 21054947Sheideman * Clear out buffer cache. I don't think we 21154947Sheideman * ever get anything cached at this level at the 21254947Sheideman * moment, but who knows... 21354947Sheideman */ 21455031Smckusick #ifdef notyet 21554947Sheideman mntflushbuf(mp, 0); 21654947Sheideman if (mntinvalbuf(mp, 1)) 21754947Sheideman return (EBUSY); 21854947Sheideman #endif 21954947Sheideman if (umapm_rootvp->v_usecount > 1) 22054947Sheideman return (EBUSY); 22154947Sheideman if (error = vflush(mp, umapm_rootvp, flags)) 22254947Sheideman return (error); 22354947Sheideman 22454947Sheideman #ifdef UMAPFS_DIAGNOSTIC 22554959Sheideman vprint("alias root of lower", umapm_rootvp); 22654947Sheideman #endif 22754947Sheideman /* 22854947Sheideman * Release reference on underlying root vnode 22954947Sheideman */ 23054947Sheideman vrele(umapm_rootvp); 23154947Sheideman /* 23254947Sheideman * And blow it away for future re-use 23354947Sheideman */ 234*69363Spendry vgone(umapm_rootvp); 23554947Sheideman /* 23654947Sheideman * Finally, throw away the umap_mount structure 23754947Sheideman */ 23854947Sheideman free(mp->mnt_data, M_UFSMNT); /* XXX */ 23954947Sheideman mp->mnt_data = 0; 24065726Sbostic return (0); 24154947Sheideman } 24254947Sheideman 24354947Sheideman int 24454947Sheideman umapfs_root(mp, vpp) 24554947Sheideman struct mount *mp; 24654947Sheideman struct vnode **vpp; 24754947Sheideman { 24854947Sheideman struct vnode *vp; 24954947Sheideman 25054947Sheideman #ifdef UMAPFS_DIAGNOSTIC 25154947Sheideman printf("umapfs_root(mp = %x, vp = %x->%x)\n", mp, 25254947Sheideman MOUNTTOUMAPMOUNT(mp)->umapm_rootvp, 25354947Sheideman UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp) 25454947Sheideman ); 25554947Sheideman #endif 25654947Sheideman 25754947Sheideman /* 25854947Sheideman * Return locked reference to root. 25954947Sheideman */ 26054947Sheideman vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp; 26154947Sheideman VREF(vp); 26254947Sheideman VOP_LOCK(vp); 26354947Sheideman *vpp = vp; 26465726Sbostic return (0); 26554947Sheideman } 26654947Sheideman 26754947Sheideman int 26854947Sheideman umapfs_quotactl(mp, cmd, uid, arg, p) 26954947Sheideman struct mount *mp; 27054947Sheideman int cmd; 27154947Sheideman uid_t uid; 27254947Sheideman caddr_t arg; 27354947Sheideman struct proc *p; 27454947Sheideman { 27565726Sbostic return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p)); 27654947Sheideman } 27754947Sheideman 27854947Sheideman int 27954947Sheideman umapfs_statfs(mp, sbp, p) 28054947Sheideman struct mount *mp; 28154947Sheideman struct statfs *sbp; 28254947Sheideman struct proc *p; 28354947Sheideman { 28454947Sheideman int error; 28554947Sheideman struct statfs mstat; 28654947Sheideman 28754947Sheideman #ifdef UMAPFS_DIAGNOSTIC 28854947Sheideman printf("umapfs_statfs(mp = %x, vp = %x->%x)\n", mp, 28954947Sheideman MOUNTTOUMAPMOUNT(mp)->umapm_rootvp, 29054947Sheideman UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp) 29154947Sheideman ); 29254947Sheideman #endif 29354947Sheideman 29454947Sheideman bzero(&mstat, sizeof(mstat)); 29554947Sheideman 29654947Sheideman error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p); 29754947Sheideman if (error) 29854947Sheideman return (error); 29954947Sheideman 30054947Sheideman /* now copy across the "interesting" information and fake the rest */ 30154947Sheideman sbp->f_type = mstat.f_type; 30254947Sheideman sbp->f_flags = mstat.f_flags; 30354947Sheideman sbp->f_bsize = mstat.f_bsize; 30454947Sheideman sbp->f_iosize = mstat.f_iosize; 30554947Sheideman sbp->f_blocks = mstat.f_blocks; 30654947Sheideman sbp->f_bfree = mstat.f_bfree; 30754947Sheideman sbp->f_bavail = mstat.f_bavail; 30854947Sheideman sbp->f_files = mstat.f_files; 30954947Sheideman sbp->f_ffree = mstat.f_ffree; 31054947Sheideman if (sbp != &mp->mnt_stat) { 31154947Sheideman bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 31254947Sheideman bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 31354947Sheideman bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 31454947Sheideman } 31554947Sheideman return (0); 31654947Sheideman } 31754947Sheideman 31854947Sheideman int 31954947Sheideman umapfs_sync(mp, waitfor, cred, p) 32054947Sheideman struct mount *mp; 32154947Sheideman int waitfor; 32254947Sheideman struct ucred *cred; 32354947Sheideman struct proc *p; 32454947Sheideman { 32554947Sheideman /* 32654947Sheideman * XXX - Assumes no data cached at umap layer. 32754947Sheideman */ 32854947Sheideman return (0); 32954947Sheideman } 33054947Sheideman 33154947Sheideman int 33254947Sheideman umapfs_vget(mp, ino, vpp) 33354947Sheideman struct mount *mp; 33454947Sheideman ino_t ino; 33554947Sheideman struct vnode **vpp; 33654947Sheideman { 33754947Sheideman 33865726Sbostic return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp)); 33954947Sheideman } 34054947Sheideman 34154947Sheideman int 34254947Sheideman umapfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp) 34354947Sheideman struct mount *mp; 34454947Sheideman struct fid *fidp; 34554947Sheideman struct mbuf *nam; 34654947Sheideman struct vnode **vpp; 34754947Sheideman int *exflagsp; 34854947Sheideman struct ucred**credanonp; 34954947Sheideman { 35054947Sheideman 35165726Sbostic return (VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, nam, vpp, exflagsp,credanonp)); 35254947Sheideman } 35354947Sheideman 35454947Sheideman int 35554947Sheideman umapfs_vptofh(vp, fhp) 35654947Sheideman struct vnode *vp; 35754947Sheideman struct fid *fhp; 35854947Sheideman { 35965726Sbostic return (VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp)); 36054947Sheideman } 36154947Sheideman 36268624Smckusick int umapfs_init __P((struct vfsconf *)); 36368624Smckusick #define umapfs_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \ 36468624Smckusick size_t, struct proc *)))eopnotsupp) 36554947Sheideman 36654947Sheideman struct vfsops umap_vfsops = { 36754947Sheideman umapfs_mount, 36854947Sheideman umapfs_start, 36954947Sheideman umapfs_unmount, 37054947Sheideman umapfs_root, 37154947Sheideman umapfs_quotactl, 37254947Sheideman umapfs_statfs, 37354947Sheideman umapfs_sync, 37454947Sheideman umapfs_vget, 37554947Sheideman umapfs_fhtovp, 37654947Sheideman umapfs_vptofh, 37754947Sheideman umapfs_init, 37868624Smckusick umapfs_sysctl, 37954947Sheideman }; 380