2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * The contents of this file constitute Original Code as defined in and 
   7  * are subject to the Apple Public Source License Version 1.1 (the 
   8  * "License").  You may not use this file except in compliance with the 
   9  * License.  Please obtain a copy of the License at 
  10  * http://www.apple.com/publicsource and read it before using this file. 
  12  * This Original Code and all software distributed under the License are 
  13  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  14  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  15  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  16  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the 
  17  * License for the specific language governing rights and limitations 
  20  * @APPLE_LICENSE_HEADER_END@ 
  22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ 
  24  * Copyright (c) 1992, 1993 
  25  *      The Regents of the University of California.  All rights reserved. 
  27  * This code is derived from software donated to Berkeley by 
  30  * Redistribution and use in source and binary forms, with or without 
  31  * modification, are permitted provided that the following conditions 
  33  * 1. Redistributions of source code must retain the above copyright 
  34  *    notice, this list of conditions and the following disclaimer. 
  35  * 2. Redistributions in binary form must reproduce the above copyright 
  36  *    notice, this list of conditions and the following disclaimer in the 
  37  *    documentation and/or other materials provided with the distribution. 
  38  * 3. All advertising materials mentioning features or use of this software 
  39  *    must display the following acknowledgement: 
  40  *      This product includes software developed by the University of 
  41  *      California, Berkeley and its contributors. 
  42  * 4. Neither the name of the University nor the names of its contributors 
  43  *    may be used to endorse or promote products derived from this software 
  44  *    without specific prior written permission. 
  46  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 
  47  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  48  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  49  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 
  50  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
  51  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
  52  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  53  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  54  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
  55  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  58  *      @(#)null_vfsops.c       8.7 (Berkeley) 5/14/95 
  60  * @(#)lofs_vfsops.c    1.2 (Berkeley) 6/18/92 
  65  * (See null_vnops.c for a description of what this does.) 
  68 #include <sys/param.h> 
  69 #include <sys/systm.h> 
  71 #include <sys/kauth.h> 
  73 #include <sys/types.h> 
  74 #include <sys/vnode.h> 
  75 #include <sys/mount_internal.h> 
  76 #include <sys/namei.h> 
  77 #include <sys/malloc.h> 
  78 #include <miscfs/nullfs/null.h> 
  84 nullfs_mount(mp
, devvp
, data
, context
) 
  88         vfs_context_t context
; 
  91         struct user_null_args args
; 
  92         struct vnode 
*lowerrootvp
, *vp
; 
  93         struct vnode 
*nullm_rootvp
; 
  94         struct null_mount 
*xmp
; 
  97 #ifdef NULLFS_DIAGNOSTIC 
  98         printf("nullfs_mount(mp = %x)\n", mp
); 
 104         if (mp
->mnt_flag 
& MNT_UPDATE
) { 
 106                 /* return VFS_MOUNT(MOUNTTONULLMOUNT(mp)->nullm_vfs, devvp, data,  p);*/ 
 112         if (vfs_context_is64bit(context
)) { 
 113                 error 
= copyin(data
, (caddr_t
)&args
, sizeof (args
)); 
 116                 struct null_args temp
; 
 117                 error 
= copyin(data
, (caddr_t
)&temp
, sizeof (temp
)); 
 118                 args
.target 
= CAST_USER_ADDR_T(temp
.target
); 
 126         NDINIT(ndp
, LOOKUP
, FOLLOW
|WANTPARENT
|LOCKLEAF
, 
 127                 UIO_USERSPACE
, args
.target
, context
); 
 128         if (error 
= namei(ndp
)) 
 132          * Sanity check on lower vnode 
 134         lowerrootvp 
= ndp
->ni_vp
; 
 136         vnode_put(ndp
->ni_dvp
); 
 139         xmp 
= (struct null_mount 
*) _MALLOC(sizeof(struct null_mount
), 
 140                                 M_UFSMNT
, M_WAITOK
);    /* XXX */ 
 143          * Save reference to underlying FS 
 145         xmp
->nullm_vfs 
= lowerrootvp
->v_mount
; 
 148          * Save reference.  Each mount also holds 
 149          * a reference on the root vnode. 
 151         error 
= null_node_create(mp
, lowerrootvp
, &vp
); 
 153          * Make sure the node alias worked 
 156                 vnode_put(lowerrootvp
); 
 157                 FREE(xmp
, M_UFSMNT
);    /* XXX */ 
 162          * Keep a held reference to the root vnode. 
 163          * It is vnode_put'd in nullfs_unmount. 
 166         nullm_rootvp
->v_flag 
|= VROOT
; 
 167         xmp
->nullm_rootvp 
= nullm_rootvp
; 
 168         if (NULLVPTOLOWERVP(nullm_rootvp
)->v_mount
->mnt_flag 
& MNT_LOCAL
) 
 169                 mp
->mnt_flag 
|= MNT_LOCAL
; 
 170         mp
->mnt_data 
= (qaddr_t
) xmp
; 
 173         (void) copyinstr(args
.target
, mp
->mnt_vfsstat
.f_mntfromname
, MAXPATHLEN 
- 1,  
 175         bzero(mp
->mnt_vfsstat
.f_mntfromname 
+ size
, MNAMELEN 
- size
); 
 176 #ifdef NULLFS_DIAGNOSTIC 
 177         printf("nullfs_mount: lower %s, alias at %s\n", 
 178                 mp
->mnt_vfsstat
.f_mntfromname
, mp
->mnt_vfsstat
.f_mntonname
); 
 184  * VFS start.  Nothing needed here - the start routine 
 185  * on the underlying filesystem will have been called 
 186  * when that filesystem was mounted. 
 189 nullfs_start(mp
, flags
, context
) 
 192         vfs_context_t context
; 
 195         /* return VFS_START(MOUNTTONULLMOUNT(mp)->nullm_vfs, flags, context); */ 
 199  * Free reference to null layer 
 202 nullfs_unmount(mp
, mntflags
, context
) 
 205         vfs_context_t context
; 
 207         struct vnode 
*nullm_rootvp 
= MOUNTTONULLMOUNT(mp
)->nullm_rootvp
; 
 212 #ifdef NULLFS_DIAGNOSTIC 
 213         printf("nullfs_unmount(mp = %x)\n", mp
); 
 216         if (mntflags 
& MNT_FORCE
) { 
 221         if ( (nullm_rootvp
->v_usecount 
> 1) && !force 
) 
 223         if ( (error 
= vflush(mp
, nullm_rootvp
, flags
)) && !force 
) 
 226 #ifdef NULLFS_DIAGNOSTIC 
 227         vprint("alias root of lower", nullm_rootvp
); 
 230          * Release reference on underlying root vnode 
 232         vnode_put(nullm_rootvp
); 
 234          * And blow it away for future re-use 
 236         vnode_reclaim(nullm_rootvp
); 
 238          * Finally, throw away the null_mount structure 
 240         FREE(mp
->mnt_data
, M_UFSMNT
);   /* XXX */ 
 246 nullfs_root(mp
, vpp
, context
) 
 249         vfs_context_t context
; 
 251         struct proc 
*p 
= curproc
;       /* XXX */ 
 254 #ifdef NULLFS_DIAGNOSTIC 
 255         printf("nullfs_root(mp = %x, vp = %x->%x)\n", mp
, 
 256                         MOUNTTONULLMOUNT(mp
)->nullm_rootvp
, 
 257                         NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp
)->nullm_rootvp
) 
 262          * Return locked reference to root. 
 264         vp 
= MOUNTTONULLMOUNT(mp
)->nullm_rootvp
; 
 271 nullfs_quotactl(mp
, cmd
, uid
, datap
, context
) 
 276         vfs_context_t context
; 
 278         return VFS_QUOTACTL(MOUNTTONULLMOUNT(mp
)->nullm_vfs
, cmd
, uid
, datap
, context
); 
 282 nullfs_statfs(mp
, sbp
, context
) 
 284         struct vfsstatfs 
*sbp
; 
 285         vfs_context_t context
; 
 288         struct vfsstatfs mstat
; 
 290 #ifdef NULLFS_DIAGNOSTIC 
 291         printf("nullfs_statfs(mp = %x, vp = %x->%x)\n", mp
, 
 292                         MOUNTTONULLMOUNT(mp
)->nullm_rootvp
, 
 293                         NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp
)->nullm_rootvp
) 
 297         bzero(&mstat
, sizeof(mstat
)); 
 299         error 
= VFS_STATFS(MOUNTTONULLMOUNT(mp
)->nullm_vfs
, &mstat
, context
); 
 303         /* now copy across the "interesting" information and fake the rest */ 
 304         //sbp->f_type = mstat.f_type; 
 305         sbp
->f_flags 
= mstat
.f_flags
; 
 306         sbp
->f_bsize 
= mstat
.f_bsize
; 
 307         sbp
->f_iosize 
= mstat
.f_iosize
; 
 308         sbp
->f_blocks 
= mstat
.f_blocks
; 
 309         sbp
->f_bfree 
= mstat
.f_bfree
; 
 310         sbp
->f_bavail 
= mstat
.f_bavail
; 
 311         sbp
->f_files 
= mstat
.f_files
; 
 312         sbp
->f_ffree 
= mstat
.f_ffree
; 
 317 nullfs_sync(__unused 
struct mount 
*mp
, __unused 
int waitfor
, 
 318         __unused kauth_cred_t cred
, __unused vfs_context_t context
) 
 321          * XXX - Assumes no data cached at null layer. 
 327 nullfs_vget(mp
, ino
, vpp
, context
) 
 331         vfs_context_t context
; 
 334         return VFS_VGET(MOUNTTONULLMOUNT(mp
)->nullm_vfs
, ino
, vpp
, context
); 
 338 nullfs_fhtovp(mp
, fhlen
, fhp
, vpp
, context
) 
 343         vfs_context_t context
; 
 346         return VFS_FHTOVP(MOUNTTONULLMOUNT(mp
)->nullm_vfs
, fhlen
, fhp
, vpp
, context
); 
 350 nullfs_vptofh(vp
, fhlenp
, fhp
, context
) 
 354         vfs_context_t context
; 
 356         return VFS_VPTOFH(NULLVPTOLOWERVP(vp
), fhlenp
, fhp
, context
); 
 359 int nullfs_init (struct vfsconf 
*); 
 361 #define nullfs_sysctl (int (*) (int *, u_int, user_addr_t, size_t *, user_addr_t, size_t, proc_t))eopnotsupp 
 363 struct vfsops null_vfsops 
= {