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