1 /* 2 * Copyright (c) 1992, 1993, 1995 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.8 (Berkeley) 05/14/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/proc.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, 0, p); 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 vfs_getnewfsid(mp); 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 203 #ifdef UMAPFS_DIAGNOSTIC 204 printf("umapfs_unmount(mp = %x)\n", mp); 205 #endif 206 207 if (mntflags & MNT_FORCE) 208 flags |= FORCECLOSE; 209 210 /* 211 * Clear out buffer cache. I don't think we 212 * ever get anything cached at this level at the 213 * moment, but who knows... 214 */ 215 #ifdef notyet 216 mntflushbuf(mp, 0); 217 if (mntinvalbuf(mp, 1)) 218 return (EBUSY); 219 #endif 220 if (umapm_rootvp->v_usecount > 1) 221 return (EBUSY); 222 if (error = vflush(mp, umapm_rootvp, flags)) 223 return (error); 224 225 #ifdef UMAPFS_DIAGNOSTIC 226 vprint("alias root of lower", umapm_rootvp); 227 #endif 228 /* 229 * Release reference on underlying root vnode 230 */ 231 vrele(umapm_rootvp); 232 /* 233 * And blow it away for future re-use 234 */ 235 vgone(umapm_rootvp); 236 /* 237 * Finally, throw away the umap_mount structure 238 */ 239 free(mp->mnt_data, M_UFSMNT); /* XXX */ 240 mp->mnt_data = 0; 241 return (0); 242 } 243 244 int 245 umapfs_root(mp, vpp) 246 struct mount *mp; 247 struct vnode **vpp; 248 { 249 struct proc *p = curproc; /* XXX */ 250 struct vnode *vp; 251 252 #ifdef UMAPFS_DIAGNOSTIC 253 printf("umapfs_root(mp = %x, vp = %x->%x)\n", mp, 254 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp, 255 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp) 256 ); 257 #endif 258 259 /* 260 * Return locked reference to root. 261 */ 262 vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp; 263 VREF(vp); 264 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 265 *vpp = vp; 266 return (0); 267 } 268 269 int 270 umapfs_quotactl(mp, cmd, uid, arg, p) 271 struct mount *mp; 272 int cmd; 273 uid_t uid; 274 caddr_t arg; 275 struct proc *p; 276 { 277 return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p)); 278 } 279 280 int 281 umapfs_statfs(mp, sbp, p) 282 struct mount *mp; 283 struct statfs *sbp; 284 struct proc *p; 285 { 286 int error; 287 struct statfs mstat; 288 289 #ifdef UMAPFS_DIAGNOSTIC 290 printf("umapfs_statfs(mp = %x, vp = %x->%x)\n", mp, 291 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp, 292 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp) 293 ); 294 #endif 295 296 bzero(&mstat, sizeof(mstat)); 297 298 error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p); 299 if (error) 300 return (error); 301 302 /* now copy across the "interesting" information and fake the rest */ 303 sbp->f_type = mstat.f_type; 304 sbp->f_flags = mstat.f_flags; 305 sbp->f_bsize = mstat.f_bsize; 306 sbp->f_iosize = mstat.f_iosize; 307 sbp->f_blocks = mstat.f_blocks; 308 sbp->f_bfree = mstat.f_bfree; 309 sbp->f_bavail = mstat.f_bavail; 310 sbp->f_files = mstat.f_files; 311 sbp->f_ffree = mstat.f_ffree; 312 if (sbp != &mp->mnt_stat) { 313 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 314 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 315 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 316 } 317 return (0); 318 } 319 320 int 321 umapfs_sync(mp, waitfor, cred, p) 322 struct mount *mp; 323 int waitfor; 324 struct ucred *cred; 325 struct proc *p; 326 { 327 /* 328 * XXX - Assumes no data cached at umap layer. 329 */ 330 return (0); 331 } 332 333 int 334 umapfs_vget(mp, ino, vpp) 335 struct mount *mp; 336 ino_t ino; 337 struct vnode **vpp; 338 { 339 340 return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp)); 341 } 342 343 int 344 umapfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp) 345 struct mount *mp; 346 struct fid *fidp; 347 struct mbuf *nam; 348 struct vnode **vpp; 349 int *exflagsp; 350 struct ucred**credanonp; 351 { 352 353 return (VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, nam, vpp, exflagsp,credanonp)); 354 } 355 356 int 357 umapfs_vptofh(vp, fhp) 358 struct vnode *vp; 359 struct fid *fhp; 360 { 361 return (VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp)); 362 } 363 364 int umapfs_init __P((struct vfsconf *)); 365 #define umapfs_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \ 366 size_t, struct proc *)))eopnotsupp) 367 368 struct vfsops umap_vfsops = { 369 umapfs_mount, 370 umapfs_start, 371 umapfs_unmount, 372 umapfs_root, 373 umapfs_quotactl, 374 umapfs_statfs, 375 umapfs_sync, 376 umapfs_vget, 377 umapfs_fhtovp, 378 umapfs_vptofh, 379 umapfs_init, 380 umapfs_sysctl, 381 }; 382