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