null_vfsops.c revision 2946
1227825Stheraven/* 2227825Stheraven * Copyright (c) 1992, 1993 3227825Stheraven * The Regents of the University of California. All rights reserved. 4227825Stheraven * 5227825Stheraven * This code is derived from software donated to Berkeley by 6227825Stheraven * Jan-Simon Pendry. 7227825Stheraven * 8227825Stheraven * Redistribution and use in source and binary forms, with or without 9227825Stheraven * modification, are permitted provided that the following conditions 10227825Stheraven * are met: 11227825Stheraven * 1. Redistributions of source code must retain the above copyright 12227825Stheraven * notice, this list of conditions and the following disclaimer. 13227825Stheraven * 2. Redistributions in binary form must reproduce the above copyright 14227825Stheraven * notice, this list of conditions and the following disclaimer in the 15227825Stheraven * documentation and/or other materials provided with the distribution. 16227825Stheraven * 3. All advertising materials mentioning features or use of this software 17227825Stheraven * must display the following acknowledgement: 18227825Stheraven * This product includes software developed by the University of 19227825Stheraven * California, Berkeley and its contributors. 20227825Stheraven * 4. Neither the name of the University nor the names of its contributors 21227825Stheraven * may be used to endorse or promote products derived from this software 22227825Stheraven * without specific prior written permission. 23227825Stheraven * 24234976Stheraven * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25234976Stheraven * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26234976Stheraven * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27234976Stheraven * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28227825Stheraven * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29234976Stheraven * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30234976Stheraven * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31234976Stheraven * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32234976Stheraven * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33234976Stheraven * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34234976Stheraven * SUCH DAMAGE. 35234976Stheraven * 36234976Stheraven * @(#)null_vfsops.c 8.2 (Berkeley) 1/21/94 37234976Stheraven * 38227825Stheraven * @(#)lofs_vfsops.c 1.2 (Berkeley) 6/18/92 39234976Stheraven * $Id: null_vfsops.c,v 1.1.1.1 1994/05/24 10:05:03 rgrimes Exp $ 40234976Stheraven */ 41234976Stheraven 42234976Stheraven/* 43227825Stheraven * Null Layer 44234976Stheraven * (See null_vnops.c for a description of what this does.) 45234976Stheraven */ 46234976Stheraven 47234976Stheraven#include <sys/param.h> 48234976Stheraven#include <sys/systm.h> 49234976Stheraven#include <sys/time.h> 50234976Stheraven#include <sys/types.h> 51234976Stheraven#include <sys/vnode.h> 52234976Stheraven#include <sys/mount.h> 53227825Stheraven#include <sys/namei.h> 54234976Stheraven#include <sys/malloc.h> 55234976Stheraven#include <miscfs/nullfs/null.h> 56234976Stheraven 57227825Stheraven/* 58234976Stheraven * Mount null layer 59234976Stheraven */ 60234976Stheravenint 61227825Stheravennullfs_mount(mp, path, data, ndp, p) 62227825Stheraven struct mount *mp; 63227825Stheraven char *path; 64227825Stheraven caddr_t data; 65227825Stheraven struct nameidata *ndp; 66227825Stheraven struct proc *p; 67227825Stheraven{ 68227825Stheraven int error = 0; 69227825Stheraven struct null_args args; 70227825Stheraven struct vnode *lowerrootvp, *vp; 71227825Stheraven struct vnode *nullm_rootvp; 72227825Stheraven struct null_mount *xmp; 73227825Stheraven u_int size; 74227825Stheraven 75227825Stheraven#ifdef NULLFS_DIAGNOSTIC 76227825Stheraven printf("nullfs_mount(mp = %x)\n", mp); 77227825Stheraven#endif 78227825Stheraven 79227825Stheraven /* 80227825Stheraven * Update is a no-op 81227825Stheraven */ 82227825Stheraven if (mp->mnt_flag & MNT_UPDATE) { 83227825Stheraven return (EOPNOTSUPP); 84227825Stheraven /* return VFS_MOUNT(MOUNTTONULLMOUNT(mp)->nullm_vfs, path, data, ndp, p);*/ 85227825Stheraven } 86227825Stheraven 87227825Stheraven /* 88227825Stheraven * Get argument 89227825Stheraven */ 90227825Stheraven if (error = copyin(data, (caddr_t)&args, sizeof(struct null_args))) 91227825Stheraven return (error); 92227825Stheraven 93227825Stheraven /* 94227825Stheraven * Find lower node 95227825Stheraven */ 96227825Stheraven NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF, 97227825Stheraven UIO_USERSPACE, args.target, p); 98227825Stheraven if (error = namei(ndp)) 99227825Stheraven return (error); 100227825Stheraven 101227825Stheraven /* 102227825Stheraven * Sanity check on lower vnode 103227825Stheraven */ 104227825Stheraven lowerrootvp = ndp->ni_vp; 105227825Stheraven 106227825Stheraven vrele(ndp->ni_dvp); 107227825Stheraven ndp->ni_dvp = NULL; 108227825Stheraven 109227825Stheraven xmp = (struct null_mount *) malloc(sizeof(struct null_mount), 110227825Stheraven M_UFSMNT, M_WAITOK); /* XXX */ 111227825Stheraven 112232950Stheraven /* 113232950Stheraven * Save reference to underlying FS 114262801Sdim */ 115227825Stheraven xmp->nullm_vfs = lowerrootvp->v_mount; 116262801Sdim 117227825Stheraven /* 118262801Sdim * Save reference. Each mount also holds 119262801Sdim * a reference on the root vnode. 120262801Sdim */ 121262801Sdim error = null_node_create(mp, lowerrootvp, &vp); 122227825Stheraven /* 123227825Stheraven * Unlock the node (either the lower or the alias) 124227825Stheraven */ 125227825Stheraven VOP_UNLOCK(vp); 126227825Stheraven /* 127227825Stheraven * Make sure the node alias worked 128227825Stheraven */ 129227825Stheraven if (error) { 130227825Stheraven vrele(lowerrootvp); 131227825Stheraven free(xmp, M_UFSMNT); /* XXX */ 132227825Stheraven return (error); 133227825Stheraven } 134227825Stheraven 135227825Stheraven /* 136227825Stheraven * Keep a held reference to the root vnode. 137227825Stheraven * It is vrele'd in nullfs_unmount. 138227825Stheraven */ 139227825Stheraven nullm_rootvp = vp; 140227825Stheraven nullm_rootvp->v_flag |= VROOT; 141227825Stheraven xmp->nullm_rootvp = nullm_rootvp; 142227825Stheraven if (NULLVPTOLOWERVP(nullm_rootvp)->v_mount->mnt_flag & MNT_LOCAL) 143227825Stheraven mp->mnt_flag |= MNT_LOCAL; 144227825Stheraven mp->mnt_data = (qaddr_t) xmp; 145227825Stheraven getnewfsid(mp, MOUNT_LOFS); 146234976Stheraven 147234976Stheraven (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); 148234976Stheraven bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); 149234976Stheraven (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 150227825Stheraven &size); 151234976Stheraven bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 152234976Stheraven#ifdef NULLFS_DIAGNOSTIC 153234976Stheraven printf("nullfs_mount: lower %s, alias at %s\n", 154234976Stheraven mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname); 155234976Stheraven#endif 156234976Stheraven return (0); 157234976Stheraven} 158234976Stheraven 159234976Stheraven/* 160227825Stheraven * VFS start. Nothing needed here - the start routine 161234976Stheraven * on the underlying filesystem will have been called 162234976Stheraven * when that filesystem was mounted. 163234976Stheraven */ 164234976Stheravenint 165227825Stheravennullfs_start(mp, flags, p) 166234976Stheraven struct mount *mp; 167234976Stheraven int flags; 168234976Stheraven struct proc *p; 169234976Stheraven{ 170234976Stheraven return (0); 171234976Stheraven /* return VFS_START(MOUNTTONULLMOUNT(mp)->nullm_vfs, flags, p); */ 172234976Stheraven} 173234976Stheraven 174234976Stheraven/* 175227825Stheraven * Free reference to null layer 176234976Stheraven */ 177234976Stheravenint 178234976Stheravennullfs_unmount(mp, mntflags, p) 179227825Stheraven struct mount *mp; 180234976Stheraven int mntflags; 181234976Stheraven struct proc *p; 182234976Stheraven{ 183227825Stheraven struct vnode *nullm_rootvp = MOUNTTONULLMOUNT(mp)->nullm_rootvp; 184227825Stheraven int error; 185227825Stheraven int flags = 0; 186227825Stheraven extern int doforce; 187227825Stheraven 188234976Stheraven#ifdef NULLFS_DIAGNOSTIC 189227825Stheraven printf("nullfs_unmount(mp = %x)\n", mp); 190227825Stheraven#endif 191227825Stheraven 192227825Stheraven if (mntflags & MNT_FORCE) { 193227825Stheraven /* lofs can never be rootfs so don't check for it */ 194234976Stheraven if (!doforce) 195227825Stheraven return (EINVAL); 196227825Stheraven flags |= FORCECLOSE; 197227825Stheraven } 198227825Stheraven 199227825Stheraven /* 200227825Stheraven * Clear out buffer cache. I don't think we 201227825Stheraven * ever get anything cached at this level at the 202227825Stheraven * moment, but who knows... 203234976Stheraven */ 204227825Stheraven#if 0 205234976Stheraven mntflushbuf(mp, 0); 206234976Stheraven if (mntinvalbuf(mp, 1)) 207234976Stheraven return (EBUSY); 208234976Stheraven#endif 209234976Stheraven if (nullm_rootvp->v_usecount > 1) 210234976Stheraven return (EBUSY); 211234976Stheraven if (error = vflush(mp, nullm_rootvp, flags)) 212234976Stheraven return (error); 213234976Stheraven 214227825Stheraven#ifdef NULLFS_DIAGNOSTIC 215234976Stheraven vprint("alias root of lower", nullm_rootvp); 216234976Stheraven#endif 217234976Stheraven /* 218234976Stheraven * Release reference on underlying root vnode 219234976Stheraven */ 220227825Stheraven vrele(nullm_rootvp); 221234976Stheraven /* 222234976Stheraven * And blow it away for future re-use 223234976Stheraven */ 224234976Stheraven vgone(nullm_rootvp); 225227825Stheraven /* 226234976Stheraven * Finally, throw away the null_mount structure 227234976Stheraven */ 228234976Stheraven free(mp->mnt_data, M_UFSMNT); /* XXX */ 229234976Stheraven mp->mnt_data = 0; 230234976Stheraven return 0; 231234976Stheraven} 232234976Stheraven 233234976Stheravenint 234234976Stheravennullfs_root(mp, vpp) 235227825Stheraven struct mount *mp; 236234976Stheraven struct vnode **vpp; 237234976Stheraven{ 238278724Sdim struct vnode *vp; 239227825Stheraven 240278724Sdim#ifdef NULLFS_DIAGNOSTIC 241234976Stheraven printf("nullfs_root(mp = %x, vp = %x->%x)\n", mp, 242227825Stheraven MOUNTTONULLMOUNT(mp)->nullm_rootvp, 243234976Stheraven NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp) 244227825Stheraven ); 245234976Stheraven#endif 246234976Stheraven 247227825Stheraven /* 248227825Stheraven * Return locked reference to root. 249227825Stheraven */ 250227825Stheraven vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp; 251227825Stheraven VREF(vp); 252227825Stheraven VOP_LOCK(vp); 253227825Stheraven *vpp = vp; 254227825Stheraven return 0; 255234976Stheraven} 256227825Stheraven 257234976Stheravenint 258234976Stheravennullfs_quotactl(mp, cmd, uid, arg, p) 259234976Stheraven struct mount *mp; 260234976Stheraven int cmd; 261234976Stheraven uid_t uid; 262234976Stheraven caddr_t arg; 263234976Stheraven struct proc *p; 264234976Stheraven{ 265234976Stheraven return VFS_QUOTACTL(MOUNTTONULLMOUNT(mp)->nullm_vfs, cmd, uid, arg, p); 266227825Stheraven} 267234976Stheraven 268234976Stheravenint 269234976Stheravennullfs_statfs(mp, sbp, p) 270234976Stheraven struct mount *mp; 271234976Stheraven struct statfs *sbp; 272227825Stheraven struct proc *p; 273234976Stheraven{ 274234976Stheraven int error; 275234976Stheraven struct statfs mstat; 276234976Stheraven 277227825Stheraven#ifdef NULLFS_DIAGNOSTIC 278234976Stheraven printf("nullfs_statfs(mp = %x, vp = %x->%x)\n", mp, 279234976Stheraven MOUNTTONULLMOUNT(mp)->nullm_rootvp, 280234976Stheraven NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp) 281234976Stheraven ); 282234976Stheraven#endif 283234976Stheraven 284234976Stheraven bzero(&mstat, sizeof(mstat)); 285234976Stheraven 286234976Stheraven error = VFS_STATFS(MOUNTTONULLMOUNT(mp)->nullm_vfs, &mstat, p); 287227825Stheraven if (error) 288234976Stheraven return (error); 289234976Stheraven 290234976Stheraven /* now copy across the "interesting" information and fake the rest */ 291227825Stheraven sbp->f_type = mstat.f_type; 292234976Stheraven sbp->f_flags = mstat.f_flags; 293234976Stheraven sbp->f_bsize = mstat.f_bsize; 294234976Stheraven sbp->f_iosize = mstat.f_iosize; 295227825Stheraven sbp->f_blocks = mstat.f_blocks; 296227825Stheraven sbp->f_bfree = mstat.f_bfree; 297227825Stheraven sbp->f_bavail = mstat.f_bavail; 298227825Stheraven sbp->f_files = mstat.f_files; 299227825Stheraven sbp->f_ffree = mstat.f_ffree; 300227825Stheraven if (sbp != &mp->mnt_stat) { 301227825Stheraven bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); 302227825Stheraven bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 303234976Stheraven bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 304227825Stheraven } 305234976Stheraven return (0); 306234976Stheraven} 307234976Stheraven 308234976Stheravenint 309234976Stheravennullfs_sync(mp, waitfor, cred, p) 310234976Stheraven struct mount *mp; 311234976Stheraven int waitfor; 312227825Stheraven struct ucred *cred; 313234976Stheraven struct proc *p; 314234976Stheraven{ 315234976Stheraven /* 316234976Stheraven * XXX - Assumes no data cached at null layer. 317234976Stheraven */ 318227825Stheraven return (0); 319234976Stheraven} 320234976Stheraven 321234976Stheravenint 322234976Stheravennullfs_vget(mp, ino, vpp) 323227825Stheraven struct mount *mp; 324234976Stheraven ino_t ino; 325234976Stheraven struct vnode **vpp; 326234976Stheraven{ 327234976Stheraven 328234976Stheraven return VFS_VGET(MOUNTTONULLMOUNT(mp)->nullm_vfs, ino, vpp); 329234976Stheraven} 330234976Stheraven 331234976Stheravenint 332234976Stheravennullfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp) 333227825Stheraven struct mount *mp; 334234976Stheraven struct fid *fidp; 335234976Stheraven struct mbuf *nam; 336234976Stheraven struct vnode **vpp; 337227825Stheraven int *exflagsp; 338234976Stheraven struct ucred**credanonp; 339234976Stheraven{ 340234976Stheraven 341227825Stheraven return VFS_FHTOVP(MOUNTTONULLMOUNT(mp)->nullm_vfs, fidp, nam, vpp, exflagsp,credanonp); 342227825Stheraven} 343227825Stheraven 344227825Stheravenint 345227825Stheravennullfs_vptofh(vp, fhp) 346227825Stheraven struct vnode *vp; 347227825Stheraven struct fid *fhp; 348227825Stheraven{ 349234976Stheraven return VFS_VPTOFH(NULLVPTOLOWERVP(vp), fhp); 350227825Stheraven} 351234976Stheraven 352234976Stheravenint nullfs_init __P((void)); 353234976Stheraven 354234976Stheravenstruct vfsops null_vfsops = { 355234976Stheraven nullfs_mount, 356234976Stheraven nullfs_start, 357234976Stheraven nullfs_unmount, 358227825Stheraven nullfs_root, 359234976Stheraven nullfs_quotactl, 360234976Stheraven nullfs_statfs, 361234976Stheraven nullfs_sync, 362234976Stheraven nullfs_vget, 363234976Stheraven nullfs_fhtovp, 364227825Stheraven nullfs_vptofh, 365234976Stheraven nullfs_init, 366234976Stheraven}; 367234976Stheraven 368234976StheravenVFS_SET(null_vfsops, null, MOUNT_NULL, 0); 369227825Stheraven