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 * the UCLA Ficus project. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)umap_vfsops.c 8.1 (Berkeley) 06/10/93 12 * 13 * @(#)null_vfsops.c 1.5 (Berkeley) 7/10/92 14 */ 15 16 /* 17 * Umap Layer 18 * (See mount_umap(8) for a description of this layer.) 19 */ 20 21 #include <sys/param.h> 22 #include <sys/systm.h> 23 #include <sys/time.h> 24 #include <sys/types.h> 25 #include <sys/vnode.h> 26 #include <sys/mount.h> 27 #include <sys/namei.h> 28 #include <sys/malloc.h> 29 #include <miscfs/umapfs/umap.h> 30 31 /* 32 * Mount umap layer 33 */ 34 int 35 umapfs_mount(mp, path, data, ndp, p) 36 struct mount *mp; 37 char *path; 38 caddr_t data; 39 struct nameidata *ndp; 40 struct proc *p; 41 { 42 int i; 43 int error = 0; 44 struct umap_args args; 45 struct vnode *lowerrootvp, *vp; 46 struct vnode *umapm_rootvp; 47 struct umap_mount *amp; 48 u_int size; 49 50 #ifdef UMAPFS_DIAGNOSTIC 51 printf("umapfs_mount(mp = %x)\n", mp); 52 #endif 53 54 /* 55 * Update is a no-op 56 */ 57 if (mp->mnt_flag & MNT_UPDATE) { 58 return (EOPNOTSUPP); 59 /* return VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, p);*/ 60 } 61 62 /* 63 * Get argument 64 */ 65 if (error = copyin(data, (caddr_t)&args, sizeof(struct umap_args))) 66 return (error); 67 68 /* 69 * Find lower node 70 */ 71 NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF, 72 UIO_USERSPACE, args.target, p); 73 if (error = namei(ndp)) 74 return (error); 75 76 /* 77 * Sanity check on lower vnode 78 */ 79 lowerrootvp = ndp->ni_vp; 80 #ifdef UMAPFS_DIAGNOSTIC 81 printf("vp = %x, check for VDIR...\n", lowerrootvp); 82 #endif 83 vrele(ndp->ni_dvp); 84 ndp->ni_dvp = 0; 85 86 if (lowerrootvp->v_type != VDIR) { 87 vput(lowerrootvp); 88 return (EINVAL); 89 } 90 91 #ifdef UMAPFS_DIAGNOSTIC 92 printf("mp = %x\n", mp); 93 #endif 94 95 amp = (struct umap_mount *) malloc(sizeof(struct umap_mount), 96 M_UFSMNT, M_WAITOK); /* XXX */ 97 98 /* 99 * Save reference to underlying FS 100 */ 101 amp->umapm_vfs = lowerrootvp->v_mount; 102 103 /* 104 * Now copy in the number of entries and maps for umap mapping. 105 */ 106 amp->info_nentries = args.nentries; 107 amp->info_gnentries = args.gnentries; 108 error = copyin(args.mapdata, (caddr_t)amp->info_mapdata, 109 2*sizeof(int)*args.nentries); 110 if (error) return (error); 111 112 #ifdef UMAP_DIAGNOSTIC 113 printf("umap_mount:nentries %d\n",args.nentries); 114 for (i = 0; i < args.nentries; i++) 115 printf(" %d maps to %d\n", amp->info_mapdata[i][0], 116 amp->info_mapdata[i][1]); 117 #endif 118 119 error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata, 120 2*sizeof(int)*args.nentries); 121 if (error) return (error); 122 123 #ifdef UMAP_DIAGNOSTIC 124 printf("umap_mount:gnentries %d\n",args.gnentries); 125 for (i = 0; i < args.gnentries; i++) 126 printf(" group %d maps to %d\n", 127 amp->info_gmapdata[i][0], 128 amp->info_gmapdata[i][1]); 129 #endif 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 lower 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: lower %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 #ifdef notyet 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 vprint("alias root of lower", umapm_rootvp); 231 #endif 232 /* 233 * Release reference on underlying root vnode 234 */ 235 vrele(umapm_rootvp); 236 /* 237 * And blow it away for future re-use 238 */ 239 vgone(umapm_rootvp); 240 /* 241 * Finally, throw away the umap_mount structure 242 */ 243 free(mp->mnt_data, M_UFSMNT); /* XXX */ 244 mp->mnt_data = 0; 245 return 0; 246 } 247 248 int 249 umapfs_root(mp, vpp) 250 struct mount *mp; 251 struct vnode **vpp; 252 { 253 struct vnode *vp; 254 255 #ifdef UMAPFS_DIAGNOSTIC 256 printf("umapfs_root(mp = %x, vp = %x->%x)\n", mp, 257 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp, 258 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp) 259 ); 260 #endif 261 262 /* 263 * Return locked reference to root. 264 */ 265 vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp; 266 VREF(vp); 267 VOP_LOCK(vp); 268 *vpp = vp; 269 return 0; 270 } 271 272 int 273 umapfs_quotactl(mp, cmd, uid, arg, p) 274 struct mount *mp; 275 int cmd; 276 uid_t uid; 277 caddr_t arg; 278 struct proc *p; 279 { 280 return VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p); 281 } 282 283 int 284 umapfs_statfs(mp, sbp, p) 285 struct mount *mp; 286 struct statfs *sbp; 287 struct proc *p; 288 { 289 int error; 290 struct statfs mstat; 291 292 #ifdef UMAPFS_DIAGNOSTIC 293 printf("umapfs_statfs(mp = %x, vp = %x->%x)\n", mp, 294 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp, 295 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp) 296 ); 297 #endif 298 299 bzero(&mstat, sizeof(mstat)); 300 301 error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p); 302 if (error) 303 return (error); 304 305 /* now copy across the "interesting" information and fake the rest */ 306 sbp->f_type = mstat.f_type; 307 sbp->f_flags = mstat.f_flags; 308 sbp->f_bsize = mstat.f_bsize; 309 sbp->f_iosize = mstat.f_iosize; 310 sbp->f_blocks = mstat.f_blocks; 311 sbp->f_bfree = mstat.f_bfree; 312 sbp->f_bavail = mstat.f_bavail; 313 sbp->f_files = mstat.f_files; 314 sbp->f_ffree = mstat.f_ffree; 315 if (sbp != &mp->mnt_stat) { 316 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 317 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 318 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 319 } 320 return (0); 321 } 322 323 int 324 umapfs_sync(mp, waitfor, cred, p) 325 struct mount *mp; 326 int waitfor; 327 struct ucred *cred; 328 struct proc *p; 329 { 330 /* 331 * XXX - Assumes no data cached at umap layer. 332 */ 333 return (0); 334 } 335 336 int 337 umapfs_vget(mp, ino, vpp) 338 struct mount *mp; 339 ino_t ino; 340 struct vnode **vpp; 341 { 342 343 return VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp); 344 } 345 346 int 347 umapfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp) 348 struct mount *mp; 349 struct fid *fidp; 350 struct mbuf *nam; 351 struct vnode **vpp; 352 int *exflagsp; 353 struct ucred**credanonp; 354 { 355 356 return VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, nam, vpp, exflagsp,credanonp); 357 } 358 359 int 360 umapfs_vptofh(vp, fhp) 361 struct vnode *vp; 362 struct fid *fhp; 363 { 364 return VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp); 365 } 366 367 int umapfs_init __P((void)); 368 369 struct vfsops umap_vfsops = { 370 umapfs_mount, 371 umapfs_start, 372 umapfs_unmount, 373 umapfs_root, 374 umapfs_quotactl, 375 umapfs_statfs, 376 umapfs_sync, 377 umapfs_vget, 378 umapfs_fhtovp, 379 umapfs_vptofh, 380 umapfs_init, 381 }; 382