1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software donated to Berkeley by 6 * the UCLA Ficus project. 7 * 8 * %sccs.include.redist.c% 9 * 10 * @(#)umap_vfsops.c 8.6 (Berkeley) 05/10/95 11 * 12 * @(#)null_vfsops.c 1.5 (Berkeley) 7/10/92 13 */ 14 15 /* 16 * Umap Layer 17 * (See mount_umap(8) for a description of this layer.) 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/umapfs/umap.h> 29 30 /* 31 * Mount umap layer 32 */ 33 int 34 umapfs_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 struct umap_args args; 42 struct vnode *lowerrootvp, *vp; 43 struct vnode *umapm_rootvp; 44 struct umap_mount *amp; 45 u_int size; 46 int error; 47 48 #ifdef UMAPFS_DIAGNOSTIC 49 printf("umapfs_mount(mp = %x)\n", mp); 50 #endif 51 52 /* 53 * Update is a no-op 54 */ 55 if (mp->mnt_flag & MNT_UPDATE) { 56 return (EOPNOTSUPP); 57 /* return (VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, p));*/ 58 } 59 60 /* 61 * Get argument 62 */ 63 if (error = copyin(data, (caddr_t)&args, sizeof(struct umap_args))) 64 return (error); 65 66 /* 67 * Find lower node 68 */ 69 NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF, 70 UIO_USERSPACE, args.target, p); 71 if (error = namei(ndp)) 72 return (error); 73 74 /* 75 * Sanity check on lower vnode 76 */ 77 lowerrootvp = ndp->ni_vp; 78 #ifdef UMAPFS_DIAGNOSTIC 79 printf("vp = %x, check for VDIR...\n", lowerrootvp); 80 #endif 81 vrele(ndp->ni_dvp); 82 ndp->ni_dvp = 0; 83 84 if (lowerrootvp->v_type != VDIR) { 85 vput(lowerrootvp); 86 return (EINVAL); 87 } 88 89 #ifdef UMAPFS_DIAGNOSTIC 90 printf("mp = %x\n", mp); 91 #endif 92 93 amp = (struct umap_mount *) malloc(sizeof(struct umap_mount), 94 M_UFSMNT, M_WAITOK); /* XXX */ 95 96 /* 97 * Save reference to underlying FS 98 */ 99 amp->umapm_vfs = lowerrootvp->v_mount; 100 101 /* 102 * Now copy in the number of entries and maps for umap mapping. 103 */ 104 amp->info_nentries = args.nentries; 105 amp->info_gnentries = args.gnentries; 106 error = copyin(args.mapdata, (caddr_t)amp->info_mapdata, 107 2*sizeof(u_long)*args.nentries); 108 if (error) 109 return (error); 110 111 #ifdef UMAP_DIAGNOSTIC 112 printf("umap_mount:nentries %d\n",args.nentries); 113 for (i = 0; i < args.nentries; i++) 114 printf(" %d maps to %d\n", amp->info_mapdata[i][0], 115 amp->info_mapdata[i][1]); 116 #endif 117 118 error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata, 119 2*sizeof(u_long)*args.nentries); 120 if (error) 121 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 vfs_getnewfsid(mp); 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 202 #ifdef UMAPFS_DIAGNOSTIC 203 printf("umapfs_unmount(mp = %x)\n", mp); 204 #endif 205 206 if (mntflags & MNT_FORCE) 207 flags |= FORCECLOSE; 208 209 /* 210 * Clear out buffer cache. I don't think we 211 * ever get anything cached at this level at the 212 * moment, but who knows... 213 */ 214 #ifdef notyet 215 mntflushbuf(mp, 0); 216 if (mntinvalbuf(mp, 1)) 217 return (EBUSY); 218 #endif 219 if (umapm_rootvp->v_usecount > 1) 220 return (EBUSY); 221 if (error = vflush(mp, umapm_rootvp, flags)) 222 return (error); 223 224 #ifdef UMAPFS_DIAGNOSTIC 225 vprint("alias root of lower", umapm_rootvp); 226 #endif 227 /* 228 * Release reference on underlying root vnode 229 */ 230 vrele(umapm_rootvp); 231 /* 232 * And blow it away for future re-use 233 */ 234 VOP_REVOKE(umapm_rootvp, 0); 235 /* 236 * Finally, throw away the umap_mount structure 237 */ 238 free(mp->mnt_data, M_UFSMNT); /* XXX */ 239 mp->mnt_data = 0; 240 return (0); 241 } 242 243 int 244 umapfs_root(mp, vpp) 245 struct mount *mp; 246 struct vnode **vpp; 247 { 248 struct vnode *vp; 249 250 #ifdef UMAPFS_DIAGNOSTIC 251 printf("umapfs_root(mp = %x, vp = %x->%x)\n", mp, 252 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp, 253 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp) 254 ); 255 #endif 256 257 /* 258 * Return locked reference to root. 259 */ 260 vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp; 261 VREF(vp); 262 VOP_LOCK(vp); 263 *vpp = vp; 264 return (0); 265 } 266 267 int 268 umapfs_quotactl(mp, cmd, uid, arg, p) 269 struct mount *mp; 270 int cmd; 271 uid_t uid; 272 caddr_t arg; 273 struct proc *p; 274 { 275 return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p)); 276 } 277 278 int 279 umapfs_statfs(mp, sbp, p) 280 struct mount *mp; 281 struct statfs *sbp; 282 struct proc *p; 283 { 284 int error; 285 struct statfs mstat; 286 287 #ifdef UMAPFS_DIAGNOSTIC 288 printf("umapfs_statfs(mp = %x, vp = %x->%x)\n", mp, 289 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp, 290 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp) 291 ); 292 #endif 293 294 bzero(&mstat, sizeof(mstat)); 295 296 error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p); 297 if (error) 298 return (error); 299 300 /* now copy across the "interesting" information and fake the rest */ 301 sbp->f_type = mstat.f_type; 302 sbp->f_flags = mstat.f_flags; 303 sbp->f_bsize = mstat.f_bsize; 304 sbp->f_iosize = mstat.f_iosize; 305 sbp->f_blocks = mstat.f_blocks; 306 sbp->f_bfree = mstat.f_bfree; 307 sbp->f_bavail = mstat.f_bavail; 308 sbp->f_files = mstat.f_files; 309 sbp->f_ffree = mstat.f_ffree; 310 if (sbp != &mp->mnt_stat) { 311 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 312 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 313 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 314 } 315 return (0); 316 } 317 318 int 319 umapfs_sync(mp, waitfor, cred, p) 320 struct mount *mp; 321 int waitfor; 322 struct ucred *cred; 323 struct proc *p; 324 { 325 /* 326 * XXX - Assumes no data cached at umap layer. 327 */ 328 return (0); 329 } 330 331 int 332 umapfs_vget(mp, ino, vpp) 333 struct mount *mp; 334 ino_t ino; 335 struct vnode **vpp; 336 { 337 338 return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp)); 339 } 340 341 int 342 umapfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp) 343 struct mount *mp; 344 struct fid *fidp; 345 struct mbuf *nam; 346 struct vnode **vpp; 347 int *exflagsp; 348 struct ucred**credanonp; 349 { 350 351 return (VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, nam, vpp, exflagsp,credanonp)); 352 } 353 354 int 355 umapfs_vptofh(vp, fhp) 356 struct vnode *vp; 357 struct fid *fhp; 358 { 359 return (VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp)); 360 } 361 362 int umapfs_init __P((struct vfsconf *)); 363 #define umapfs_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \ 364 size_t, struct proc *)))eopnotsupp) 365 366 struct vfsops umap_vfsops = { 367 umapfs_mount, 368 umapfs_start, 369 umapfs_unmount, 370 umapfs_root, 371 umapfs_quotactl, 372 umapfs_statfs, 373 umapfs_sync, 374 umapfs_vget, 375 umapfs_fhtovp, 376 umapfs_vptofh, 377 umapfs_init, 378 umapfs_sysctl, 379 }; 380