umap_vfsops.c revision 1.19
1/* $NetBSD: umap_vfsops.c,v 1.19 1998/08/09 20:51:10 perry 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.8 (Berkeley) 5/14/95 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/proc.h> 50#include <sys/time.h> 51#include <sys/types.h> 52#include <sys/vnode.h> 53#include <sys/mount.h> 54#include <sys/namei.h> 55#include <sys/malloc.h> 56#include <miscfs/umapfs/umap.h> 57 58int umapfs_mount __P((struct mount *, const char *, void *, 59 struct nameidata *, struct proc *)); 60int umapfs_start __P((struct mount *, int, struct proc *)); 61int umapfs_unmount __P((struct mount *, int, struct proc *)); 62int umapfs_root __P((struct mount *, struct vnode **)); 63int umapfs_quotactl __P((struct mount *, int, uid_t, caddr_t, 64 struct proc *)); 65int umapfs_statfs __P((struct mount *, struct statfs *, struct proc *)); 66int umapfs_sync __P((struct mount *, int, struct ucred *, struct proc *)); 67int umapfs_vget __P((struct mount *, ino_t, struct vnode **)); 68int umapfs_fhtovp __P((struct mount *, struct fid *, struct mbuf *, 69 struct vnode **, int *, struct ucred **)); 70int umapfs_vptofh __P((struct vnode *, struct fid *)); 71int umapfs_sysctl __P((int *, u_int, void *, size_t *, void *, size_t, 72 struct proc *)); 73 74/* 75 * Mount umap layer 76 */ 77int 78umapfs_mount(mp, path, data, ndp, p) 79 struct mount *mp; 80 const char *path; 81 void *data; 82 struct nameidata *ndp; 83 struct proc *p; 84{ 85 struct umap_args args; 86 struct vnode *lowerrootvp, *vp; 87 struct vnode *umapm_rootvp; 88 struct umap_mount *amp; 89 size_t size; 90 int error; 91 92#ifdef UMAPFS_DIAGNOSTIC 93 printf("umapfs_mount(mp = %p)\n", mp); 94#endif 95 96 /* 97 * Update is a no-op 98 */ 99 if (mp->mnt_flag & MNT_UPDATE) { 100 return (EOPNOTSUPP); 101 /* return (VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, p));*/ 102 } 103 104 /* 105 * Get argument 106 */ 107 error = copyin(data, (caddr_t)&args, sizeof(struct umap_args)); 108 if (error) 109 return (error); 110 111 /* 112 * Find lower node 113 */ 114 NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF, 115 UIO_USERSPACE, args.target, p); 116 if ((error = namei(ndp)) != 0) 117 return (error); 118 119 /* 120 * Sanity check on lower vnode 121 */ 122 lowerrootvp = ndp->ni_vp; 123#ifdef UMAPFS_DIAGNOSTIC 124 printf("vp = %p, check for VDIR...\n", lowerrootvp); 125#endif 126 vrele(ndp->ni_dvp); 127 ndp->ni_dvp = 0; 128 129 if (lowerrootvp->v_type != VDIR) { 130 vput(lowerrootvp); 131 return (EINVAL); 132 } 133 134#ifdef UMAPFS_DIAGNOSTIC 135 printf("mp = %p\n", mp); 136#endif 137 138 amp = (struct umap_mount *) malloc(sizeof(struct umap_mount), 139 M_UFSMNT, M_WAITOK); /* XXX */ 140 141 /* 142 * Save reference to underlying FS 143 */ 144 amp->umapm_vfs = lowerrootvp->v_mount; 145 146 /* 147 * Now copy in the number of entries and maps for umap mapping. 148 */ 149 amp->info_nentries = args.nentries; 150 amp->info_gnentries = args.gnentries; 151 error = copyin(args.mapdata, (caddr_t)amp->info_mapdata, 152 2*sizeof(u_long)*args.nentries); 153 if (error) 154 return (error); 155 156#ifdef UMAP_DIAGNOSTIC 157 printf("umap_mount:nentries %d\n",args.nentries); 158 for (i = 0; i < args.nentries; i++) 159 printf(" %d maps to %d\n", amp->info_mapdata[i][0], 160 amp->info_mapdata[i][1]); 161#endif 162 163 error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata, 164 2*sizeof(u_long)*args.gnentries); 165 if (error) 166 return (error); 167 168#ifdef UMAP_DIAGNOSTIC 169 printf("umap_mount:gnentries %d\n",args.gnentries); 170 for (i = 0; i < args.gnentries; i++) 171 printf("\tgroup %d maps to %d\n", 172 amp->info_gmapdata[i][0], 173 amp->info_gmapdata[i][1]); 174#endif 175 176 177 /* 178 * Save reference. Each mount also holds 179 * a reference on the root vnode. 180 */ 181 error = umap_node_create(mp, lowerrootvp, &vp); 182 /* 183 * Unlock the node (either the lower or the alias) 184 */ 185 VOP_UNLOCK(vp, 0); 186 /* 187 * Make sure the node alias worked 188 */ 189 if (error) { 190 vrele(lowerrootvp); 191 free(amp, M_UFSMNT); /* XXX */ 192 return (error); 193 } 194 195 /* 196 * Keep a held reference to the root vnode. 197 * It is vrele'd in umapfs_unmount. 198 */ 199 umapm_rootvp = vp; 200 umapm_rootvp->v_flag |= VROOT; 201 amp->umapm_rootvp = umapm_rootvp; 202 if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL) 203 mp->mnt_flag |= MNT_LOCAL; 204 mp->mnt_data = (qaddr_t) amp; 205 vfs_getnewfsid(mp, MOUNT_UMAP); 206 207 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); 208 memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size); 209 (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 210 &size); 211 memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size); 212#ifdef UMAPFS_DIAGNOSTIC 213 printf("umapfs_mount: lower %s, alias at %s\n", 214 mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname); 215#endif 216 return (0); 217} 218 219/* 220 * VFS start. Nothing needed here - the start routine 221 * on the underlying filesystem will have been called 222 * when that filesystem was mounted. 223 */ 224int 225umapfs_start(mp, flags, p) 226 struct mount *mp; 227 int flags; 228 struct proc *p; 229{ 230 231 return (0); 232 /* return (VFS_START(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, flags, p)); */ 233} 234 235/* 236 * Free reference to umap layer 237 */ 238int 239umapfs_unmount(mp, mntflags, p) 240 struct mount *mp; 241 int mntflags; 242 struct proc *p; 243{ 244 struct vnode *umapm_rootvp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp; 245 int error; 246 int flags = 0; 247 248#ifdef UMAPFS_DIAGNOSTIC 249 printf("umapfs_unmount(mp = %p)\n", mp); 250#endif 251 252 if (mntflags & MNT_FORCE) 253 flags |= FORCECLOSE; 254 255 /* 256 * Clear out buffer cache. I don't think we 257 * ever get anything cached at this level at the 258 * moment, but who knows... 259 */ 260#ifdef notyet 261 mntflushbuf(mp, 0); 262 if (mntinvalbuf(mp, 1)) 263 return (EBUSY); 264#endif 265 if (umapm_rootvp->v_usecount > 1) 266 return (EBUSY); 267 if ((error = vflush(mp, umapm_rootvp, flags)) != 0) 268 return (error); 269 270#ifdef UMAPFS_DIAGNOSTIC 271 vprint("alias root of lower", umapm_rootvp); 272#endif 273 /* 274 * Release reference on underlying root vnode 275 */ 276 vrele(umapm_rootvp); 277 /* 278 * And blow it away for future re-use 279 */ 280 vgone(umapm_rootvp); 281 /* 282 * Finally, throw away the umap_mount structure 283 */ 284 free(mp->mnt_data, M_UFSMNT); /* XXX */ 285 mp->mnt_data = 0; 286 return (0); 287} 288 289int 290umapfs_root(mp, vpp) 291 struct mount *mp; 292 struct vnode **vpp; 293{ 294 struct vnode *vp; 295 296#ifdef UMAPFS_DIAGNOSTIC 297 printf("umapfs_root(mp = %p, vp = %p->%p)\n", mp, 298 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp, 299 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp)); 300#endif 301 302 /* 303 * Return locked reference to root. 304 */ 305 vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp; 306 VREF(vp); 307 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 308 *vpp = vp; 309 return (0); 310} 311 312int 313umapfs_quotactl(mp, cmd, uid, arg, p) 314 struct mount *mp; 315 int cmd; 316 uid_t uid; 317 caddr_t arg; 318 struct proc *p; 319{ 320 321 return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p)); 322} 323 324int 325umapfs_statfs(mp, sbp, p) 326 struct mount *mp; 327 struct statfs *sbp; 328 struct proc *p; 329{ 330 int error; 331 struct statfs mstat; 332 333#ifdef UMAPFS_DIAGNOSTIC 334 printf("umapfs_statfs(mp = %p, vp = %p->%p)\n", mp, 335 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp, 336 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp)); 337#endif 338 339 memset(&mstat, 0, sizeof(mstat)); 340 341 error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p); 342 if (error) 343 return (error); 344 345 /* now copy across the "interesting" information and fake the rest */ 346 sbp->f_type = mstat.f_type; 347 sbp->f_flags = mstat.f_flags; 348 sbp->f_bsize = mstat.f_bsize; 349 sbp->f_iosize = mstat.f_iosize; 350 sbp->f_blocks = mstat.f_blocks; 351 sbp->f_bfree = mstat.f_bfree; 352 sbp->f_bavail = mstat.f_bavail; 353 sbp->f_files = mstat.f_files; 354 sbp->f_ffree = mstat.f_ffree; 355 if (sbp != &mp->mnt_stat) { 356 memcpy(&sbp->f_fsid, &mp->mnt_stat.f_fsid, sizeof(sbp->f_fsid)); 357 memcpy(sbp->f_mntonname, mp->mnt_stat.f_mntonname, MNAMELEN); 358 memcpy(sbp->f_mntfromname, mp->mnt_stat.f_mntfromname, MNAMELEN); 359 } 360 strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN); 361 return (0); 362} 363 364int 365umapfs_sync(mp, waitfor, cred, p) 366 struct mount *mp; 367 int waitfor; 368 struct ucred *cred; 369 struct proc *p; 370{ 371 372 /* 373 * XXX - Assumes no data cached at umap layer. 374 */ 375 return (0); 376} 377 378int 379umapfs_vget(mp, ino, vpp) 380 struct mount *mp; 381 ino_t ino; 382 struct vnode **vpp; 383{ 384 385 return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp)); 386} 387 388int 389umapfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp) 390 struct mount *mp; 391 struct fid *fidp; 392 struct mbuf *nam; 393 struct vnode **vpp; 394 int *exflagsp; 395 struct ucred**credanonp; 396{ 397 398 return (EOPNOTSUPP); 399} 400 401int 402umapfs_vptofh(vp, fhp) 403 struct vnode *vp; 404 struct fid *fhp; 405{ 406 407 return (EOPNOTSUPP); 408} 409 410int 411umapfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 412 int *name; 413 u_int namelen; 414 void *oldp; 415 size_t *oldlenp; 416 void *newp; 417 size_t newlen; 418 struct proc *p; 419{ 420 return (EOPNOTSUPP); 421} 422 423extern struct vnodeopv_desc umapfs_vnodeop_opv_desc; 424 425struct vnodeopv_desc *umapfs_vnodeopv_descs[] = { 426 &umapfs_vnodeop_opv_desc, 427 NULL, 428}; 429 430struct vfsops umapfs_vfsops = { 431 MOUNT_UMAP, 432 umapfs_mount, 433 umapfs_start, 434 umapfs_unmount, 435 umapfs_root, 436 umapfs_quotactl, 437 umapfs_statfs, 438 umapfs_sync, 439 umapfs_vget, 440 umapfs_fhtovp, 441 umapfs_vptofh, 442 umapfs_init, 443 umapfs_sysctl, 444 NULL, /* vfs_mountroot */ 445 umapfs_vnodeopv_descs, 446}; 447