2  * Copyright (c) 2000-2009 Apple Inc.  All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  28 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ 
  30  * Copyright (c) 1989, 1993, 1995 
  31  *      The Regents of the University of California.  All rights reserved. 
  33  * This code is derived from software contributed to Berkeley by 
  34  * Rick Macklem at The University of Guelph. 
  36  * Redistribution and use in source and binary forms, with or without 
  37  * modification, are permitted provided that the following conditions 
  39  * 1. Redistributions of source code must retain the above copyright 
  40  *    notice, this list of conditions and the following disclaimer. 
  41  * 2. Redistributions in binary form must reproduce the above copyright 
  42  *    notice, this list of conditions and the following disclaimer in the 
  43  *    documentation and/or other materials provided with the distribution. 
  44  * 3. All advertising materials mentioning features or use of this software 
  45  *    must display the following acknowledgement: 
  46  *      This product includes software developed by the University of 
  47  *      California, Berkeley and its contributors. 
  48  * 4. Neither the name of the University nor the names of its contributors 
  49  *    may be used to endorse or promote products derived from this software 
  50  *    without specific prior written permission. 
  52  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 
  53  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  54  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  55  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 
  56  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
  57  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
  58  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  59  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  60  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
  61  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  64  *      @(#)nfs_vfsops.c        8.12 (Berkeley) 5/20/95 
  65  * FreeBSD-Id: nfs_vfsops.c,v 1.52 1997/11/12 05:42:21 julian Exp $ 
  68  * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce 
  69  * support for mandatory and extensible security protections.  This notice 
  70  * is included in support of clause 2.2 (b) of the Apple Public License, 
  74 #include <sys/param.h> 
  75 #include <sys/systm.h> 
  77 #include <sys/ioctl.h> 
  78 #include <sys/signal.h> 
  79 #include <sys/proc_internal.h> /* for fs rooting to update rootdir in fdp */ 
  80 #include <sys/kauth.h> 
  81 #include <sys/vnode_internal.h> 
  82 #include <sys/malloc.h> 
  83 #include <sys/kernel.h> 
  84 #include <sys/sysctl.h> 
  85 #include <sys/mount_internal.h> 
  86 #include <sys/kpi_mbuf.h> 
  87 #include <sys/socket.h> 
  88 #include <sys/socketvar.h> 
  89 #include <sys/fcntl.h> 
  90 #include <sys/quota.h> 
  91 #include <libkern/OSAtomic.h> 
  94 #include <sys/vmparam.h> 
  96 #if !defined(NO_MOUNT_PRIVATE) 
  97 #include <sys/filedesc.h> 
  98 #endif /* NO_MOUNT_PRIVATE */ 
 101 #include <net/route.h> 
 102 #include <netinet/in.h> 
 104 #include <nfs/rpcv2.h> 
 105 #include <nfs/krpc.h> 
 106 #include <nfs/nfsproto.h> 
 108 #include <nfs/nfsnode.h> 
 109 #include <nfs/nfs_gss.h> 
 110 #include <nfs/nfsmount.h> 
 111 #include <nfs/xdr_subs.h> 
 112 #include <nfs/nfsm_subs.h> 
 113 #include <nfs/nfsdiskless.h> 
 114 #include <nfs/nfs_lock.h> 
 116 #include <security/mac_framework.h> 
 119 #include <pexpert/pexpert.h> 
 126 static lck_grp_t 
*nfs_global_grp
, *nfs_mount_grp
; 
 127 lck_mtx_t 
*nfs_global_mutex
; 
 128 uint32_t nfs_fs_attr_bitmap
[NFS_ATTR_BITMAP_LEN
]; 
 129 uint32_t nfs_object_attr_bitmap
[NFS_ATTR_BITMAP_LEN
]; 
 130 uint32_t nfs_getattr_bitmap
[NFS_ATTR_BITMAP_LEN
]; 
 131 struct nfsclientidlist nfsclientids
; 
 134 struct nfs_reqqhead nfs_reqq
; 
 135 lck_grp_t 
*nfs_request_grp
; 
 136 lck_mtx_t 
*nfs_request_mutex
; 
 137 thread_call_t nfs_request_timer_call
; 
 138 int nfs_request_timer_on
; 
 139 u_int32_t nfs_xid 
= 0; 
 140 u_int32_t nfs_xidwrap 
= 0;              /* to build a (non-wrapping) 64 bit xid */ 
 142 thread_call_t nfs_buf_timer_call
; 
 145 lck_grp_t 
*nfs_open_grp
; 
 146 uint32_t nfs_open_owner_seqnum 
= 0; 
 147 uint32_t nfs_lock_owner_seqnum 
= 0; 
 148 thread_call_t nfs4_callback_timer_call
; 
 149 int nfs4_callback_timer_on 
= 0; 
 152 lck_grp_t 
*nfsiod_lck_grp
; 
 153 lck_mtx_t 
*nfsiod_mutex
; 
 154 struct nfsiodlist nfsiodfree
, nfsiodwork
; 
 155 struct nfsiodmountlist nfsiodmounts
; 
 156 int nfsiod_thread_count 
= 0; 
 157 int nfsiod_thread_max 
= NFS_DEFASYNCTHREAD
; 
 158 int nfs_max_async_writes 
= NFS_DEFMAXASYNCWRITES
; 
 160 int nfs_iosize 
= NFS_IOSIZE
; 
 161 int nfs_access_cache_timeout 
= NFS_MAXATTRTIMO
; 
 162 int nfs_access_delete 
= 0; 
 163 int nfs_allow_async 
= 0; 
 164 int nfs_statfs_rate_limit 
= NFS_DEFSTATFSRATELIMIT
; 
 165 int nfs_lockd_mounts 
= 0; 
 166 int nfs_lockd_request_sent 
= 0; 
 168 int nfs_tprintf_initial_delay 
= NFS_TPRINTF_INITIAL_DELAY
; 
 169 int nfs_tprintf_delay 
= NFS_TPRINTF_DELAY
; 
 172 int             mountnfs(struct user_nfs_args 
*,mount_t
,mbuf_t
,vfs_context_t
,vnode_t 
*); 
 173 static int      nfs_mount_diskless(struct nfs_dlmount 
*, const char *, int, vnode_t 
*, mount_t 
*, vfs_context_t
); 
 174 #if !defined(NO_MOUNT_PRIVATE) 
 175 static int      nfs_mount_diskless_private(struct nfs_dlmount 
*, const char *, int, vnode_t 
*, mount_t 
*, vfs_context_t
); 
 176 #endif /* NO_MOUNT_PRIVATE */ 
 179  * NFS VFS operations. 
 181 int     nfs_vfs_mount(mount_t
, vnode_t
, user_addr_t
, vfs_context_t
); 
 182 int     nfs_vfs_start(mount_t
, int, vfs_context_t
); 
 183 int     nfs_vfs_unmount(mount_t
, int, vfs_context_t
); 
 184 int     nfs_vfs_root(mount_t
, vnode_t 
*, vfs_context_t
); 
 185 int     nfs_vfs_quotactl(mount_t
, int, uid_t
, caddr_t
, vfs_context_t
); 
 186 int     nfs_vfs_getattr(mount_t
, struct vfs_attr 
*, vfs_context_t
); 
 187 int     nfs_vfs_sync(mount_t
, int, vfs_context_t
); 
 188 int     nfs_vfs_vget(mount_t
, ino64_t
, vnode_t 
*, vfs_context_t
); 
 189 int     nfs_vfs_vptofh(vnode_t
, int *, unsigned char *, vfs_context_t
); 
 190 int     nfs_vfs_fhtovp(mount_t
, int, unsigned char *, vnode_t 
*, vfs_context_t
); 
 191 int     nfs_vfs_init(struct vfsconf 
*); 
 192 int     nfs_vfs_sysctl(int *, u_int
, user_addr_t
, size_t *, user_addr_t
, size_t, vfs_context_t
); 
 194 struct vfsops nfs_vfsops 
= { 
 208         { NULL
,         /* reserved */ 
 214           NULL 
}        /* reserved */ 
 219  * version-specific NFS functions 
 221 int nfs3_mount(struct nfsmount 
*, vfs_context_t
, struct user_nfs_args 
*, nfsnode_t 
*); 
 222 int nfs4_mount(struct nfsmount 
*, vfs_context_t
, struct user_nfs_args 
*, nfsnode_t 
*); 
 223 int nfs3_fsinfo(struct nfsmount 
*, nfsnode_t
, vfs_context_t
); 
 224 int nfs3_update_statfs(struct nfsmount 
*, vfs_context_t
); 
 225 int nfs4_update_statfs(struct nfsmount 
*, vfs_context_t
); 
 227 #define nfs3_getquota   NULL 
 228 #define nfs4_getquota   NULL 
 230 int nfs3_getquota(struct nfsmount 
*, vfs_context_t
, uid_t
, int, struct dqblk 
*); 
 231 int nfs4_getquota(struct nfsmount 
*, vfs_context_t
, uid_t
, int, struct dqblk 
*); 
 234 struct nfs_funcs nfs3_funcs 
= { 
 242         nfs3_read_rpc_async_finish
, 
 244         nfs3_write_rpc_async
, 
 245         nfs3_write_rpc_async_finish
, 
 247         nfs3_lookup_rpc_async
, 
 248         nfs3_lookup_rpc_async_finish
, 
 252 struct nfs_funcs nfs4_funcs 
= { 
 260         nfs4_read_rpc_async_finish
, 
 262         nfs4_write_rpc_async
, 
 263         nfs4_write_rpc_async_finish
, 
 265         nfs4_lookup_rpc_async
, 
 266         nfs4_lookup_rpc_async_finish
, 
 272  * Called once to initialize data structures... 
 275 nfs_vfs_init(__unused 
struct vfsconf 
*vfsp
) 
 280          * Check to see if major data structures haven't bloated. 
 282         if (sizeof (struct nfsnode
) > NFS_NODEALLOC
) { 
 283                 printf("struct nfsnode bloated (> %dbytes)\n", NFS_NODEALLOC
); 
 284                 printf("Try reducing NFS_SMALLFH\n"); 
 286         if (sizeof (struct nfsmount
) > NFS_MNTALLOC
) 
 287                 printf("struct nfsmount bloated (> %dbytes)\n", NFS_MNTALLOC
); 
 289         nfs_ticks 
= (hz 
* NFS_TICKINTVL 
+ 500) / 1000; 
 293         /* init async I/O thread pool state */ 
 294         TAILQ_INIT(&nfsiodfree
); 
 295         TAILQ_INIT(&nfsiodwork
); 
 296         TAILQ_INIT(&nfsiodmounts
); 
 297         nfsiod_lck_grp 
= lck_grp_alloc_init("nfsiod", LCK_GRP_ATTR_NULL
); 
 298         nfsiod_mutex 
= lck_mtx_alloc_init(nfsiod_lck_grp
, LCK_ATTR_NULL
); 
 300         /* init lock groups, etc. */ 
 301         nfs_mount_grp 
= lck_grp_alloc_init("nfs_mount", LCK_GRP_ATTR_NULL
); 
 302         nfs_open_grp 
= lck_grp_alloc_init("nfs_open", LCK_GRP_ATTR_NULL
); 
 303         nfs_global_grp 
= lck_grp_alloc_init("nfs_global", LCK_GRP_ATTR_NULL
); 
 305         nfs_global_mutex 
= lck_mtx_alloc_init(nfs_global_grp
, LCK_ATTR_NULL
); 
 307         /* init request list mutex */ 
 308         nfs_request_grp 
= lck_grp_alloc_init("nfs_request", LCK_GRP_ATTR_NULL
); 
 309         nfs_request_mutex 
= lck_mtx_alloc_init(nfs_request_grp
, LCK_ATTR_NULL
); 
 311         /* initialize NFS request list */ 
 312         TAILQ_INIT(&nfs_reqq
); 
 314         nfs_nbinit();                   /* Init the nfsbuf table */ 
 315         nfs_nhinit();                   /* Init the nfsnode table */ 
 316         nfs_lockinit();                 /* Init the nfs lock state */ 
 317         nfs_gss_init();                 /* Init RPCSEC_GSS security */ 
 320         NFS4_PER_FS_ATTRIBUTES(nfs_fs_attr_bitmap
); 
 321         NFS4_PER_OBJECT_ATTRIBUTES(nfs_object_attr_bitmap
); 
 322         NFS4_DEFAULT_ATTRIBUTES(nfs_getattr_bitmap
); 
 323         for (i
=0; i 
< NFS_ATTR_BITMAP_LEN
; i
++) 
 324                 nfs_getattr_bitmap
[i
] &= nfs_object_attr_bitmap
[i
]; 
 325         TAILQ_INIT(&nfsclientids
); 
 327         /* initialize NFS timer callouts */ 
 328         nfs_request_timer_call 
= thread_call_allocate(nfs_request_timer
, NULL
); 
 329         nfs_buf_timer_call 
= thread_call_allocate(nfs_buf_timer
, NULL
); 
 330         nfs4_callback_timer_call 
= thread_call_allocate(nfs4_callback_timer
, NULL
); 
 339 nfs3_update_statfs(struct nfsmount 
*nmp
, vfs_context_t ctx
) 
 342         int error 
= 0, lockerror
, status
, nfsvers
; 
 344         struct nfsm_chain nmreq
, nmrep
; 
 347         nfsvers 
= nmp
->nm_vers
; 
 351         if ((error 
= vnode_get(NFSTOV(np
)))) 
 354         nfsm_chain_null(&nmreq
); 
 355         nfsm_chain_null(&nmrep
); 
 357         nfsm_chain_build_alloc_init(error
, &nmreq
, NFSX_FH(nfsvers
)); 
 358         nfsm_chain_add_fh(error
, &nmreq
, nfsvers
, np
->n_fhp
, np
->n_fhsize
); 
 359         nfsm_chain_build_done(error
, &nmreq
); 
 361         error 
= nfs_request(np
, NULL
, &nmreq
, NFSPROC_FSSTAT
, ctx
, 
 362                    &nmrep
, &xid
, &status
); 
 363         if ((lockerror 
= nfs_node_lock(np
))) 
 365         if (nfsvers 
== NFS_VER3
) 
 366                 nfsm_chain_postop_attr_update(error
, &nmrep
, np
, &xid
); 
 371         nfsm_assert(error
, NFSTONMP(np
), ENXIO
); 
 373         lck_mtx_lock(&nmp
->nm_lock
); 
 374         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SPACE_TOTAL
); 
 375         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SPACE_FREE
); 
 376         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SPACE_AVAIL
); 
 377         if (nfsvers 
== NFS_VER3
) { 
 378                 NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_FILES_AVAIL
); 
 379                 NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_FILES_TOTAL
); 
 380                 NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_FILES_FREE
); 
 381                 nmp
->nm_fsattr
.nfsa_bsize 
= NFS_FABLKSIZE
; 
 382                 nfsm_chain_get_64(error
, &nmrep
, nmp
->nm_fsattr
.nfsa_space_total
); 
 383                 nfsm_chain_get_64(error
, &nmrep
, nmp
->nm_fsattr
.nfsa_space_free
); 
 384                 nfsm_chain_get_64(error
, &nmrep
, nmp
->nm_fsattr
.nfsa_space_avail
); 
 385                 nfsm_chain_get_64(error
, &nmrep
, nmp
->nm_fsattr
.nfsa_files_total
); 
 386                 nfsm_chain_get_64(error
, &nmrep
, nmp
->nm_fsattr
.nfsa_files_free
); 
 387                 nfsm_chain_get_64(error
, &nmrep
, nmp
->nm_fsattr
.nfsa_files_avail
); 
 390                 nfsm_chain_adv(error
, &nmrep
, NFSX_UNSIGNED
); // skip tsize? 
 391                 nfsm_chain_get_32(error
, &nmrep
, nmp
->nm_fsattr
.nfsa_bsize
); 
 392                 nfsm_chain_get_32(error
, &nmrep
, val
); 
 394                 if (nmp
->nm_fsattr
.nfsa_bsize 
<= 0) 
 395                         nmp
->nm_fsattr
.nfsa_bsize 
= NFS_FABLKSIZE
; 
 396                 nmp
->nm_fsattr
.nfsa_space_total 
= (uint64_t)val 
* nmp
->nm_fsattr
.nfsa_bsize
; 
 397                 nfsm_chain_get_32(error
, &nmrep
, val
); 
 399                 nmp
->nm_fsattr
.nfsa_space_free 
= (uint64_t)val 
* nmp
->nm_fsattr
.nfsa_bsize
; 
 400                 nfsm_chain_get_32(error
, &nmrep
, val
); 
 402                 nmp
->nm_fsattr
.nfsa_space_avail 
= (uint64_t)val 
* nmp
->nm_fsattr
.nfsa_bsize
; 
 404         lck_mtx_unlock(&nmp
->nm_lock
); 
 406         nfsm_chain_cleanup(&nmreq
); 
 407         nfsm_chain_cleanup(&nmrep
); 
 408         vnode_put(NFSTOV(np
)); 
 413 nfs4_update_statfs(struct nfsmount 
*nmp
, vfs_context_t ctx
) 
 416         int error 
= 0, lockerror
, status
, nfsvers
, numops
; 
 418         struct nfsm_chain nmreq
, nmrep
; 
 419         uint32_t bitmap
[NFS_ATTR_BITMAP_LEN
]; 
 420         struct nfs_vattr nvattr
; 
 422         nfsvers 
= nmp
->nm_vers
; 
 426         if ((error 
= vnode_get(NFSTOV(np
)))) 
 429         nfsm_chain_null(&nmreq
); 
 430         nfsm_chain_null(&nmrep
); 
 434         nfsm_chain_build_alloc_init(error
, &nmreq
, 15 * NFSX_UNSIGNED
); 
 435         nfsm_chain_add_compound_header(error
, &nmreq
, "statfs", numops
); 
 437         nfsm_chain_add_32(error
, &nmreq
, NFS_OP_PUTFH
); 
 438         nfsm_chain_add_fh(error
, &nmreq
, nfsvers
, np
->n_fhp
, np
->n_fhsize
); 
 440         nfsm_chain_add_32(error
, &nmreq
, NFS_OP_GETATTR
); 
 441         NFS_COPY_ATTRIBUTES(nfs_getattr_bitmap
, bitmap
); 
 442         NFS4_STATFS_ATTRIBUTES(bitmap
); 
 443         nfsm_chain_add_bitmap_masked(error
, &nmreq
, bitmap
, 
 444                 NFS_ATTR_BITMAP_LEN
, nmp
->nm_fsattr
.nfsa_supp_attr
); 
 445         nfsm_chain_build_done(error
, &nmreq
); 
 446         nfsm_assert(error
, (numops 
== 0), EPROTO
); 
 448         error 
= nfs_request(np
, NULL
, &nmreq
, NFSPROC4_COMPOUND
, ctx
, &nmrep
, &xid
, &status
); 
 449         nfsm_chain_skip_tag(error
, &nmrep
); 
 450         nfsm_chain_get_32(error
, &nmrep
, numops
); 
 451         nfsm_chain_op_check(error
, &nmrep
, NFS_OP_PUTFH
); 
 452         nfsm_chain_op_check(error
, &nmrep
, NFS_OP_GETATTR
); 
 453         nfsm_assert(error
, NFSTONMP(np
), ENXIO
); 
 455         lck_mtx_lock(&nmp
->nm_lock
); 
 456         NFS_CLEAR_ATTRIBUTES(nvattr
.nva_bitmap
); 
 457         error 
= nfs4_parsefattr(&nmrep
, &nmp
->nm_fsattr
, &nvattr
, NULL
, NULL
); 
 458         lck_mtx_unlock(&nmp
->nm_lock
); 
 460         if ((lockerror 
= nfs_node_lock(np
))) 
 463                 nfs_loadattrcache(np
, &nvattr
, &xid
, 0); 
 466         nfsm_assert(error
, NFSTONMP(np
), ENXIO
); 
 468         nmp
->nm_fsattr
.nfsa_bsize 
= NFS_FABLKSIZE
; 
 470         nfsm_chain_cleanup(&nmreq
); 
 471         nfsm_chain_cleanup(&nmrep
); 
 472         vnode_put(NFSTOV(np
)); 
 478  * The NFS VFS_GETATTR function: "statfs"-type information is retrieved 
 479  * using the nf_update_statfs() function, and other attributes are cobbled 
 480  * together from whatever sources we can (getattr, fsinfo, pathconf). 
 483 nfs_vfs_getattr(mount_t mp
, struct vfs_attr 
*fsap
, vfs_context_t ctx
) 
 485         struct nfsmount 
*nmp
; 
 487         int error 
= 0, nfsvers
; 
 489         if (!(nmp 
= VFSTONFS(mp
))) 
 491         nfsvers 
= nmp
->nm_vers
; 
 493         if (VFSATTR_IS_ACTIVE(fsap
, f_bsize
)  || 
 494             VFSATTR_IS_ACTIVE(fsap
, f_iosize
) || 
 495             VFSATTR_IS_ACTIVE(fsap
, f_blocks
) || 
 496             VFSATTR_IS_ACTIVE(fsap
, f_bfree
)  || 
 497             VFSATTR_IS_ACTIVE(fsap
, f_bavail
) || 
 498             VFSATTR_IS_ACTIVE(fsap
, f_bused
)  || 
 499             VFSATTR_IS_ACTIVE(fsap
, f_files
)  || 
 500             VFSATTR_IS_ACTIVE(fsap
, f_ffree
)) { 
 501                 int statfsrate 
= nfs_statfs_rate_limit
; 
 505                  * Are we rate-limiting statfs RPCs? 
 506                  * (Treat values less than 1 or greater than 1,000,000 as no limit.) 
 508                 if ((statfsrate 
> 0) && (statfsrate 
< 1000000)) { 
 513                         lck_mtx_lock(&nmp
->nm_lock
); 
 514                         stamp 
= (now
.tv_sec 
* statfsrate
) + (now
.tv_usec 
/ (1000000/statfsrate
)); 
 515                         if (stamp 
!= nmp
->nm_fsattrstamp
) { 
 517                                 nmp
->nm_fsattrstamp 
= stamp
; 
 521                         lck_mtx_unlock(&nmp
->nm_lock
); 
 525                         error 
= nmp
->nm_funcs
->nf_update_statfs(nmp
, ctx
); 
 526                 if ((error 
== ESTALE
) || (error 
== ETIMEDOUT
)) 
 531                 lck_mtx_lock(&nmp
->nm_lock
); 
 532                 VFSATTR_RETURN(fsap
, f_iosize
, nfs_iosize
); 
 533                 VFSATTR_RETURN(fsap
, f_bsize
, nmp
->nm_fsattr
.nfsa_bsize
); 
 534                 bsize 
= nmp
->nm_fsattr
.nfsa_bsize
; 
 535                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SPACE_TOTAL
)) 
 536                         VFSATTR_RETURN(fsap
, f_blocks
, nmp
->nm_fsattr
.nfsa_space_total 
/ bsize
); 
 537                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SPACE_FREE
)) 
 538                         VFSATTR_RETURN(fsap
, f_bfree
, nmp
->nm_fsattr
.nfsa_space_free 
/ bsize
); 
 539                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SPACE_AVAIL
)) 
 540                         VFSATTR_RETURN(fsap
, f_bavail
, nmp
->nm_fsattr
.nfsa_space_avail 
/ bsize
); 
 541                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SPACE_TOTAL
) && 
 542                     NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SPACE_FREE
)) 
 543                         VFSATTR_RETURN(fsap
, f_bused
, 
 544                                 (nmp
->nm_fsattr
.nfsa_space_total 
/ bsize
) - 
 545                                 (nmp
->nm_fsattr
.nfsa_space_free 
/ bsize
)); 
 546                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_FILES_TOTAL
)) 
 547                         VFSATTR_RETURN(fsap
, f_files
, nmp
->nm_fsattr
.nfsa_files_total
); 
 548                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_FILES_FREE
)) 
 549                         VFSATTR_RETURN(fsap
, f_ffree
, nmp
->nm_fsattr
.nfsa_files_free
); 
 550                 lck_mtx_unlock(&nmp
->nm_lock
); 
 553         if (VFSATTR_IS_ACTIVE(fsap
, f_capabilities
)) { 
 554                 u_int32_t caps
, valid
; 
 555                 nfsnode_t np 
= nmp
->nm_dnp
; 
 557                 nfsm_assert(error
, VFSTONFS(mp
) && np
, ENXIO
); 
 560                 lck_mtx_lock(&nmp
->nm_lock
); 
 563                  * The capabilities[] array defines what this volume supports. 
 565                  * The valid[] array defines which bits this code understands 
 566                  * the meaning of (whether the volume has that capability or not). 
 567                  * Any zero bits here means "I don't know what you're asking about" 
 568                  * and the caller cannot tell whether that capability is 
 572                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SYMLINK_SUPPORT
)) { 
 573                         valid 
|= VOL_CAP_FMT_SYMBOLICLINKS
; 
 574                         if (nmp
->nm_fsattr
.nfsa_flags 
& NFS_FSFLAG_SYMLINK
) 
 575                                 caps 
|= VOL_CAP_FMT_SYMBOLICLINKS
; 
 577                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_LINK_SUPPORT
)) { 
 578                         valid 
|= VOL_CAP_FMT_HARDLINKS
; 
 579                         if (nmp
->nm_fsattr
.nfsa_flags 
& NFS_FSFLAG_LINK
) 
 580                                 caps 
|= VOL_CAP_FMT_HARDLINKS
; 
 582                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_CASE_INSENSITIVE
)) { 
 583                         valid 
|= VOL_CAP_FMT_CASE_SENSITIVE
; 
 584                         if (!(nmp
->nm_fsattr
.nfsa_flags 
& NFS_FSFLAG_CASE_INSENSITIVE
)) 
 585                                 caps 
|= VOL_CAP_FMT_CASE_SENSITIVE
; 
 587                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_CASE_PRESERVING
)) { 
 588                         valid 
|= VOL_CAP_FMT_CASE_PRESERVING
; 
 589                         if (nmp
->nm_fsattr
.nfsa_flags 
& NFS_FSFLAG_CASE_PRESERVING
) 
 590                                 caps 
|= VOL_CAP_FMT_CASE_PRESERVING
; 
 592                 /* Note: VOL_CAP_FMT_2TB_FILESIZE is actually used to test for "large file support" */ 
 593                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_MAXFILESIZE
)) { 
 594                         /* Is server's max file size at least 4GB? */ 
 595                         if (nmp
->nm_fsattr
.nfsa_maxfilesize 
>= 0x100000000ULL
) 
 596                                 caps 
|= VOL_CAP_FMT_2TB_FILESIZE
; 
 597                 } else if (nfsvers 
>= NFS_VER3
) { 
 599                          * NFSv3 and up supports 64 bits of file size. 
 600                          * So, we'll just assume maxfilesize >= 4GB 
 602                         caps 
|= VOL_CAP_FMT_2TB_FILESIZE
; 
 604                 if (nfsvers 
>= NFS_VER4
) { 
 605                         caps 
|= VOL_CAP_FMT_HIDDEN_FILES
; 
 606                         valid 
|= VOL_CAP_FMT_HIDDEN_FILES
; 
 607                         // VOL_CAP_FMT_OPENDENYMODES 
 609                 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_FORMAT
] = 
 610                         // VOL_CAP_FMT_PERSISTENTOBJECTIDS | 
 611                         // VOL_CAP_FMT_SYMBOLICLINKS | 
 612                         // VOL_CAP_FMT_HARDLINKS | 
 613                         // VOL_CAP_FMT_JOURNAL | 
 614                         // VOL_CAP_FMT_JOURNAL_ACTIVE | 
 615                         // VOL_CAP_FMT_NO_ROOT_TIMES | 
 616                         // VOL_CAP_FMT_SPARSE_FILES | 
 617                         // VOL_CAP_FMT_ZERO_RUNS | 
 618                         // VOL_CAP_FMT_CASE_SENSITIVE | 
 619                         // VOL_CAP_FMT_CASE_PRESERVING | 
 620                         // VOL_CAP_FMT_FAST_STATFS | 
 621                         // VOL_CAP_FMT_2TB_FILESIZE | 
 622                         // VOL_CAP_FMT_OPENDENYMODES | 
 623                         // VOL_CAP_FMT_HIDDEN_FILES | 
 625                 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_FORMAT
] = 
 626                         VOL_CAP_FMT_PERSISTENTOBJECTIDS 
| 
 627                         // VOL_CAP_FMT_SYMBOLICLINKS | 
 628                         // VOL_CAP_FMT_HARDLINKS | 
 629                         // VOL_CAP_FMT_JOURNAL | 
 630                         // VOL_CAP_FMT_JOURNAL_ACTIVE | 
 631                         // VOL_CAP_FMT_NO_ROOT_TIMES | 
 632                         // VOL_CAP_FMT_SPARSE_FILES | 
 633                         // VOL_CAP_FMT_ZERO_RUNS | 
 634                         // VOL_CAP_FMT_CASE_SENSITIVE | 
 635                         // VOL_CAP_FMT_CASE_PRESERVING | 
 636                         VOL_CAP_FMT_FAST_STATFS 
| 
 637                         VOL_CAP_FMT_2TB_FILESIZE 
| 
 638                         // VOL_CAP_FMT_OPENDENYMODES | 
 639                         // VOL_CAP_FMT_HIDDEN_FILES | 
 643                  * We don't support most of the interfaces. 
 645                  * We MAY support locking, but we don't have any easy way of probing. 
 646                  * We can tell if there's no lockd running or if locks have been 
 647                  * disabled for a mount, so we can definitely answer NO in that case. 
 648                  * Any attempt to send a request to lockd to test for locking support 
 649                  * may cause the lazily-launched locking daemons to be started 
 650                  * unnecessarily.  So we avoid that.  However, we do record if we ever 
 651                  * successfully perform a lock operation on a mount point, so if it 
 652                  * looks like lock ops have worked, we do report that we support them. 
 655                 if (nfsvers 
>= NFS_VER4
) { 
 656                         caps 
= VOL_CAP_INT_ADVLOCK 
| VOL_CAP_INT_FLOCK
; 
 657                         valid 
= VOL_CAP_INT_ADVLOCK 
| VOL_CAP_INT_FLOCK
; 
 658                         // VOL_CAP_INT_EXTENDED_SECURITY 
 659                         // VOL_CAP_INT_NAMEDSTREAMS 
 660                         // VOL_CAP_INT_EXTENDED_ATTR 
 661                 } else if ((nmp
->nm_flag 
& NFSMNT_NOLOCKS
)) { 
 662                         /* locks disabled on this mount, so they definitely won't work */ 
 663                         valid 
= VOL_CAP_INT_ADVLOCK 
| VOL_CAP_INT_FLOCK
; 
 664                 } else if (nmp
->nm_state 
& NFSSTA_LOCKSWORK
) { 
 665                         caps 
= VOL_CAP_INT_ADVLOCK 
| VOL_CAP_INT_FLOCK
; 
 666                         valid 
= VOL_CAP_INT_ADVLOCK 
| VOL_CAP_INT_FLOCK
; 
 668                 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_INTERFACES
] = 
 669                         // VOL_CAP_INT_SEARCHFS | 
 670                         // VOL_CAP_INT_ATTRLIST | 
 671                         // VOL_CAP_INT_NFSEXPORT | 
 672                         // VOL_CAP_INT_READDIRATTR | 
 673                         // VOL_CAP_INT_EXCHANGEDATA | 
 674                         // VOL_CAP_INT_COPYFILE | 
 675                         // VOL_CAP_INT_ALLOCATE | 
 676                         // VOL_CAP_INT_VOL_RENAME | 
 677                         // VOL_CAP_INT_ADVLOCK | 
 678                         // VOL_CAP_INT_FLOCK | 
 679                         // VOL_CAP_INT_EXTENDED_SECURITY | 
 680                         // VOL_CAP_INT_USERACCESS | 
 681                         // VOL_CAP_INT_MANLOCK | 
 682                         // VOL_CAP_INT_NAMEDSTREAMS | 
 683                         // VOL_CAP_INT_EXTENDED_ATTR | 
 685                 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_INTERFACES
] = 
 686                         VOL_CAP_INT_SEARCHFS 
| 
 687                         VOL_CAP_INT_ATTRLIST 
| 
 688                         VOL_CAP_INT_NFSEXPORT 
| 
 689                         VOL_CAP_INT_READDIRATTR 
| 
 690                         VOL_CAP_INT_EXCHANGEDATA 
| 
 691                         VOL_CAP_INT_COPYFILE 
| 
 692                         VOL_CAP_INT_ALLOCATE 
| 
 693                         VOL_CAP_INT_VOL_RENAME 
| 
 694                         // VOL_CAP_INT_ADVLOCK | 
 695                         // VOL_CAP_INT_FLOCK | 
 696                         // VOL_CAP_INT_EXTENDED_SECURITY | 
 697                         // VOL_CAP_INT_USERACCESS | 
 698                         // VOL_CAP_INT_MANLOCK | 
 699                         // VOL_CAP_INT_NAMEDSTREAMS | 
 700                         // VOL_CAP_INT_EXTENDED_ATTR | 
 703                 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_RESERVED1
] = 0; 
 704                 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_RESERVED1
] = 0; 
 706                 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_RESERVED2
] = 0; 
 707                 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_RESERVED2
] = 0; 
 709                 VFSATTR_SET_SUPPORTED(fsap
, f_capabilities
); 
 710                 lck_mtx_unlock(&nmp
->nm_lock
); 
 713         if (VFSATTR_IS_ACTIVE(fsap
, f_attributes
)) { 
 714                 fsap
->f_attributes
.validattr
.commonattr 
= 0; 
 715                 fsap
->f_attributes
.validattr
.volattr 
= 
 716                         ATTR_VOL_CAPABILITIES 
| ATTR_VOL_ATTRIBUTES
; 
 717                 fsap
->f_attributes
.validattr
.dirattr 
= 0; 
 718                 fsap
->f_attributes
.validattr
.fileattr 
= 0; 
 719                 fsap
->f_attributes
.validattr
.forkattr 
= 0; 
 721                 fsap
->f_attributes
.nativeattr
.commonattr 
= 0; 
 722                 fsap
->f_attributes
.nativeattr
.volattr 
= 
 723                         ATTR_VOL_CAPABILITIES 
| ATTR_VOL_ATTRIBUTES
; 
 724                 fsap
->f_attributes
.nativeattr
.dirattr 
= 0; 
 725                 fsap
->f_attributes
.nativeattr
.fileattr 
= 0; 
 726                 fsap
->f_attributes
.nativeattr
.forkattr 
= 0; 
 728                 VFSATTR_SET_SUPPORTED(fsap
, f_attributes
); 
 735  * nfs version 3 fsinfo rpc call 
 738 nfs3_fsinfo(struct nfsmount 
*nmp
, nfsnode_t np
, vfs_context_t ctx
) 
 740         int error 
= 0, lockerror
, status
, nmlocked 
= 0; 
 742         uint32_t val
, prefsize
, maxsize
; 
 743         struct nfsm_chain nmreq
, nmrep
; 
 745         nfsm_chain_null(&nmreq
); 
 746         nfsm_chain_null(&nmrep
); 
 748         nfsm_chain_build_alloc_init(error
, &nmreq
, NFSX_FH(nmp
->nm_vers
)); 
 749         nfsm_chain_add_fh(error
, &nmreq
, nmp
->nm_vers
, np
->n_fhp
, np
->n_fhsize
); 
 750         nfsm_chain_build_done(error
, &nmreq
); 
 752         error 
= nfs_request(np
, NULL
, &nmreq
, NFSPROC_FSINFO
, ctx
, 
 753                         &nmrep
, &xid
, &status
); 
 754         if ((lockerror 
= nfs_node_lock(np
))) 
 756         nfsm_chain_postop_attr_update(error
, &nmrep
, np
, &xid
); 
 763         lck_mtx_lock(&nmp
->nm_lock
); 
 766         nfsm_chain_get_32(error
, &nmrep
, maxsize
); 
 767         nfsm_chain_get_32(error
, &nmrep
, prefsize
); 
 769         nmp
->nm_fsattr
.nfsa_maxread 
= maxsize
; 
 770         if (prefsize 
< nmp
->nm_rsize
) 
 771                 nmp
->nm_rsize 
= (prefsize 
+ NFS_FABLKSIZE 
- 1) & 
 772                         ~(NFS_FABLKSIZE 
- 1); 
 773         if (maxsize 
< nmp
->nm_rsize
) { 
 774                 nmp
->nm_rsize 
= maxsize 
& ~(NFS_FABLKSIZE 
- 1); 
 775                 if (nmp
->nm_rsize 
== 0) 
 776                         nmp
->nm_rsize 
= maxsize
; 
 778         nfsm_chain_adv(error
, &nmrep
, NFSX_UNSIGNED
); // skip rtmult 
 780         nfsm_chain_get_32(error
, &nmrep
, maxsize
); 
 781         nfsm_chain_get_32(error
, &nmrep
, prefsize
); 
 783         nmp
->nm_fsattr
.nfsa_maxwrite 
= maxsize
; 
 784         if (prefsize 
< nmp
->nm_wsize
) 
 785                 nmp
->nm_wsize 
= (prefsize 
+ NFS_FABLKSIZE 
- 1) & 
 786                         ~(NFS_FABLKSIZE 
- 1); 
 787         if (maxsize 
< nmp
->nm_wsize
) { 
 788                 nmp
->nm_wsize 
= maxsize 
& ~(NFS_FABLKSIZE 
- 1); 
 789                 if (nmp
->nm_wsize 
== 0) 
 790                         nmp
->nm_wsize 
= maxsize
; 
 792         nfsm_chain_adv(error
, &nmrep
, NFSX_UNSIGNED
); // skip wtmult 
 794         nfsm_chain_get_32(error
, &nmrep
, prefsize
); 
 796         if (prefsize 
< nmp
->nm_readdirsize
) 
 797                 nmp
->nm_readdirsize 
= prefsize
; 
 798         if (maxsize 
< nmp
->nm_readdirsize
) 
 799                 nmp
->nm_readdirsize 
= maxsize
; 
 801         nfsm_chain_get_64(error
, &nmrep
, nmp
->nm_fsattr
.nfsa_maxfilesize
); 
 803         nfsm_chain_adv(error
, &nmrep
, 2 * NFSX_UNSIGNED
); // skip time_delta 
 805         /* convert FS properties to our own flags */ 
 806         nfsm_chain_get_32(error
, &nmrep
, val
); 
 808         if (val 
& NFSV3FSINFO_LINK
) 
 809                 nmp
->nm_fsattr
.nfsa_flags 
|= NFS_FSFLAG_LINK
; 
 810         if (val 
& NFSV3FSINFO_SYMLINK
) 
 811                 nmp
->nm_fsattr
.nfsa_flags 
|= NFS_FSFLAG_SYMLINK
; 
 812         if (val 
& NFSV3FSINFO_HOMOGENEOUS
) 
 813                 nmp
->nm_fsattr
.nfsa_flags 
|= NFS_FSFLAG_HOMOGENEOUS
; 
 814         if (val 
& NFSV3FSINFO_CANSETTIME
) 
 815                 nmp
->nm_fsattr
.nfsa_flags 
|= NFS_FSFLAG_SET_TIME
; 
 816         nmp
->nm_state 
|= NFSSTA_GOTFSINFO
; 
 817         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_MAXREAD
); 
 818         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_MAXWRITE
); 
 819         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_MAXFILESIZE
); 
 820         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_LINK_SUPPORT
); 
 821         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SYMLINK_SUPPORT
); 
 822         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_HOMOGENEOUS
); 
 823         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_CANSETTIME
); 
 826                 lck_mtx_unlock(&nmp
->nm_lock
); 
 827         nfsm_chain_cleanup(&nmreq
); 
 828         nfsm_chain_cleanup(&nmrep
); 
 833  * Mount a remote root fs via. nfs. This depends on the info in the 
 834  * nfs_diskless structure that has been filled in properly by some primary 
 836  * It goes something like this: 
 837  * - do enough of "ifconfig" by calling ifioctl() so that the system 
 838  *   can talk to the server 
 839  * - If nfs_diskless.mygateway is filled in, use that address as 
 841  * - hand craft the swap nfs vnode hanging off a fake mount point 
 842  *      if swdevt[0].sw_dev == NODEV 
 843  * - build the rootfs mount point and call mountnfs() to do the rest. 
 848         struct nfs_diskless nd
; 
 849         struct nfs_vattr nvattr
; 
 854 #if !defined(NO_MOUNT_PRIVATE) 
 855         mount_t mppriv 
= NULL
; 
 856         vnode_t vppriv 
= NULL
; 
 857 #endif /* NO_MOUNT_PRIVATE */ 
 861          * Call nfs_boot_init() to fill in the nfs_diskless struct. 
 862          * Note: networking must already have been configured before 
 865         bzero((caddr_t
) &nd
, sizeof(nd
)); 
 866         error 
= nfs_boot_init(&nd
); 
 868                 panic("nfs_boot_init failed with %d\n", error
); 
 872          * Try NFSv3 first, then fallback to NFSv2. 
 873          * Likewise, try TCP first, then fall back to UDP. 
 876         sotype 
= SOCK_STREAM
; 
 879         error 
= nfs_boot_getfh(&nd
, v3
, sotype
); 
 881                 if (error 
== EHOSTDOWN 
|| error 
== EHOSTUNREACH
) { 
 882                         if (nd
.nd_root
.ndm_mntfrom
) 
 883                                 FREE_ZONE(nd
.nd_root
.ndm_mntfrom
, 
 884                                           MAXPATHLEN
, M_NAMEI
); 
 885                         if (nd
.nd_root
.ndm_path
) 
 886                                 FREE_ZONE(nd
.nd_root
.ndm_path
, 
 887                                           MAXPATHLEN
, M_NAMEI
); 
 888                         if (nd
.nd_private
.ndm_mntfrom
) 
 889                                 FREE_ZONE(nd
.nd_private
.ndm_mntfrom
, 
 890                                           MAXPATHLEN
, M_NAMEI
); 
 891                         if (nd
.nd_private
.ndm_path
) 
 892                                 FREE_ZONE(nd
.nd_private
.ndm_path
, 
 893                                           MAXPATHLEN
, M_NAMEI
); 
 897                         if (sotype 
== SOCK_STREAM
) { 
 898                                 printf("nfs_boot_getfh(v3,TCP) failed with %d, trying UDP...\n", error
); 
 902                         printf("nfs_boot_getfh(v3,UDP) failed with %d, trying v2...\n", error
); 
 904                         sotype 
= SOCK_STREAM
; 
 906                 } else if (sotype 
== SOCK_STREAM
) { 
 907                         printf("nfs_boot_getfh(v2,TCP) failed with %d, trying UDP...\n", error
); 
 913                         panic("nfs_boot_getfh(v2,UDP) failed: NFS server mountd not responding - check server configuration: %s", PE_boot_args()); 
 916                         panic("nfs_boot_getfh(v2,UDP) failed: NFS server refused mount - check server configuration: %s", PE_boot_args()); 
 918                         panic("nfs_boot_getfh(v2,UDP) failed with %d: %s", error
, PE_boot_args()); 
 922         ctx 
= vfs_context_kernel(); 
 925          * Create the root mount point. 
 927 #if !defined(NO_MOUNT_PRIVATE) 
 929                 //PWC hack until we have a real "mount" tool to remount root rw 
 931                 int flags 
= MNT_ROOTFS
|MNT_RDONLY
; 
 932                 PE_parse_boot_argn("-rwroot_hack", &rw_root
, sizeof (rw_root
)); 
 936                         kprintf("-rwroot_hack in effect: mounting root fs read/write\n"); 
 939         if ((error 
= nfs_mount_diskless(&nd
.nd_root
, "/", flags
, &vp
, &mp
, ctx
))) 
 941         if ((error 
= nfs_mount_diskless(&nd
.nd_root
, "/", MNT_ROOTFS
, &vp
, &mp
, ctx
))) 
 942 #endif /* NO_MOUNT_PRIVATE */ 
 945                         if (sotype 
== SOCK_STREAM
) { 
 946                                 printf("nfs_mount_diskless(v3,TCP) failed with %d, trying UDP...\n", error
); 
 950                         printf("nfs_mount_diskless(v3,UDP) failed with %d, trying v2...\n", error
); 
 952                         sotype 
= SOCK_STREAM
; 
 954                 } else if (sotype 
== SOCK_STREAM
) { 
 955                         printf("nfs_mount_diskless(v2,TCP) failed with %d, trying UDP...\n", error
); 
 959                 panic("nfs_mount_diskless(v2,UDP) root failed with %d: %s\n", error
, PE_boot_args()); 
 962         printf("root on %s\n", nd
.nd_root
.ndm_mntfrom
); 
 968 #if !defined(NO_MOUNT_PRIVATE) 
 969         if (nd
.nd_private
.ndm_saddr
.sin_addr
.s_addr
) { 
 970             error 
= nfs_mount_diskless_private(&nd
.nd_private
, "/private", 
 971                                                0, &vppriv
, &mppriv
, ctx
); 
 973                 panic("nfs_mount_diskless private failed with %d\n", error
); 
 975             printf("private on %s\n", nd
.nd_private
.ndm_mntfrom
); 
 978             mount_list_add(mppriv
); 
 981 #endif /* NO_MOUNT_PRIVATE */ 
 983         if (nd
.nd_root
.ndm_mntfrom
) 
 984                 FREE_ZONE(nd
.nd_root
.ndm_mntfrom
, MAXPATHLEN
, M_NAMEI
); 
 985         if (nd
.nd_root
.ndm_path
) 
 986                 FREE_ZONE(nd
.nd_root
.ndm_path
, MAXPATHLEN
, M_NAMEI
); 
 987         if (nd
.nd_private
.ndm_mntfrom
) 
 988                 FREE_ZONE(nd
.nd_private
.ndm_mntfrom
, MAXPATHLEN
, M_NAMEI
); 
 989         if (nd
.nd_private
.ndm_path
) 
 990                 FREE_ZONE(nd
.nd_private
.ndm_path
, MAXPATHLEN
, M_NAMEI
); 
 992         /* Get root attributes (for the time). */ 
 993         error 
= nfs_getattr(VTONFS(vp
), &nvattr
, ctx
, NGA_UNCACHED
); 
 994         if (error
) panic("nfs_mountroot: getattr for root"); 
 999  * Internal version of mount system call for diskless setup. 
1003         struct nfs_dlmount 
*ndmntp
, 
1004         const char *mntname
, 
1010         struct user_nfs_args args
; 
1015         if ((error 
= vfs_rootmountalloc("nfs", ndmntp
->ndm_mntfrom
, &mp
))) { 
1016                 printf("nfs_mount_diskless: NFS not configured"); 
1020         mp
->mnt_flag 
|= mntflag
; 
1021         if (!(mntflag 
& MNT_RDONLY
)) 
1022                 mp
->mnt_flag 
&= ~MNT_RDONLY
; 
1024         /* Initialize mount args. */ 
1025         bzero((caddr_t
) &args
, sizeof(args
)); 
1026         args
.addr     
= CAST_USER_ADDR_T(&ndmntp
->ndm_saddr
); 
1027         args
.addrlen  
= ndmntp
->ndm_saddr
.sin_len
; 
1028         args
.sotype   
= ndmntp
->ndm_sotype
; 
1029         args
.fh       
= CAST_USER_ADDR_T(&ndmntp
->ndm_fh
[0]); 
1030         args
.fhsize   
= ndmntp
->ndm_fhlen
; 
1031         args
.hostname 
= CAST_USER_ADDR_T(ndmntp
->ndm_mntfrom
); 
1032         args
.flags    
= NFSMNT_RESVPORT
; 
1033         if (ndmntp
->ndm_nfsv3
) 
1034                 args
.flags 
|= NFSMNT_NFSV3
; 
1036         error 
= mbuf_get(MBUF_WAITOK
, MBUF_TYPE_SONAME
, &m
); 
1038                 printf("nfs_mount_diskless: mbuf_get(soname) failed"); 
1041         mbuf_setlen(m
, ndmntp
->ndm_saddr
.sin_len
); 
1042         bcopy(&ndmntp
->ndm_saddr
, mbuf_data(m
), ndmntp
->ndm_saddr
.sin_len
); 
1043         if ((error 
= mountnfs(&args
, mp
, m
, ctx
, vpp
))) { 
1044                 printf("nfs_mountroot: mount %s failed: %d\n", mntname
, error
); 
1045                 // XXX vfs_rootmountfailed(mp); 
1047                 mp
->mnt_vtable
->vfc_refcount
--; 
1048                 mount_list_unlock(); 
1050                 mount_lock_destroy(mp
); 
1052                 mac_mount_label_destroy(mp
); 
1054                 FREE_ZONE(mp
, sizeof(struct mount
), M_MOUNT
); 
1061 #if !defined(NO_MOUNT_PRIVATE) 
1063  * Internal version of mount system call to mount "/private" 
1064  * separately in diskless setup 
1067 nfs_mount_diskless_private( 
1068         struct nfs_dlmount 
*ndmntp
, 
1069         const char *mntname
, 
1075         struct user_nfs_args args
; 
1080         struct vfstable 
*vfsp
; 
1081         struct nameidata nd
; 
1084         procp 
= current_proc(); /* XXX */ 
1088          * mimic main()!. Temporarily set up rootvnode and other stuff so 
1089          * that namei works. Need to undo this because main() does it, too 
1091                 struct filedesc 
*fdp
;   /* pointer to file descriptor state */ 
1093                 mountlist
.tqh_first
->mnt_flag 
|= MNT_ROOTFS
; 
1095                 /* Get the vnode for '/'. Set fdp->fd_cdir to reference it. */ 
1096                 if (VFS_ROOT(mountlist
.tqh_first
, &rootvnode
, NULL
)) 
1097                         panic("cannot find root vnode"); 
1098                 error 
= vnode_ref(rootvnode
); 
1100                         printf("nfs_mountroot: vnode_ref() failed on root vnode!\n"); 
1103                 fdp
->fd_cdir 
= rootvnode
; 
1104                 fdp
->fd_rdir 
= NULL
; 
1108          * Get vnode to be covered 
1110         NDINIT(&nd
, LOOKUP
, FOLLOW 
| LOCKLEAF
, UIO_SYSSPACE
, 
1111             CAST_USER_ADDR_T(mntname
), ctx
); 
1112         if ((error 
= namei(&nd
))) { 
1113                 printf("nfs_mountroot: private namei failed!\n"); 
1117                 /* undo vnode_ref() in mimic main()! */ 
1118                 vnode_rele(rootvnode
); 
1123         if ((error 
= VNOP_FSYNC(vp
, MNT_WAIT
, ctx
)) || 
1124             (error 
= buf_invalidateblks(vp
, BUF_WRITE_DATA
, 0, 0))) { 
1128         if (vnode_vtype(vp
) != VDIR
) { 
1133         for (vfsp 
= vfsconf
; vfsp
; vfsp 
= vfsp
->vfc_next
) 
1134                 if (!strncmp(vfsp
->vfc_name
, "nfs", sizeof(vfsp
->vfc_name
))) 
1137                 printf("nfs_mountroot: private NFS not configured\n"); 
1142         if (vnode_mountedhere(vp
) != NULL
) { 
1149          * Allocate and initialize the filesystem. 
1151         mp 
= _MALLOC_ZONE((u_int32_t
)sizeof(struct mount
), M_MOUNT
, M_WAITOK
); 
1153                 printf("nfs_mountroot: unable to allocate mount structure\n"); 
1158         bzero((char *)mp
, sizeof(struct mount
)); 
1160         /* Initialize the default IO constraints */ 
1161         mp
->mnt_maxreadcnt 
= mp
->mnt_maxwritecnt 
= MAXPHYS
; 
1162         mp
->mnt_segreadcnt 
= mp
->mnt_segwritecnt 
= 32; 
1163         mp
->mnt_ioflags 
= 0; 
1164         mp
->mnt_realrootvp 
= NULLVP
; 
1165         mp
->mnt_authcache_ttl 
= CACHED_LOOKUP_RIGHT_TTL
; 
1167         mount_lock_init(mp
); 
1168         TAILQ_INIT(&mp
->mnt_vnodelist
); 
1169         TAILQ_INIT(&mp
->mnt_workerqueue
); 
1170         TAILQ_INIT(&mp
->mnt_newvnodes
); 
1171         (void)vfs_busy(mp
, LK_NOWAIT
); 
1172         TAILQ_INIT(&mp
->mnt_vnodelist
); 
1174         vfsp
->vfc_refcount
++; 
1175         mount_list_unlock(); 
1176         mp
->mnt_vtable 
= vfsp
; 
1177         mp
->mnt_op 
= vfsp
->vfc_vfsops
; 
1178         // mp->mnt_stat.f_type = vfsp->vfc_typenum; 
1179         mp
->mnt_flag 
= mntflag
; 
1180         mp
->mnt_flag 
|= vfsp
->vfc_flags 
& MNT_VISFLAGMASK
; 
1181         strncpy(mp
->mnt_vfsstat
.f_fstypename
, vfsp
->vfc_name
, MFSNAMELEN
-1); 
1182         vp
->v_mountedhere 
= mp
; 
1183         mp
->mnt_vnodecovered 
= vp
; 
1184         mp
->mnt_vfsstat
.f_owner 
= kauth_cred_getuid(kauth_cred_get()); 
1185         (void) copystr(mntname
, mp
->mnt_vfsstat
.f_mntonname
, MAXPATHLEN 
- 1, 0); 
1186         (void) copystr(ndmntp
->ndm_mntfrom
, mp
->mnt_vfsstat
.f_mntfromname
, MAXPATHLEN 
- 1, 0); 
1188         mac_mount_label_init(mp
); 
1189         mac_mount_label_associate(ctx
, mp
); 
1192         /* Initialize mount args. */ 
1193         bzero((caddr_t
) &args
, sizeof(args
)); 
1194         args
.addr     
= CAST_USER_ADDR_T(&ndmntp
->ndm_saddr
); 
1195         args
.addrlen  
= ndmntp
->ndm_saddr
.sin_len
; 
1196         args
.sotype   
= ndmntp
->ndm_sotype
; 
1197         args
.fh       
= CAST_USER_ADDR_T(ndmntp
->ndm_fh
); 
1198         args
.fhsize   
= ndmntp
->ndm_fhlen
; 
1199         args
.hostname 
= CAST_USER_ADDR_T(ndmntp
->ndm_mntfrom
); 
1200         args
.flags    
= NFSMNT_RESVPORT
; 
1201         if (ndmntp
->ndm_nfsv3
) 
1202                 args
.flags 
|= NFSMNT_NFSV3
; 
1204         error 
= mbuf_get(MBUF_WAITOK
, MBUF_TYPE_SONAME
, &m
); 
1206                 printf("nfs_mount_diskless_private: mbuf_get(soname) failed"); 
1209         mbuf_setlen(m
, ndmntp
->ndm_saddr
.sin_len
); 
1210         bcopy(&ndmntp
->ndm_saddr
, mbuf_data(m
), ndmntp
->ndm_saddr
.sin_len
); 
1211         if ((error 
= mountnfs(&args
, mp
, m
, ctx
, &vp
))) { 
1212                 printf("nfs_mountroot: mount %s failed: %d\n", mntname
, error
); 
1214                 vfsp
->vfc_refcount
--; 
1215                 mount_list_unlock(); 
1217                 mount_lock_destroy(mp
); 
1219                 mac_mount_label_destroy(mp
); 
1221                 FREE_ZONE(mp
, sizeof (struct mount
), M_MOUNT
); 
1230 #endif /* NO_MOUNT_PRIVATE */ 
1238 nfs_vfs_mount(mount_t mp
, vnode_t vp
, user_addr_t data
, vfs_context_t ctx
) 
1240         int error
, argsvers
; 
1241         struct user_nfs_args args
; 
1242         struct nfs_args tempargs
; 
1245         u_char nfh
[NFSX_V3FHMAX
]; 
1248         error 
= copyin(data
, (caddr_t
)&argsvers
, sizeof (argsvers
)); 
1254                 if (vfs_context_is64bit(ctx
)) 
1255                         error 
= copyin(data
, (caddr_t
)&args
, sizeof (struct user_nfs_args3
)); 
1257                         error 
= copyin(data
, (caddr_t
)&tempargs
, sizeof (struct nfs_args3
)); 
1260                 if (vfs_context_is64bit(ctx
)) 
1261                         error 
= copyin(data
, (caddr_t
)&args
, sizeof (struct user_nfs_args4
)); 
1263                         error 
= copyin(data
, (caddr_t
)&tempargs
, sizeof (struct nfs_args4
)); 
1266                 if (vfs_context_is64bit(ctx
)) 
1267                         error 
= copyin(data
, (caddr_t
)&args
, sizeof (struct user_nfs_args5
)); 
1269                         error 
= copyin(data
, (caddr_t
)&tempargs
, sizeof (struct nfs_args5
)); 
1272                 if (vfs_context_is64bit(ctx
)) 
1273                         error 
= copyin(data
, (caddr_t
)&args
, sizeof (args
)); 
1275                         error 
= copyin(data
, (caddr_t
)&tempargs
, sizeof (tempargs
)); 
1278                 return (EPROGMISMATCH
); 
1283         if (!vfs_context_is64bit(ctx
)) { 
1284                 args
.version 
= tempargs
.version
; 
1285                 args
.addrlen 
= tempargs
.addrlen
; 
1286                 args
.sotype 
= tempargs
.sotype
; 
1287                 args
.proto 
= tempargs
.proto
; 
1288                 args
.fhsize 
= tempargs
.fhsize
; 
1289                 args
.flags 
= tempargs
.flags
; 
1290                 args
.wsize 
= tempargs
.wsize
; 
1291                 args
.rsize 
= tempargs
.rsize
; 
1292                 args
.readdirsize 
= tempargs
.readdirsize
; 
1293                 args
.timeo 
= tempargs
.timeo
; 
1294                 args
.retrans 
= tempargs
.retrans
; 
1295                 args
.maxgrouplist 
= tempargs
.maxgrouplist
; 
1296                 args
.readahead 
= tempargs
.readahead
; 
1297                 args
.leaseterm 
= tempargs
.leaseterm
; 
1298                 args
.deadthresh 
= tempargs
.deadthresh
; 
1299                 args
.addr 
= CAST_USER_ADDR_T(tempargs
.addr
); 
1300                 args
.fh 
= CAST_USER_ADDR_T(tempargs
.fh
); 
1301                 args
.hostname 
= CAST_USER_ADDR_T(tempargs
.hostname
); 
1302                 if (argsvers 
>= 4) { 
1303                         args
.acregmin 
= tempargs
.acregmin
; 
1304                         args
.acregmax 
= tempargs
.acregmax
; 
1305                         args
.acdirmin 
= tempargs
.acdirmin
; 
1306                         args
.acdirmax 
= tempargs
.acdirmax
; 
1309                         args
.auth 
= tempargs
.auth
; 
1311                         args
.deadtimeout 
= tempargs
.deadtimeout
; 
1314         if (args
.fhsize 
< 0 || args
.fhsize 
> NFSX_V3FHMAX
) 
1316         if (args
.fhsize 
> 0) { 
1317                 error 
= copyin(args
.fh
, (caddr_t
)nfh
, args
.fhsize
); 
1322         mntfrom 
= &vfs_statfs(mp
)->f_mntfromname
[0]; 
1323         error 
= copyinstr(args
.hostname
, mntfrom
, MAXPATHLEN
-1, &len
); 
1326         bzero(&mntfrom
[len
], MAXPATHLEN 
- len
); 
1328         /* sockargs() call must be after above copyin() calls */ 
1329         error 
= sockargs(&nam
, args
.addr
, args
.addrlen
, MBUF_TYPE_SONAME
); 
1333         args
.fh 
= CAST_USER_ADDR_T(&nfh
[0]); 
1334         error 
= mountnfs(&args
, mp
, nam
, ctx
, &vp
); 
1339  * Common code for mount and mountroot 
1344         struct nfsmount 
*nmp
, 
1346         struct user_nfs_args 
*argp
, 
1350         struct nfs_vattr nvattr
; 
1357          * Get file attributes for the mountpoint.  These are needed 
1358          * in order to properly create the root vnode. 
1360         fhp 
= CAST_DOWN(u_char 
*, argp
->fh
); 
1361         error 
= nfs3_getattr_rpc(NULL
, nmp
->nm_mountp
, fhp
, argp
->fhsize
, 
1362                         ctx
, &nvattr
, &xid
); 
1366         error 
= nfs_nget(nmp
->nm_mountp
, NULL
, NULL
, fhp
, argp
->fhsize
, 
1367                         &nvattr
, &xid
, NG_MARKROOT
, npp
); 
1369                 nfs_node_unlock(*npp
); 
1374          * Try to make sure we have all the general info from the server. 
1376         if (nmp
->nm_vers 
== NFS_VER2
) { 
1377                 NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_MAXNAME
); 
1378                 nmp
->nm_fsattr
.nfsa_maxname 
= NFS_MAXNAMLEN
; 
1379         } else if (nmp
->nm_vers 
== NFS_VER3
) { 
1380                 /* get the NFSv3 FSINFO */ 
1381                 error 
= nfs3_fsinfo(nmp
, *npp
, ctx
); 
1384                 /* If the server indicates all pathconf info is */ 
1385                 /* the same, grab a copy of that info now */ 
1386                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_HOMOGENEOUS
) && 
1387                     (nmp
->nm_fsattr
.nfsa_flags 
& NFS_FSFLAG_HOMOGENEOUS
)) { 
1388                         struct nfs_fsattr nfsa
; 
1389                         if (!nfs3_pathconf_rpc(*npp
, &nfsa
, ctx
)) { 
1390                                 /* cache a copy of the results */ 
1391                                 lck_mtx_lock(&nmp
->nm_lock
); 
1392                                 nfs3_pathconf_cache(nmp
, &nfsa
); 
1393                                 lck_mtx_unlock(&nmp
->nm_lock
); 
1398         if (*npp 
&& error
) { 
1399                 vnode_put(NFSTOV(*npp
)); 
1400                 vnode_recycle(NFSTOV(*npp
)); 
1408         struct nfsmount 
*nmp
, 
1410         __unused 
struct user_nfs_args 
*argp
, 
1413         struct nfsm_chain nmreq
, nmrep
; 
1414         int error 
= 0, numops
, status
, interval
; 
1415         char *path 
= &vfs_statfs(nmp
->nm_mountp
)->f_mntfromname
[0]; 
1416         char *name
, *nextname
; 
1418         struct nfs_vattr nvattr
; 
1423         TAILQ_INIT(&nmp
->nm_open_owners
); 
1424         TAILQ_INIT(&nmp
->nm_recallq
); 
1425         nmp
->nm_stategenid 
= 1; 
1427         /* look up path to get fh and attrs for mount point root */ 
1428         numops 
= 2; // PUTROOTFH + LOOKUP* + GETATTR 
1429         while (*path 
&& (*path 
!= '/')) 
1433                 while (*name 
&& (*name 
== '/')) 
1438                 while (*nextname 
&& (*nextname 
!= '/')) 
1443         nfsm_chain_build_alloc_init(error
, &nmreq
, 25 * NFSX_UNSIGNED
); 
1444         nfsm_chain_add_compound_header(error
, &nmreq
, "mount", numops
); 
1446         nfsm_chain_add_32(error
, &nmreq
, NFS_OP_PUTROOTFH
); 
1450                 while (*name 
&& (*name 
== '/')) 
1455                 while (*nextname 
&& (*nextname 
!= '/')) 
1458                 nfsm_chain_add_32(error
, &nmreq
, NFS_OP_LOOKUP
); 
1459                 nfsm_chain_add_string(error
, &nmreq
, name
, nextname 
- name
); 
1463         nfsm_chain_add_32(error
, &nmreq
, NFS_OP_GETATTR
); 
1464         NFS4_DEFAULT_ATTRIBUTES(nmp
->nm_fsattr
.nfsa_supp_attr
); 
1465         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_supp_attr
, NFS_FATTR_FILEHANDLE
); 
1466         nfsm_chain_add_bitmap(error
, &nmreq
, nmp
->nm_fsattr
.nfsa_supp_attr
, NFS_ATTR_BITMAP_LEN
); 
1467         nfsm_chain_build_done(error
, &nmreq
); 
1468         nfsm_assert(error
, (numops 
== 0), EPROTO
); 
1470         error 
= nfs_request(NULL
, nmp
->nm_mountp
, &nmreq
, NFSPROC4_COMPOUND
, ctx
, &nmrep
, &xid
, &status
); 
1471         nfsm_chain_skip_tag(error
, &nmrep
); 
1472         nfsm_chain_get_32(error
, &nmrep
, numops
); 
1473         nfsm_chain_op_check(error
, &nmrep
, NFS_OP_PUTROOTFH
); 
1476                 while (*name 
&& (*name 
== '/')) 
1481                 while (*nextname 
&& (*nextname 
!= '/')) 
1483                 nfsm_chain_op_check(error
, &nmrep
, NFS_OP_LOOKUP
); 
1486         nfsm_chain_op_check(error
, &nmrep
, NFS_OP_GETATTR
); 
1488         NFS_CLEAR_ATTRIBUTES(nmp
->nm_fsattr
.nfsa_bitmap
); 
1489         NFS_CLEAR_ATTRIBUTES(&nvattr
.nva_bitmap
); 
1490         error 
= nfs4_parsefattr(&nmrep
, &nmp
->nm_fsattr
, &nvattr
, &fh
, NULL
); 
1491         if (!error 
&& !NFS_BITMAP_ISSET(&nvattr
.nva_bitmap
, NFS_FATTR_FILEHANDLE
)) { 
1492                 printf("nfs: mount didn't return filehandle?\n"); 
1497         error 
= nfs_nget(nmp
->nm_mountp
, NULL
, NULL
, fh
.fh_data
, fh
.fh_len
, &nvattr
, &xid
, NG_MARKROOT
, npp
); 
1500         /* adjust I/O sizes to server limits */ 
1501         if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_MAXREAD
)) { 
1502                 if (nmp
->nm_fsattr
.nfsa_maxread 
< (uint64_t)nmp
->nm_rsize
) { 
1503                         nmp
->nm_rsize 
= nmp
->nm_fsattr
.nfsa_maxread 
& ~(NFS_FABLKSIZE 
- 1); 
1504                         if (nmp
->nm_rsize 
== 0) 
1505                                 nmp
->nm_rsize 
= nmp
->nm_fsattr
.nfsa_maxread
; 
1508         if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_MAXWRITE
)) { 
1509                 if (nmp
->nm_fsattr
.nfsa_maxwrite 
< (uint64_t)nmp
->nm_wsize
) { 
1510                         nmp
->nm_wsize 
= nmp
->nm_fsattr
.nfsa_maxwrite 
& ~(NFS_FABLKSIZE 
- 1); 
1511                         if (nmp
->nm_wsize 
== 0) 
1512                                 nmp
->nm_wsize 
= nmp
->nm_fsattr
.nfsa_maxwrite
; 
1516         /* set up lease renew timer */ 
1517         nmp
->nm_renew_timer 
= thread_call_allocate(nfs4_renew_timer
, nmp
); 
1518         interval 
= nmp
->nm_fsattr
.nfsa_lease 
/ 2; 
1521         nfs_interval_timer_start(nmp
->nm_renew_timer
, interval 
* 1000); 
1525                 nfs_node_unlock(*npp
); 
1531         struct user_nfs_args 
*argp
, 
1537         struct nfsmount 
*nmp
; 
1540         uint32_t maxio
, iosize
; 
1541         struct vfsstatfs 
*sbp
; 
1542         struct timespec ts 
= { 1, 0 }; 
1545          * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes 
1546          * no sense in that context. 
1548         if (argp
->sotype 
== SOCK_STREAM
) 
1549                 argp
->flags 
&= ~NFSMNT_NOCONN
; 
1551         if (vfs_flags(mp
) & MNT_UPDATE
) { 
1553                 /* update paths, file handles, etc, here        XXX */ 
1557                 MALLOC_ZONE(nmp
, struct nfsmount 
*, 
1558                                 sizeof (struct nfsmount
), M_NFSMNT
, M_WAITOK
); 
1563                 bzero((caddr_t
)nmp
, sizeof (struct nfsmount
)); 
1564                 lck_mtx_init(&nmp
->nm_lock
, nfs_mount_grp
, LCK_ATTR_NULL
); 
1565                 TAILQ_INIT(&nmp
->nm_resendq
); 
1566                 TAILQ_INIT(&nmp
->nm_iodq
); 
1567                 TAILQ_INIT(&nmp
->nm_gsscl
); 
1568                 vfs_setfsprivate(mp
, nmp
); 
1570                 nfs_nhinit_finish(); 
1572         lck_mtx_lock(&nmp
->nm_lock
); 
1574         /* setup defaults */ 
1575         nmp
->nm_vers 
= NFS_VER2
; 
1576         nmp
->nm_timeo 
= NFS_TIMEO
; 
1577         nmp
->nm_retry 
= NFS_RETRANS
; 
1578         if (argp
->sotype 
== SOCK_DGRAM
) { 
1579                 nmp
->nm_wsize 
= NFS_DGRAM_WSIZE
; 
1580                 nmp
->nm_rsize 
= NFS_DGRAM_RSIZE
; 
1582                 nmp
->nm_wsize 
= NFS_WSIZE
; 
1583                 nmp
->nm_rsize 
= NFS_RSIZE
; 
1585         nmp
->nm_readdirsize 
= NFS_READDIRSIZE
; 
1586         nmp
->nm_numgrps 
= NFS_MAXGRPS
; 
1587         nmp
->nm_readahead 
= NFS_DEFRAHEAD
; 
1588         nmp
->nm_tprintf_delay 
= nfs_tprintf_delay
; 
1589         if (nmp
->nm_tprintf_delay 
< 0) 
1590                 nmp
->nm_tprintf_delay 
= 0; 
1591         nmp
->nm_tprintf_initial_delay 
= nfs_tprintf_initial_delay
; 
1592         if (nmp
->nm_tprintf_initial_delay 
< 0) 
1593                 nmp
->nm_tprintf_initial_delay 
= 0; 
1594         nmp
->nm_acregmin 
= NFS_MINATTRTIMO
; 
1595         nmp
->nm_acregmax 
= NFS_MAXATTRTIMO
; 
1596         nmp
->nm_acdirmin 
= NFS_MINDIRATTRTIMO
; 
1597         nmp
->nm_acdirmax 
= NFS_MAXDIRATTRTIMO
; 
1598         nmp
->nm_auth 
= RPCAUTH_SYS
; 
1599         nmp
->nm_deadtimeout 
= 0; 
1602         nmp
->nm_mountp 
= mp
; 
1603         vfs_setauthopaque(mp
); 
1604         nmp
->nm_flag 
= argp
->flags
; 
1607         if (argp
->flags 
& NFSMNT_NFSV4
) { 
1608                 nmp
->nm_vers 
= NFS_VER4
; 
1609                 /* NFSv4 is only allowed over TCP. */ 
1610                 if (argp
->sotype 
!= SOCK_STREAM
) { 
1614         } else if (argp
->flags 
& NFSMNT_NFSV3
) 
1615                 nmp
->nm_vers 
= NFS_VER3
; 
1617         if (nmp
->nm_vers 
== NFS_VER2
) 
1618                 nmp
->nm_flag 
&= ~NFSMNT_RDIRPLUS
; 
1620         if ((argp
->flags 
& NFSMNT_TIMEO
) && argp
->timeo 
> 0) { 
1621                 nmp
->nm_timeo 
= (argp
->timeo 
* NFS_HZ 
+ 5) / 10; 
1622                 if (nmp
->nm_timeo 
< NFS_MINTIMEO
) 
1623                         nmp
->nm_timeo 
= NFS_MINTIMEO
; 
1624                 else if (nmp
->nm_timeo 
> NFS_MAXTIMEO
) 
1625                         nmp
->nm_timeo 
= NFS_MAXTIMEO
; 
1628         if ((argp
->flags 
& NFSMNT_RETRANS
) && argp
->retrans 
> 1) { 
1629                 nmp
->nm_retry 
= argp
->retrans
; 
1630                 if (nmp
->nm_retry 
> NFS_MAXREXMIT
) 
1631                         nmp
->nm_retry 
= NFS_MAXREXMIT
; 
1634         if (nmp
->nm_vers 
!= NFS_VER2
) { 
1635                 if (argp
->sotype 
== SOCK_DGRAM
) 
1636                         maxio 
= NFS_MAXDGRAMDATA
; 
1638                         maxio 
= NFS_MAXDATA
; 
1640                 maxio 
= NFS_V2MAXDATA
; 
1642         if ((argp
->flags 
& NFSMNT_WSIZE
) && argp
->wsize 
> 0) { 
1643                 nmp
->nm_wsize 
= argp
->wsize
; 
1644                 /* Round down to multiple of blocksize */ 
1645                 nmp
->nm_wsize 
&= ~(NFS_FABLKSIZE 
- 1); 
1646                 if (nmp
->nm_wsize 
<= 0) 
1647                         nmp
->nm_wsize 
= NFS_FABLKSIZE
; 
1649         if (nmp
->nm_wsize 
> maxio
) 
1650                 nmp
->nm_wsize 
= maxio
; 
1651         if (nmp
->nm_wsize 
> NFS_MAXBSIZE
) 
1652                 nmp
->nm_wsize 
= NFS_MAXBSIZE
; 
1654         if ((argp
->flags 
& NFSMNT_RSIZE
) && argp
->rsize 
> 0) { 
1655                 nmp
->nm_rsize 
= argp
->rsize
; 
1656                 /* Round down to multiple of blocksize */ 
1657                 nmp
->nm_rsize 
&= ~(NFS_FABLKSIZE 
- 1); 
1658                 if (nmp
->nm_rsize 
<= 0) 
1659                         nmp
->nm_rsize 
= NFS_FABLKSIZE
; 
1661         if (nmp
->nm_rsize 
> maxio
) 
1662                 nmp
->nm_rsize 
= maxio
; 
1663         if (nmp
->nm_rsize 
> NFS_MAXBSIZE
) 
1664                 nmp
->nm_rsize 
= NFS_MAXBSIZE
; 
1666         if ((argp
->flags 
& NFSMNT_READDIRSIZE
) && argp
->readdirsize 
> 0) { 
1667                 nmp
->nm_readdirsize 
= argp
->readdirsize
; 
1669         if (nmp
->nm_readdirsize 
> maxio
) 
1670                 nmp
->nm_readdirsize 
= maxio
; 
1671         if (nmp
->nm_readdirsize 
> nmp
->nm_rsize
) 
1672                 nmp
->nm_readdirsize 
= nmp
->nm_rsize
; 
1674         if ((argp
->flags 
& NFSMNT_MAXGRPS
) && argp
->maxgrouplist 
>= 0 && 
1675                 argp
->maxgrouplist 
<= NFS_MAXGRPS
) 
1676                 nmp
->nm_numgrps 
= argp
->maxgrouplist
; 
1677         if ((argp
->flags 
& NFSMNT_READAHEAD
) && argp
->readahead 
>= 0 && 
1678                 argp
->readahead 
<= NFS_MAXRAHEAD
) 
1679                 nmp
->nm_readahead 
= argp
->readahead
; 
1680         if (argp
->flags 
& NFSMNT_READAHEAD
) 
1681                 nmp
->nm_readahead 
= argp
->readahead
; 
1682         if (nmp
->nm_readahead 
< 0) 
1683                 nmp
->nm_readahead 
= 0; 
1684         else if (nmp
->nm_readahead 
> NFS_MAXRAHEAD
) 
1685                 nmp
->nm_readahead 
= NFS_MAXRAHEAD
; 
1687         if (argp
->version 
>= 4) { 
1688                 if ((argp
->flags 
& NFSMNT_ACREGMIN
) && argp
->acregmin 
>= 0) 
1689                         nmp
->nm_acregmin 
= argp
->acregmin
; 
1690                 if ((argp
->flags 
& NFSMNT_ACREGMAX
) && argp
->acregmax 
>= 0) 
1691                         nmp
->nm_acregmax 
= argp
->acregmax
; 
1692                 if ((argp
->flags 
& NFSMNT_ACDIRMIN
) && argp
->acdirmin 
>= 0) 
1693                         nmp
->nm_acdirmin 
= argp
->acdirmin
; 
1694                 if ((argp
->flags 
& NFSMNT_ACDIRMAX
) && argp
->acdirmax 
>= 0) 
1695                         nmp
->nm_acdirmax 
= argp
->acdirmax
; 
1696                 if (nmp
->nm_acregmin 
> nmp
->nm_acregmax
) 
1697                         nmp
->nm_acregmin 
= nmp
->nm_acregmax
; 
1698                 if (nmp
->nm_acdirmin 
> nmp
->nm_acdirmax
) 
1699                         nmp
->nm_acdirmin 
= nmp
->nm_acdirmax
; 
1701         if (argp
->version 
>= 5) { 
1702                 if (argp
->flags 
& NFSMNT_SECFLAVOR
) { 
1704                          * Check for valid security flavor 
1706                         switch (argp
->auth
) { 
1711                                 nmp
->nm_auth 
= argp
->auth
; 
1719         if (argp
->version 
>= 6) { 
1720                 if (argp
->flags 
& NFSMNT_DEADTIMEOUT
) 
1721                         nmp
->nm_deadtimeout 
= argp
->deadtimeout
; 
1723         if ((nmp
->nm_flag 
& NFSMNT_DEADTIMEOUT
) && (nmp
->nm_deadtimeout 
<= 0)) 
1724                 nmp
->nm_flag 
&= ~NFSMNT_DEADTIMEOUT
; 
1726         /* set up the version-specific function tables */ 
1727         if (nmp
->nm_vers 
< NFS_VER4
) 
1728                 nmp
->nm_funcs 
= &nfs3_funcs
; 
1730                 nmp
->nm_funcs 
= &nfs4_funcs
; 
1732         /* Set up the sockets and related info */ 
1733         nmp
->nm_sotype 
= argp
->sotype
; 
1734         nmp
->nm_soproto 
= argp
->proto
; 
1735         if (nmp
->nm_sotype 
== SOCK_DGRAM
) 
1736                 TAILQ_INIT(&nmp
->nm_cwndq
); 
1738         lck_mtx_unlock(&nmp
->nm_lock
); 
1740         /* make sure mbuf constants are set up */ 
1741         if (!nfs_mbuf_mhlen
) 
1744         if (nmp
->nm_vers 
>= NFS_VER4
) { 
1747                 nmp
->nm_mounttime 
= ((uint64_t)now
.tv_sec 
<< 32) | now
.tv_usec
; 
1748                 nmp
->nm_mcred 
= vfs_context_ucred(ctx
); 
1749                 if (IS_VALID_CRED(nmp
->nm_mcred
)) 
1750                         kauth_cred_ref(nmp
->nm_mcred
); 
1751                 nfs4_mount_callback_setup(nmp
); 
1754         /* set up the socket */ 
1755         if ((error 
= nfs_connect(nmp
, 1))) 
1759          * Get the root node/attributes from the NFS server and 
1760          * do any basic, version-specific setup. 
1762         error 
= nmp
->nm_funcs
->nf_mount(nmp
, ctx
, argp
, &np
); 
1767          * A reference count is needed on the node representing the 
1768          * remote root.  If this object is not persistent, then backward 
1769          * traversals of the mount point (i.e. "..") will not work if 
1770          * the node gets flushed out of the cache. 
1774         /* get usecount and drop iocount */ 
1775         error 
= vnode_ref(*vpp
); 
1778                 vnode_recycle(*vpp
); 
1783          * Do statfs to ensure static info gets set to reasonable values. 
1785         if ((error 
= nmp
->nm_funcs
->nf_update_statfs(nmp
, ctx
))) { 
1786                 int error2 
= vnode_getwithref(*vpp
); 
1790                 vnode_recycle(*vpp
); 
1793         sbp 
= vfs_statfs(mp
); 
1794         sbp
->f_bsize 
= nmp
->nm_fsattr
.nfsa_bsize
; 
1795         sbp
->f_blocks 
= nmp
->nm_fsattr
.nfsa_space_total 
/ sbp
->f_bsize
; 
1796         sbp
->f_bfree 
= nmp
->nm_fsattr
.nfsa_space_free 
/ sbp
->f_bsize
; 
1797         sbp
->f_bavail 
= nmp
->nm_fsattr
.nfsa_space_avail 
/ sbp
->f_bsize
; 
1798         sbp
->f_bused 
= (nmp
->nm_fsattr
.nfsa_space_total 
/ sbp
->f_bsize
) - 
1799                         (nmp
->nm_fsattr
.nfsa_space_free 
/ sbp
->f_bsize
); 
1800         sbp
->f_files 
= nmp
->nm_fsattr
.nfsa_files_total
; 
1801         sbp
->f_ffree 
= nmp
->nm_fsattr
.nfsa_files_free
; 
1802         sbp
->f_iosize 
= nfs_iosize
; 
1805          * Calculate the size used for I/O buffers.  Use the larger 
1806          * of the two sizes to minimise NFS requests but make sure 
1807          * that it is at least one VM page to avoid wasting buffer 
1808          * space and to allow easy mmapping of I/O buffers. 
1809          * The read/write RPC calls handle the splitting up of 
1810          * buffers into multiple requests if the buffer size is 
1811          * larger than the I/O size. 
1813         iosize 
= max(nmp
->nm_rsize
, nmp
->nm_wsize
); 
1814         if (iosize 
< PAGE_SIZE
) 
1816         nmp
->nm_biosize 
= trunc_page_32(iosize
); 
1819          * V3 mounts give us a (relatively) reliable remote access(2) 
1820          * call, so advertise the fact. 
1822          * XXX this may not be the best way to go, as the granularity 
1823          *     offered isn't a good match to our needs. 
1825         if (nmp
->nm_vers 
!= NFS_VER2
) 
1826                 vfs_setauthopaqueaccess(mp
); 
1828         if (nmp
->nm_flag 
& NFSMNT_LOCALLOCKS
) 
1829                 vfs_setlocklocal(nmp
->nm_mountp
); 
1830         if (!(nmp
->nm_flag 
& (NFSMNT_NOLOCKS
|NFSMNT_LOCALLOCKS
))) 
1831                 nfs_lockd_mount_change(1); 
1833         lck_mtx_lock(&nmp
->nm_lock
); 
1834         nmp
->nm_state 
|= NFSSTA_MOUNTED
; 
1835         lck_mtx_unlock(&nmp
->nm_lock
); 
1838         /* mark the socket for termination */ 
1839         lck_mtx_lock(&nmp
->nm_lock
); 
1840         nmp
->nm_sockflags 
|= NMSOCK_UNMOUNT
; 
1841         /* wait for any socket poking to complete */ 
1842         while (nmp
->nm_sockflags 
& NMSOCK_POKE
) 
1843                 msleep(&nmp
->nm_sockflags
, &nmp
->nm_lock
, PZERO
-1, "nfswaitpoke", &ts
); 
1844         /* wait for the socket thread to terminate */ 
1845         while (nmp
->nm_sockthd
) { 
1846                 wakeup(&nmp
->nm_sockthd
); 
1847                 msleep(&nmp
->nm_sockthd
, &nmp
->nm_lock
, PZERO
-1, "nfswaitsockthd", &ts
); 
1849         /* tear down the socket */ 
1850         lck_mtx_unlock(&nmp
->nm_lock
); 
1851         nfs_disconnect(nmp
); 
1852         if (nmp
->nm_vers 
>= NFS_VER4
) { 
1854                         nfs4_mount_callback_shutdown(nmp
); 
1855                 if (nmp
->nm_renew_timer
) { 
1856                         thread_call_cancel(nmp
->nm_renew_timer
); 
1857                         thread_call_free(nmp
->nm_renew_timer
); 
1859                 if (nmp
->nm_longid
) { 
1860                         /* remove/deallocate the client ID data */ 
1861                         lck_mtx_lock(nfs_global_mutex
); 
1862                         TAILQ_REMOVE(&nfsclientids
, nmp
->nm_longid
, nci_link
); 
1863                         if (nmp
->nm_longid
->nci_id
) 
1864                                 FREE(nmp
->nm_longid
->nci_id
, M_TEMP
); 
1865                         FREE(nmp
->nm_longid
, M_TEMP
); 
1866                         lck_mtx_unlock(nfs_global_mutex
); 
1868                 if (IS_VALID_CRED(nmp
->nm_mcred
)) 
1869                         kauth_cred_unref(&nmp
->nm_mcred
); 
1871         lck_mtx_destroy(&nmp
->nm_lock
, nfs_mount_grp
); 
1872         FREE_ZONE((caddr_t
)nmp
, sizeof (struct nfsmount
), M_NFSMNT
); 
1878 nfs3_umount_rpc(struct nfsmount 
*nmp
, vfs_context_t ctx
, int timeo
) 
1880         int error 
= 0, auth_len
, slen
; 
1881         thread_t thd 
= vfs_context_thread(ctx
); 
1882         kauth_cred_t cred 
= vfs_context_ucred(ctx
); 
1885         struct nfsm_chain nmreq
, nmrep
; 
1887         uint32_t mntport 
= 0; 
1888         struct sockaddr 
*nam 
= mbuf_data(nmp
->nm_nam
); 
1889         struct sockaddr_in saddr
; 
1891         bcopy(nam
, &saddr
, min(sizeof(saddr
), nam
->sa_len
)); 
1892         auth_len 
= ((((cred
->cr_ngroups 
- 1) > nmp
->nm_numgrps
) ? 
1893                         nmp
->nm_numgrps 
: (cred
->cr_ngroups 
- 1)) << 2) + 
1895         nfsm_chain_null(&nmreq
); 
1896         nfsm_chain_null(&nmrep
); 
1898         /* send portmap request to get mountd port */ 
1899         saddr
.sin_port 
= htons(PMAPPORT
); 
1900         nfsm_chain_build_alloc_init(error
, &nmreq
, 4*NFSX_UNSIGNED
); 
1901         nfsm_chain_add_32(error
, &nmreq
, RPCPROG_MNT
); 
1902         nfsm_chain_add_32(error
, &nmreq
, RPCMNT_VER1
); 
1903         nfsm_chain_add_32(error
, &nmreq
, IPPROTO_UDP
); 
1904         nfsm_chain_add_32(error
, &nmreq
, 0); 
1905         nfsm_chain_build_done(error
, &nmreq
); 
1907         error 
= nfsm_rpchead2(SOCK_DGRAM
, PMAPPROG
, PMAPVERS
, PMAPPROC_GETPORT
, 
1908                         RPCAUTH_SYS
, auth_len
, cred
, NULL
, nmreq
.nmc_mhead
, &xid
, &mreq
); 
1910         nmreq
.nmc_mhead 
= NULL
; 
1911         error 
= nfs_aux_request(nmp
, thd
, &saddr
, mreq
, R_XID32(xid
), 0, timeo
, &nmrep
); 
1914         /* grab mountd port from portmap response */ 
1915         nfsm_chain_get_32(error
, &nmrep
, mntport
); 
1917         nfsm_chain_cleanup(&nmreq
); 
1918         nfsm_chain_cleanup(&nmrep
); 
1921         /* MOUNT protocol UNMOUNT request */ 
1922         saddr
.sin_port 
= htons(mntport
); 
1923         path 
= &vfs_statfs(nmp
->nm_mountp
)->f_mntfromname
[0]; 
1924         while (*path 
&& (*path 
!= '/')) 
1926         slen 
= strlen(path
); 
1927         nfsm_chain_build_alloc_init(error
, &nmreq
, NFSX_UNSIGNED 
+ nfsm_rndup(slen
)); 
1928         nfsm_chain_add_string(error
, &nmreq
, path
, slen
); 
1929         nfsm_chain_build_done(error
, &nmreq
); 
1931         error 
= nfsm_rpchead2(SOCK_DGRAM
, RPCPROG_MNT
, RPCMNT_VER1
, RPCMNT_UMOUNT
, 
1932                         RPCAUTH_SYS
, auth_len
, cred
, NULL
, nmreq
.nmc_mhead
, &xid
, &mreq
); 
1934         nmreq
.nmc_mhead 
= NULL
; 
1935         error 
= nfs_aux_request(nmp
, thd
, &saddr
, mreq
, R_XID32(xid
), 1, timeo
, &nmrep
); 
1937         nfsm_chain_cleanup(&nmreq
); 
1938         nfsm_chain_cleanup(&nmrep
); 
1942  * unmount system call 
1948         __unused vfs_context_t ctx
) 
1950         struct nfsmount 
*nmp
; 
1952         int error
, flags 
= 0, docallback
; 
1953         struct nfsreq 
*req
, *treq
; 
1954         struct nfs_reqqhead iodq
; 
1955         struct timespec ts 
= { 1, 0 }; 
1956         struct nfs_open_owner 
*noop
, *nextnoop
; 
1960         lck_mtx_lock(&nmp
->nm_lock
); 
1962          * During a force unmount we want to... 
1963          *   Mark that we are doing a force unmount. 
1964          *   Make the mountpoint soft. 
1966         if (mntflags 
& MNT_FORCE
) { 
1967                 flags 
|= FORCECLOSE
; 
1968                 nmp
->nm_state 
|= NFSSTA_FORCE
; 
1969                 nmp
->nm_flag 
|= NFSMNT_SOFT
; 
1972          * Goes something like this.. 
1973          * - Call vflush() to clear out vnodes for this file system, 
1974          *   except for the swap files. Deal with them in 2nd pass. 
1975          * - Decrement reference on the vnode representing remote root. 
1976          * - Close the socket 
1977          * - Free up the data structures 
1979         vp 
= NFSTOV(nmp
->nm_dnp
); 
1980         lck_mtx_unlock(&nmp
->nm_lock
); 
1983          * vflush will check for busy vnodes on mountpoint. 
1984          * Will do the right thing for MNT_FORCE. That is, we should 
1985          * not get EBUSY back. 
1987         error 
= vflush(mp
, vp
, SKIPSWAP 
| flags
); 
1988         if (mntflags 
& MNT_FORCE
) { 
1989                 error 
= vflush(mp
, NULLVP
, flags
); /* locks vp in the process */ 
1991                 if (vnode_isinuse(vp
, 1)) 
1993                 error 
= vflush(mp
, vp
, flags
); 
1998         lck_mtx_lock(&nmp
->nm_lock
); 
1999         nmp
->nm_state 
&= ~NFSSTA_MOUNTED
; 
2001         lck_mtx_unlock(&nmp
->nm_lock
); 
2004          * Release the root vnode reference held by mountnfs() 
2006         error 
= vnode_get(vp
); 
2011         vflush(mp
, NULLVP
, FORCECLOSE
); 
2014          * Destroy any RPCSEC_GSS contexts 
2016         if (!TAILQ_EMPTY(&nmp
->nm_gsscl
)) 
2017                 nfs_gss_clnt_ctx_unmount(nmp
, mntflags
); 
2019         /* mark the socket for termination */ 
2020         lck_mtx_lock(&nmp
->nm_lock
); 
2021         nmp
->nm_sockflags 
|= NMSOCK_UNMOUNT
; 
2023         /* stop callbacks */ 
2024         if ((nmp
->nm_vers 
>= NFS_VER4
) && nmp
->nm_cbid
) 
2025                 nfs4_mount_callback_shutdown(nmp
); 
2027         /* wait for any socket poking to complete */ 
2028         while (nmp
->nm_sockflags 
& NMSOCK_POKE
) 
2029                 msleep(&nmp
->nm_sockflags
, &nmp
->nm_lock
, PZERO
-1, "nfswaitpoke", &ts
); 
2031         /* Have the socket thread send the unmount RPC, if requested/appropriate. */ 
2032         if ((nmp
->nm_vers 
< NFS_VER4
) && !(mntflags 
& MNT_FORCE
) && (nmp
->nm_flag 
& NFSMNT_CALLUMNT
)) 
2033                 nfs_mount_sock_thread_wake(nmp
); 
2035         /* wait for the socket thread to terminate */ 
2036         while (nmp
->nm_sockthd
) { 
2037                 wakeup(&nmp
->nm_sockthd
); 
2038                 msleep(&nmp
->nm_sockthd
, &nmp
->nm_lock
, PZERO
-1, "nfswaitsockthd", &ts
); 
2041         lck_mtx_unlock(&nmp
->nm_lock
); 
2043         /* tear down the socket */ 
2044         nfs_disconnect(nmp
); 
2046         vfs_setfsprivate(mp
, NULL
); 
2048         lck_mtx_lock(&nmp
->nm_lock
); 
2050         if ((nmp
->nm_vers 
>= NFS_VER4
) && nmp
->nm_cbid
) { 
2051                 /* clear out any pending recall requests */ 
2052                 while ((np 
= TAILQ_FIRST(&nmp
->nm_recallq
))) { 
2053                         TAILQ_REMOVE(&nmp
->nm_recallq
, np
, n_dlink
); 
2054                         np
->n_dlink
.tqe_next 
= NFSNOLIST
; 
2058         /* cancel any renew timer */ 
2059         if ((nmp
->nm_vers 
>= NFS_VER4
) && nmp
->nm_renew_timer
) { 
2060                 thread_call_cancel(nmp
->nm_renew_timer
); 
2061                 thread_call_free(nmp
->nm_renew_timer
); 
2064         mbuf_freem(nmp
->nm_nam
); 
2065         lck_mtx_unlock(&nmp
->nm_lock
); 
2067         if ((nmp
->nm_vers 
< NFS_VER4
) && !(nmp
->nm_flag 
& (NFSMNT_NOLOCKS
|NFSMNT_LOCALLOCKS
))) 
2068                 nfs_lockd_mount_change(-1); 
2070         if ((nmp
->nm_vers 
>= NFS_VER4
) && nmp
->nm_longid
) { 
2071                 /* remove/deallocate the client ID data */ 
2072                 lck_mtx_lock(nfs_global_mutex
); 
2073                 TAILQ_REMOVE(&nfsclientids
, nmp
->nm_longid
, nci_link
); 
2074                 if (nmp
->nm_longid
->nci_id
) 
2075                         FREE(nmp
->nm_longid
->nci_id
, M_TEMP
); 
2076                 FREE(nmp
->nm_longid
, M_TEMP
); 
2077                 lck_mtx_unlock(nfs_global_mutex
); 
2081          * Loop through outstanding request list and remove dangling 
2082          * references to defunct nfsmount struct 
2085         lck_mtx_lock(nfs_request_mutex
); 
2086         TAILQ_FOREACH(req
, &nfs_reqq
, r_chain
) { 
2087                 if (req
->r_nmp 
== nmp
) { 
2088                         lck_mtx_lock(&req
->r_mtx
); 
2090                         lck_mtx_unlock(&req
->r_mtx
); 
2091                         if (req
->r_callback
.rcb_func
) { 
2092                                 /* async I/O RPC needs to be finished */ 
2093                                 lck_mtx_lock(nfsiod_mutex
); 
2094                                 if (req
->r_achain
.tqe_next 
== NFSREQNOLIST
) 
2095                                         TAILQ_INSERT_TAIL(&iodq
, req
, r_achain
); 
2096                                 lck_mtx_unlock(nfsiod_mutex
); 
2098                         lck_mtx_lock(&req
->r_mtx
); 
2099                         lck_mtx_lock(&nmp
->nm_lock
); 
2100                         if (req
->r_flags 
& R_RESENDQ
) { 
2101                                 if (req
->r_rchain
.tqe_next 
!= NFSREQNOLIST
) { 
2102                                         TAILQ_REMOVE(&nmp
->nm_resendq
, req
, r_rchain
); 
2103                                         req
->r_rchain
.tqe_next 
= NFSREQNOLIST
; 
2105                                 req
->r_flags 
&= ~R_RESENDQ
; 
2107                         lck_mtx_unlock(&nmp
->nm_lock
); 
2108                         lck_mtx_unlock(&req
->r_mtx
); 
2112         lck_mtx_unlock(nfs_request_mutex
); 
2114         /* finish any async I/O RPCs queued up */ 
2115         lck_mtx_lock(nfsiod_mutex
); 
2116         TAILQ_CONCAT(&iodq
, &nmp
->nm_iodq
, r_achain
); 
2117         lck_mtx_unlock(nfsiod_mutex
); 
2118         TAILQ_FOREACH_SAFE(req
, &iodq
, r_achain
, treq
) { 
2119                 TAILQ_REMOVE(&iodq
, req
, r_achain
); 
2120                 req
->r_achain
.tqe_next 
= NFSREQNOLIST
; 
2121                 lck_mtx_lock(&req
->r_mtx
); 
2122                 req
->r_error 
= ENXIO
; 
2123                 docallback 
= !(req
->r_flags 
& R_WAITSENT
); 
2124                 lck_mtx_unlock(&req
->r_mtx
); 
2126                         req
->r_callback
.rcb_func(req
); 
2129         /* clean up open owner list */ 
2130         if (nmp
->nm_vers 
>= NFS_VER4
) { 
2131                 lck_mtx_lock(&nmp
->nm_lock
); 
2132                 TAILQ_FOREACH_SAFE(noop
, &nmp
->nm_open_owners
, noo_link
, nextnoop
) { 
2133                         TAILQ_REMOVE(&nmp
->nm_open_owners
, noop
, noo_link
); 
2134                         noop
->noo_flags 
&= ~NFS_OPEN_OWNER_LINK
; 
2135                         if (noop
->noo_refcnt
) 
2137                         nfs_open_owner_destroy(noop
); 
2139                 lck_mtx_unlock(&nmp
->nm_lock
); 
2140                 if (IS_VALID_CRED(nmp
->nm_mcred
)) 
2141                         kauth_cred_unref(&nmp
->nm_mcred
); 
2144         lck_mtx_destroy(&nmp
->nm_lock
, nfs_mount_grp
); 
2145         FREE_ZONE((caddr_t
)nmp
, sizeof (struct nfsmount
), M_NFSMNT
); 
2150  * Return root of a filesystem 
2153 nfs_vfs_root(mount_t mp
, vnode_t 
*vpp
, __unused vfs_context_t ctx
) 
2156         struct nfsmount 
*nmp
; 
2161         if (!nmp 
|| !nmp
->nm_dnp
) 
2163         vp 
= NFSTOV(nmp
->nm_dnp
); 
2164         vpid 
= vnode_vid(vp
); 
2165         while ((error 
= vnode_getwithvid(vp
, vpid
))) { 
2166                 /* vnode_get() may return ENOENT if the dir changes. */ 
2167                 /* If that happens, just try it again, else return the error. */ 
2168                 if ((error 
!= ENOENT
) || (vnode_vid(vp
) == vpid
)) 
2170                 vpid 
= vnode_vid(vp
); 
2177  * Do operations associated with quotas 
2182         __unused mount_t mp
, 
2185         __unused caddr_t datap
, 
2186         __unused vfs_context_t context
) 
2193 nfs3_getquota(struct nfsmount 
*nmp
, vfs_context_t ctx
, uid_t id
, int type
, struct dqblk 
*dqb
) 
2195         int error 
= 0, auth_len
, slen
, timeo
; 
2196         int rqvers 
= (type 
== GRPQUOTA
) ? RPCRQUOTA_EXT_VER 
: RPCRQUOTA_VER
; 
2197         thread_t thd 
= vfs_context_thread(ctx
); 
2198         kauth_cred_t cred 
= vfs_context_ucred(ctx
); 
2201         struct nfsm_chain nmreq
, nmrep
; 
2203         uint32_t val 
= 0, bsize 
= 0; 
2204         struct sockaddr 
*nam 
= mbuf_data(nmp
->nm_nam
); 
2205         struct sockaddr_in saddr
; 
2208         bcopy(nam
, &saddr
, min(sizeof(saddr
), nam
->sa_len
)); 
2209         auth_len 
= ((((cred
->cr_ngroups 
- 1) > nmp
->nm_numgrps
) ? 
2210                         nmp
->nm_numgrps 
: (cred
->cr_ngroups 
- 1)) << 2) + 
2212         timeo 
= (nmp
->nm_flag 
& NFSMNT_SOFT
) ? 10 : 60; 
2213         nfsm_chain_null(&nmreq
); 
2214         nfsm_chain_null(&nmrep
); 
2216         /* check if we have a recently cached rquota port */ 
2217         if (nmp
->nm_rqport
) { 
2219                 if ((nmp
->nm_rqportstamp 
+ 60) >= (uint32_t)now
.tv_sec
) 
2223         /* send portmap request to get rquota port */ 
2224         saddr
.sin_port 
= htons(PMAPPORT
); 
2225         nfsm_chain_build_alloc_init(error
, &nmreq
, 4*NFSX_UNSIGNED
); 
2226         nfsm_chain_add_32(error
, &nmreq
, RPCPROG_RQUOTA
); 
2227         nfsm_chain_add_32(error
, &nmreq
, rqvers
); 
2228         nfsm_chain_add_32(error
, &nmreq
, IPPROTO_UDP
); 
2229         nfsm_chain_add_32(error
, &nmreq
, 0); 
2230         nfsm_chain_build_done(error
, &nmreq
); 
2232         error 
= nfsm_rpchead2(SOCK_DGRAM
, PMAPPROG
, PMAPVERS
, PMAPPROC_GETPORT
, 
2233                         RPCAUTH_SYS
, auth_len
, cred
, NULL
, nmreq
.nmc_mhead
, &xid
, &mreq
); 
2235         nmreq
.nmc_mhead 
= NULL
; 
2236         error 
= nfs_aux_request(nmp
, thd
, &saddr
, mreq
, R_XID32(xid
), 0, timeo
, &nmrep
); 
2239         /* grab rquota port from portmap response */ 
2240         nfsm_chain_get_32(error
, &nmrep
, val
); 
2242         nmp
->nm_rqport 
= val
; 
2244         nmp
->nm_rqportstamp 
= now
.tv_sec
; 
2245         nfsm_chain_cleanup(&nmreq
); 
2246         nfsm_chain_cleanup(&nmrep
); 
2250         /* rquota request */ 
2251         saddr
.sin_port 
= htons(nmp
->nm_rqport
); 
2252         path 
= &vfs_statfs(nmp
->nm_mountp
)->f_mntfromname
[0]; 
2253         while (*path 
&& (*path 
!= '/')) 
2255         slen 
= strlen(path
); 
2256         nfsm_chain_build_alloc_init(error
, &nmreq
, 3 * NFSX_UNSIGNED 
+ nfsm_rndup(slen
)); 
2257         nfsm_chain_add_string(error
, &nmreq
, path
, slen
); 
2258         if (type 
== GRPQUOTA
) 
2259                 nfsm_chain_add_32(error
, &nmreq
, type
); 
2260         nfsm_chain_add_32(error
, &nmreq
, id
); 
2261         nfsm_chain_build_done(error
, &nmreq
); 
2263         error 
= nfsm_rpchead2(SOCK_DGRAM
, RPCPROG_RQUOTA
, rqvers
, RPCRQUOTA_GET
, 
2264                         RPCAUTH_SYS
, auth_len
, cred
, NULL
, nmreq
.nmc_mhead
, &xid
, &mreq
); 
2266         nmreq
.nmc_mhead 
= NULL
; 
2267         error 
= nfs_aux_request(nmp
, thd
, &saddr
, mreq
, R_XID32(xid
), 0, timeo
, &nmrep
); 
2270         /* parse rquota response */ 
2271         nfsm_chain_get_32(error
, &nmrep
, val
); 
2272         if (!error 
&& (val 
!= RQUOTA_STAT_OK
)) { 
2273                 if (val 
== RQUOTA_STAT_NOQUOTA
) 
2275                 else if (val 
== RQUOTA_STAT_EPERM
) 
2280         nfsm_chain_get_32(error
, &nmrep
, bsize
); 
2281         nfsm_chain_adv(error
, &nmrep
, NFSX_UNSIGNED
); 
2282         nfsm_chain_get_32(error
, &nmrep
, val
); 
2284         dqb
->dqb_bhardlimit 
= (uint64_t)val 
* bsize
; 
2285         nfsm_chain_get_32(error
, &nmrep
, val
); 
2287         dqb
->dqb_bsoftlimit 
= (uint64_t)val 
* bsize
; 
2288         nfsm_chain_get_32(error
, &nmrep
, val
); 
2290         dqb
->dqb_curbytes 
= (uint64_t)val 
* bsize
; 
2291         nfsm_chain_get_32(error
, &nmrep
, dqb
->dqb_ihardlimit
); 
2292         nfsm_chain_get_32(error
, &nmrep
, dqb
->dqb_isoftlimit
); 
2293         nfsm_chain_get_32(error
, &nmrep
, dqb
->dqb_curinodes
); 
2294         nfsm_chain_get_32(error
, &nmrep
, dqb
->dqb_btime
); 
2295         nfsm_chain_get_32(error
, &nmrep
, dqb
->dqb_itime
); 
2299         nfsm_chain_cleanup(&nmreq
); 
2300         nfsm_chain_cleanup(&nmrep
); 
2305 nfs4_getquota(struct nfsmount 
*nmp
, vfs_context_t ctx
, uid_t id
, int type
, struct dqblk 
*dqb
) 
2308         int error 
= 0, status
, nfsvers
, numops
; 
2310         struct nfsm_chain nmreq
, nmrep
; 
2311         uint32_t bitmap
[NFS_ATTR_BITMAP_LEN
]; 
2312         thread_t thd 
= vfs_context_thread(ctx
); 
2313         kauth_cred_t cred 
= vfs_context_ucred(ctx
); 
2315         if (type 
!= USRQUOTA
)  /* NFSv4 only supports user quotas */ 
2318         /* first check that the server supports any of the quota attributes */ 
2319         if (!NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_supp_attr
, NFS_FATTR_QUOTA_AVAIL_HARD
) && 
2320             !NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_supp_attr
, NFS_FATTR_QUOTA_AVAIL_SOFT
) && 
2321             !NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_supp_attr
, NFS_FATTR_QUOTA_USED
)) 
2325          * The credential passed to the server needs to have 
2326          * an effective uid that matches the given uid. 
2328         if (id 
!= kauth_cred_getuid(cred
)) { 
2329                 struct ucred temp_cred
; 
2330                 bzero(&temp_cred
, sizeof(temp_cred
)); 
2331                 temp_cred
.cr_uid 
= id
; 
2332                 temp_cred
.cr_ngroups 
= cred
->cr_ngroups
; 
2333                 bcopy(cred
->cr_groups
, temp_cred
.cr_groups
, sizeof(temp_cred
.cr_groups
)); 
2334                 cred 
= kauth_cred_create(&temp_cred
); 
2335                 if (!IS_VALID_CRED(cred
)) 
2338                 kauth_cred_ref(cred
); 
2341         nfsvers 
= nmp
->nm_vers
; 
2345         if (error 
|| ((error 
= vnode_get(NFSTOV(np
))))) { 
2346                 kauth_cred_unref(&cred
); 
2350         nfsm_chain_null(&nmreq
); 
2351         nfsm_chain_null(&nmrep
); 
2355         nfsm_chain_build_alloc_init(error
, &nmreq
, 15 * NFSX_UNSIGNED
); 
2356         nfsm_chain_add_compound_header(error
, &nmreq
, "quota", numops
); 
2358         nfsm_chain_add_32(error
, &nmreq
, NFS_OP_PUTFH
); 
2359         nfsm_chain_add_fh(error
, &nmreq
, nfsvers
, np
->n_fhp
, np
->n_fhsize
); 
2361         nfsm_chain_add_32(error
, &nmreq
, NFS_OP_GETATTR
); 
2362         NFS_CLEAR_ATTRIBUTES(bitmap
); 
2363         NFS_BITMAP_SET(bitmap
, NFS_FATTR_QUOTA_AVAIL_HARD
); 
2364         NFS_BITMAP_SET(bitmap
, NFS_FATTR_QUOTA_AVAIL_SOFT
); 
2365         NFS_BITMAP_SET(bitmap
, NFS_FATTR_QUOTA_USED
); 
2366         nfsm_chain_add_bitmap_masked(error
, &nmreq
, bitmap
, 
2367                 NFS_ATTR_BITMAP_LEN
, nmp
->nm_fsattr
.nfsa_supp_attr
); 
2368         nfsm_chain_build_done(error
, &nmreq
); 
2369         nfsm_assert(error
, (numops 
== 0), EPROTO
); 
2371         error 
= nfs_request2(np
, NULL
, &nmreq
, NFSPROC4_COMPOUND
, thd
, cred
, 0, &nmrep
, &xid
, &status
); 
2372         nfsm_chain_skip_tag(error
, &nmrep
); 
2373         nfsm_chain_get_32(error
, &nmrep
, numops
); 
2374         nfsm_chain_op_check(error
, &nmrep
, NFS_OP_PUTFH
); 
2375         nfsm_chain_op_check(error
, &nmrep
, NFS_OP_GETATTR
); 
2376         nfsm_assert(error
, NFSTONMP(np
), ENXIO
); 
2378         error 
= nfs4_parsefattr(&nmrep
, NULL
, NULL
, NULL
, dqb
); 
2380         nfsm_assert(error
, NFSTONMP(np
), ENXIO
); 
2382         nfsm_chain_cleanup(&nmreq
); 
2383         nfsm_chain_cleanup(&nmrep
); 
2384         vnode_put(NFSTOV(np
)); 
2385         kauth_cred_unref(&cred
); 
2390 nfs_vfs_quotactl(mount_t mp
, int cmds
, uid_t uid
, caddr_t datap
, vfs_context_t ctx
) 
2392         struct nfsmount 
*nmp
; 
2393         int cmd
, type
, error
, nfsvers
; 
2394         uid_t ruid 
= vfs_context_ucred(ctx
)->cr_ruid
; 
2395         struct dqblk 
*dqb 
= (struct dqblk
*)datap
; 
2397         if (!(nmp 
= VFSTONFS(mp
))) 
2399         nfsvers 
= nmp
->nm_vers
; 
2404         /* we can only support Q_GETQUOTA */ 
2405         cmd 
= cmds 
>> SUBCMDSHIFT
; 
2420         type 
= cmds 
& SUBCMDMASK
; 
2421         if ((u_int
)type 
>= MAXQUOTAS
) 
2423         if ((uid 
!= ruid
) && ((error 
= vfs_context_suser(ctx
)))) 
2426         if (vfs_busy(mp
, LK_NOWAIT
)) 
2428         bzero(dqb
, sizeof(*dqb
)); 
2429         error 
= nmp
->nm_funcs
->nf_getquota(nmp
, ctx
, uid
, type
, dqb
); 
2436  * Flush out the buffer cache 
2438 int nfs_sync_callout(vnode_t
, void *); 
2440 struct nfs_sync_cargs 
{ 
2447 nfs_sync_callout(vnode_t vp
, void *arg
) 
2449         struct nfs_sync_cargs 
*cargs 
= (struct nfs_sync_cargs
*)arg
; 
2452         if (LIST_EMPTY(&VTONFS(vp
)->n_dirtyblkhd
)) 
2453                 return (VNODE_RETURNED
); 
2454         if (VTONFS(vp
)->n_wrbusy 
> 0) 
2455                 return (VNODE_RETURNED
); 
2456         if (VTONFS(vp
)->n_bflag 
& (NBFLUSHINPROG
|NBINVALINPROG
)) 
2457                 return (VNODE_RETURNED
); 
2459         error 
= nfs_flush(VTONFS(vp
), cargs
->waitfor
, cargs
->thd
, 0); 
2461                 cargs
->error 
= error
; 
2463         return (VNODE_RETURNED
); 
2467 nfs_vfs_sync(mount_t mp
, int waitfor
, vfs_context_t ctx
) 
2469         struct nfs_sync_cargs cargs
; 
2471         cargs
.waitfor 
= waitfor
; 
2472         cargs
.thd 
= vfs_context_thread(ctx
); 
2475         vnode_iterate(mp
, 0, nfs_sync_callout
, &cargs
); 
2477         return (cargs
.error
); 
2481  * NFS flat namespace lookup. 
2482  * Currently unsupported. 
2487         __unused mount_t mp
, 
2488         __unused ino64_t ino
, 
2489         __unused vnode_t 
*vpp
, 
2490         __unused vfs_context_t ctx
) 
2497  * At this point, this should never happen 
2502         __unused mount_t mp
, 
2504         __unused 
unsigned char *fhp
, 
2505         __unused vnode_t 
*vpp
, 
2506         __unused vfs_context_t ctx
) 
2513  * Vnode pointer to File handle, should never happen either 
2518         __unused vnode_t vp
, 
2519         __unused 
int *fhlenp
, 
2520         __unused 
unsigned char *fhp
, 
2521         __unused vfs_context_t ctx
) 
2528  * Vfs start routine, a no-op. 
2533         __unused mount_t mp
, 
2535         __unused vfs_context_t ctx
) 
2542  * Do that sysctl thang... 
2545 nfs_vfs_sysctl(int *name
, u_int namelen
, user_addr_t oldp
, size_t *oldlenp
, 
2546            user_addr_t newp
, size_t newlen
, vfs_context_t ctx
) 
2548         int error 
= 0, val
, softnobrowse
; 
2549         struct sysctl_req 
*req 
= NULL
; 
2550         union union_vfsidctl vc
; 
2552         struct nfsmount 
*nmp 
= NULL
; 
2554         boolean_t is_64_bit
; 
2556         struct nfs_exportfs 
*nxfs
; 
2557         struct nfs_export 
*nx
; 
2558         struct nfs_active_user_list 
*ulist
; 
2559         struct nfs_export_stat_desc stat_desc
; 
2560         struct nfs_export_stat_rec statrec
; 
2561         struct nfs_user_stat_node 
*unode
, *unode_next
; 
2562         struct nfs_user_stat_desc ustat_desc
; 
2563         struct nfs_user_stat_user_rec ustat_rec
; 
2564         struct nfs_user_stat_path_rec upath_rec
; 
2565         uint bytes_avail
, bytes_total
, recs_copied
; 
2566         uint numExports
, totlen
, pos
, numRecs
, count
; 
2567 #endif /* NFSSERVER */ 
2570          * All names at this level are terminal. 
2573                 return (ENOTDIR
);       /* overloaded */ 
2575         is_64_bit 
= vfs_context_is64bit(ctx
); 
2577         /* common code for "new style" VFS_CTL sysctl, get the mount. */ 
2581         case VFS_CTL_NOLOCKS
: 
2582                 req 
= CAST_DOWN(struct sysctl_req 
*, oldp
); 
2583                 error 
= SYSCTL_IN(req
, &vc
, is_64_bit
? sizeof(vc
.vc64
):sizeof(vc
.vc32
)); 
2586                 mp 
= vfs_getvfs(&vc
.vc32
.vc_fsid
); /* works for 32 and 64 */ 
2592                 bzero(&vq
, sizeof(vq
)); 
2595                         req
->newptr 
= vc
.vc64
.vc_ptr
; 
2596                         req
->newlen 
= (size_t)vc
.vc64
.vc_len
; 
2598                         req
->newptr 
= CAST_USER_ADDR_T(vc
.vc32
.vc_ptr
); 
2599                         req
->newlen 
= vc
.vc32
.vc_len
; 
2606                         *oldlenp 
= sizeof nfsstats
; 
2610                 if (*oldlenp 
< sizeof nfsstats
) { 
2611                         *oldlenp 
= sizeof nfsstats
; 
2615                 error 
= copyout(&nfsstats
, oldp
, sizeof nfsstats
); 
2619                 if (newp 
&& newlen 
!= sizeof nfsstats
) 
2623                         return copyin(newp
, &nfsstats
, sizeof nfsstats
); 
2626         case NFS_EXPORTSTATS
: 
2627                 /* setup export stat descriptor */ 
2628                 stat_desc
.rec_vers 
= NFS_EXPORT_STAT_REC_VERSION
; 
2630                 if (!nfsrv_is_initialized()) { 
2631                         stat_desc
.rec_count 
= 0; 
2632                         if (oldp 
&& (*oldlenp 
>= sizeof(struct nfs_export_stat_desc
))) 
2633                                 error 
= copyout(&stat_desc
, oldp
, sizeof(struct nfs_export_stat_desc
)); 
2634                         *oldlenp 
= sizeof(struct nfs_export_stat_desc
); 
2638                 /* Count the number of exported directories */ 
2639                 lck_rw_lock_shared(&nfsrv_export_rwlock
); 
2641                 LIST_FOREACH(nxfs
, &nfsrv_exports
, nxfs_next
) 
2642                         LIST_FOREACH(nx
, &nxfs
->nxfs_exports
, nx_next
) 
2645                 /* update stat descriptor's export record count */ 
2646                 stat_desc
.rec_count 
= numExports
; 
2648                 /* calculate total size of required buffer */ 
2649                 totlen 
= sizeof(struct nfs_export_stat_desc
) + (numExports 
* sizeof(struct nfs_export_stat_rec
)); 
2651                 /* Check caller's buffer */ 
2653                         lck_rw_done(&nfsrv_export_rwlock
); 
2654                         /* indicate required buffer len */ 
2659                 /* We require the caller's buffer to be at least large enough to hold the descriptor */ 
2660                 if (*oldlenp 
< sizeof(struct nfs_export_stat_desc
)) { 
2661                         lck_rw_done(&nfsrv_export_rwlock
); 
2662                         /* indicate required buffer len */ 
2667                 /* indicate required buffer len */ 
2670                 /* check if export table is empty */ 
2672                         lck_rw_done(&nfsrv_export_rwlock
); 
2673                         error 
= copyout(&stat_desc
, oldp
, sizeof(struct nfs_export_stat_desc
)); 
2677                 /* calculate how many actual export stat records fit into caller's buffer */ 
2678                 numRecs 
= (*oldlenp 
- sizeof(struct nfs_export_stat_desc
)) / sizeof(struct nfs_export_stat_rec
); 
2681                         /* caller's buffer can only accomodate descriptor */ 
2682                         lck_rw_done(&nfsrv_export_rwlock
); 
2683                         stat_desc
.rec_count 
= 0; 
2684                         error 
= copyout(&stat_desc
, oldp
, sizeof(struct nfs_export_stat_desc
)); 
2688                 /* adjust to actual number of records to copyout to caller's buffer */ 
2689                 if (numRecs 
> numExports
) 
2690                         numRecs 
= numExports
; 
2692                 /* set actual number of records we are returning */ 
2693                 stat_desc
.rec_count 
= numRecs
; 
2695                 /* first copy out the stat descriptor */ 
2697                 error 
= copyout(&stat_desc
, oldp 
+ pos
, sizeof(struct nfs_export_stat_desc
)); 
2699                         lck_rw_done(&nfsrv_export_rwlock
); 
2702                 pos 
+= sizeof(struct nfs_export_stat_desc
); 
2704                 /* Loop through exported directories */ 
2706                 LIST_FOREACH(nxfs
, &nfsrv_exports
, nxfs_next
) { 
2707                         LIST_FOREACH(nx
, &nxfs
->nxfs_exports
, nx_next
) { 
2709                                 if (count 
>= numRecs
) 
2712                                 /* build exported filesystem path */ 
2713                                 snprintf(statrec
.path
, sizeof(statrec
.path
), "%s%s%s", 
2714                                         nxfs
->nxfs_path
, ((nxfs
->nxfs_path
[1] && nx
->nx_path
[0]) ? "/" : ""), 
2717                                 /* build the 64-bit export stat counters */ 
2718                                 statrec
.ops 
= ((uint64_t)nx
->nx_stats
.ops
.hi 
<< 32) | 
2719                                                 nx
->nx_stats
.ops
.lo
; 
2720                                 statrec
.bytes_read 
= ((uint64_t)nx
->nx_stats
.bytes_read
.hi 
<< 32) | 
2721                                                 nx
->nx_stats
.bytes_read
.lo
; 
2722                                 statrec
.bytes_written 
= ((uint64_t)nx
->nx_stats
.bytes_written
.hi 
<< 32) | 
2723                                                 nx
->nx_stats
.bytes_written
.lo
; 
2724                                 error 
= copyout(&statrec
, oldp 
+ pos
, sizeof(statrec
)); 
2726                                         lck_rw_done(&nfsrv_export_rwlock
); 
2729                                 /* advance buffer position */ 
2730                                 pos 
+= sizeof(statrec
); 
2733                 lck_rw_done(&nfsrv_export_rwlock
); 
2736                 /* init structures used for copying out of kernel */ 
2737                 ustat_desc
.rec_vers 
= NFS_USER_STAT_REC_VERSION
; 
2738                 ustat_rec
.rec_type 
= NFS_USER_STAT_USER_REC
; 
2739                 upath_rec
.rec_type 
= NFS_USER_STAT_PATH_REC
; 
2741                 /* initialize counters */ 
2742                 bytes_total 
= sizeof(struct nfs_user_stat_desc
); 
2743                 bytes_avail  
= *oldlenp
; 
2746                 if (!nfsrv_is_initialized()) /* NFS server not initialized, so no stats */ 
2749                 /* reclaim old expired user nodes */ 
2750                 nfsrv_active_user_list_reclaim(); 
2752                 /* reserve space for the buffer descriptor */ 
2753                 if (bytes_avail 
>= sizeof(struct nfs_user_stat_desc
)) 
2754                         bytes_avail 
-= sizeof(struct nfs_user_stat_desc
); 
2758                 /* put buffer position past the buffer descriptor */ 
2759                 pos 
= sizeof(struct nfs_user_stat_desc
); 
2761                 /* Loop through exported directories */ 
2762                 lck_rw_lock_shared(&nfsrv_export_rwlock
); 
2763                 LIST_FOREACH(nxfs
, &nfsrv_exports
, nxfs_next
) { 
2764                         LIST_FOREACH(nx
, &nxfs
->nxfs_exports
, nx_next
) { 
2766                                 if (bytes_avail 
>= sizeof(struct nfs_user_stat_path_rec
)) { 
2767                                         snprintf(upath_rec
.path
, sizeof(upath_rec
.path
), "%s%s%s", 
2768                                             nxfs
->nxfs_path
, ((nxfs
->nxfs_path
[1] && nx
->nx_path
[0]) ? "/" : ""), 
2771                                         error 
= copyout(&upath_rec
, oldp 
+ pos
, sizeof(struct nfs_user_stat_path_rec
)); 
2777                                         pos 
+= sizeof(struct nfs_user_stat_path_rec
); 
2778                                         bytes_avail 
-= sizeof(struct nfs_user_stat_path_rec
); 
2782                                         /* Caller's buffer is exhausted */ 
2786                                 bytes_total 
+= sizeof(struct nfs_user_stat_path_rec
); 
2788                                 /* Scan through all user nodes of this export */ 
2789                                 ulist 
= &nx
->nx_user_list
; 
2790                                 lck_mtx_lock(&ulist
->user_mutex
); 
2791                                 for (unode 
= TAILQ_FIRST(&ulist
->user_lru
); unode
; unode 
= unode_next
) { 
2792                                         unode_next 
= TAILQ_NEXT(unode
, lru_link
); 
2794                                         /* copy out node if there is space */ 
2795                                         if (bytes_avail 
>= sizeof(struct nfs_user_stat_user_rec
)) { 
2796                                                 /* prepare a user stat rec for copying out */ 
2797                                                 ustat_rec
.uid 
= unode
->uid
; 
2798                                                 bcopy(&unode
->sock
, &ustat_rec
.sock
, unode
->sock
.ss_len
); 
2799                                                 ustat_rec
.ops 
= unode
->ops
; 
2800                                                 ustat_rec
.bytes_read 
= unode
->bytes_read
; 
2801                                                 ustat_rec
.bytes_written 
= unode
->bytes_written
; 
2802                                                 ustat_rec
.tm_start 
= unode
->tm_start
; 
2803                                                 ustat_rec
.tm_last 
= unode
->tm_last
; 
2805                                                 error 
= copyout(&ustat_rec
, oldp 
+ pos
, sizeof(struct nfs_user_stat_user_rec
)); 
2809                                                         lck_mtx_unlock(&ulist
->user_mutex
); 
2813                                                 pos 
+= sizeof(struct nfs_user_stat_user_rec
); 
2814                                                 bytes_avail 
-= sizeof(struct nfs_user_stat_user_rec
); 
2818                                                 /* Caller's buffer is exhausted */ 
2821                                         bytes_total 
+= sizeof(struct nfs_user_stat_user_rec
); 
2823                                 /* can unlock this export's list now */ 
2824                                 lck_mtx_unlock(&ulist
->user_mutex
); 
2829                 /* unlock the export table */ 
2830                 lck_rw_done(&nfsrv_export_rwlock
); 
2833                 /* indicate number of actual records copied */ 
2834                 ustat_desc
.rec_count 
= recs_copied
; 
2837                         /* check if there was enough room for the buffer descriptor */ 
2838                         if (*oldlenp 
>= sizeof(struct nfs_user_stat_desc
)) 
2839                                 error 
= copyout(&ustat_desc
, oldp
, sizeof(struct nfs_user_stat_desc
)); 
2843                         /* always indicate required buffer size */ 
2844                         *oldlenp 
= bytes_total
; 
2849                         *oldlenp 
= sizeof(nfsrv_user_stat_node_count
); 
2853                 if (*oldlenp 
< sizeof(nfsrv_user_stat_node_count
)) { 
2854                         *oldlenp 
= sizeof(nfsrv_user_stat_node_count
); 
2858                 if (nfsrv_is_initialized()) { 
2859                         /* reclaim old expired user nodes */ 
2860                         nfsrv_active_user_list_reclaim(); 
2863                 error 
= copyout(&nfsrv_user_stat_node_count
, oldp
, sizeof(nfsrv_user_stat_node_count
)); 
2865 #endif /* NFSSERVER */ 
2866         case VFS_CTL_NOLOCKS
: 
2867                 if (req
->oldptr 
!= USER_ADDR_NULL
) { 
2868                         lck_mtx_lock(&nmp
->nm_lock
); 
2869                         val 
= (nmp
->nm_flag 
& NFSMNT_NOLOCKS
) ? 1 : 0; 
2870                         lck_mtx_unlock(&nmp
->nm_lock
); 
2871                         error 
= SYSCTL_OUT(req
, &val
, sizeof(val
)); 
2875                 if (req
->newptr 
!= USER_ADDR_NULL
) { 
2876                         error 
= SYSCTL_IN(req
, &val
, sizeof(val
)); 
2879                         lck_mtx_lock(&nmp
->nm_lock
); 
2880                         if (nmp
->nm_flag 
& NFSMNT_LOCALLOCKS
) { 
2881                                 /* can't toggle locks when using local locks */ 
2884                                 if (!(nmp
->nm_flag 
& NFSMNT_NOLOCKS
)) 
2885                                         nfs_lockd_mount_change(-1); 
2886                                 nmp
->nm_flag 
|= NFSMNT_NOLOCKS
; 
2887                                 nmp
->nm_state 
&= ~NFSSTA_LOCKTIMEO
; 
2889                                 if (nmp
->nm_flag 
& NFSMNT_NOLOCKS
) 
2890                                         nfs_lockd_mount_change(1); 
2891                                 nmp
->nm_flag 
&= ~NFSMNT_NOLOCKS
; 
2893                         lck_mtx_unlock(&nmp
->nm_lock
); 
2897                 lck_mtx_lock(&nmp
->nm_lock
); 
2898                 /* XXX don't allow users to know about/disconnect unresponsive, soft, nobrowse mounts */ 
2899                 softnobrowse 
= ((nmp
->nm_flag 
& NFSMNT_SOFT
) && (vfs_flags(nmp
->nm_mountp
) & MNT_DONTBROWSE
)); 
2900                 if (!softnobrowse 
&& (nmp
->nm_state 
& NFSSTA_TIMEO
)) 
2901                         vq
.vq_flags 
|= VQ_NOTRESP
; 
2902                 if (!softnobrowse 
&& (nmp
->nm_state 
& NFSSTA_JUKEBOXTIMEO
) && 
2903                     !(nmp
->nm_flag 
& NFSMNT_MUTEJUKEBOX
)) 
2904                         vq
.vq_flags 
|= VQ_NOTRESP
; 
2905                 if (!softnobrowse 
&& (nmp
->nm_state 
& NFSSTA_LOCKTIMEO
) && 
2906                     !(nmp
->nm_flag 
& (NFSMNT_NOLOCKS
|NFSMNT_LOCALLOCKS
))) 
2907                         vq
.vq_flags 
|= VQ_NOTRESP
; 
2908                 if (nmp
->nm_state 
& NFSSTA_DEAD
) 
2909                         vq
.vq_flags 
|= VQ_DEAD
; 
2910                 lck_mtx_unlock(&nmp
->nm_lock
); 
2911                 error 
= SYSCTL_OUT(req
, &vq
, sizeof(vq
)); 
2914                 if (req
->oldptr 
!= USER_ADDR_NULL
) { 
2915                         lck_mtx_lock(&nmp
->nm_lock
); 
2916                         val 
= nmp
->nm_tprintf_initial_delay
; 
2917                         lck_mtx_unlock(&nmp
->nm_lock
); 
2918                         error 
= SYSCTL_OUT(req
, &val
, sizeof(val
)); 
2922                 if (req
->newptr 
!= USER_ADDR_NULL
) { 
2923                         error 
= SYSCTL_IN(req
, &val
, sizeof(val
)); 
2926                         lck_mtx_lock(&nmp
->nm_lock
); 
2928                                 nmp
->nm_tprintf_initial_delay 
= 0; 
2930                                 nmp
->nm_tprintf_initial_delay 
= val
; 
2931                         lck_mtx_unlock(&nmp
->nm_lock
);