154752Sjohnh /* 254752Sjohnh * Copyright (c) 1992 The Regents of the University of California 354752Sjohnh * Copyright (c) 1990, 1992 Jan-Simon Pendry 454752Sjohnh * All rights reserved. 554752Sjohnh * 654752Sjohnh * This code is derived from software donated to Berkeley by 754752Sjohnh * Jan-Simon Pendry. 854752Sjohnh * 954752Sjohnh * %sccs.include.redist.c% 1054752Sjohnh * 11*54893Sheideman * @(#)null_vfsops.c 1.4 (Berkeley) 07/10/92 1254752Sjohnh * 1354766Sjohnh * @(#)lofs_vfsops.c 1.2 (Berkeley) 6/18/92 1454766Sjohnh * $Id: lofs_vfsops.c,v 1.9 1992/05/30 10:26:24 jsp Exp jsp $ 1554752Sjohnh */ 1654752Sjohnh 1754752Sjohnh /* 1854766Sjohnh * Null Layer 1954766Sjohnh * (See null_vnops.c for a description of what this does.) 2054752Sjohnh */ 2154752Sjohnh 2254752Sjohnh #include <sys/param.h> 2354752Sjohnh #include <sys/systm.h> 2454752Sjohnh #include <sys/time.h> 2554752Sjohnh #include <sys/types.h> 2654752Sjohnh #include <sys/vnode.h> 2754752Sjohnh #include <sys/mount.h> 2854752Sjohnh #include <sys/namei.h> 2954752Sjohnh #include <sys/malloc.h> 30*54893Sheideman #include <nullfs/null.h> 3154752Sjohnh 3254752Sjohnh /* 3354766Sjohnh * Mount null layer 3454752Sjohnh */ 35*54893Sheideman int 3654754Sjohnh nullfs_mount(mp, path, data, ndp, p) 3754752Sjohnh struct mount *mp; 3854752Sjohnh char *path; 3954752Sjohnh caddr_t data; 4054752Sjohnh struct nameidata *ndp; 4154752Sjohnh struct proc *p; 4254752Sjohnh { 4354752Sjohnh int error = 0; 4454754Sjohnh struct null_args args; 4554766Sjohnh struct vnode *lowerrootvp, *vp; 4654754Sjohnh struct vnode *nullm_rootvp; 4754754Sjohnh struct null_mount *amp; 4854752Sjohnh u_int size; 4954752Sjohnh 5054754Sjohnh #ifdef NULLFS_DIAGNOSTIC 5154754Sjohnh printf("nullfs_mount(mp = %x)\n", mp); 5254752Sjohnh #endif 5354752Sjohnh 5454752Sjohnh /* 5554752Sjohnh * Update is a no-op 5654752Sjohnh */ 5754752Sjohnh if (mp->mnt_flag & MNT_UPDATE) { 5854752Sjohnh return (EOPNOTSUPP); 5954754Sjohnh /* return VFS_MOUNT(MOUNTTONULLMOUNT(mp)->nullm_vfs, path, data, ndp, p);*/ 6054752Sjohnh } 6154752Sjohnh 6254752Sjohnh /* 6354752Sjohnh * Get argument 6454752Sjohnh */ 6554754Sjohnh if (error = copyin(data, (caddr_t)&args, sizeof(struct null_args))) 6654752Sjohnh return (error); 6754752Sjohnh 6854752Sjohnh /* 6954752Sjohnh * Find target node 7054752Sjohnh */ 7154752Sjohnh NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF, 7254752Sjohnh UIO_USERSPACE, args.target, p); 7354752Sjohnh if (error = namei(ndp)) 7454752Sjohnh return (error); 7554752Sjohnh 7654752Sjohnh /* 7754752Sjohnh * Sanity check on target vnode 7854752Sjohnh */ 7954766Sjohnh lowerrootvp = ndp->ni_vp; 8054754Sjohnh #ifdef NULLFS_DIAGNOSTIC 8154766Sjohnh printf("vp = %x, check for VDIR...\n", lowerrootvp); 8254752Sjohnh #endif 8354752Sjohnh vrele(ndp->ni_dvp); 8454752Sjohnh ndp->ni_dvp = 0; 8554752Sjohnh 8654766Sjohnh /* 8754766Sjohnh * NEEDSWORK: Is this really bad, or just not 8854766Sjohnh * the way it's been? 8954766Sjohnh */ 9054766Sjohnh if (lowerrootvp->v_type != VDIR) { 9154766Sjohnh vput(lowerrootvp); 9254752Sjohnh return (EINVAL); 9354752Sjohnh } 9454752Sjohnh 9554754Sjohnh #ifdef NULLFS_DIAGNOSTIC 9654752Sjohnh printf("mp = %x\n", mp); 9754752Sjohnh #endif 9854752Sjohnh 9954754Sjohnh amp = (struct null_mount *) malloc(sizeof(struct null_mount), 10054752Sjohnh M_UFSMNT, M_WAITOK); /* XXX */ 10154752Sjohnh 10254752Sjohnh /* 10354752Sjohnh * Save reference to underlying target FS 10454752Sjohnh */ 10554766Sjohnh amp->nullm_vfs = lowerrootvp->v_mount; 10654752Sjohnh 10754752Sjohnh /* 10854752Sjohnh * Save reference. Each mount also holds 10954752Sjohnh * a reference on the root vnode. 11054752Sjohnh */ 111*54893Sheideman error = null_node_create(mp, lowerrootvp, &vp); 11254752Sjohnh /* 11354752Sjohnh * Unlock the node (either the target or the alias) 11454752Sjohnh */ 11554752Sjohnh VOP_UNLOCK(vp); 11654752Sjohnh /* 11754752Sjohnh * Make sure the node alias worked 11854752Sjohnh */ 11954752Sjohnh if (error) { 12054766Sjohnh vrele(lowerrootvp); 12154752Sjohnh free(amp, M_UFSMNT); /* XXX */ 12254752Sjohnh return (error); 12354752Sjohnh } 12454752Sjohnh 12554752Sjohnh /* 12654752Sjohnh * Keep a held reference to the root vnode. 12754754Sjohnh * It is vrele'd in nullfs_unmount. 12854752Sjohnh */ 12954754Sjohnh nullm_rootvp = vp; 13054754Sjohnh nullm_rootvp->v_flag |= VROOT; 13154754Sjohnh amp->nullm_rootvp = nullm_rootvp; 132*54893Sheideman if (NULLVPTOLOWERVP(nullm_rootvp)->v_mount->mnt_flag & MNT_LOCAL) 13354752Sjohnh mp->mnt_flag |= MNT_LOCAL; 13454752Sjohnh mp->mnt_data = (qaddr_t) amp; 13554752Sjohnh getnewfsid(mp, MOUNT_LOFS); 13654752Sjohnh 13754752Sjohnh (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); 13854752Sjohnh bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); 13954752Sjohnh (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 14054752Sjohnh &size); 14154752Sjohnh bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 14254754Sjohnh #ifdef NULLFS_DIAGNOSTIC 14354754Sjohnh printf("nullfs_mount: target %s, alias at %s\n", 14454752Sjohnh mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname); 14554752Sjohnh #endif 14654752Sjohnh return (0); 14754752Sjohnh } 14854752Sjohnh 14954752Sjohnh /* 15054752Sjohnh * VFS start. Nothing needed here - the start routine 15154752Sjohnh * on the underlying filesystem will have been called 15254752Sjohnh * when that filesystem was mounted. 15354752Sjohnh */ 154*54893Sheideman int 15554754Sjohnh nullfs_start(mp, flags, p) 15654752Sjohnh struct mount *mp; 15754752Sjohnh int flags; 15854752Sjohnh struct proc *p; 15954752Sjohnh { 16054752Sjohnh return (0); 16154754Sjohnh /* return VFS_START(MOUNTTONULLMOUNT(mp)->nullm_vfs, flags, p); */ 16254752Sjohnh } 16354752Sjohnh 16454752Sjohnh /* 16554766Sjohnh * Free reference to null layer 16654752Sjohnh */ 167*54893Sheideman int 16854754Sjohnh nullfs_unmount(mp, mntflags, p) 16954752Sjohnh struct mount *mp; 17054752Sjohnh int mntflags; 17154752Sjohnh struct proc *p; 17254752Sjohnh { 17354754Sjohnh struct vnode *nullm_rootvp = MOUNTTONULLMOUNT(mp)->nullm_rootvp; 17454752Sjohnh int error; 17554752Sjohnh int flags = 0; 17654752Sjohnh extern int doforce; 17754752Sjohnh 17854754Sjohnh #ifdef NULLFS_DIAGNOSTIC 17954754Sjohnh printf("nullfs_unmount(mp = %x)\n", mp); 18054752Sjohnh #endif 18154752Sjohnh 18254752Sjohnh if (mntflags & MNT_FORCE) { 18354752Sjohnh /* lofs can never be rootfs so don't check for it */ 18454752Sjohnh if (!doforce) 18554752Sjohnh return (EINVAL); 18654752Sjohnh flags |= FORCECLOSE; 18754752Sjohnh } 18854752Sjohnh 18954752Sjohnh /* 19054752Sjohnh * Clear out buffer cache. I don't think we 19154752Sjohnh * ever get anything cached at this level at the 19254752Sjohnh * moment, but who knows... 19354752Sjohnh */ 194*54893Sheideman #if 0 19554752Sjohnh mntflushbuf(mp, 0); 19654752Sjohnh if (mntinvalbuf(mp, 1)) 19754752Sjohnh return (EBUSY); 198*54893Sheideman #endif 19954754Sjohnh if (nullm_rootvp->v_usecount > 1) 20054752Sjohnh return (EBUSY); 20154754Sjohnh if (error = vflush(mp, nullm_rootvp, flags)) 20254752Sjohnh return (error); 20354752Sjohnh 20454754Sjohnh #ifdef NULLFS_DIAGNOSTIC 20554752Sjohnh /* 20654752Sjohnh * Flush any remaining vnode references 20754752Sjohnh */ 20854754Sjohnh null_node_flushmp (mp); 20954752Sjohnh #endif 21054752Sjohnh 21154754Sjohnh #ifdef NULLFS_DIAGNOSTIC 21254754Sjohnh vprint("alias root of target", nullm_rootvp); 21354752Sjohnh #endif 21454752Sjohnh /* 21554752Sjohnh * Release reference on underlying root vnode 21654752Sjohnh */ 21754754Sjohnh vrele(nullm_rootvp); 21854752Sjohnh /* 21954752Sjohnh * And blow it away for future re-use 22054752Sjohnh */ 22154754Sjohnh vgone(nullm_rootvp); 22254752Sjohnh /* 22354754Sjohnh * Finally, throw away the null_mount structure 22454752Sjohnh */ 22554752Sjohnh free(mp->mnt_data, M_UFSMNT); /* XXX */ 22654752Sjohnh mp->mnt_data = 0; 22754752Sjohnh return 0; 22854752Sjohnh } 22954752Sjohnh 230*54893Sheideman int 23154754Sjohnh nullfs_root(mp, vpp) 23254752Sjohnh struct mount *mp; 23354752Sjohnh struct vnode **vpp; 23454752Sjohnh { 23554752Sjohnh struct vnode *vp; 23654752Sjohnh 23754754Sjohnh #ifdef NULLFS_DIAGNOSTIC 23854754Sjohnh printf("nullfs_root(mp = %x, vp = %x->%x)\n", mp, 23954754Sjohnh MOUNTTONULLMOUNT(mp)->nullm_rootvp, 240*54893Sheideman NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp) 24154752Sjohnh ); 24254752Sjohnh #endif 24354752Sjohnh 24454752Sjohnh /* 24554752Sjohnh * Return locked reference to root. 24654752Sjohnh */ 24754754Sjohnh vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp; 24854752Sjohnh VREF(vp); 24954752Sjohnh VOP_LOCK(vp); 25054752Sjohnh *vpp = vp; 25154752Sjohnh return 0; 25254752Sjohnh } 25354752Sjohnh 254*54893Sheideman int 25554754Sjohnh nullfs_quotactl(mp, cmd, uid, arg, p) 25654752Sjohnh struct mount *mp; 25754752Sjohnh int cmd; 25854752Sjohnh uid_t uid; 25954752Sjohnh caddr_t arg; 26054752Sjohnh struct proc *p; 26154752Sjohnh { 26254754Sjohnh return VFS_QUOTACTL(MOUNTTONULLMOUNT(mp)->nullm_vfs, cmd, uid, arg, p); 26354752Sjohnh } 26454752Sjohnh 265*54893Sheideman int 26654754Sjohnh nullfs_statfs(mp, sbp, p) 26754752Sjohnh struct mount *mp; 26854752Sjohnh struct statfs *sbp; 26954752Sjohnh struct proc *p; 27054752Sjohnh { 27154752Sjohnh int error; 27254752Sjohnh struct statfs mstat; 27354752Sjohnh 27454754Sjohnh #ifdef NULLFS_DIAGNOSTIC 27554754Sjohnh printf("nullfs_statfs(mp = %x, vp = %x->%x)\n", mp, 27654754Sjohnh MOUNTTONULLMOUNT(mp)->nullm_rootvp, 277*54893Sheideman NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp) 27854752Sjohnh ); 27954752Sjohnh #endif 28054752Sjohnh 28154752Sjohnh bzero(&mstat, sizeof(mstat)); 28254752Sjohnh 28354754Sjohnh error = VFS_STATFS(MOUNTTONULLMOUNT(mp)->nullm_vfs, &mstat, p); 28454752Sjohnh if (error) 28554752Sjohnh return (error); 28654752Sjohnh 28754752Sjohnh /* now copy across the "interesting" information and fake the rest */ 28854752Sjohnh sbp->f_type = mstat.f_type; 28954752Sjohnh sbp->f_flags = mstat.f_flags; 29054752Sjohnh sbp->f_bsize = mstat.f_bsize; 29154752Sjohnh sbp->f_iosize = mstat.f_iosize; 29254752Sjohnh sbp->f_blocks = mstat.f_blocks; 29354752Sjohnh sbp->f_bfree = mstat.f_bfree; 29454752Sjohnh sbp->f_bavail = mstat.f_bavail; 29554752Sjohnh sbp->f_files = mstat.f_files; 29654752Sjohnh sbp->f_ffree = mstat.f_ffree; 29754752Sjohnh if (sbp != &mp->mnt_stat) { 29854752Sjohnh bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 29954752Sjohnh bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 30054752Sjohnh bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 30154752Sjohnh } 30254752Sjohnh return (0); 30354752Sjohnh } 30454752Sjohnh 305*54893Sheideman int 306*54893Sheideman nullfs_sync(mp, waitfor, cred, p) 307*54893Sheideman struct mount *mp; 308*54893Sheideman int waitfor; 309*54893Sheideman struct ucred *cred; 310*54893Sheideman struct proc *p; 31154752Sjohnh { 31254766Sjohnh /* 313*54893Sheideman * XXX - Assumes no data cached at null layer. 31454766Sjohnh */ 31554752Sjohnh return (0); 31654752Sjohnh } 31754752Sjohnh 318*54893Sheideman int 319*54893Sheideman nullfs_vget(mp, ino, vpp) 32054752Sjohnh struct mount *mp; 321*54893Sheideman ino_t ino; 32254752Sjohnh struct vnode **vpp; 32354752Sjohnh { 324*54893Sheideman 325*54893Sheideman return VFS_VGET(MOUNTTONULLMOUNT(mp)->nullm_vfs, ino, vpp); 32654752Sjohnh } 32754752Sjohnh 328*54893Sheideman int 329*54893Sheideman nullfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp) 330*54893Sheideman struct mount *mp; 331*54893Sheideman struct fid *fidp; 332*54893Sheideman struct mbuf *nam; 333*54893Sheideman struct vnode **vpp; 334*54893Sheideman int *exflagsp; 335*54893Sheideman struct ucred**credanonp; 336*54893Sheideman { 337*54893Sheideman 338*54893Sheideman return VFS_FHTOVP(MOUNTTONULLMOUNT(mp)->nullm_vfs, fidp, nam, vpp, exflagsp,credanonp); 339*54893Sheideman } 340*54893Sheideman 341*54893Sheideman int 34254754Sjohnh nullfs_vptofh(vp, fhp) 34354752Sjohnh struct vnode *vp; 34454752Sjohnh struct fid *fhp; 34554752Sjohnh { 346*54893Sheideman return VFS_VPTOFH(NULLVPTOLOWERVP(vp), fhp); 34754752Sjohnh } 34854752Sjohnh 34954754Sjohnh int nullfs_init __P((void)); 35054752Sjohnh 35154754Sjohnh struct vfsops null_vfsops = { 35254754Sjohnh nullfs_mount, 35354754Sjohnh nullfs_start, 35454754Sjohnh nullfs_unmount, 35554754Sjohnh nullfs_root, 35654754Sjohnh nullfs_quotactl, 35754754Sjohnh nullfs_statfs, 35854754Sjohnh nullfs_sync, 359*54893Sheideman nullfs_vget, 36054754Sjohnh nullfs_fhtovp, 36154754Sjohnh nullfs_vptofh, 36254754Sjohnh nullfs_init, 36354752Sjohnh }; 364