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