1*54947Sheideman /* 2*54947Sheideman * Copyright (c) 1992 The Regents of the University of California 3*54947Sheideman * Copyright (c) 1990, 1992 Jan-Simon Pendry 4*54947Sheideman * All rights reserved. 5*54947Sheideman * 6*54947Sheideman * This code is derived from software donated to Berkeley by 7*54947Sheideman * Jan-Simon Pendry. 8*54947Sheideman * 9*54947Sheideman * %sccs.include.redist.c% 10*54947Sheideman * 11*54947Sheideman * @(#)umap_vfsops.c 1.1 (Berkeley) 07/11/92 12*54947Sheideman * 13*54947Sheideman * @(#)lofs_vfsops.c 1.2 (Berkeley) 6/18/92 14*54947Sheideman * $Id: lofs_vfsops.c,v 1.9 1992/05/30 10:26:24 jsp Exp jsp $ 15*54947Sheideman */ 16*54947Sheideman 17*54947Sheideman /* 18*54947Sheideman * Null Layer 19*54947Sheideman * (See umap_vnops.c for a description of what this does.) 20*54947Sheideman */ 21*54947Sheideman 22*54947Sheideman #include <sys/param.h> 23*54947Sheideman #include <sys/systm.h> 24*54947Sheideman #include <sys/time.h> 25*54947Sheideman #include <sys/types.h> 26*54947Sheideman #include <sys/vnode.h> 27*54947Sheideman #include <sys/mount.h> 28*54947Sheideman #include <sys/namei.h> 29*54947Sheideman #include <sys/malloc.h> 30*54947Sheideman #include <umapfs/umap.h> 31*54947Sheideman 32*54947Sheideman /* 33*54947Sheideman * Mount umap layer 34*54947Sheideman */ 35*54947Sheideman int 36*54947Sheideman umapfs_mount(mp, path, data, ndp, p) 37*54947Sheideman struct mount *mp; 38*54947Sheideman char *path; 39*54947Sheideman caddr_t data; 40*54947Sheideman struct nameidata *ndp; 41*54947Sheideman struct proc *p; 42*54947Sheideman { 43*54947Sheideman int i; 44*54947Sheideman int error = 0; 45*54947Sheideman struct umap_args args; 46*54947Sheideman struct vnode *lowerrootvp, *vp; 47*54947Sheideman struct vnode *umapm_rootvp; 48*54947Sheideman struct umap_mount *amp; 49*54947Sheideman u_int size; 50*54947Sheideman 51*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC 52*54947Sheideman printf("umapfs_mount(mp = %x)\n", mp); 53*54947Sheideman #endif 54*54947Sheideman 55*54947Sheideman /* 56*54947Sheideman * Update is a no-op 57*54947Sheideman */ 58*54947Sheideman if (mp->mnt_flag & MNT_UPDATE) { 59*54947Sheideman return (EOPNOTSUPP); 60*54947Sheideman /* return VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, p);*/ 61*54947Sheideman } 62*54947Sheideman 63*54947Sheideman /* 64*54947Sheideman * Get argument 65*54947Sheideman */ 66*54947Sheideman if (error = copyin(data, (caddr_t)&args, sizeof(struct umap_args))) 67*54947Sheideman return (error); 68*54947Sheideman 69*54947Sheideman /* 70*54947Sheideman * Find target node 71*54947Sheideman */ 72*54947Sheideman NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF, 73*54947Sheideman UIO_USERSPACE, args.target, p); 74*54947Sheideman if (error = namei(ndp)) 75*54947Sheideman return (error); 76*54947Sheideman 77*54947Sheideman /* 78*54947Sheideman * Sanity check on target vnode 79*54947Sheideman */ 80*54947Sheideman lowerrootvp = ndp->ni_vp; 81*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC 82*54947Sheideman printf("vp = %x, check for VDIR...\n", lowerrootvp); 83*54947Sheideman #endif 84*54947Sheideman vrele(ndp->ni_dvp); 85*54947Sheideman ndp->ni_dvp = 0; 86*54947Sheideman 87*54947Sheideman /* 88*54947Sheideman * NEEDSWORK: Is this really bad, or just not 89*54947Sheideman * the way it's been? 90*54947Sheideman */ 91*54947Sheideman if (lowerrootvp->v_type != VDIR) { 92*54947Sheideman vput(lowerrootvp); 93*54947Sheideman return (EINVAL); 94*54947Sheideman } 95*54947Sheideman 96*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC 97*54947Sheideman printf("mp = %x\n", mp); 98*54947Sheideman #endif 99*54947Sheideman 100*54947Sheideman amp = (struct umap_mount *) malloc(sizeof(struct umap_mount), 101*54947Sheideman M_UFSMNT, M_WAITOK); /* XXX */ 102*54947Sheideman 103*54947Sheideman /* 104*54947Sheideman * Save reference to underlying target FS 105*54947Sheideman */ 106*54947Sheideman amp->umapm_vfs = lowerrootvp->v_mount; 107*54947Sheideman 108*54947Sheideman /* 109*54947Sheideman * Now copy in the number of entries and maps for umap mapping. 110*54947Sheideman */ 111*54947Sheideman 112*54947Sheideman amp->info_nentries = args.nentries; 113*54947Sheideman amp->info_gnentries = args.gnentries; 114*54947Sheideman error = copyin(args.mapdata, (caddr_t)amp->info_mapdata, 115*54947Sheideman 8*args.nentries); 116*54947Sheideman if (error) return (error); 117*54947Sheideman printf("umap_mount:nentries %d\n",args.nentries); 118*54947Sheideman for (i=0; i<args.nentries;i++) 119*54947Sheideman printf(" %d maps to %d\n", amp->info_mapdata[i][0], 120*54947Sheideman amp->info_mapdata[i][1]); 121*54947Sheideman 122*54947Sheideman error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata, 123*54947Sheideman 8*args.nentries); 124*54947Sheideman if (error) return (error); 125*54947Sheideman printf("umap_mount:gnentries %d\n",args.gnentries); 126*54947Sheideman for (i=0; i<args.gnentries;i++) 127*54947Sheideman printf(" group %d maps to %d\n", 128*54947Sheideman amp->info_gmapdata[i][0], 129*54947Sheideman amp->info_gmapdata[i][1]); 130*54947Sheideman 131*54947Sheideman 132*54947Sheideman /* 133*54947Sheideman * Save reference. Each mount also holds 134*54947Sheideman * a reference on the root vnode. 135*54947Sheideman */ 136*54947Sheideman error = umap_node_create(mp, lowerrootvp, &vp); 137*54947Sheideman /* 138*54947Sheideman * Unlock the node (either the target or the alias) 139*54947Sheideman */ 140*54947Sheideman VOP_UNLOCK(vp); 141*54947Sheideman /* 142*54947Sheideman * Make sure the node alias worked 143*54947Sheideman */ 144*54947Sheideman if (error) { 145*54947Sheideman vrele(lowerrootvp); 146*54947Sheideman free(amp, M_UFSMNT); /* XXX */ 147*54947Sheideman return (error); 148*54947Sheideman } 149*54947Sheideman 150*54947Sheideman /* 151*54947Sheideman * Keep a held reference to the root vnode. 152*54947Sheideman * It is vrele'd in umapfs_unmount. 153*54947Sheideman */ 154*54947Sheideman umapm_rootvp = vp; 155*54947Sheideman umapm_rootvp->v_flag |= VROOT; 156*54947Sheideman amp->umapm_rootvp = umapm_rootvp; 157*54947Sheideman if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL) 158*54947Sheideman mp->mnt_flag |= MNT_LOCAL; 159*54947Sheideman mp->mnt_data = (qaddr_t) amp; 160*54947Sheideman getnewfsid(mp, MOUNT_LOFS); 161*54947Sheideman 162*54947Sheideman (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); 163*54947Sheideman bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); 164*54947Sheideman (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 165*54947Sheideman &size); 166*54947Sheideman bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 167*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC 168*54947Sheideman printf("umapfs_mount: target %s, alias at %s\n", 169*54947Sheideman mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname); 170*54947Sheideman #endif 171*54947Sheideman return (0); 172*54947Sheideman } 173*54947Sheideman 174*54947Sheideman /* 175*54947Sheideman * VFS start. Nothing needed here - the start routine 176*54947Sheideman * on the underlying filesystem will have been called 177*54947Sheideman * when that filesystem was mounted. 178*54947Sheideman */ 179*54947Sheideman int 180*54947Sheideman umapfs_start(mp, flags, p) 181*54947Sheideman struct mount *mp; 182*54947Sheideman int flags; 183*54947Sheideman struct proc *p; 184*54947Sheideman { 185*54947Sheideman return (0); 186*54947Sheideman /* return VFS_START(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, flags, p); */ 187*54947Sheideman } 188*54947Sheideman 189*54947Sheideman /* 190*54947Sheideman * Free reference to umap layer 191*54947Sheideman */ 192*54947Sheideman int 193*54947Sheideman umapfs_unmount(mp, mntflags, p) 194*54947Sheideman struct mount *mp; 195*54947Sheideman int mntflags; 196*54947Sheideman struct proc *p; 197*54947Sheideman { 198*54947Sheideman struct vnode *umapm_rootvp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp; 199*54947Sheideman int error; 200*54947Sheideman int flags = 0; 201*54947Sheideman extern int doforce; 202*54947Sheideman 203*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC 204*54947Sheideman printf("umapfs_unmount(mp = %x)\n", mp); 205*54947Sheideman #endif 206*54947Sheideman 207*54947Sheideman if (mntflags & MNT_FORCE) { 208*54947Sheideman /* lofs can never be rootfs so don't check for it */ 209*54947Sheideman if (!doforce) 210*54947Sheideman return (EINVAL); 211*54947Sheideman flags |= FORCECLOSE; 212*54947Sheideman } 213*54947Sheideman 214*54947Sheideman /* 215*54947Sheideman * Clear out buffer cache. I don't think we 216*54947Sheideman * ever get anything cached at this level at the 217*54947Sheideman * moment, but who knows... 218*54947Sheideman */ 219*54947Sheideman #if 0 220*54947Sheideman mntflushbuf(mp, 0); 221*54947Sheideman if (mntinvalbuf(mp, 1)) 222*54947Sheideman return (EBUSY); 223*54947Sheideman #endif 224*54947Sheideman if (umapm_rootvp->v_usecount > 1) 225*54947Sheideman return (EBUSY); 226*54947Sheideman if (error = vflush(mp, umapm_rootvp, flags)) 227*54947Sheideman return (error); 228*54947Sheideman 229*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC 230*54947Sheideman /* 231*54947Sheideman * Flush any remaining vnode references 232*54947Sheideman */ 233*54947Sheideman umap_node_flushmp (mp); 234*54947Sheideman #endif 235*54947Sheideman 236*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC 237*54947Sheideman vprint("alias root of target", umapm_rootvp); 238*54947Sheideman #endif 239*54947Sheideman /* 240*54947Sheideman * Release reference on underlying root vnode 241*54947Sheideman */ 242*54947Sheideman vrele(umapm_rootvp); 243*54947Sheideman /* 244*54947Sheideman * And blow it away for future re-use 245*54947Sheideman */ 246*54947Sheideman vgone(umapm_rootvp); 247*54947Sheideman /* 248*54947Sheideman * Finally, throw away the umap_mount structure 249*54947Sheideman */ 250*54947Sheideman free(mp->mnt_data, M_UFSMNT); /* XXX */ 251*54947Sheideman mp->mnt_data = 0; 252*54947Sheideman return 0; 253*54947Sheideman } 254*54947Sheideman 255*54947Sheideman int 256*54947Sheideman umapfs_root(mp, vpp) 257*54947Sheideman struct mount *mp; 258*54947Sheideman struct vnode **vpp; 259*54947Sheideman { 260*54947Sheideman struct vnode *vp; 261*54947Sheideman 262*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC 263*54947Sheideman printf("umapfs_root(mp = %x, vp = %x->%x)\n", mp, 264*54947Sheideman MOUNTTOUMAPMOUNT(mp)->umapm_rootvp, 265*54947Sheideman UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp) 266*54947Sheideman ); 267*54947Sheideman #endif 268*54947Sheideman 269*54947Sheideman /* 270*54947Sheideman * Return locked reference to root. 271*54947Sheideman */ 272*54947Sheideman vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp; 273*54947Sheideman VREF(vp); 274*54947Sheideman VOP_LOCK(vp); 275*54947Sheideman *vpp = vp; 276*54947Sheideman return 0; 277*54947Sheideman } 278*54947Sheideman 279*54947Sheideman int 280*54947Sheideman umapfs_quotactl(mp, cmd, uid, arg, p) 281*54947Sheideman struct mount *mp; 282*54947Sheideman int cmd; 283*54947Sheideman uid_t uid; 284*54947Sheideman caddr_t arg; 285*54947Sheideman struct proc *p; 286*54947Sheideman { 287*54947Sheideman return VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p); 288*54947Sheideman } 289*54947Sheideman 290*54947Sheideman int 291*54947Sheideman umapfs_statfs(mp, sbp, p) 292*54947Sheideman struct mount *mp; 293*54947Sheideman struct statfs *sbp; 294*54947Sheideman struct proc *p; 295*54947Sheideman { 296*54947Sheideman int error; 297*54947Sheideman struct statfs mstat; 298*54947Sheideman 299*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC 300*54947Sheideman printf("umapfs_statfs(mp = %x, vp = %x->%x)\n", mp, 301*54947Sheideman MOUNTTOUMAPMOUNT(mp)->umapm_rootvp, 302*54947Sheideman UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp) 303*54947Sheideman ); 304*54947Sheideman #endif 305*54947Sheideman 306*54947Sheideman bzero(&mstat, sizeof(mstat)); 307*54947Sheideman 308*54947Sheideman error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p); 309*54947Sheideman if (error) 310*54947Sheideman return (error); 311*54947Sheideman 312*54947Sheideman /* now copy across the "interesting" information and fake the rest */ 313*54947Sheideman sbp->f_type = mstat.f_type; 314*54947Sheideman sbp->f_flags = mstat.f_flags; 315*54947Sheideman sbp->f_bsize = mstat.f_bsize; 316*54947Sheideman sbp->f_iosize = mstat.f_iosize; 317*54947Sheideman sbp->f_blocks = mstat.f_blocks; 318*54947Sheideman sbp->f_bfree = mstat.f_bfree; 319*54947Sheideman sbp->f_bavail = mstat.f_bavail; 320*54947Sheideman sbp->f_files = mstat.f_files; 321*54947Sheideman sbp->f_ffree = mstat.f_ffree; 322*54947Sheideman if (sbp != &mp->mnt_stat) { 323*54947Sheideman bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 324*54947Sheideman bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 325*54947Sheideman bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 326*54947Sheideman } 327*54947Sheideman return (0); 328*54947Sheideman } 329*54947Sheideman 330*54947Sheideman int 331*54947Sheideman umapfs_sync(mp, waitfor, cred, p) 332*54947Sheideman struct mount *mp; 333*54947Sheideman int waitfor; 334*54947Sheideman struct ucred *cred; 335*54947Sheideman struct proc *p; 336*54947Sheideman { 337*54947Sheideman /* 338*54947Sheideman * XXX - Assumes no data cached at umap layer. 339*54947Sheideman */ 340*54947Sheideman return (0); 341*54947Sheideman } 342*54947Sheideman 343*54947Sheideman int 344*54947Sheideman umapfs_vget(mp, ino, vpp) 345*54947Sheideman struct mount *mp; 346*54947Sheideman ino_t ino; 347*54947Sheideman struct vnode **vpp; 348*54947Sheideman { 349*54947Sheideman 350*54947Sheideman return VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp); 351*54947Sheideman } 352*54947Sheideman 353*54947Sheideman int 354*54947Sheideman umapfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp) 355*54947Sheideman struct mount *mp; 356*54947Sheideman struct fid *fidp; 357*54947Sheideman struct mbuf *nam; 358*54947Sheideman struct vnode **vpp; 359*54947Sheideman int *exflagsp; 360*54947Sheideman struct ucred**credanonp; 361*54947Sheideman { 362*54947Sheideman 363*54947Sheideman return VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, nam, vpp, exflagsp,credanonp); 364*54947Sheideman } 365*54947Sheideman 366*54947Sheideman int 367*54947Sheideman umapfs_vptofh(vp, fhp) 368*54947Sheideman struct vnode *vp; 369*54947Sheideman struct fid *fhp; 370*54947Sheideman { 371*54947Sheideman return VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp); 372*54947Sheideman } 373*54947Sheideman 374*54947Sheideman int umapfs_init __P((void)); 375*54947Sheideman 376*54947Sheideman struct vfsops umap_vfsops = { 377*54947Sheideman umapfs_mount, 378*54947Sheideman umapfs_start, 379*54947Sheideman umapfs_unmount, 380*54947Sheideman umapfs_root, 381*54947Sheideman umapfs_quotactl, 382*54947Sheideman umapfs_statfs, 383*54947Sheideman umapfs_sync, 384*54947Sheideman umapfs_vget, 385*54947Sheideman umapfs_fhtovp, 386*54947Sheideman umapfs_vptofh, 387*54947Sheideman umapfs_init, 388*54947Sheideman }; 389