umap_vfsops.c revision 1.5
1/* $NetBSD: umap_vfsops.c,v 1.5 1995/01/18 09:34:32 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 */ 60int 61umapfs_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#ifdef UMAPFS_DIAGNOSTIC 195 printf("umapfs_mount: lower %s, alias at %s\n", 196 mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname); 197#endif 198 return (0); 199} 200 201/* 202 * VFS start. Nothing needed here - the start routine 203 * on the underlying filesystem will have been called 204 * when that filesystem was mounted. 205 */ 206int 207umapfs_start(mp, flags, p) 208 struct mount *mp; 209 int flags; 210 struct proc *p; 211{ 212 213 return (0); 214 /* return (VFS_START(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, flags, p)); */ 215} 216 217/* 218 * Free reference to umap layer 219 */ 220int 221umapfs_unmount(mp, mntflags, p) 222 struct mount *mp; 223 int mntflags; 224 struct proc *p; 225{ 226 struct vnode *umapm_rootvp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp; 227 int error; 228 int flags = 0; 229 extern int doforce; 230 231#ifdef UMAPFS_DIAGNOSTIC 232 printf("umapfs_unmount(mp = %x)\n", mp); 233#endif 234 235 if (mntflags & MNT_FORCE) { 236 /* lofs can never be rootfs so don't check for it */ 237 if (!doforce) 238 return (EINVAL); 239 flags |= FORCECLOSE; 240 } 241 242 /* 243 * Clear out buffer cache. I don't think we 244 * ever get anything cached at this level at the 245 * moment, but who knows... 246 */ 247#ifdef notyet 248 mntflushbuf(mp, 0); 249 if (mntinvalbuf(mp, 1)) 250 return (EBUSY); 251#endif 252 if (umapm_rootvp->v_usecount > 1) 253 return (EBUSY); 254 if (error = vflush(mp, umapm_rootvp, flags)) 255 return (error); 256 257#ifdef UMAPFS_DIAGNOSTIC 258 vprint("alias root of lower", umapm_rootvp); 259#endif 260 /* 261 * Release reference on underlying root vnode 262 */ 263 vrele(umapm_rootvp); 264 /* 265 * And blow it away for future re-use 266 */ 267 vgone(umapm_rootvp); 268 /* 269 * Finally, throw away the umap_mount structure 270 */ 271 free(mp->mnt_data, M_UFSMNT); /* XXX */ 272 mp->mnt_data = 0; 273 return (0); 274} 275 276int 277umapfs_root(mp, vpp) 278 struct mount *mp; 279 struct vnode **vpp; 280{ 281 struct vnode *vp; 282 283#ifdef UMAPFS_DIAGNOSTIC 284 printf("umapfs_root(mp = %x, vp = %x->%x)\n", mp, 285 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp, 286 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp) 287 ); 288#endif 289 290 /* 291 * Return locked reference to root. 292 */ 293 vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp; 294 VREF(vp); 295 VOP_LOCK(vp); 296 *vpp = vp; 297 return (0); 298} 299 300int 301umapfs_quotactl(mp, cmd, uid, arg, p) 302 struct mount *mp; 303 int cmd; 304 uid_t uid; 305 caddr_t arg; 306 struct proc *p; 307{ 308 309 return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p)); 310} 311 312int 313umapfs_statfs(mp, sbp, p) 314 struct mount *mp; 315 struct statfs *sbp; 316 struct proc *p; 317{ 318 int error; 319 struct statfs mstat; 320 321#ifdef UMAPFS_DIAGNOSTIC 322 printf("umapfs_statfs(mp = %x, vp = %x->%x)\n", mp, 323 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp, 324 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp) 325 ); 326#endif 327 328 bzero(&mstat, sizeof(mstat)); 329 330 error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p); 331 if (error) 332 return (error); 333 334 /* now copy across the "interesting" information and fake the rest */ 335 sbp->f_type = mstat.f_type; 336 sbp->f_flags = mstat.f_flags; 337 sbp->f_bsize = mstat.f_bsize; 338 sbp->f_iosize = mstat.f_iosize; 339 sbp->f_blocks = mstat.f_blocks; 340 sbp->f_bfree = mstat.f_bfree; 341 sbp->f_bavail = mstat.f_bavail; 342 sbp->f_files = mstat.f_files; 343 sbp->f_ffree = mstat.f_ffree; 344 if (sbp != &mp->mnt_stat) { 345 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 346 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 347 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 348 } 349 strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN); 350 sbp->f_fstypename[MFSNAMELEN] = '\0'; 351 return (0); 352} 353 354int 355umapfs_sync(mp, waitfor, cred, p) 356 struct mount *mp; 357 int waitfor; 358 struct ucred *cred; 359 struct proc *p; 360{ 361 362 /* 363 * XXX - Assumes no data cached at umap layer. 364 */ 365 return (0); 366} 367 368int 369umapfs_vget(mp, ino, vpp) 370 struct mount *mp; 371 ino_t ino; 372 struct vnode **vpp; 373{ 374 375 return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp)); 376} 377 378int 379umapfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp) 380 struct mount *mp; 381 struct fid *fidp; 382 struct mbuf *nam; 383 struct vnode **vpp; 384 int *exflagsp; 385 struct ucred**credanonp; 386{ 387 388 return (VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, nam, vpp, exflagsp,credanonp)); 389} 390 391int 392umapfs_vptofh(vp, fhp) 393 struct vnode *vp; 394 struct fid *fhp; 395{ 396 397 return (VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp)); 398} 399 400int umapfs_init __P((void)); 401 402struct vfsops umap_vfsops = { 403 MOUNT_UMAP, 404 umapfs_mount, 405 umapfs_start, 406 umapfs_unmount, 407 umapfs_root, 408 umapfs_quotactl, 409 umapfs_statfs, 410 umapfs_sync, 411 umapfs_vget, 412 umapfs_fhtovp, 413 umapfs_vptofh, 414 umapfs_init, 415}; 416