153841Spendry /* 263237Sbostic * Copyright (c) 1992, 1993 363237Sbostic * The Regents of the University of California. All rights reserved. 453841Spendry * All rights reserved. 553841Spendry * 653841Spendry * This code is derived from software donated to Berkeley by 753841Spendry * Jan-Simon Pendry. 853841Spendry * 953841Spendry * %sccs.include.redist.c% 1053841Spendry * 11*65518Spendry * @(#)lofs_vfsops.c 8.2 (Berkeley) 01/05/94 1253841Spendry * 1353841Spendry * $Id: lofs_vfsops.c,v 1.9 1992/05/30 10:26:24 jsp Exp jsp $ 1453841Spendry */ 1553841Spendry 1653841Spendry /* 1753841Spendry * Loopback Filesystem 1853841Spendry */ 1953841Spendry 2053841Spendry #include <sys/param.h> 2153841Spendry #include <sys/systm.h> 2253841Spendry #include <sys/time.h> 2353841Spendry #include <sys/types.h> 2453841Spendry #include <sys/vnode.h> 2553841Spendry #include <sys/mount.h> 2653841Spendry #include <sys/namei.h> 2753841Spendry #include <sys/malloc.h> 2855022Smckusick #include <miscfs/lofs/lofs.h> 2953841Spendry 3053841Spendry /* 3153841Spendry * Mount loopback copy of existing name space 3253841Spendry */ 33*65518Spendry int 3453841Spendry lofs_mount(mp, path, data, ndp, p) 3553841Spendry struct mount *mp; 3653841Spendry char *path; 3753841Spendry caddr_t data; 3853841Spendry struct nameidata *ndp; 3953841Spendry struct proc *p; 4053841Spendry { 4153841Spendry int error = 0; 4253841Spendry struct lofs_args args; 4353841Spendry struct vnode *vp; 4453841Spendry struct vnode *rootvp; 4553841Spendry struct lofsmount *amp; 4653841Spendry u_int size; 4753841Spendry 4853841Spendry /* 4953841Spendry * Update is a no-op 5053841Spendry */ 51*65518Spendry if (mp->mnt_flag & MNT_UPDATE) 5253841Spendry return (EOPNOTSUPP); 5353841Spendry 5453841Spendry /* 5553841Spendry * Get argument 5653841Spendry */ 5753841Spendry if (error = copyin(data, (caddr_t)&args, sizeof(struct lofs_args))) 5853841Spendry return (error); 5953841Spendry 6053841Spendry /* 6153841Spendry * Find target node 6253841Spendry */ 6353841Spendry NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF, 6453841Spendry UIO_USERSPACE, args.target, p); 6553841Spendry if (error = namei(ndp)) 6653841Spendry return (error); 6753841Spendry 6853841Spendry /* 6953841Spendry * Sanity check on target vnode 7053841Spendry */ 7153841Spendry vp = ndp->ni_vp; 7253841Spendry vrele(ndp->ni_dvp); 7353841Spendry ndp->ni_dvp = 0; 7453841Spendry 7553841Spendry if (vp->v_type != VDIR) { 7653841Spendry vput(vp); 7753841Spendry return (EINVAL); 7853841Spendry } 7953841Spendry 8053841Spendry amp = (struct lofsmount *) malloc(sizeof(struct lofsmount), 8153841Spendry M_UFSMNT, M_WAITOK); /* XXX */ 8253841Spendry 8353841Spendry /* 8453841Spendry * Save reference to underlying target FS 8553841Spendry */ 8653841Spendry amp->looped_vfs = vp->v_mount; 8753841Spendry 8853841Spendry /* 8953841Spendry * Save reference. Each mount also holds 9053841Spendry * a reference on the root vnode. 9153841Spendry */ 9253841Spendry error = make_lofs(mp, &vp); 9353841Spendry /* 9453841Spendry * Unlock the node (either the target or the alias) 9553841Spendry */ 9653841Spendry VOP_UNLOCK(vp); 9753841Spendry /* 9853841Spendry * Make sure the node alias worked 9953841Spendry */ 10053841Spendry if (error) { 10153841Spendry vrele(vp); 10253841Spendry free(amp, M_UFSMNT); /* XXX */ 10353841Spendry return (error); 10453841Spendry } 10553841Spendry 10653841Spendry /* 10753841Spendry * Keep a held reference to the root vnode. 10853841Spendry * It is vrele'd in lofs_unmount. 10953841Spendry */ 11053841Spendry rootvp = vp; 11153841Spendry rootvp->v_flag |= VROOT; 11253841Spendry amp->rootvp = rootvp; 11353841Spendry if (LOFSVP(rootvp)->v_mount->mnt_flag & MNT_LOCAL) 11453841Spendry mp->mnt_flag |= MNT_LOCAL; 11553841Spendry mp->mnt_data = (qaddr_t) amp; 11653841Spendry getnewfsid(mp, MOUNT_LOFS); 11753841Spendry 11853841Spendry (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); 11953841Spendry bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); 12053841Spendry (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 12153841Spendry &size); 12253841Spendry bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 12353841Spendry return (0); 12453841Spendry } 12553841Spendry 12653841Spendry /* 12753841Spendry * VFS start. Nothing needed here - the start routine 12853841Spendry * on the underlying filesystem will have been called 12953841Spendry * when that filesystem was mounted. 13053841Spendry */ 131*65518Spendry int 13253841Spendry lofs_start(mp, flags, p) 13353841Spendry struct mount *mp; 13453841Spendry int flags; 13553841Spendry struct proc *p; 13653841Spendry { 137*65518Spendry 13853841Spendry return (0); 13953841Spendry } 14053841Spendry 14153841Spendry /* 14253841Spendry * Free reference to looped FS 14353841Spendry */ 144*65518Spendry int 14553841Spendry lofs_unmount(mp, mntflags, p) 14653841Spendry struct mount *mp; 14753841Spendry int mntflags; 14853841Spendry struct proc *p; 14953841Spendry { 15053841Spendry struct vnode *rootvp = VFSTOLOFS(mp)->rootvp; 15153841Spendry int error; 15253841Spendry int flags = 0; 15353841Spendry extern int doforce; 15453841Spendry 15553841Spendry if (mntflags & MNT_FORCE) { 15653841Spendry /* lofs can never be rootfs so don't check for it */ 15753841Spendry if (!doforce) 15853841Spendry return (EINVAL); 15953841Spendry flags |= FORCECLOSE; 16053841Spendry } 16153841Spendry 16253841Spendry /* 16353841Spendry * Clear out buffer cache. I don't think we 16453841Spendry * ever get anything cached at this level at the 16553841Spendry * moment, but who knows... 16653841Spendry */ 16753841Spendry if (rootvp->v_usecount > 1) 16853841Spendry return (EBUSY); 16953841Spendry if (error = vflush(mp, rootvp, flags)) 17053841Spendry return (error); 17153841Spendry 17253841Spendry /* 17353841Spendry * Release reference on underlying root vnode 17453841Spendry */ 17553841Spendry vrele(rootvp); 17653841Spendry /* 17753841Spendry * And blow it away for future re-use 17853841Spendry */ 17953841Spendry vgone(rootvp); 18053841Spendry /* 18153841Spendry * Finally, throw away the lofsmount structure 18253841Spendry */ 18353841Spendry free(mp->mnt_data, M_UFSMNT); /* XXX */ 18453841Spendry mp->mnt_data = 0; 185*65518Spendry return (0); 18653841Spendry } 18753841Spendry 188*65518Spendry int 18953841Spendry lofs_root(mp, vpp) 19053841Spendry struct mount *mp; 19153841Spendry struct vnode **vpp; 19253841Spendry { 19353841Spendry struct vnode *vp; 19453841Spendry 19553841Spendry /* 19653841Spendry * Return locked reference to root. 19753841Spendry */ 19853841Spendry vp = VFSTOLOFS(mp)->rootvp; 19953841Spendry VREF(vp); 20053841Spendry VOP_LOCK(vp); 20153841Spendry *vpp = vp; 202*65518Spendry return (0); 20353841Spendry } 20453841Spendry 205*65518Spendry int 20653841Spendry lofs_quotactl(mp, cmd, uid, arg, p) 20753841Spendry struct mount *mp; 20853841Spendry int cmd; 20953841Spendry uid_t uid; 21053841Spendry caddr_t arg; 21153841Spendry struct proc *p; 21253841Spendry { 213*65518Spendry return (VFS_QUOTACTL(VFSTOLOFS(mp)->looped_vfs, cmd, uid, arg, p)); 21453841Spendry } 21553841Spendry 216*65518Spendry int 21753841Spendry lofs_statfs(mp, sbp, p) 21853841Spendry struct mount *mp; 21953841Spendry struct statfs *sbp; 22053841Spendry struct proc *p; 22153841Spendry { 22253841Spendry int error; 22353841Spendry struct statfs mstat; 22453841Spendry 22553841Spendry bzero(&mstat, sizeof(mstat)); 22653841Spendry 22753841Spendry error = VFS_STATFS(VFSTOLOFS(mp)->looped_vfs, &mstat, p); 22853841Spendry if (error) 22953841Spendry return (error); 23053841Spendry 23153841Spendry /* now copy across the "interesting" information and fake the rest */ 23253841Spendry sbp->f_type = mstat.f_type; 23353841Spendry sbp->f_flags = mstat.f_flags; 23453841Spendry sbp->f_bsize = mstat.f_bsize; 23553841Spendry sbp->f_iosize = mstat.f_iosize; 23653841Spendry sbp->f_blocks = mstat.f_blocks; 23753841Spendry sbp->f_bfree = mstat.f_bfree; 23853841Spendry sbp->f_bavail = mstat.f_bavail; 23953841Spendry sbp->f_files = mstat.f_files; 24053841Spendry sbp->f_ffree = mstat.f_ffree; 24153841Spendry if (sbp != &mp->mnt_stat) { 24253841Spendry bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 24353841Spendry bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 24453841Spendry bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 24553841Spendry } 24653841Spendry return (0); 24753841Spendry } 24853841Spendry 249*65518Spendry int 25053841Spendry lofs_sync(mp, waitfor) 25153841Spendry struct mount *mp; 25253841Spendry int waitfor; 25353841Spendry { 25454051Spendry return (0); 25553841Spendry } 25653841Spendry 25754982Spendry /* 25854982Spendry * LOFS flat namespace lookup. 25954982Spendry * Currently unsupported. 26054982Spendry */ 261*65518Spendry int 26254982Spendry lofs_vget(mp, ino, vpp) 26353841Spendry struct mount *mp; 26454982Spendry ino_t ino; 26554982Spendry struct vnode **vpp; 26654982Spendry { 26754982Spendry 26854982Spendry return (EOPNOTSUPP); 26954982Spendry } 27054982Spendry 271*65518Spendry int 27254982Spendry lofs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) 27354982Spendry register struct mount *mp; 27453841Spendry struct fid *fhp; 27554982Spendry struct mbuf *nam; 27653841Spendry struct vnode **vpp; 27754982Spendry int *exflagsp; 27854982Spendry struct ucred **credanonp; 27953841Spendry { 280*65518Spendry return (VFS_FHTOVP(VFSTOLOFS(mp)->looped_vfs, fhp, nam, vpp, exflagsp, credanonp)); 28153841Spendry } 28253841Spendry 283*65518Spendry int 28453841Spendry lofs_vptofh(vp, fhp) 28553841Spendry struct vnode *vp; 28653841Spendry struct fid *fhp; 28753841Spendry { 288*65518Spendry return (VFS_VPTOFH(LOFSVP(vp), fhp)); 28953841Spendry } 29053841Spendry 29153841Spendry struct vfsops lofs_vfsops = { 29253841Spendry lofs_mount, 29353841Spendry lofs_start, 29453841Spendry lofs_unmount, 29553841Spendry lofs_root, 29653841Spendry lofs_quotactl, 29753841Spendry lofs_statfs, 29853841Spendry lofs_sync, 29954982Spendry lofs_vget, 30053841Spendry lofs_fhtovp, 30153841Spendry lofs_vptofh, 30253841Spendry lofs_init, 30353841Spendry }; 304