154947Sheideman /* 263248Sbostic * Copyright (c) 1992, 1993 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*68430Smckusick * @(#)umap_vfsops.c 8.4 (Berkeley) 02/23/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; 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); 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 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 */ 239*68430Smckusick VOP_REVOKE(umapm_rootvp, 0); 24054947Sheideman /* 24154947Sheideman * Finally, throw away the umap_mount structure 24254947Sheideman */ 24354947Sheideman free(mp->mnt_data, M_UFSMNT); /* XXX */ 24454947Sheideman mp->mnt_data = 0; 24565726Sbostic 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; 26965726Sbostic 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 { 28065726Sbostic 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 34365726Sbostic 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 35665726Sbostic 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 { 36465726Sbostic 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