1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * All rights reserved. 5 * 6 * This code is derived from software donated to Berkeley by 7 * Jan-Simon Pendry. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)lofs_vfsops.c 8.2 (Berkeley) 01/05/94 12 * 13 * $Id: lofs_vfsops.c,v 1.9 1992/05/30 10:26:24 jsp Exp jsp $ 14 */ 15 16 /* 17 * Loopback Filesystem 18 */ 19 20 #include <sys/param.h> 21 #include <sys/systm.h> 22 #include <sys/time.h> 23 #include <sys/types.h> 24 #include <sys/vnode.h> 25 #include <sys/mount.h> 26 #include <sys/namei.h> 27 #include <sys/malloc.h> 28 #include <miscfs/lofs/lofs.h> 29 30 /* 31 * Mount loopback copy of existing name space 32 */ 33 int 34 lofs_mount(mp, path, data, ndp, p) 35 struct mount *mp; 36 char *path; 37 caddr_t data; 38 struct nameidata *ndp; 39 struct proc *p; 40 { 41 int error = 0; 42 struct lofs_args args; 43 struct vnode *vp; 44 struct vnode *rootvp; 45 struct lofsmount *amp; 46 u_int size; 47 48 /* 49 * Update is a no-op 50 */ 51 if (mp->mnt_flag & MNT_UPDATE) 52 return (EOPNOTSUPP); 53 54 /* 55 * Get argument 56 */ 57 if (error = copyin(data, (caddr_t)&args, sizeof(struct lofs_args))) 58 return (error); 59 60 /* 61 * Find target node 62 */ 63 NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF, 64 UIO_USERSPACE, args.target, p); 65 if (error = namei(ndp)) 66 return (error); 67 68 /* 69 * Sanity check on target vnode 70 */ 71 vp = ndp->ni_vp; 72 vrele(ndp->ni_dvp); 73 ndp->ni_dvp = 0; 74 75 if (vp->v_type != VDIR) { 76 vput(vp); 77 return (EINVAL); 78 } 79 80 amp = (struct lofsmount *) malloc(sizeof(struct lofsmount), 81 M_UFSMNT, M_WAITOK); /* XXX */ 82 83 /* 84 * Save reference to underlying target FS 85 */ 86 amp->looped_vfs = vp->v_mount; 87 88 /* 89 * Save reference. Each mount also holds 90 * a reference on the root vnode. 91 */ 92 error = make_lofs(mp, &vp); 93 /* 94 * Unlock the node (either the target or the alias) 95 */ 96 VOP_UNLOCK(vp); 97 /* 98 * Make sure the node alias worked 99 */ 100 if (error) { 101 vrele(vp); 102 free(amp, M_UFSMNT); /* XXX */ 103 return (error); 104 } 105 106 /* 107 * Keep a held reference to the root vnode. 108 * It is vrele'd in lofs_unmount. 109 */ 110 rootvp = vp; 111 rootvp->v_flag |= VROOT; 112 amp->rootvp = rootvp; 113 if (LOFSVP(rootvp)->v_mount->mnt_flag & MNT_LOCAL) 114 mp->mnt_flag |= MNT_LOCAL; 115 mp->mnt_data = (qaddr_t) amp; 116 getnewfsid(mp, MOUNT_LOFS); 117 118 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); 119 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); 120 (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 121 &size); 122 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 123 return (0); 124 } 125 126 /* 127 * VFS start. Nothing needed here - the start routine 128 * on the underlying filesystem will have been called 129 * when that filesystem was mounted. 130 */ 131 int 132 lofs_start(mp, flags, p) 133 struct mount *mp; 134 int flags; 135 struct proc *p; 136 { 137 138 return (0); 139 } 140 141 /* 142 * Free reference to looped FS 143 */ 144 int 145 lofs_unmount(mp, mntflags, p) 146 struct mount *mp; 147 int mntflags; 148 struct proc *p; 149 { 150 struct vnode *rootvp = VFSTOLOFS(mp)->rootvp; 151 int error; 152 int flags = 0; 153 extern int doforce; 154 155 if (mntflags & MNT_FORCE) { 156 /* lofs can never be rootfs so don't check for it */ 157 if (!doforce) 158 return (EINVAL); 159 flags |= FORCECLOSE; 160 } 161 162 /* 163 * Clear out buffer cache. I don't think we 164 * ever get anything cached at this level at the 165 * moment, but who knows... 166 */ 167 if (rootvp->v_usecount > 1) 168 return (EBUSY); 169 if (error = vflush(mp, rootvp, flags)) 170 return (error); 171 172 /* 173 * Release reference on underlying root vnode 174 */ 175 vrele(rootvp); 176 /* 177 * And blow it away for future re-use 178 */ 179 vgone(rootvp); 180 /* 181 * Finally, throw away the lofsmount structure 182 */ 183 free(mp->mnt_data, M_UFSMNT); /* XXX */ 184 mp->mnt_data = 0; 185 return (0); 186 } 187 188 int 189 lofs_root(mp, vpp) 190 struct mount *mp; 191 struct vnode **vpp; 192 { 193 struct vnode *vp; 194 195 /* 196 * Return locked reference to root. 197 */ 198 vp = VFSTOLOFS(mp)->rootvp; 199 VREF(vp); 200 VOP_LOCK(vp); 201 *vpp = vp; 202 return (0); 203 } 204 205 int 206 lofs_quotactl(mp, cmd, uid, arg, p) 207 struct mount *mp; 208 int cmd; 209 uid_t uid; 210 caddr_t arg; 211 struct proc *p; 212 { 213 return (VFS_QUOTACTL(VFSTOLOFS(mp)->looped_vfs, cmd, uid, arg, p)); 214 } 215 216 int 217 lofs_statfs(mp, sbp, p) 218 struct mount *mp; 219 struct statfs *sbp; 220 struct proc *p; 221 { 222 int error; 223 struct statfs mstat; 224 225 bzero(&mstat, sizeof(mstat)); 226 227 error = VFS_STATFS(VFSTOLOFS(mp)->looped_vfs, &mstat, p); 228 if (error) 229 return (error); 230 231 /* now copy across the "interesting" information and fake the rest */ 232 sbp->f_type = mstat.f_type; 233 sbp->f_flags = mstat.f_flags; 234 sbp->f_bsize = mstat.f_bsize; 235 sbp->f_iosize = mstat.f_iosize; 236 sbp->f_blocks = mstat.f_blocks; 237 sbp->f_bfree = mstat.f_bfree; 238 sbp->f_bavail = mstat.f_bavail; 239 sbp->f_files = mstat.f_files; 240 sbp->f_ffree = mstat.f_ffree; 241 if (sbp != &mp->mnt_stat) { 242 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 243 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 244 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 245 } 246 return (0); 247 } 248 249 int 250 lofs_sync(mp, waitfor) 251 struct mount *mp; 252 int waitfor; 253 { 254 return (0); 255 } 256 257 /* 258 * LOFS flat namespace lookup. 259 * Currently unsupported. 260 */ 261 int 262 lofs_vget(mp, ino, vpp) 263 struct mount *mp; 264 ino_t ino; 265 struct vnode **vpp; 266 { 267 268 return (EOPNOTSUPP); 269 } 270 271 int 272 lofs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) 273 register struct mount *mp; 274 struct fid *fhp; 275 struct mbuf *nam; 276 struct vnode **vpp; 277 int *exflagsp; 278 struct ucred **credanonp; 279 { 280 return (VFS_FHTOVP(VFSTOLOFS(mp)->looped_vfs, fhp, nam, vpp, exflagsp, credanonp)); 281 } 282 283 int 284 lofs_vptofh(vp, fhp) 285 struct vnode *vp; 286 struct fid *fhp; 287 { 288 return (VFS_VPTOFH(LOFSVP(vp), fhp)); 289 } 290 291 struct vfsops lofs_vfsops = { 292 lofs_mount, 293 lofs_start, 294 lofs_unmount, 295 lofs_root, 296 lofs_quotactl, 297 lofs_statfs, 298 lofs_sync, 299 lofs_vget, 300 lofs_fhtovp, 301 lofs_vptofh, 302 lofs_init, 303 }; 304