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