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 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: @(#)null_vfsops.c 1.5 (Berkeley) 7/10/92 37 * from: @(#)umap_vfsops.c 8.3 (Berkeley) 1/21/94 38 * $Id: umap_vfsops.c,v 1.1 1994/06/08 11:33:53 mycroft Exp $ 39 */ 40 41 /* 42 * Umap Layer 43 * (See mount_umap(8) for a description of this layer.) 44 */ 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/time.h> 49 #include <sys/types.h> 50 #include <sys/vnode.h> 51 #include <sys/mount.h> 52 #include <sys/namei.h> 53 #include <sys/malloc.h> 54 #include <miscfs/umapfs/umap.h> 55 56 /* 57 * Mount umap layer 58 */ 59 int 60 umapfs_mount(mp, path, data, ndp, p) 61 struct mount *mp; 62 char *path; 63 caddr_t data; 64 struct nameidata *ndp; 65 struct proc *p; 66 { 67 struct umap_args args; 68 struct vnode *lowerrootvp, *vp; 69 struct vnode *umapm_rootvp; 70 struct umap_mount *amp; 71 u_int size; 72 int error; 73 74 #ifdef UMAPFS_DIAGNOSTIC 75 printf("umapfs_mount(mp = %x)\n", mp); 76 #endif 77 78 /* 79 * Update is a no-op 80 */ 81 if (mp->mnt_flag & MNT_UPDATE) { 82 return (EOPNOTSUPP); 83 /* return (VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, p));*/ 84 } 85 86 /* 87 * Get argument 88 */ 89 if (error = copyin(data, (caddr_t)&args, sizeof(struct umap_args))) 90 return (error); 91 92 /* 93 * Find lower node 94 */ 95 NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF, 96 UIO_USERSPACE, args.target, p); 97 if (error = namei(ndp)) 98 return (error); 99 100 /* 101 * Sanity check on lower vnode 102 */ 103 lowerrootvp = ndp->ni_vp; 104 #ifdef UMAPFS_DIAGNOSTIC 105 printf("vp = %x, check for VDIR...\n", lowerrootvp); 106 #endif 107 vrele(ndp->ni_dvp); 108 ndp->ni_dvp = 0; 109 110 if (lowerrootvp->v_type != VDIR) { 111 vput(lowerrootvp); 112 return (EINVAL); 113 } 114 115 #ifdef UMAPFS_DIAGNOSTIC 116 printf("mp = %x\n", mp); 117 #endif 118 119 amp = (struct umap_mount *) malloc(sizeof(struct umap_mount), 120 M_UFSMNT, M_WAITOK); /* XXX */ 121 122 /* 123 * Save reference to underlying FS 124 */ 125 amp->umapm_vfs = lowerrootvp->v_mount; 126 127 /* 128 * Now copy in the number of entries and maps for umap mapping. 129 */ 130 amp->info_nentries = args.nentries; 131 amp->info_gnentries = args.gnentries; 132 error = copyin(args.mapdata, (caddr_t)amp->info_mapdata, 133 2*sizeof(u_long)*args.nentries); 134 if (error) 135 return (error); 136 137 #ifdef UMAP_DIAGNOSTIC 138 printf("umap_mount:nentries %d\n",args.nentries); 139 for (i = 0; i < args.nentries; i++) 140 printf(" %d maps to %d\n", amp->info_mapdata[i][0], 141 amp->info_mapdata[i][1]); 142 #endif 143 144 error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata, 145 2*sizeof(u_long)*args.nentries); 146 if (error) 147 return (error); 148 149 #ifdef UMAP_DIAGNOSTIC 150 printf("umap_mount:gnentries %d\n",args.gnentries); 151 for (i = 0; i < args.gnentries; i++) 152 printf(" group %d maps to %d\n", 153 amp->info_gmapdata[i][0], 154 amp->info_gmapdata[i][1]); 155 #endif 156 157 158 /* 159 * Save reference. Each mount also holds 160 * a reference on the root vnode. 161 */ 162 error = umap_node_create(mp, lowerrootvp, &vp); 163 /* 164 * Unlock the node (either the lower or the alias) 165 */ 166 VOP_UNLOCK(vp); 167 /* 168 * Make sure the node alias worked 169 */ 170 if (error) { 171 vrele(lowerrootvp); 172 free(amp, M_UFSMNT); /* XXX */ 173 return (error); 174 } 175 176 /* 177 * Keep a held reference to the root vnode. 178 * It is vrele'd in umapfs_unmount. 179 */ 180 umapm_rootvp = vp; 181 umapm_rootvp->v_flag |= VROOT; 182 amp->umapm_rootvp = umapm_rootvp; 183 if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL) 184 mp->mnt_flag |= MNT_LOCAL; 185 mp->mnt_data = (qaddr_t) amp; 186 getnewfsid(mp, makefstype(MOUNT_LOFS)); 187 188 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); 189 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); 190 (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 191 &size); 192 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 193 #ifdef UMAPFS_DIAGNOSTIC 194 printf("umapfs_mount: lower %s, alias at %s\n", 195 mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname); 196 #endif 197 return (0); 198 } 199 200 /* 201 * VFS start. Nothing needed here - the start routine 202 * on the underlying filesystem will have been called 203 * when that filesystem was mounted. 204 */ 205 int 206 umapfs_start(mp, flags, p) 207 struct mount *mp; 208 int flags; 209 struct proc *p; 210 { 211 212 return (0); 213 /* return (VFS_START(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, flags, p)); */ 214 } 215 216 /* 217 * Free reference to umap layer 218 */ 219 int 220 umapfs_unmount(mp, mntflags, p) 221 struct mount *mp; 222 int mntflags; 223 struct proc *p; 224 { 225 struct vnode *umapm_rootvp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp; 226 int error; 227 int flags = 0; 228 extern int doforce; 229 230 #ifdef UMAPFS_DIAGNOSTIC 231 printf("umapfs_unmount(mp = %x)\n", mp); 232 #endif 233 234 if (mntflags & MNT_FORCE) { 235 /* lofs can never be rootfs so don't check for it */ 236 if (!doforce) 237 return (EINVAL); 238 flags |= FORCECLOSE; 239 } 240 241 /* 242 * Clear out buffer cache. I don't think we 243 * ever get anything cached at this level at the 244 * moment, but who knows... 245 */ 246 #ifdef notyet 247 mntflushbuf(mp, 0); 248 if (mntinvalbuf(mp, 1)) 249 return (EBUSY); 250 #endif 251 if (umapm_rootvp->v_usecount > 1) 252 return (EBUSY); 253 if (error = vflush(mp, umapm_rootvp, flags)) 254 return (error); 255 256 #ifdef UMAPFS_DIAGNOSTIC 257 vprint("alias root of lower", umapm_rootvp); 258 #endif 259 /* 260 * Release reference on underlying root vnode 261 */ 262 vrele(umapm_rootvp); 263 /* 264 * And blow it away for future re-use 265 */ 266 vgone(umapm_rootvp); 267 /* 268 * Finally, throw away the umap_mount structure 269 */ 270 free(mp->mnt_data, M_UFSMNT); /* XXX */ 271 mp->mnt_data = 0; 272 return (0); 273 } 274 275 int 276 umapfs_root(mp, vpp) 277 struct mount *mp; 278 struct vnode **vpp; 279 { 280 struct vnode *vp; 281 282 #ifdef UMAPFS_DIAGNOSTIC 283 printf("umapfs_root(mp = %x, vp = %x->%x)\n", mp, 284 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp, 285 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp) 286 ); 287 #endif 288 289 /* 290 * Return locked reference to root. 291 */ 292 vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp; 293 VREF(vp); 294 VOP_LOCK(vp); 295 *vpp = vp; 296 return (0); 297 } 298 299 int 300 umapfs_quotactl(mp, cmd, uid, arg, p) 301 struct mount *mp; 302 int cmd; 303 uid_t uid; 304 caddr_t arg; 305 struct proc *p; 306 { 307 308 return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p)); 309 } 310 311 int 312 umapfs_statfs(mp, sbp, p) 313 struct mount *mp; 314 struct statfs *sbp; 315 struct proc *p; 316 { 317 int error; 318 struct statfs mstat; 319 320 #ifdef UMAPFS_DIAGNOSTIC 321 printf("umapfs_statfs(mp = %x, vp = %x->%x)\n", mp, 322 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp, 323 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp) 324 ); 325 #endif 326 327 bzero(&mstat, sizeof(mstat)); 328 329 error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p); 330 if (error) 331 return (error); 332 333 /* now copy across the "interesting" information and fake the rest */ 334 sbp->f_type = mstat.f_type; 335 sbp->f_flags = mstat.f_flags; 336 sbp->f_bsize = mstat.f_bsize; 337 sbp->f_iosize = mstat.f_iosize; 338 sbp->f_blocks = mstat.f_blocks; 339 sbp->f_bfree = mstat.f_bfree; 340 sbp->f_bavail = mstat.f_bavail; 341 sbp->f_files = mstat.f_files; 342 sbp->f_ffree = mstat.f_ffree; 343 if (sbp != &mp->mnt_stat) { 344 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 345 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 346 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 347 } 348 strncpy(&sbp->f_fstypename[0], &mstat.f_fstypename[0], MFSNAMELEN); 349 sbp->f_fstypename[MFSNAMELEN] = '\0'; 350 return (0); 351 } 352 353 int 354 umapfs_sync(mp, waitfor, cred, p) 355 struct mount *mp; 356 int waitfor; 357 struct ucred *cred; 358 struct proc *p; 359 { 360 361 /* 362 * XXX - Assumes no data cached at umap layer. 363 */ 364 return (0); 365 } 366 367 int 368 umapfs_vget(mp, ino, vpp) 369 struct mount *mp; 370 ino_t ino; 371 struct vnode **vpp; 372 { 373 374 return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp)); 375 } 376 377 int 378 umapfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp) 379 struct mount *mp; 380 struct fid *fidp; 381 struct mbuf *nam; 382 struct vnode **vpp; 383 int *exflagsp; 384 struct ucred**credanonp; 385 { 386 387 return (VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, nam, vpp, exflagsp,credanonp)); 388 } 389 390 int 391 umapfs_vptofh(vp, fhp) 392 struct vnode *vp; 393 struct fid *fhp; 394 { 395 396 return (VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp)); 397 } 398 399 int umapfs_init __P((void)); 400 401 struct vfsops umap_vfsops = { 402 MOUNT_UMAP, 403 umapfs_mount, 404 umapfs_start, 405 umapfs_unmount, 406 umapfs_root, 407 umapfs_quotactl, 408 umapfs_statfs, 409 umapfs_sync, 410 umapfs_vget, 411 umapfs_fhtovp, 412 umapfs_vptofh, 413 umapfs_init, 414 }; 415