2  * Copyright (c) 2000-2008 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_mount_grp
; 
 127 uint32_t nfs_fs_attr_bitmap
[NFS_ATTR_BITMAP_LEN
]; 
 128 uint32_t nfs_object_attr_bitmap
[NFS_ATTR_BITMAP_LEN
]; 
 129 uint32_t nfs_getattr_bitmap
[NFS_ATTR_BITMAP_LEN
]; 
 132 struct nfs_reqqhead nfs_reqq
; 
 133 lck_grp_t 
*nfs_request_grp
; 
 134 lck_mtx_t 
*nfs_request_mutex
; 
 135 thread_call_t nfs_request_timer_call
; 
 136 int nfs_request_timer_on
; 
 138 u_long nfs_xidwrap 
= 0;         /* to build a (non-wrapping) 64 bit xid */ 
 140 thread_call_t nfs_buf_timer_call
; 
 143 lck_grp_t 
*nfsiod_lck_grp
; 
 144 lck_mtx_t 
*nfsiod_mutex
; 
 145 struct nfsiodlist nfsiodfree
, nfsiodwork
; 
 146 struct nfsiodmountlist nfsiodmounts
; 
 147 int nfsiod_thread_count 
= 0; 
 148 int nfsiod_thread_max 
= NFS_DEFASYNCTHREAD
; 
 149 int nfs_max_async_writes 
= NFS_DEFMAXASYNCWRITES
; 
 151 int nfs_iosize 
= NFS_IOSIZE
; 
 152 int nfs_access_cache_timeout 
= NFS_MAXATTRTIMO
; 
 153 int nfs_allow_async 
= 0; 
 154 int nfs_statfs_rate_limit 
= NFS_DEFSTATFSRATELIMIT
; 
 155 int nfs_lockd_mounts 
= 0; 
 156 int nfs_lockd_request_sent 
= 0; 
 158 int nfs_tprintf_initial_delay 
= NFS_TPRINTF_INITIAL_DELAY
; 
 159 int nfs_tprintf_delay 
= NFS_TPRINTF_DELAY
; 
 162 static int      mountnfs(struct user_nfs_args 
*,mount_t
,mbuf_t
,vfs_context_t
,vnode_t 
*); 
 163 static int      nfs_mount_diskless(struct nfs_dlmount 
*, const char *, int, vnode_t 
*, mount_t 
*, vfs_context_t
); 
 164 #if !defined(NO_MOUNT_PRIVATE) 
 165 static int      nfs_mount_diskless_private(struct nfs_dlmount 
*, const char *, int, vnode_t 
*, mount_t 
*, vfs_context_t
); 
 166 #endif /* NO_MOUNT_PRIVATE */ 
 169  * NFS VFS operations. 
 171 static int      nfs_vfs_mount(mount_t
, vnode_t
, user_addr_t
, vfs_context_t
); 
 172 static int      nfs_vfs_start(mount_t
, int, vfs_context_t
); 
 173 static int      nfs_vfs_unmount(mount_t
, int, vfs_context_t
); 
 174 static int      nfs_vfs_root(mount_t
, vnode_t 
*, vfs_context_t
); 
 175 static int      nfs_vfs_quotactl(mount_t
, int, uid_t
, caddr_t
, vfs_context_t
); 
 176 static int      nfs_vfs_getattr(mount_t
, struct vfs_attr 
*, vfs_context_t
); 
 177 static int      nfs_vfs_sync(mount_t
, int, vfs_context_t
); 
 178 static int      nfs_vfs_vget(mount_t
, ino64_t
, vnode_t 
*, vfs_context_t
); 
 179 static int      nfs_vfs_vptofh(vnode_t
, int *, unsigned char *, vfs_context_t
); 
 180 static int      nfs_vfs_fhtovp(mount_t
, int, unsigned char *, vnode_t 
*, vfs_context_t
); 
 181 static int      nfs_vfs_init(struct vfsconf 
*); 
 182 static int      nfs_vfs_sysctl(int *, u_int
, user_addr_t
, size_t *, user_addr_t
, size_t, vfs_context_t
); 
 184 struct vfsops nfs_vfsops 
= { 
 198         { NULL
,         /* reserved */ 
 204           NULL 
}        /* reserved */ 
 209  * version-specific NFS functions 
 211 static int nfs3_mount(struct nfsmount 
*, vfs_context_t
, struct user_nfs_args 
*, nfsnode_t 
*); 
 212 static int nfs4_mount(struct nfsmount 
*, vfs_context_t
, struct user_nfs_args 
*, nfsnode_t 
*); 
 213 static int nfs3_update_statfs(struct nfsmount 
*, vfs_context_t
); 
 214 static int nfs4_update_statfs(struct nfsmount 
*, vfs_context_t
); 
 216 #define nfs3_getquota   NULL 
 217 #define nfs4_getquota   NULL 
 219 static int nfs3_getquota(struct nfsmount 
*, vfs_context_t
, u_long
, int, struct dqblk 
*); 
 220 static int nfs4_getquota(struct nfsmount 
*, vfs_context_t
, u_long
, int, struct dqblk 
*); 
 223 struct nfs_funcs nfs3_funcs 
= { 
 231         nfs3_read_rpc_async_finish
, 
 233         nfs3_write_rpc_async
, 
 234         nfs3_write_rpc_async_finish
, 
 236         nfs3_lookup_rpc_async
, 
 237         nfs3_lookup_rpc_async_finish
, 
 241 struct nfs_funcs nfs4_funcs 
= { 
 249         nfs4_read_rpc_async_finish
, 
 251         nfs4_write_rpc_async
, 
 252         nfs4_write_rpc_async_finish
, 
 254         nfs4_lookup_rpc_async
, 
 255         nfs4_lookup_rpc_async_finish
, 
 261  * Called once to initialize data structures... 
 264 nfs_vfs_init(struct vfsconf 
*vfsp
) 
 269          * Check to see if major data structures haven't bloated. 
 271         if (sizeof (struct nfsnode
) > NFS_NODEALLOC
) { 
 272                 printf("struct nfsnode bloated (> %dbytes)\n", NFS_NODEALLOC
); 
 273                 printf("Try reducing NFS_SMALLFH\n"); 
 275         if (sizeof (struct nfsmount
) > NFS_MNTALLOC
) { 
 276                 printf("struct nfsmount bloated (> %dbytes)\n", NFS_MNTALLOC
); 
 277                 printf("Try reducing NFS_MUIDHASHSIZ\n"); 
 280         nfs_ticks 
= (hz 
* NFS_TICKINTVL 
+ 500) / 1000; 
 284         /* init async I/O thread pool state */ 
 285         TAILQ_INIT(&nfsiodfree
); 
 286         TAILQ_INIT(&nfsiodwork
); 
 287         TAILQ_INIT(&nfsiodmounts
); 
 288         nfsiod_lck_grp 
= lck_grp_alloc_init("nfsiod", LCK_GRP_ATTR_NULL
); 
 289         nfsiod_mutex 
= lck_mtx_alloc_init(nfsiod_lck_grp
, LCK_ATTR_NULL
); 
 291         /* init mount lock group */ 
 292         nfs_mount_grp 
= lck_grp_alloc_init("nfs_mount", LCK_GRP_ATTR_NULL
); 
 294         /* init request list mutex */ 
 295         nfs_request_grp 
= lck_grp_alloc_init("nfs_request", LCK_GRP_ATTR_NULL
); 
 296         nfs_request_mutex 
= lck_mtx_alloc_init(nfs_request_grp
, LCK_ATTR_NULL
); 
 298         /* initialize NFS request list */ 
 299         TAILQ_INIT(&nfs_reqq
); 
 301         nfs_nbinit();                   /* Init the nfsbuf table */ 
 302         nfs_nhinit();                   /* Init the nfsnode table */ 
 303         nfs_lockinit();                 /* Init the nfs lock state */ 
 304         nfs_gss_init();                 /* Init RPCSEC_GSS security */ 
 307         NFS4_PER_FS_ATTRIBUTES(nfs_fs_attr_bitmap
); 
 308         NFS4_PER_OBJECT_ATTRIBUTES(nfs_object_attr_bitmap
); 
 309         NFS4_DEFAULT_ATTRIBUTES(nfs_getattr_bitmap
); 
 310         for (i
=0; i 
< NFS_ATTR_BITMAP_LEN
; i
++) 
 311                 nfs_getattr_bitmap
[i
] &= nfs_object_attr_bitmap
[i
]; 
 313         /* initialize NFS timer callouts */ 
 314         nfs_request_timer_call 
= thread_call_allocate(nfs_request_timer
, NULL
); 
 315         nfs_buf_timer_call 
= thread_call_allocate(nfs_buf_timer
, NULL
); 
 317         vfsp
->vfc_refcount
++; /* make us non-unloadable */ 
 325 nfs3_update_statfs(struct nfsmount 
*nmp
, vfs_context_t ctx
) 
 328         int error 
= 0, lockerror
, status
, nfsvers
; 
 330         struct nfsm_chain nmreq
, nmrep
; 
 333         nfsvers 
= nmp
->nm_vers
; 
 335         if ((error 
= vnode_get(NFSTOV(np
)))) 
 338         nfsm_chain_null(&nmreq
); 
 339         nfsm_chain_null(&nmrep
); 
 341         nfsm_chain_build_alloc_init(error
, &nmreq
, NFSX_FH(nfsvers
)); 
 342         nfsm_chain_add_fh(error
, &nmreq
, nfsvers
, np
->n_fhp
, np
->n_fhsize
); 
 343         nfsm_chain_build_done(error
, &nmreq
); 
 345         error 
= nfs_request(np
, NULL
, &nmreq
, NFSPROC_FSSTAT
, ctx
, 
 346                    &nmrep
, &xid
, &status
); 
 347         if ((lockerror 
= nfs_lock(np
, NFS_NODE_LOCK_EXCLUSIVE
))) 
 349         if (nfsvers 
== NFS_VER3
) 
 350                 nfsm_chain_postop_attr_update(error
, &nmrep
, np
, &xid
); 
 355         nfsm_assert(error
, NFSTONMP(np
), ENXIO
); 
 357         lck_mtx_lock(&nmp
->nm_lock
); 
 358         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SPACE_TOTAL
); 
 359         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SPACE_FREE
); 
 360         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SPACE_AVAIL
); 
 361         if (nfsvers 
== NFS_VER3
) { 
 362                 NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_FILES_AVAIL
); 
 363                 NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_FILES_TOTAL
); 
 364                 NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_FILES_FREE
); 
 365                 nmp
->nm_fsattr
.nfsa_bsize 
= NFS_FABLKSIZE
; 
 366                 nfsm_chain_get_64(error
, &nmrep
, nmp
->nm_fsattr
.nfsa_space_total
); 
 367                 nfsm_chain_get_64(error
, &nmrep
, nmp
->nm_fsattr
.nfsa_space_free
); 
 368                 nfsm_chain_get_64(error
, &nmrep
, nmp
->nm_fsattr
.nfsa_space_avail
); 
 369                 nfsm_chain_get_64(error
, &nmrep
, nmp
->nm_fsattr
.nfsa_files_total
); 
 370                 nfsm_chain_get_64(error
, &nmrep
, nmp
->nm_fsattr
.nfsa_files_free
); 
 371                 nfsm_chain_get_64(error
, &nmrep
, nmp
->nm_fsattr
.nfsa_files_avail
); 
 374                 nfsm_chain_adv(error
, &nmrep
, NFSX_UNSIGNED
); // skip tsize? 
 375                 nfsm_chain_get_32(error
, &nmrep
, nmp
->nm_fsattr
.nfsa_bsize
); 
 376                 nfsm_chain_get_32(error
, &nmrep
, val
); 
 378                 if (nmp
->nm_fsattr
.nfsa_bsize 
<= 0) 
 379                         nmp
->nm_fsattr
.nfsa_bsize 
= NFS_FABLKSIZE
; 
 380                 nmp
->nm_fsattr
.nfsa_space_total 
= (uint64_t)val 
* nmp
->nm_fsattr
.nfsa_bsize
; 
 381                 nfsm_chain_get_32(error
, &nmrep
, val
); 
 383                 nmp
->nm_fsattr
.nfsa_space_free 
= (uint64_t)val 
* nmp
->nm_fsattr
.nfsa_bsize
; 
 384                 nfsm_chain_get_32(error
, &nmrep
, val
); 
 386                 nmp
->nm_fsattr
.nfsa_space_avail 
= (uint64_t)val 
* nmp
->nm_fsattr
.nfsa_bsize
; 
 388         lck_mtx_unlock(&nmp
->nm_lock
); 
 390         nfsm_chain_cleanup(&nmreq
); 
 391         nfsm_chain_cleanup(&nmrep
); 
 392         vnode_put(NFSTOV(np
)); 
 397 nfs4_update_statfs(struct nfsmount 
*nmp
, vfs_context_t ctx
) 
 400         int error 
= 0, lockerror
, status
, nfsvers
, numops
; 
 402         struct nfsm_chain nmreq
, nmrep
; 
 403         uint32_t bitmap
[NFS_ATTR_BITMAP_LEN
]; 
 404         struct nfs_vattr nvattr
; 
 406         nfsvers 
= nmp
->nm_vers
; 
 408         if ((error 
= vnode_get(NFSTOV(np
)))) 
 411         nfsm_chain_null(&nmreq
); 
 412         nfsm_chain_null(&nmrep
); 
 416         nfsm_chain_build_alloc_init(error
, &nmreq
, 15 * NFSX_UNSIGNED
); 
 417         nfsm_chain_add_compound_header(error
, &nmreq
, "statfs", numops
); 
 419         nfsm_chain_add_32(error
, &nmreq
, NFS_OP_PUTFH
); 
 420         nfsm_chain_add_fh(error
, &nmreq
, nfsvers
, np
->n_fhp
, np
->n_fhsize
); 
 422         nfsm_chain_add_32(error
, &nmreq
, NFS_OP_GETATTR
); 
 423         NFS_COPY_ATTRIBUTES(nfs_getattr_bitmap
, bitmap
); 
 424         NFS4_STATFS_ATTRIBUTES(bitmap
); 
 425         nfsm_chain_add_bitmap_masked(error
, &nmreq
, bitmap
, 
 426                 NFS_ATTR_BITMAP_LEN
, nmp
->nm_fsattr
.nfsa_supp_attr
); 
 427         nfsm_chain_build_done(error
, &nmreq
); 
 428         nfsm_assert(error
, (numops 
== 0), EPROTO
); 
 430         error 
= nfs_request(np
, NULL
, &nmreq
, NFSPROC4_COMPOUND
, ctx
, &nmrep
, &xid
, &status
); 
 431         nfsm_chain_skip_tag(error
, &nmrep
); 
 432         nfsm_chain_get_32(error
, &nmrep
, numops
); 
 433         nfsm_chain_op_check(error
, &nmrep
, NFS_OP_PUTFH
); 
 434         nfsm_chain_op_check(error
, &nmrep
, NFS_OP_GETATTR
); 
 435         nfsm_assert(error
, NFSTONMP(np
), ENXIO
); 
 437         lck_mtx_lock(&nmp
->nm_lock
); 
 438         NFS_CLEAR_ATTRIBUTES(nvattr
.nva_bitmap
); 
 439         error 
= nfs4_parsefattr(&nmrep
, &nmp
->nm_fsattr
, &nvattr
, NULL
, NULL
); 
 440         lck_mtx_unlock(&nmp
->nm_lock
); 
 442         if ((lockerror 
= nfs_lock(np
, NFS_NODE_LOCK_EXCLUSIVE
))) 
 445                 nfs_loadattrcache(np
, &nvattr
, &xid
, 0); 
 448         nfsm_assert(error
, NFSTONMP(np
), ENXIO
); 
 450         nmp
->nm_fsattr
.nfsa_bsize 
= NFS_FABLKSIZE
; 
 452         nfsm_chain_cleanup(&nmreq
); 
 453         nfsm_chain_cleanup(&nmrep
); 
 454         vnode_put(NFSTOV(np
)); 
 460  * The NFS VFS_GETATTR function: "statfs"-type information is retrieved 
 461  * using the nf_update_statfs() function, and other attributes are cobbled 
 462  * together from whatever sources we can (getattr, fsinfo, pathconf). 
 465 nfs_vfs_getattr(mount_t mp
, struct vfs_attr 
*fsap
, vfs_context_t ctx
) 
 467         struct nfsmount 
*nmp
; 
 469         int error 
= 0, nfsvers
; 
 471         if (!(nmp 
= VFSTONFS(mp
))) 
 473         nfsvers 
= nmp
->nm_vers
; 
 475         if (VFSATTR_IS_ACTIVE(fsap
, f_bsize
)  || 
 476             VFSATTR_IS_ACTIVE(fsap
, f_iosize
) || 
 477             VFSATTR_IS_ACTIVE(fsap
, f_blocks
) || 
 478             VFSATTR_IS_ACTIVE(fsap
, f_bfree
)  || 
 479             VFSATTR_IS_ACTIVE(fsap
, f_bavail
) || 
 480             VFSATTR_IS_ACTIVE(fsap
, f_bused
)  || 
 481             VFSATTR_IS_ACTIVE(fsap
, f_files
)  || 
 482             VFSATTR_IS_ACTIVE(fsap
, f_ffree
)) { 
 483                 int statfsrate 
= nfs_statfs_rate_limit
; 
 487                  * Are we rate-limiting statfs RPCs? 
 488                  * (Treat values less than 1 or greater than 1,000,000 as no limit.) 
 490                 if ((statfsrate 
> 0) && (statfsrate 
< 1000000)) { 
 495                         lck_mtx_lock(&nmp
->nm_lock
); 
 496                         stamp 
= (now
.tv_sec 
* statfsrate
) + (now
.tv_usec 
/ (1000000/statfsrate
)); 
 497                         if (stamp 
!= nmp
->nm_fsattrstamp
) { 
 499                                 nmp
->nm_fsattrstamp 
= stamp
; 
 503                         lck_mtx_unlock(&nmp
->nm_lock
); 
 507                         error 
= nmp
->nm_funcs
->nf_update_statfs(nmp
, ctx
); 
 508                 if ((error 
== ESTALE
) || (error 
== ETIMEDOUT
)) 
 513                 lck_mtx_lock(&nmp
->nm_lock
); 
 514                 VFSATTR_RETURN(fsap
, f_iosize
, nfs_iosize
); 
 515                 VFSATTR_RETURN(fsap
, f_bsize
, nmp
->nm_fsattr
.nfsa_bsize
); 
 516                 bsize 
= nmp
->nm_fsattr
.nfsa_bsize
; 
 517                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SPACE_TOTAL
)) 
 518                         VFSATTR_RETURN(fsap
, f_blocks
, nmp
->nm_fsattr
.nfsa_space_total 
/ bsize
); 
 519                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SPACE_FREE
)) 
 520                         VFSATTR_RETURN(fsap
, f_bfree
, nmp
->nm_fsattr
.nfsa_space_free 
/ bsize
); 
 521                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SPACE_AVAIL
)) 
 522                         VFSATTR_RETURN(fsap
, f_bavail
, nmp
->nm_fsattr
.nfsa_space_avail 
/ bsize
); 
 523                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SPACE_TOTAL
) && 
 524                     NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SPACE_FREE
)) 
 525                         VFSATTR_RETURN(fsap
, f_bused
, 
 526                                 (nmp
->nm_fsattr
.nfsa_space_total 
/ bsize
) - 
 527                                 (nmp
->nm_fsattr
.nfsa_space_free 
/ bsize
)); 
 528                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_FILES_TOTAL
)) 
 529                         VFSATTR_RETURN(fsap
, f_files
, nmp
->nm_fsattr
.nfsa_files_total
); 
 530                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_FILES_FREE
)) 
 531                         VFSATTR_RETURN(fsap
, f_ffree
, nmp
->nm_fsattr
.nfsa_files_free
); 
 532                 lck_mtx_unlock(&nmp
->nm_lock
); 
 535         if (VFSATTR_IS_ACTIVE(fsap
, f_capabilities
)) { 
 536                 u_int32_t caps
, valid
; 
 539                 nfsm_assert(error
, VFSTONFS(mp
), ENXIO
); 
 543                 lck_mtx_lock(&nmp
->nm_lock
); 
 546                  * The capabilities[] array defines what this volume supports. 
 548                  * The valid[] array defines which bits this code understands 
 549                  * the meaning of (whether the volume has that capability or not). 
 550                  * Any zero bits here means "I don't know what you're asking about" 
 551                  * and the caller cannot tell whether that capability is 
 555                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SYMLINK_SUPPORT
)) { 
 556                         valid 
|= VOL_CAP_FMT_SYMBOLICLINKS
; 
 557                         if (nmp
->nm_fsattr
.nfsa_flags 
& NFS_FSFLAG_SYMLINK
) 
 558                                 caps 
|= VOL_CAP_FMT_SYMBOLICLINKS
; 
 560                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_LINK_SUPPORT
)) { 
 561                         valid 
|= VOL_CAP_FMT_HARDLINKS
; 
 562                         if (nmp
->nm_fsattr
.nfsa_flags 
& NFS_FSFLAG_LINK
) 
 563                                 caps 
|= VOL_CAP_FMT_HARDLINKS
; 
 565                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_CASE_INSENSITIVE
)) { 
 566                         valid 
|= VOL_CAP_FMT_CASE_SENSITIVE
; 
 567                         if (!(nmp
->nm_fsattr
.nfsa_flags 
& NFS_FSFLAG_CASE_INSENSITIVE
)) 
 568                                 caps 
|= VOL_CAP_FMT_CASE_SENSITIVE
; 
 570                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_CASE_PRESERVING
)) { 
 571                         valid 
|= VOL_CAP_FMT_CASE_PRESERVING
; 
 572                         if (nmp
->nm_fsattr
.nfsa_flags 
& NFS_FSFLAG_CASE_PRESERVING
) 
 573                                 caps 
|= VOL_CAP_FMT_CASE_PRESERVING
; 
 575                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_MAXFILESIZE
)) { 
 576                         /* Is server's max file size at least 2TB? */ 
 577                         if (nmp
->nm_fsattr
.nfsa_maxfilesize 
>= 0x20000000000ULL
) 
 578                                 caps 
|= VOL_CAP_FMT_2TB_FILESIZE
; 
 579                 } else if (nfsvers 
>= NFS_VER3
) { 
 581                          * NFSv3 and up supports 64 bits of file size. 
 582                          * So, we'll just assume maxfilesize >= 2TB 
 584                         caps 
|= VOL_CAP_FMT_2TB_FILESIZE
; 
 586                 if (nfsvers 
>= NFS_VER4
) { 
 587                         caps 
|= VOL_CAP_FMT_HIDDEN_FILES
; 
 588                         valid 
|= VOL_CAP_FMT_HIDDEN_FILES
; 
 589                         // VOL_CAP_FMT_OPENDENYMODES 
 591                 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_FORMAT
] = 
 592                         // VOL_CAP_FMT_PERSISTENTOBJECTIDS | 
 593                         // VOL_CAP_FMT_SYMBOLICLINKS | 
 594                         // VOL_CAP_FMT_HARDLINKS | 
 595                         // VOL_CAP_FMT_JOURNAL | 
 596                         // VOL_CAP_FMT_JOURNAL_ACTIVE | 
 597                         // VOL_CAP_FMT_NO_ROOT_TIMES | 
 598                         // VOL_CAP_FMT_SPARSE_FILES | 
 599                         // VOL_CAP_FMT_ZERO_RUNS | 
 600                         // VOL_CAP_FMT_CASE_SENSITIVE | 
 601                         // VOL_CAP_FMT_CASE_PRESERVING | 
 602                         // VOL_CAP_FMT_FAST_STATFS | 
 603                         // VOL_CAP_FMT_2TB_FILESIZE | 
 604                         // VOL_CAP_FMT_OPENDENYMODES | 
 605                         // VOL_CAP_FMT_HIDDEN_FILES | 
 607                 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_FORMAT
] = 
 608                         VOL_CAP_FMT_PERSISTENTOBJECTIDS 
| 
 609                         // VOL_CAP_FMT_SYMBOLICLINKS | 
 610                         // VOL_CAP_FMT_HARDLINKS | 
 611                         // VOL_CAP_FMT_JOURNAL | 
 612                         // VOL_CAP_FMT_JOURNAL_ACTIVE | 
 613                         // VOL_CAP_FMT_NO_ROOT_TIMES | 
 614                         // VOL_CAP_FMT_SPARSE_FILES | 
 615                         // VOL_CAP_FMT_ZERO_RUNS | 
 616                         // VOL_CAP_FMT_CASE_SENSITIVE | 
 617                         // VOL_CAP_FMT_CASE_PRESERVING | 
 618                         VOL_CAP_FMT_FAST_STATFS 
| 
 619                         VOL_CAP_FMT_2TB_FILESIZE 
| 
 620                         // VOL_CAP_FMT_OPENDENYMODES | 
 621                         // VOL_CAP_FMT_HIDDEN_FILES | 
 625                  * We don't support most of the interfaces. 
 627                  * We MAY support locking, but we don't have any easy way of probing. 
 628                  * We can tell if there's no lockd running or if locks have been 
 629                  * disabled for a mount, so we can definitely answer NO in that case. 
 630                  * Any attempt to send a request to lockd to test for locking support 
 631                  * may cause the lazily-launched locking daemons to be started 
 632                  * unnecessarily.  So we avoid that.  However, we do record if we ever 
 633                  * successfully perform a lock operation on a mount point, so if it 
 634                  * looks like lock ops have worked, we do report that we support them. 
 637                 if (nfsvers 
>= NFS_VER4
) { 
 638                         caps 
= VOL_CAP_INT_ADVLOCK 
| VOL_CAP_INT_FLOCK
; 
 639                         valid 
= VOL_CAP_INT_ADVLOCK 
| VOL_CAP_INT_FLOCK
; 
 640                         // VOL_CAP_INT_EXTENDED_SECURITY 
 641                         // VOL_CAP_INT_NAMEDSTREAMS 
 642                         // VOL_CAP_INT_EXTENDED_ATTR 
 643                 } else if ((nmp
->nm_flag 
& NFSMNT_NOLOCKS
)) { 
 644                         /* locks disabled on this mount, so they definitely won't work */ 
 645                         valid 
= VOL_CAP_INT_ADVLOCK 
| VOL_CAP_INT_FLOCK
; 
 646                 } else if (nmp
->nm_state 
& NFSSTA_LOCKSWORK
) { 
 647                         caps 
= VOL_CAP_INT_ADVLOCK 
| VOL_CAP_INT_FLOCK
; 
 648                         valid 
= VOL_CAP_INT_ADVLOCK 
| VOL_CAP_INT_FLOCK
; 
 650                 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_INTERFACES
] = 
 651                         // VOL_CAP_INT_SEARCHFS | 
 652                         // VOL_CAP_INT_ATTRLIST | 
 653                         // VOL_CAP_INT_NFSEXPORT | 
 654                         // VOL_CAP_INT_READDIRATTR | 
 655                         // VOL_CAP_INT_EXCHANGEDATA | 
 656                         // VOL_CAP_INT_COPYFILE | 
 657                         // VOL_CAP_INT_ALLOCATE | 
 658                         // VOL_CAP_INT_VOL_RENAME | 
 659                         // VOL_CAP_INT_ADVLOCK | 
 660                         // VOL_CAP_INT_FLOCK | 
 661                         // VOL_CAP_INT_EXTENDED_SECURITY | 
 662                         // VOL_CAP_INT_USERACCESS | 
 663                         // VOL_CAP_INT_MANLOCK | 
 664                         // VOL_CAP_INT_NAMEDSTREAMS | 
 665                         // VOL_CAP_INT_EXTENDED_ATTR | 
 667                 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_INTERFACES
] = 
 668                         VOL_CAP_INT_SEARCHFS 
| 
 669                         VOL_CAP_INT_ATTRLIST 
| 
 670                         VOL_CAP_INT_NFSEXPORT 
| 
 671                         VOL_CAP_INT_READDIRATTR 
| 
 672                         VOL_CAP_INT_EXCHANGEDATA 
| 
 673                         VOL_CAP_INT_COPYFILE 
| 
 674                         VOL_CAP_INT_ALLOCATE 
| 
 675                         VOL_CAP_INT_VOL_RENAME 
| 
 676                         // VOL_CAP_INT_ADVLOCK | 
 677                         // VOL_CAP_INT_FLOCK | 
 678                         // VOL_CAP_INT_EXTENDED_SECURITY | 
 679                         // VOL_CAP_INT_USERACCESS | 
 680                         // VOL_CAP_INT_MANLOCK | 
 681                         // VOL_CAP_INT_NAMEDSTREAMS | 
 682                         // VOL_CAP_INT_EXTENDED_ATTR | 
 685                 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_RESERVED1
] = 0; 
 686                 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_RESERVED1
] = 0; 
 688                 fsap
->f_capabilities
.capabilities
[VOL_CAPABILITIES_RESERVED2
] = 0; 
 689                 fsap
->f_capabilities
.valid
[VOL_CAPABILITIES_RESERVED2
] = 0; 
 691                 VFSATTR_SET_SUPPORTED(fsap
, f_capabilities
); 
 692                 lck_mtx_unlock(&nmp
->nm_lock
); 
 695         if (VFSATTR_IS_ACTIVE(fsap
, f_attributes
)) { 
 696                 fsap
->f_attributes
.validattr
.commonattr 
= 0; 
 697                 fsap
->f_attributes
.validattr
.volattr 
= 
 698                         ATTR_VOL_CAPABILITIES 
| ATTR_VOL_ATTRIBUTES
; 
 699                 fsap
->f_attributes
.validattr
.dirattr 
= 0; 
 700                 fsap
->f_attributes
.validattr
.fileattr 
= 0; 
 701                 fsap
->f_attributes
.validattr
.forkattr 
= 0; 
 703                 fsap
->f_attributes
.nativeattr
.commonattr 
= 0; 
 704                 fsap
->f_attributes
.nativeattr
.volattr 
= 
 705                         ATTR_VOL_CAPABILITIES 
| ATTR_VOL_ATTRIBUTES
; 
 706                 fsap
->f_attributes
.nativeattr
.dirattr 
= 0; 
 707                 fsap
->f_attributes
.nativeattr
.fileattr 
= 0; 
 708                 fsap
->f_attributes
.nativeattr
.forkattr 
= 0; 
 710                 VFSATTR_SET_SUPPORTED(fsap
, f_attributes
); 
 717  * nfs version 3 fsinfo rpc call 
 720 nfs3_fsinfo(struct nfsmount 
*nmp
, nfsnode_t np
, vfs_context_t ctx
) 
 722         int error 
= 0, lockerror
, status
, prefsize
, maxsize
, nmlocked 
= 0; 
 725         struct nfsm_chain nmreq
, nmrep
; 
 727         nfsm_chain_null(&nmreq
); 
 728         nfsm_chain_null(&nmrep
); 
 730         nfsm_chain_build_alloc_init(error
, &nmreq
, NFSX_FH(nmp
->nm_vers
)); 
 731         nfsm_chain_add_fh(error
, &nmreq
, nmp
->nm_vers
, np
->n_fhp
, np
->n_fhsize
); 
 732         nfsm_chain_build_done(error
, &nmreq
); 
 734         error 
= nfs_request(np
, NULL
, &nmreq
, NFSPROC_FSINFO
, ctx
, 
 735                         &nmrep
, &xid
, &status
); 
 736         if ((lockerror 
= nfs_lock(np
, NFS_NODE_LOCK_EXCLUSIVE
))) 
 738         nfsm_chain_postop_attr_update(error
, &nmrep
, np
, &xid
); 
 745         lck_mtx_lock(&nmp
->nm_lock
); 
 748         nfsm_chain_get_32(error
, &nmrep
, maxsize
); 
 749         nfsm_chain_get_32(error
, &nmrep
, prefsize
); 
 751         nmp
->nm_fsattr
.nfsa_maxread 
= maxsize
; 
 752         if (prefsize 
< nmp
->nm_rsize
) 
 753                 nmp
->nm_rsize 
= (prefsize 
+ NFS_FABLKSIZE 
- 1) & 
 754                         ~(NFS_FABLKSIZE 
- 1); 
 755         if (maxsize 
< nmp
->nm_rsize
) { 
 756                 nmp
->nm_rsize 
= maxsize 
& ~(NFS_FABLKSIZE 
- 1); 
 757                 if (nmp
->nm_rsize 
== 0) 
 758                         nmp
->nm_rsize 
= maxsize
; 
 760         nfsm_chain_adv(error
, &nmrep
, NFSX_UNSIGNED
); // skip rtmult 
 762         nfsm_chain_get_32(error
, &nmrep
, maxsize
); 
 763         nfsm_chain_get_32(error
, &nmrep
, prefsize
); 
 765         nmp
->nm_fsattr
.nfsa_maxwrite 
= maxsize
; 
 766         if (prefsize 
< nmp
->nm_wsize
) 
 767                 nmp
->nm_wsize 
= (prefsize 
+ NFS_FABLKSIZE 
- 1) & 
 768                         ~(NFS_FABLKSIZE 
- 1); 
 769         if (maxsize 
< nmp
->nm_wsize
) { 
 770                 nmp
->nm_wsize 
= maxsize 
& ~(NFS_FABLKSIZE 
- 1); 
 771                 if (nmp
->nm_wsize 
== 0) 
 772                         nmp
->nm_wsize 
= maxsize
; 
 774         nfsm_chain_adv(error
, &nmrep
, NFSX_UNSIGNED
); // skip wtmult 
 776         nfsm_chain_get_32(error
, &nmrep
, prefsize
); 
 778         if (prefsize 
< nmp
->nm_readdirsize
) 
 779                 nmp
->nm_readdirsize 
= prefsize
; 
 780         if (maxsize 
< nmp
->nm_readdirsize
) 
 781                 nmp
->nm_readdirsize 
= maxsize
; 
 783         nfsm_chain_get_64(error
, &nmrep
, maxsize
); 
 784         nmp
->nm_fsattr
.nfsa_maxfilesize 
= maxsize
; 
 786         nfsm_chain_adv(error
, &nmrep
, 2 * NFSX_UNSIGNED
); // skip time_delta 
 788         /* convert FS properties to our own flags */ 
 789         nfsm_chain_get_32(error
, &nmrep
, val
); 
 791         if (val 
& NFSV3FSINFO_LINK
) 
 792                 nmp
->nm_fsattr
.nfsa_flags 
|= NFS_FSFLAG_LINK
; 
 793         if (val 
& NFSV3FSINFO_SYMLINK
) 
 794                 nmp
->nm_fsattr
.nfsa_flags 
|= NFS_FSFLAG_SYMLINK
; 
 795         if (val 
& NFSV3FSINFO_HOMOGENEOUS
) 
 796                 nmp
->nm_fsattr
.nfsa_flags 
|= NFS_FSFLAG_HOMOGENEOUS
; 
 797         if (val 
& NFSV3FSINFO_CANSETTIME
) 
 798                 nmp
->nm_fsattr
.nfsa_flags 
|= NFS_FSFLAG_SET_TIME
; 
 799         nmp
->nm_state 
|= NFSSTA_GOTFSINFO
; 
 800         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_MAXREAD
); 
 801         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_MAXWRITE
); 
 802         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_MAXFILESIZE
); 
 803         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_LINK_SUPPORT
); 
 804         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_SYMLINK_SUPPORT
); 
 805         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_HOMOGENEOUS
); 
 806         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_CANSETTIME
); 
 809                 lck_mtx_unlock(&nmp
->nm_lock
); 
 810         nfsm_chain_cleanup(&nmreq
); 
 811         nfsm_chain_cleanup(&nmrep
); 
 816  * Mount a remote root fs via. nfs. This depends on the info in the 
 817  * nfs_diskless structure that has been filled in properly by some primary 
 819  * It goes something like this: 
 820  * - do enough of "ifconfig" by calling ifioctl() so that the system 
 821  *   can talk to the server 
 822  * - If nfs_diskless.mygateway is filled in, use that address as 
 824  * - hand craft the swap nfs vnode hanging off a fake mount point 
 825  *      if swdevt[0].sw_dev == NODEV 
 826  * - build the rootfs mount point and call mountnfs() to do the rest. 
 831         struct nfs_diskless nd
; 
 832         struct nfs_vattr nvattr
; 
 837 #if !defined(NO_MOUNT_PRIVATE) 
 838         mount_t mppriv 
= NULL
; 
 839         vnode_t vppriv 
= NULL
; 
 840 #endif /* NO_MOUNT_PRIVATE */ 
 844          * Call nfs_boot_init() to fill in the nfs_diskless struct. 
 845          * Note: networking must already have been configured before 
 848         bzero((caddr_t
) &nd
, sizeof(nd
)); 
 849         error 
= nfs_boot_init(&nd
); 
 851                 panic("nfs_boot_init failed with %d\n", error
); 
 855          * Try NFSv3 first, then fallback to NFSv2. 
 856          * Likewise, try TCP first, then fall back to UDP. 
 859         sotype 
= SOCK_STREAM
; 
 862         error 
= nfs_boot_getfh(&nd
, v3
, sotype
); 
 864                 if (error 
== EHOSTDOWN 
|| error 
== EHOSTUNREACH
) { 
 865                         if (nd
.nd_root
.ndm_path
) 
 866                                 FREE_ZONE(nd
.nd_root
.ndm_path
, 
 867                                           MAXPATHLEN
, M_NAMEI
); 
 868                         if (nd
.nd_private
.ndm_path
) 
 869                                 FREE_ZONE(nd
.nd_private
.ndm_path
, 
 870                                           MAXPATHLEN
, M_NAMEI
); 
 874                         if (sotype 
== SOCK_STREAM
) { 
 875                                 printf("nfs_boot_getfh(v3,TCP) failed with %d, trying UDP...\n", error
); 
 879                         printf("nfs_boot_getfh(v3,UDP) failed with %d, trying v2...\n", error
); 
 881                         sotype 
= SOCK_STREAM
; 
 883                 } else if (sotype 
== SOCK_STREAM
) { 
 884                         printf("nfs_boot_getfh(v2,TCP) failed with %d, trying UDP...\n", error
); 
 890                         panic("nfs_boot_getfh(v2,UDP) failed: NFS server mountd not responding - check server configuration: %s", PE_boot_args()); 
 893                         panic("nfs_boot_getfh(v2,UDP) failed: NFS server refused mount - check server configuration: %s", PE_boot_args()); 
 895                         panic("nfs_boot_getfh(v2,UDP) failed with %d: %s", error
, PE_boot_args()); 
 899         ctx 
= vfs_context_kernel(); 
 902          * Create the root mount point. 
 904 #if !defined(NO_MOUNT_PRIVATE) 
 906                 //PWC hack until we have a real "mount" tool to remount root rw 
 908                 int flags 
= MNT_ROOTFS
|MNT_RDONLY
; 
 909                 PE_parse_boot_arg("-rwroot_hack", &rw_root
); 
 913                         kprintf("-rwroot_hack in effect: mounting root fs read/write\n"); 
 916         if ((error 
= nfs_mount_diskless(&nd
.nd_root
, "/", flags
, &vp
, &mp
, ctx
))) 
 918         if ((error 
= nfs_mount_diskless(&nd
.nd_root
, "/", MNT_ROOTFS
, &vp
, &mp
, ctx
))) 
 919 #endif /* NO_MOUNT_PRIVATE */ 
 922                         if (sotype 
== SOCK_STREAM
) { 
 923                                 printf("nfs_mount_diskless(v3,TCP) failed with %d, trying UDP...\n", error
); 
 927                         printf("nfs_mount_diskless(v3,UDP) failed with %d, trying v2...\n", error
); 
 929                         sotype 
= SOCK_STREAM
; 
 931                 } else if (sotype 
== SOCK_STREAM
) { 
 932                         printf("nfs_mount_diskless(v2,TCP) failed with %d, trying UDP...\n", error
); 
 936                 panic("nfs_mount_diskless(v2,UDP) root failed with %d: %s\n", error
, PE_boot_args()); 
 939         printf("root on %s\n", (char *)&nd
.nd_root
.ndm_host
); 
 945 #if !defined(NO_MOUNT_PRIVATE) 
 946         if (nd
.nd_private
.ndm_saddr
.sin_addr
.s_addr
) { 
 947             error 
= nfs_mount_diskless_private(&nd
.nd_private
, "/private", 
 948                                                0, &vppriv
, &mppriv
, ctx
); 
 950                 panic("nfs_mount_diskless private failed with %d\n", error
); 
 952             printf("private on %s\n", (char *)&nd
.nd_private
.ndm_host
); 
 955             mount_list_add(mppriv
); 
 958 #endif /* NO_MOUNT_PRIVATE */ 
 960         if (nd
.nd_root
.ndm_path
) 
 961                 FREE_ZONE(nd
.nd_root
.ndm_path
, MAXPATHLEN
, M_NAMEI
); 
 962         if (nd
.nd_private
.ndm_path
) 
 963                 FREE_ZONE(nd
.nd_private
.ndm_path
, MAXPATHLEN
, M_NAMEI
); 
 965         /* Get root attributes (for the time). */ 
 966         error 
= nfs_getattr(VTONFS(vp
), &nvattr
, ctx
, 0); 
 967         if (error
) panic("nfs_mountroot: getattr for root"); 
 972  * Internal version of mount system call for diskless setup. 
 976         struct nfs_dlmount 
*ndmntp
, 
 983         struct user_nfs_args args
; 
 988         if ((error 
= vfs_rootmountalloc("nfs", ndmntp
->ndm_host
, &mp
))) { 
 989                 printf("nfs_mount_diskless: NFS not configured"); 
 993         mp
->mnt_flag 
|= mntflag
; 
 994         if (!(mntflag 
& MNT_RDONLY
)) 
 995                 mp
->mnt_flag 
&= ~MNT_RDONLY
; 
 997         /* Initialize mount args. */ 
 998         bzero((caddr_t
) &args
, sizeof(args
)); 
 999         args
.addr     
= CAST_USER_ADDR_T(&ndmntp
->ndm_saddr
); 
1000         args
.addrlen  
= ndmntp
->ndm_saddr
.sin_len
; 
1001         args
.sotype   
= ndmntp
->ndm_sotype
; 
1002         args
.fh       
= CAST_USER_ADDR_T(&ndmntp
->ndm_fh
[0]); 
1003         args
.fhsize   
= ndmntp
->ndm_fhlen
; 
1004         args
.hostname 
= CAST_USER_ADDR_T(ndmntp
->ndm_host
); 
1005         args
.flags    
= NFSMNT_RESVPORT
; 
1006         if (ndmntp
->ndm_nfsv3
) 
1007                 args
.flags 
|= NFSMNT_NFSV3
; 
1009         error 
= mbuf_get(MBUF_WAITOK
, MBUF_TYPE_SONAME
, &m
); 
1011                 printf("nfs_mount_diskless: mbuf_get(soname) failed"); 
1014         mbuf_setlen(m
, ndmntp
->ndm_saddr
.sin_len
); 
1015         bcopy(&ndmntp
->ndm_saddr
, mbuf_data(m
), ndmntp
->ndm_saddr
.sin_len
); 
1016         if ((error 
= mountnfs(&args
, mp
, m
, ctx
, vpp
))) { 
1017                 printf("nfs_mountroot: mount %s failed: %d\n", mntname
, error
); 
1018                 // XXX vfs_rootmountfailed(mp); 
1020                 mp
->mnt_vtable
->vfc_refcount
--; 
1021                 mount_list_unlock(); 
1023                 mount_lock_destroy(mp
); 
1025                 mac_mount_label_destroy(mp
); 
1027                 FREE_ZONE(mp
, sizeof(struct mount
), M_MOUNT
); 
1034 #if !defined(NO_MOUNT_PRIVATE) 
1036  * Internal version of mount system call to mount "/private" 
1037  * separately in diskless setup 
1040 nfs_mount_diskless_private( 
1041         struct nfs_dlmount 
*ndmntp
, 
1042         const char *mntname
, 
1048         struct user_nfs_args args
; 
1053         struct vfstable 
*vfsp
; 
1054         struct nameidata nd
; 
1057         procp 
= current_proc(); /* XXX */ 
1061          * mimic main()!. Temporarily set up rootvnode and other stuff so 
1062          * that namei works. Need to undo this because main() does it, too 
1064                 struct filedesc 
*fdp
;   /* pointer to file descriptor state */ 
1066                 mountlist
.tqh_first
->mnt_flag 
|= MNT_ROOTFS
; 
1068                 /* Get the vnode for '/'. Set fdp->fd_cdir to reference it. */ 
1069                 if (VFS_ROOT(mountlist
.tqh_first
, &rootvnode
, NULL
)) 
1070                         panic("cannot find root vnode"); 
1071                 error 
= vnode_ref(rootvnode
); 
1073                         printf("nfs_mountroot: vnode_ref() failed on root vnode!\n"); 
1076                 fdp
->fd_cdir 
= rootvnode
; 
1077                 fdp
->fd_rdir 
= NULL
; 
1081          * Get vnode to be covered 
1083         NDINIT(&nd
, LOOKUP
, FOLLOW 
| LOCKLEAF
, UIO_SYSSPACE32
, 
1084             CAST_USER_ADDR_T(mntname
), ctx
); 
1085         if ((error 
= namei(&nd
))) { 
1086                 printf("nfs_mountroot: private namei failed!\n"); 
1090                 /* undo vnode_ref() in mimic main()! */ 
1091                 vnode_rele(rootvnode
); 
1096         if ((error 
= VNOP_FSYNC(vp
, MNT_WAIT
, ctx
)) || 
1097             (error 
= buf_invalidateblks(vp
, BUF_WRITE_DATA
, 0, 0))) { 
1101         if (vnode_vtype(vp
) != VDIR
) { 
1106         for (vfsp 
= vfsconf
; vfsp
; vfsp 
= vfsp
->vfc_next
) 
1107                 if (!strncmp(vfsp
->vfc_name
, "nfs", sizeof(vfsp
->vfc_name
))) 
1110                 printf("nfs_mountroot: private NFS not configured\n"); 
1115         if (vnode_mountedhere(vp
) != NULL
) { 
1122          * Allocate and initialize the filesystem. 
1124         mp 
= _MALLOC_ZONE((u_long
)sizeof(struct mount
), M_MOUNT
, M_WAITOK
); 
1126                 printf("nfs_mountroot: unable to allocate mount structure\n"); 
1131         bzero((char *)mp
, (u_long
)sizeof(struct mount
)); 
1133         /* Initialize the default IO constraints */ 
1134         mp
->mnt_maxreadcnt 
= mp
->mnt_maxwritecnt 
= MAXPHYS
; 
1135         mp
->mnt_segreadcnt 
= mp
->mnt_segwritecnt 
= 32; 
1136         mp
->mnt_ioflags 
= 0; 
1137         mp
->mnt_realrootvp 
= NULLVP
; 
1138         mp
->mnt_authcache_ttl 
= CACHED_LOOKUP_RIGHT_TTL
; 
1140         mount_lock_init(mp
); 
1141         TAILQ_INIT(&mp
->mnt_vnodelist
); 
1142         TAILQ_INIT(&mp
->mnt_workerqueue
); 
1143         TAILQ_INIT(&mp
->mnt_newvnodes
); 
1144         (void)vfs_busy(mp
, LK_NOWAIT
); 
1145         TAILQ_INIT(&mp
->mnt_vnodelist
); 
1147         vfsp
->vfc_refcount
++; 
1148         mount_list_unlock(); 
1149         mp
->mnt_vtable 
= vfsp
; 
1150         mp
->mnt_op 
= vfsp
->vfc_vfsops
; 
1151         // mp->mnt_stat.f_type = vfsp->vfc_typenum; 
1152         mp
->mnt_flag 
= mntflag
; 
1153         mp
->mnt_flag 
|= vfsp
->vfc_flags 
& MNT_VISFLAGMASK
; 
1154         strncpy(mp
->mnt_vfsstat
.f_fstypename
, vfsp
->vfc_name
, MFSNAMELEN
-1); 
1155         vp
->v_mountedhere 
= mp
; 
1156         mp
->mnt_vnodecovered 
= vp
; 
1157         mp
->mnt_vfsstat
.f_owner 
= kauth_cred_getuid(kauth_cred_get()); 
1158         (void) copystr(mntname
, mp
->mnt_vfsstat
.f_mntonname
, MNAMELEN 
- 1, 0); 
1159         (void) copystr(ndmntp
->ndm_host
, mp
->mnt_vfsstat
.f_mntfromname
, MNAMELEN 
- 1, 0); 
1161         mac_mount_label_init(mp
); 
1162         mac_mount_label_associate(ctx
, mp
); 
1165         /* Initialize mount args. */ 
1166         bzero((caddr_t
) &args
, sizeof(args
)); 
1167         args
.addr     
= CAST_USER_ADDR_T(&ndmntp
->ndm_saddr
); 
1168         args
.addrlen  
= ndmntp
->ndm_saddr
.sin_len
; 
1169         args
.sotype   
= ndmntp
->ndm_sotype
; 
1170         args
.fh       
= CAST_USER_ADDR_T(ndmntp
->ndm_fh
); 
1171         args
.fhsize   
= ndmntp
->ndm_fhlen
; 
1172         args
.hostname 
= CAST_USER_ADDR_T(ndmntp
->ndm_host
); 
1173         args
.flags    
= NFSMNT_RESVPORT
; 
1174         if (ndmntp
->ndm_nfsv3
) 
1175                 args
.flags 
|= NFSMNT_NFSV3
; 
1177         error 
= mbuf_get(MBUF_WAITOK
, MBUF_TYPE_SONAME
, &m
); 
1179                 printf("nfs_mount_diskless_private: mbuf_get(soname) failed"); 
1182         mbuf_setlen(m
, ndmntp
->ndm_saddr
.sin_len
); 
1183         bcopy(&ndmntp
->ndm_saddr
, mbuf_data(m
), ndmntp
->ndm_saddr
.sin_len
); 
1184         if ((error 
= mountnfs(&args
, mp
, m
, ctx
, &vp
))) { 
1185                 printf("nfs_mountroot: mount %s failed: %d\n", mntname
, error
); 
1187                 vfsp
->vfc_refcount
--; 
1188                 mount_list_unlock(); 
1190                 mount_lock_destroy(mp
); 
1192                 mac_mount_label_destroy(mp
); 
1194                 FREE_ZONE(mp
, sizeof (struct mount
), M_MOUNT
); 
1203 #endif /* NO_MOUNT_PRIVATE */ 
1211 nfs_vfs_mount(mount_t mp
, vnode_t vp
, user_addr_t data
, vfs_context_t ctx
) 
1213         int error
, argsvers
; 
1214         struct user_nfs_args args
; 
1215         struct nfs_args tempargs
; 
1218         u_char nfh
[NFSX_V3FHMAX
]; 
1221         error 
= copyin(data
, (caddr_t
)&argsvers
, sizeof (argsvers
)); 
1227                 if (vfs_context_is64bit(ctx
)) 
1228                         error 
= copyin(data
, (caddr_t
)&args
, sizeof (struct user_nfs_args3
)); 
1230                         error 
= copyin(data
, (caddr_t
)&tempargs
, sizeof (struct nfs_args3
)); 
1233                 if (vfs_context_is64bit(ctx
)) 
1234                         error 
= copyin(data
, (caddr_t
)&args
, sizeof (struct user_nfs_args4
)); 
1236                         error 
= copyin(data
, (caddr_t
)&tempargs
, sizeof (struct nfs_args4
)); 
1239                 if (vfs_context_is64bit(ctx
)) 
1240                         error 
= copyin(data
, (caddr_t
)&args
, sizeof (args
)); 
1242                         error 
= copyin(data
, (caddr_t
)&tempargs
, sizeof (tempargs
)); 
1245                 return (EPROGMISMATCH
); 
1250         if (!vfs_context_is64bit(ctx
)) { 
1251                 args
.version 
= tempargs
.version
; 
1252                 args
.addrlen 
= tempargs
.addrlen
; 
1253                 args
.sotype 
= tempargs
.sotype
; 
1254                 args
.proto 
= tempargs
.proto
; 
1255                 args
.fhsize 
= tempargs
.fhsize
; 
1256                 args
.flags 
= tempargs
.flags
; 
1257                 args
.wsize 
= tempargs
.wsize
; 
1258                 args
.rsize 
= tempargs
.rsize
; 
1259                 args
.readdirsize 
= tempargs
.readdirsize
; 
1260                 args
.timeo 
= tempargs
.timeo
; 
1261                 args
.retrans 
= tempargs
.retrans
; 
1262                 args
.maxgrouplist 
= tempargs
.maxgrouplist
; 
1263                 args
.readahead 
= tempargs
.readahead
; 
1264                 args
.leaseterm 
= tempargs
.leaseterm
; 
1265                 args
.deadthresh 
= tempargs
.deadthresh
; 
1266                 args
.addr 
= CAST_USER_ADDR_T(tempargs
.addr
); 
1267                 args
.fh 
= CAST_USER_ADDR_T(tempargs
.fh
); 
1268                 args
.hostname 
= CAST_USER_ADDR_T(tempargs
.hostname
); 
1269                 if (argsvers 
>= 4) { 
1270                         args
.acregmin 
= tempargs
.acregmin
; 
1271                         args
.acregmax 
= tempargs
.acregmax
; 
1272                         args
.acdirmin 
= tempargs
.acdirmin
; 
1273                         args
.acdirmax 
= tempargs
.acdirmax
; 
1276                         args
.auth 
= tempargs
.auth
; 
1279         if (args
.fhsize 
< 0 || args
.fhsize 
> NFSX_V3FHMAX
) 
1281         if (args
.fhsize 
> 0) { 
1282                 error 
= copyin(args
.fh
, (caddr_t
)nfh
, args
.fhsize
); 
1287         mntfrom 
= &vfs_statfs(mp
)->f_mntfromname
[0]; 
1288         error 
= copyinstr(args
.hostname
, mntfrom
, MAXPATHLEN
-1, &len
); 
1291         bzero(&mntfrom
[len
], MAXPATHLEN 
- len
); 
1293         /* sockargs() call must be after above copyin() calls */ 
1294         error 
= sockargs(&nam
, args
.addr
, args
.addrlen
, MBUF_TYPE_SONAME
); 
1298         args
.fh 
= CAST_USER_ADDR_T(&nfh
[0]); 
1299         error 
= mountnfs(&args
, mp
, nam
, ctx
, &vp
); 
1304  * Common code for mount and mountroot 
1309         struct nfsmount 
*nmp
, 
1311         struct user_nfs_args 
*argp
, 
1315         struct nfs_vattr nvattr
; 
1322          * Get file attributes for the mountpoint.  These are needed 
1323          * in order to properly create the root vnode. 
1325         // LP64todo - fix CAST_DOWN of argp->fh 
1326         fhp 
= CAST_DOWN(u_char 
*, argp
->fh
); 
1327         error 
= nfs3_getattr_rpc(NULL
, nmp
->nm_mountp
, fhp
, argp
->fhsize
, 
1328                         ctx
, &nvattr
, &xid
); 
1332         error 
= nfs_nget(nmp
->nm_mountp
, NULL
, NULL
, fhp
, argp
->fhsize
, 
1333                         &nvattr
, &xid
, NG_MARKROOT
, npp
); 
1340          * Try to make sure we have all the general info from the server. 
1342         if (nmp
->nm_vers 
== NFS_VER2
) { 
1343                 NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_MAXNAME
); 
1344                 nmp
->nm_fsattr
.nfsa_maxname 
= NFS_MAXNAMLEN
; 
1345         } else if (nmp
->nm_vers 
== NFS_VER3
) { 
1346                 /* get the NFSv3 FSINFO */ 
1347                 error 
= nfs3_fsinfo(nmp
, *npp
, ctx
); 
1350                 /* If the server indicates all pathconf info is */ 
1351                 /* the same, grab a copy of that info now */ 
1352                 if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_HOMOGENEOUS
) && 
1353                     (nmp
->nm_fsattr
.nfsa_flags 
& NFS_FSFLAG_HOMOGENEOUS
)) { 
1354                         struct nfs_fsattr nfsa
; 
1355                         if (!nfs3_pathconf_rpc(*npp
, &nfsa
, ctx
)) { 
1356                                 /* cache a copy of the results */ 
1357                                 lck_mtx_lock(&nmp
->nm_lock
); 
1358                                 nfs3_pathconf_cache(nmp
, &nfsa
); 
1359                                 lck_mtx_unlock(&nmp
->nm_lock
); 
1364         if (*npp 
&& error
) { 
1365                 vnode_put(NFSTOV(*npp
)); 
1373         struct nfsmount 
*nmp
, 
1375         __unused 
struct user_nfs_args 
*argp
, 
1378         struct nfsm_chain nmreq
, nmrep
; 
1379         int error 
= 0, numops
, status
, interval
; 
1380         char *path 
= &vfs_statfs(nmp
->nm_mountp
)->f_mntfromname
[0]; 
1381         char *name
, *nextname
; 
1383         struct nfs_vattr nvattr
; 
1390         nmp
->nm_mounttime 
= ((uint64_t)now
.tv_sec 
<< 32) | now
.tv_usec
; 
1392         /* look up path to get fh and attrs for mount point root */ 
1393         numops 
= 2; // PUTROOTFH + LOOKUP* + GETATTR 
1394         while (*path 
&& (*path 
!= '/')) 
1398                 while (*name 
&& (*name 
== '/')) 
1403                 while (*nextname 
&& (*nextname 
!= '/')) 
1408         nfsm_chain_build_alloc_init(error
, &nmreq
, 25 * NFSX_UNSIGNED
); 
1409         nfsm_chain_add_compound_header(error
, &nmreq
, "mount", numops
); 
1411         nfsm_chain_add_32(error
, &nmreq
, NFS_OP_PUTROOTFH
); 
1415                 while (*name 
&& (*name 
== '/')) 
1420                 while (*nextname 
&& (*nextname 
!= '/')) 
1423                 nfsm_chain_add_32(error
, &nmreq
, NFS_OP_LOOKUP
); 
1424                 nfsm_chain_add_string(error
, &nmreq
, name
, nextname 
- name
); 
1428         nfsm_chain_add_32(error
, &nmreq
, NFS_OP_GETATTR
); 
1429         NFS4_DEFAULT_ATTRIBUTES(nmp
->nm_fsattr
.nfsa_supp_attr
); 
1430         NFS_BITMAP_SET(nmp
->nm_fsattr
.nfsa_supp_attr
, NFS_FATTR_FILEHANDLE
); 
1431         nfsm_chain_add_bitmap(error
, &nmreq
, nmp
->nm_fsattr
.nfsa_supp_attr
, NFS_ATTR_BITMAP_LEN
); 
1432         nfsm_chain_build_done(error
, &nmreq
); 
1433         nfsm_assert(error
, (numops 
== 0), EPROTO
); 
1435         error 
= nfs_request(NULL
, nmp
->nm_mountp
, &nmreq
, NFSPROC4_COMPOUND
, ctx
, &nmrep
, &xid
, &status
); 
1436         nfsm_chain_skip_tag(error
, &nmrep
); 
1437         nfsm_chain_get_32(error
, &nmrep
, numops
); 
1438         nfsm_chain_op_check(error
, &nmrep
, NFS_OP_PUTROOTFH
); 
1441                 while (*name 
&& (*name 
== '/')) 
1446                 while (*nextname 
&& (*nextname 
!= '/')) 
1448                 nfsm_chain_op_check(error
, &nmrep
, NFS_OP_LOOKUP
); 
1451         nfsm_chain_op_check(error
, &nmrep
, NFS_OP_GETATTR
); 
1453         NFS_CLEAR_ATTRIBUTES(nmp
->nm_fsattr
.nfsa_bitmap
); 
1454         NFS_CLEAR_ATTRIBUTES(&nvattr
.nva_bitmap
); 
1455         error 
= nfs4_parsefattr(&nmrep
, &nmp
->nm_fsattr
, &nvattr
, &fh
, NULL
); 
1456         if (!error 
&& !NFS_BITMAP_ISSET(&nvattr
.nva_bitmap
, NFS_FATTR_FILEHANDLE
)) { 
1457                 printf("nfs: mount didn't return filehandle?\n"); 
1462         error 
= nfs_nget(nmp
->nm_mountp
, NULL
, NULL
, fh
.fh_data
, fh
.fh_len
, &nvattr
, &xid
, NG_MARKROOT
, npp
); 
1465         /* XXX local locking for now */ 
1466         vfs_setlocklocal(nmp
->nm_mountp
); 
1468         /* adjust I/O sizes to server limits */ 
1469         if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_MAXREAD
)) { 
1470                 if (nmp
->nm_fsattr
.nfsa_maxread 
< (uint64_t)nmp
->nm_rsize
) { 
1471                         nmp
->nm_rsize 
= nmp
->nm_fsattr
.nfsa_maxread 
& ~(NFS_FABLKSIZE 
- 1); 
1472                         if (nmp
->nm_rsize 
== 0) 
1473                                 nmp
->nm_rsize 
= nmp
->nm_fsattr
.nfsa_maxread
; 
1476         if (NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_bitmap
, NFS_FATTR_MAXWRITE
)) { 
1477                 if (nmp
->nm_fsattr
.nfsa_maxwrite 
< (uint64_t)nmp
->nm_wsize
) { 
1478                         nmp
->nm_wsize 
= nmp
->nm_fsattr
.nfsa_maxwrite 
& ~(NFS_FABLKSIZE 
- 1); 
1479                         if (nmp
->nm_wsize 
== 0) 
1480                                 nmp
->nm_wsize 
= nmp
->nm_fsattr
.nfsa_maxwrite
; 
1484         /* set up lease renew timer */ 
1485         nmp
->nm_renew_timer 
= thread_call_allocate(nfs4_renew_timer
, nmp
); 
1486         interval 
= nmp
->nm_fsattr
.nfsa_lease 
/ 2; 
1489         nfs_interval_timer_start(nmp
->nm_renew_timer
, interval 
* 1000); 
1499         struct user_nfs_args 
*argp
, 
1505         struct nfsmount 
*nmp
; 
1507         int error
, maxio
, iosize
; 
1508         struct vfsstatfs 
*sbp
; 
1509         struct timespec ts 
= { 1, 0 }; 
1512          * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes 
1513          * no sense in that context. 
1515         if (argp
->sotype 
== SOCK_STREAM
) 
1516                 argp
->flags 
&= ~NFSMNT_NOCONN
; 
1518         if (vfs_flags(mp
) & MNT_UPDATE
) { 
1520                 /* update paths, file handles, etc, here        XXX */ 
1524                 MALLOC_ZONE(nmp
, struct nfsmount 
*, 
1525                                 sizeof (struct nfsmount
), M_NFSMNT
, M_WAITOK
); 
1530                 bzero((caddr_t
)nmp
, sizeof (struct nfsmount
)); 
1531                 lck_mtx_init(&nmp
->nm_lock
, nfs_mount_grp
, LCK_ATTR_NULL
); 
1532                 TAILQ_INIT(&nmp
->nm_resendq
); 
1533                 TAILQ_INIT(&nmp
->nm_iodq
); 
1534                 TAILQ_INIT(&nmp
->nm_gsscl
); 
1535                 vfs_setfsprivate(mp
, nmp
); 
1537                 nfs_nhinit_finish(); 
1539         lck_mtx_lock(&nmp
->nm_lock
); 
1541         /* setup defaults */ 
1542         nmp
->nm_vers 
= NFS_VER2
; 
1543         nmp
->nm_timeo 
= NFS_TIMEO
; 
1544         nmp
->nm_retry 
= NFS_RETRANS
; 
1545         if (argp
->sotype 
== SOCK_DGRAM
) { 
1546                 nmp
->nm_wsize 
= NFS_DGRAM_WSIZE
; 
1547                 nmp
->nm_rsize 
= NFS_DGRAM_RSIZE
; 
1549                 nmp
->nm_wsize 
= NFS_WSIZE
; 
1550                 nmp
->nm_rsize 
= NFS_RSIZE
; 
1552         nmp
->nm_readdirsize 
= NFS_READDIRSIZE
; 
1553         nmp
->nm_numgrps 
= NFS_MAXGRPS
; 
1554         nmp
->nm_readahead 
= NFS_DEFRAHEAD
; 
1555         nmp
->nm_tprintf_delay 
= nfs_tprintf_delay
; 
1556         if (nmp
->nm_tprintf_delay 
< 0) 
1557                 nmp
->nm_tprintf_delay 
= 0; 
1558         nmp
->nm_tprintf_initial_delay 
= nfs_tprintf_initial_delay
; 
1559         if (nmp
->nm_tprintf_initial_delay 
< 0) 
1560                 nmp
->nm_tprintf_initial_delay 
= 0; 
1561         nmp
->nm_acregmin 
= NFS_MINATTRTIMO
; 
1562         nmp
->nm_acregmax 
= NFS_MAXATTRTIMO
; 
1563         nmp
->nm_acdirmin 
= NFS_MINDIRATTRTIMO
; 
1564         nmp
->nm_acdirmax 
= NFS_MAXDIRATTRTIMO
; 
1565         nmp
->nm_auth 
= RPCAUTH_SYS
; 
1568         nmp
->nm_mountp 
= mp
; 
1569         vfs_setauthopaque(mp
); 
1570         nmp
->nm_flag 
= argp
->flags
; 
1573         if (argp
->flags 
& NFSMNT_NFSV4
) { 
1574                 nmp
->nm_vers 
= NFS_VER4
; 
1575                 /* NFSv4 is only allowed over TCP. */ 
1576                 if (argp
->sotype 
!= SOCK_STREAM
) { 
1580         } else if (argp
->flags 
& NFSMNT_NFSV3
) 
1581                 nmp
->nm_vers 
= NFS_VER3
; 
1583         if (nmp
->nm_vers 
== NFS_VER2
) 
1584                 nmp
->nm_flag 
&= ~NFSMNT_RDIRPLUS
; 
1586         if ((argp
->flags 
& NFSMNT_TIMEO
) && argp
->timeo 
> 0) { 
1587                 nmp
->nm_timeo 
= (argp
->timeo 
* NFS_HZ 
+ 5) / 10; 
1588                 if (nmp
->nm_timeo 
< NFS_MINTIMEO
) 
1589                         nmp
->nm_timeo 
= NFS_MINTIMEO
; 
1590                 else if (nmp
->nm_timeo 
> NFS_MAXTIMEO
) 
1591                         nmp
->nm_timeo 
= NFS_MAXTIMEO
; 
1594         if ((argp
->flags 
& NFSMNT_RETRANS
) && argp
->retrans 
> 1) { 
1595                 nmp
->nm_retry 
= argp
->retrans
; 
1596                 if (nmp
->nm_retry 
> NFS_MAXREXMIT
) 
1597                         nmp
->nm_retry 
= NFS_MAXREXMIT
; 
1600         if (nmp
->nm_vers 
!= NFS_VER2
) { 
1601                 if (argp
->sotype 
== SOCK_DGRAM
) 
1602                         maxio 
= NFS_MAXDGRAMDATA
; 
1604                         maxio 
= NFS_MAXDATA
; 
1606                 maxio 
= NFS_V2MAXDATA
; 
1608         if ((argp
->flags 
& NFSMNT_WSIZE
) && argp
->wsize 
> 0) { 
1609                 nmp
->nm_wsize 
= argp
->wsize
; 
1610                 /* Round down to multiple of blocksize */ 
1611                 nmp
->nm_wsize 
&= ~(NFS_FABLKSIZE 
- 1); 
1612                 if (nmp
->nm_wsize 
<= 0) 
1613                         nmp
->nm_wsize 
= NFS_FABLKSIZE
; 
1615         if (nmp
->nm_wsize 
> maxio
) 
1616                 nmp
->nm_wsize 
= maxio
; 
1617         if (nmp
->nm_wsize 
> NFS_MAXBSIZE
) 
1618                 nmp
->nm_wsize 
= NFS_MAXBSIZE
; 
1620         if ((argp
->flags 
& NFSMNT_RSIZE
) && argp
->rsize 
> 0) { 
1621                 nmp
->nm_rsize 
= argp
->rsize
; 
1622                 /* Round down to multiple of blocksize */ 
1623                 nmp
->nm_rsize 
&= ~(NFS_FABLKSIZE 
- 1); 
1624                 if (nmp
->nm_rsize 
<= 0) 
1625                         nmp
->nm_rsize 
= NFS_FABLKSIZE
; 
1627         if (nmp
->nm_rsize 
> maxio
) 
1628                 nmp
->nm_rsize 
= maxio
; 
1629         if (nmp
->nm_rsize 
> NFS_MAXBSIZE
) 
1630                 nmp
->nm_rsize 
= NFS_MAXBSIZE
; 
1632         if ((argp
->flags 
& NFSMNT_READDIRSIZE
) && argp
->readdirsize 
> 0) { 
1633                 nmp
->nm_readdirsize 
= argp
->readdirsize
; 
1635         if (nmp
->nm_readdirsize 
> maxio
) 
1636                 nmp
->nm_readdirsize 
= maxio
; 
1637         if (nmp
->nm_readdirsize 
> nmp
->nm_rsize
) 
1638                 nmp
->nm_readdirsize 
= nmp
->nm_rsize
; 
1640         if ((argp
->flags 
& NFSMNT_MAXGRPS
) && argp
->maxgrouplist 
>= 0 && 
1641                 argp
->maxgrouplist 
<= NFS_MAXGRPS
) 
1642                 nmp
->nm_numgrps 
= argp
->maxgrouplist
; 
1643         if ((argp
->flags 
& NFSMNT_READAHEAD
) && argp
->readahead 
>= 0 && 
1644                 argp
->readahead 
<= NFS_MAXRAHEAD
) 
1645                 nmp
->nm_readahead 
= argp
->readahead
; 
1646         if (argp
->flags 
& NFSMNT_READAHEAD
) 
1647                 nmp
->nm_readahead 
= argp
->readahead
; 
1648         if (nmp
->nm_readahead 
< 0) 
1649                 nmp
->nm_readahead 
= 0; 
1650         else if (nmp
->nm_readahead 
> NFS_MAXRAHEAD
) 
1651                 nmp
->nm_readahead 
= NFS_MAXRAHEAD
; 
1653         if (argp
->version 
>= 4) { 
1654                 if ((argp
->flags 
& NFSMNT_ACREGMIN
) && argp
->acregmin 
>= 0) 
1655                         nmp
->nm_acregmin 
= argp
->acregmin
; 
1656                 if ((argp
->flags 
& NFSMNT_ACREGMAX
) && argp
->acregmax 
>= 0) 
1657                         nmp
->nm_acregmax 
= argp
->acregmax
; 
1658                 if ((argp
->flags 
& NFSMNT_ACDIRMIN
) && argp
->acdirmin 
>= 0) 
1659                         nmp
->nm_acdirmin 
= argp
->acdirmin
; 
1660                 if ((argp
->flags 
& NFSMNT_ACDIRMAX
) && argp
->acdirmax 
>= 0) 
1661                         nmp
->nm_acdirmax 
= argp
->acdirmax
; 
1662                 if (nmp
->nm_acregmin 
> nmp
->nm_acregmax
) 
1663                         nmp
->nm_acregmin 
= nmp
->nm_acregmax
; 
1664                 if (nmp
->nm_acdirmin 
> nmp
->nm_acdirmax
) 
1665                         nmp
->nm_acdirmin 
= nmp
->nm_acdirmax
; 
1667         if (argp
->version 
>= 5) { 
1668                 if (argp
->flags 
& NFSMNT_SECFLAVOR
) { 
1670                          * Check for valid security flavor 
1672                         switch (argp
->auth
) { 
1677                                 nmp
->nm_auth 
= argp
->auth
; 
1686         /* set up the version-specific function tables */ 
1687         if (nmp
->nm_vers 
< NFS_VER4
) 
1688                 nmp
->nm_funcs 
= &nfs3_funcs
; 
1690                 nmp
->nm_funcs 
= &nfs4_funcs
; 
1692         /* Set up the sockets and related info */ 
1693         nmp
->nm_sotype 
= argp
->sotype
; 
1694         nmp
->nm_soproto 
= argp
->proto
; 
1695         if (nmp
->nm_sotype 
== SOCK_DGRAM
) 
1696                 TAILQ_INIT(&nmp
->nm_cwndq
); 
1698         lck_mtx_unlock(&nmp
->nm_lock
); 
1700         /* make sure mbuf constants are set up */ 
1701         if (!nfs_mbuf_mhlen
) 
1704         /* NFS does its own node locking */ 
1705         mp
->mnt_vtable
->vfc_threadsafe 
= TRUE
; 
1707         /* set up the socket */ 
1708         if ((error 
= nfs_connect(nmp
))) 
1712          * Get the root node/attributes from the NFS server and 
1713          * do any basic, version-specific setup. 
1715         error 
= nmp
->nm_funcs
->nf_mount(nmp
, ctx
, argp
, &np
); 
1720          * A reference count is needed on the node representing the 
1721          * remote root.  If this object is not persistent, then backward 
1722          * traversals of the mount point (i.e. "..") will not work if 
1723          * the node gets flushed out of the cache. 
1727         /* get usecount and drop iocount */ 
1728         error 
= vnode_ref(*vpp
); 
1734          * Do statfs to ensure static info gets set to reasonable values. 
1736         if ((error 
= nmp
->nm_funcs
->nf_update_statfs(nmp
, ctx
))) 
1738         sbp 
= vfs_statfs(mp
); 
1739         sbp
->f_bsize 
= nmp
->nm_fsattr
.nfsa_bsize
; 
1740         sbp
->f_blocks 
= nmp
->nm_fsattr
.nfsa_space_total 
/ sbp
->f_bsize
; 
1741         sbp
->f_bfree 
= nmp
->nm_fsattr
.nfsa_space_free 
/ sbp
->f_bsize
; 
1742         sbp
->f_bavail 
= nmp
->nm_fsattr
.nfsa_space_avail 
/ sbp
->f_bsize
; 
1743         sbp
->f_bused 
= (nmp
->nm_fsattr
.nfsa_space_total 
/ sbp
->f_bsize
) - 
1744                         (nmp
->nm_fsattr
.nfsa_space_free 
/ sbp
->f_bsize
); 
1745         sbp
->f_files 
= nmp
->nm_fsattr
.nfsa_files_total
; 
1746         sbp
->f_ffree 
= nmp
->nm_fsattr
.nfsa_files_free
; 
1747         sbp
->f_iosize 
= nfs_iosize
; 
1750          * Calculate the size used for I/O buffers.  Use the larger 
1751          * of the two sizes to minimise NFS requests but make sure 
1752          * that it is at least one VM page to avoid wasting buffer 
1753          * space and to allow easy mmapping of I/O buffers. 
1754          * The read/write RPC calls handle the splitting up of 
1755          * buffers into multiple requests if the buffer size is 
1756          * larger than the I/O size. 
1758         iosize 
= max(nmp
->nm_rsize
, nmp
->nm_wsize
); 
1759         if (iosize 
< PAGE_SIZE
) 
1761         nmp
->nm_biosize 
= trunc_page_32(iosize
); 
1764          * V3 mounts give us a (relatively) reliable remote access(2) 
1765          * call, so advertise the fact. 
1767          * XXX this may not be the best way to go, as the granularity 
1768          *     offered isn't a good match to our needs. 
1770         if (nmp
->nm_vers 
!= NFS_VER2
) 
1771                 vfs_setauthopaqueaccess(mp
); 
1773         if (nmp
->nm_flag 
& NFSMNT_LOCALLOCKS
) 
1774                 vfs_setlocklocal(nmp
->nm_mountp
); 
1775         if (!(nmp
->nm_flag 
& (NFSMNT_NOLOCKS
|NFSMNT_LOCALLOCKS
))) 
1776                 nfs_lockd_mount_change(1); 
1778         lck_mtx_lock(&nmp
->nm_lock
); 
1779         nmp
->nm_state 
|= NFSSTA_MOUNTED
; 
1780         lck_mtx_unlock(&nmp
->nm_lock
); 
1783         /* mark the socket for termination */ 
1784         lck_mtx_lock(&nmp
->nm_lock
); 
1785         nmp
->nm_sockflags 
|= NMSOCK_UNMOUNT
; 
1786         /* wait for any socket poking to complete */ 
1787         while (nmp
->nm_sockflags 
& NMSOCK_POKE
) 
1788                 msleep(&nmp
->nm_sockflags
, &nmp
->nm_lock
, PZERO
-1, "nfswaitpoke", &ts
); 
1789         /* wait for the socket thread to terminate */ 
1790         while (nmp
->nm_sockthd
) { 
1791                 wakeup(&nmp
->nm_sockthd
); 
1792                 msleep(&nmp
->nm_sockthd
, &nmp
->nm_lock
, PZERO
-1, "nfswaitsockthd", &ts
); 
1794         /* tear down the socket */ 
1795         lck_mtx_unlock(&nmp
->nm_lock
); 
1796         nfs_disconnect(nmp
); 
1797         if (nmp
->nm_renew_timer
) { 
1798                 thread_call_cancel(nmp
->nm_renew_timer
); 
1799                 thread_call_free(nmp
->nm_renew_timer
); 
1801         lck_mtx_destroy(&nmp
->nm_lock
, nfs_mount_grp
); 
1802         FREE_ZONE((caddr_t
)nmp
, sizeof (struct nfsmount
), M_NFSMNT
); 
1809  * unmount system call 
1815         __unused vfs_context_t ctx
) 
1817         struct nfsmount 
*nmp
; 
1819         int error
, flags 
= 0, docallback
; 
1820         struct nfsreq 
*req
, *treq
; 
1821         struct nfs_reqqhead iodq
; 
1822         struct timespec ts 
= { 1, 0 }; 
1825         lck_mtx_lock(&nmp
->nm_lock
); 
1827          * During a force unmount we want to... 
1828          *   Mark that we are doing a force unmount. 
1829          *   Make the mountpoint soft. 
1831         if (mntflags 
& MNT_FORCE
) { 
1832                 flags 
|= FORCECLOSE
; 
1833                 nmp
->nm_state 
|= NFSSTA_FORCE
; 
1834                 nmp
->nm_flag 
|= NFSMNT_SOFT
; 
1837          * Goes something like this.. 
1838          * - Call vflush() to clear out vnodes for this file system, 
1839          *   except for the swap files. Deal with them in 2nd pass. 
1840          * - Decrement reference on the vnode representing remote root. 
1841          * - Close the socket 
1842          * - Free up the data structures 
1844         vp 
= NFSTOV(nmp
->nm_dnp
); 
1845         lck_mtx_unlock(&nmp
->nm_lock
); 
1848          * vflush will check for busy vnodes on mountpoint. 
1849          * Will do the right thing for MNT_FORCE. That is, we should 
1850          * not get EBUSY back. 
1852         error 
= vflush(mp
, vp
, SKIPSWAP 
| flags
); 
1853         if (mntflags 
& MNT_FORCE
) { 
1854                 error 
= vflush(mp
, NULLVP
, flags
); /* locks vp in the process */ 
1856                 if (vnode_isinuse(vp
, 1)) 
1858                 error 
= vflush(mp
, vp
, flags
); 
1863         lck_mtx_lock(&nmp
->nm_lock
); 
1864         nmp
->nm_state 
&= ~NFSSTA_MOUNTED
; 
1865         lck_mtx_unlock(&nmp
->nm_lock
); 
1868          * Release the root vnode reference held by mountnfs() 
1872         vflush(mp
, NULLVP
, FORCECLOSE
); 
1875          * Destroy any RPCSEC_GSS contexts 
1877         if (!TAILQ_EMPTY(&nmp
->nm_gsscl
)) 
1878                 nfs_gss_clnt_ctx_unmount(nmp
, mntflags
); 
1880         vfs_setfsprivate(mp
, 0); /* don't want to end up using stale vp */ 
1882         /* mark the socket for termination */ 
1883         lck_mtx_lock(&nmp
->nm_lock
); 
1884         nmp
->nm_sockflags 
|= NMSOCK_UNMOUNT
; 
1886         /* wait for any socket poking to complete */ 
1887         while (nmp
->nm_sockflags 
& NMSOCK_POKE
) 
1888                 msleep(&nmp
->nm_sockflags
, &nmp
->nm_lock
, PZERO
-1, "nfswaitpoke", &ts
); 
1890         /* wait for the socket thread to terminate */ 
1891         while (nmp
->nm_sockthd
) { 
1892                 wakeup(&nmp
->nm_sockthd
); 
1893                 msleep(&nmp
->nm_sockthd
, &nmp
->nm_lock
, PZERO
-1, "nfswaitsockthd", &ts
); 
1896         /* tear down the socket */ 
1897         lck_mtx_unlock(&nmp
->nm_lock
); 
1898         nfs_disconnect(nmp
); 
1899         lck_mtx_lock(&nmp
->nm_lock
); 
1901         /* cancel any renew timer */ 
1902         if (nmp
->nm_renew_timer
) { 
1903                 thread_call_cancel(nmp
->nm_renew_timer
); 
1904                 thread_call_free(nmp
->nm_renew_timer
); 
1907         mbuf_freem(nmp
->nm_nam
); 
1908         lck_mtx_unlock(&nmp
->nm_lock
); 
1910         if (!(nmp
->nm_flag 
& (NFSMNT_NOLOCKS
|NFSMNT_LOCALLOCKS
))) 
1911                 nfs_lockd_mount_change(-1); 
1914          * Loop through outstanding request list and remove dangling 
1915          * references to defunct nfsmount struct 
1918         lck_mtx_lock(nfs_request_mutex
); 
1919         TAILQ_FOREACH(req
, &nfs_reqq
, r_chain
) { 
1920                 if (req
->r_nmp 
== nmp
) { 
1921                         lck_mtx_lock(&req
->r_mtx
); 
1923                         lck_mtx_unlock(&req
->r_mtx
); 
1924                         if (req
->r_callback
.rcb_func
) { 
1925                                 /* async I/O RPC needs to be finished */ 
1926                                 lck_mtx_lock(nfsiod_mutex
); 
1927                                 if (req
->r_achain
.tqe_next 
== NFSREQNOLIST
) 
1928                                         TAILQ_INSERT_TAIL(&iodq
, req
, r_achain
); 
1929                                 lck_mtx_unlock(nfsiod_mutex
); 
1931                         lck_mtx_lock(&nmp
->nm_lock
); 
1932                         if (req
->r_rchain
.tqe_next 
!= NFSREQNOLIST
) { 
1933                                 TAILQ_REMOVE(&nmp
->nm_resendq
, req
, r_rchain
); 
1934                                 req
->r_rchain
.tqe_next 
= NFSREQNOLIST
; 
1935                                 req
->r_flags 
&= ~R_RESENDQ
; 
1937                         lck_mtx_unlock(&nmp
->nm_lock
); 
1941         lck_mtx_unlock(nfs_request_mutex
); 
1943         /* finish any async I/O RPCs queued up */ 
1944         lck_mtx_lock(nfsiod_mutex
); 
1945         TAILQ_CONCAT(&iodq
, &nmp
->nm_iodq
, r_achain
); 
1946         lck_mtx_unlock(nfsiod_mutex
); 
1947         TAILQ_FOREACH_SAFE(req
, &iodq
, r_achain
, treq
) { 
1948                 TAILQ_REMOVE(&iodq
, req
, r_achain
); 
1949                 req
->r_achain
.tqe_next 
= NFSREQNOLIST
; 
1950                 lck_mtx_lock(&req
->r_mtx
); 
1951                 req
->r_error 
= ENXIO
; 
1952                 docallback 
= !(req
->r_flags 
& R_WAITSENT
); 
1953                 lck_mtx_unlock(&req
->r_mtx
); 
1955                         req
->r_callback
.rcb_func(req
); 
1958         lck_mtx_destroy(&nmp
->nm_lock
, nfs_mount_grp
); 
1959         FREE_ZONE((caddr_t
)nmp
, sizeof (struct nfsmount
), M_NFSMNT
); 
1964  * Return root of a filesystem 
1967 nfs_vfs_root(mount_t mp
, vnode_t 
*vpp
, __unused vfs_context_t ctx
) 
1970         struct nfsmount 
*nmp
; 
1975         vp 
= NFSTOV(nmp
->nm_dnp
); 
1976         vpid 
= vnode_vid(vp
); 
1977         while ((error 
= vnode_getwithvid(vp
, vpid
))) { 
1978                 /* vnode_get() may return ENOENT if the dir changes. */ 
1979                 /* If that happens, just try it again, else return the error. */ 
1980                 if ((error 
!= ENOENT
) || (vnode_vid(vp
) == vpid
)) 
1982                 vpid 
= vnode_vid(vp
); 
1989  * Do operations associated with quotas 
1994         __unused mount_t mp
, 
1997         __unused caddr_t datap
, 
1998         __unused vfs_context_t context
) 
2005         struct nfsmount 
*nmp
, 
2007         struct sockaddr_in 
*saddr
, 
2011         struct nfsm_chain 
*nmrep
) 
2013         int error 
= 0, on 
= 1, try, sendat 
= 2; 
2015         struct timeval tv 
= { 1, 0 }; 
2016         mbuf_t m
, mrep 
= NULL
; 
2018         uint32_t rxid
, reply
, reply_status
, rejected_status
; 
2019         uint32_t verf_type
, verf_len
, accepted_status
; 
2022         /* create socket and set options */ 
2023         if (((error 
= sock_socket(saddr
->sin_family
, SOCK_DGRAM
, IPPROTO_UDP
, NULL
, NULL
, &so
))) || 
2024             ((error 
= sock_setsockopt(so
, SOL_SOCKET
, SO_RCVTIMEO
, &tv
, sizeof(tv
)))) || 
2025             ((error 
= sock_setsockopt(so
, SOL_SOCKET
, SO_SNDTIMEO
, &tv
, sizeof(tv
)))) || 
2026             ((error 
= sock_setsockopt(so
, SOL_SOCKET
, SO_NOADDRERR
, &on
, sizeof(on
))))) 
2029         for (try=0; try < timeo
; try++) { 
2030                 if ((error 
= nfs_sigintr(nmp
, NULL
, thd
, 0))) 
2032                 if (!try || (try == sendat
)) { 
2033                         /* send the request (resending periodically) */ 
2034                         if ((error 
= mbuf_copym(mreq
, 0, MBUF_COPYALL
, MBUF_WAITOK
, &m
))) 
2036                         bzero(&msg
, sizeof(msg
)); 
2037                         msg
.msg_name 
= saddr
; 
2038                         msg
.msg_namelen 
= saddr
->sin_len
; 
2039                         if ((error 
= sock_sendmbuf(so
, &msg
, m
, 0, NULL
))) 
2045                 /* wait for the response */ 
2047                 bzero(&msg
, sizeof(msg
)); 
2048                 error 
= sock_receivembuf(so
, &msg
, &mrep
, 0, &readlen
); 
2049                 if (error 
== EWOULDBLOCK
) 
2052                 /* parse the response */ 
2053                 nfsm_chain_dissect_init(error
, nmrep
, mrep
); 
2054                 nfsm_chain_get_32(error
, nmrep
, rxid
); 
2055                 nfsm_chain_get_32(error
, nmrep
, reply
); 
2057                 if ((rxid 
!= xid
) || (reply 
!= RPC_REPLY
)) 
2059                 nfsm_chain_get_32(error
, nmrep
, reply_status
); 
2061                 if (reply_status 
== RPC_MSGDENIED
) { 
2062                         nfsm_chain_get_32(error
, nmrep
, rejected_status
); 
2064                         error 
= (rejected_status 
== RPC_MISMATCH
) ? ENOTSUP 
: EACCES
; 
2067                 nfsm_chain_get_32(error
, nmrep
, verf_type
); /* verifier flavor */ 
2068                 nfsm_chain_get_32(error
, nmrep
, verf_len
); /* verifier length */ 
2071                         nfsm_chain_adv(error
, nmrep
, nfsm_rndup(verf_len
)); 
2072                 nfsm_chain_get_32(error
, nmrep
, accepted_status
); 
2073                 nfsm_assert(error
, (accepted_status 
== RPC_SUCCESS
), EIO
); 
2078                 sock_shutdown(so
, SHUT_RDWR
); 
2086 nfs3_getquota(struct nfsmount 
*nmp
, vfs_context_t ctx
, u_long id
, int type
, struct dqblk 
*dqb
) 
2088         int error 
= 0, auth_len
, slen
, timeo
; 
2089         int rqvers 
= (type 
== GRPQUOTA
) ? RPCRQUOTA_EXT_VER 
: RPCRQUOTA_VER
; 
2090         thread_t thd 
= vfs_context_thread(ctx
); 
2091         kauth_cred_t cred 
= vfs_context_ucred(ctx
); 
2094         struct nfsm_chain nmreq
, nmrep
; 
2096         uint32_t val 
= 0, bsize
; 
2097         struct sockaddr 
*nam 
= mbuf_data(nmp
->nm_nam
); 
2098         struct sockaddr_in saddr
; 
2101         bcopy(nam
, &saddr
, min(sizeof(saddr
), nam
->sa_len
)); 
2102         auth_len 
= ((((cred
->cr_ngroups 
- 1) > nmp
->nm_numgrps
) ? 
2103                         nmp
->nm_numgrps 
: (cred
->cr_ngroups 
- 1)) << 2) + 
2105         timeo 
= (nmp
->nm_flag 
& NFSMNT_SOFT
) ? 10 : 60; 
2106         nfsm_chain_null(&nmreq
); 
2107         nfsm_chain_null(&nmrep
); 
2109         /* check if we have a recently cached rquota port */ 
2110         if (nmp
->nm_rqport
) { 
2112                 if ((nmp
->nm_rqportstamp 
+ 60) >= (uint32_t)now
.tv_sec
) 
2116         /* send portmap request to get rquota port */ 
2117         saddr
.sin_port 
= htons(PMAPPORT
); 
2118         nfsm_chain_build_alloc_init(error
, &nmreq
, 4*NFSX_UNSIGNED
); 
2119         nfsm_chain_add_32(error
, &nmreq
, RPCPROG_RQUOTA
); 
2120         nfsm_chain_add_32(error
, &nmreq
, rqvers
); 
2121         nfsm_chain_add_32(error
, &nmreq
, IPPROTO_UDP
); 
2122         nfsm_chain_add_32(error
, &nmreq
, 0); 
2123         nfsm_chain_build_done(error
, &nmreq
); 
2125         error 
= nfsm_rpchead2(SOCK_DGRAM
, PMAPPROG
, PMAPVERS
, PMAPPROC_GETPORT
, 
2126                         RPCAUTH_SYS
, auth_len
, cred
, NULL
, nmreq
.nmc_mhead
, &xid
, &mreq
); 
2128         nmreq
.nmc_mhead 
= NULL
; 
2129         error 
= nfs_aux_request(nmp
, thd
, &saddr
, mreq
, R_XID32(xid
), timeo
, &nmrep
); 
2132         /* grab rquota port from portmap response */ 
2133         nfsm_chain_get_32(error
, &nmrep
, val
); 
2135         nmp
->nm_rqport 
= val
; 
2137         nmp
->nm_rqportstamp 
= now
.tv_sec
; 
2138         nfsm_chain_cleanup(&nmreq
); 
2139         nfsm_chain_cleanup(&nmrep
); 
2143         /* rquota request */ 
2144         saddr
.sin_port 
= htons(nmp
->nm_rqport
); 
2145         path 
= &vfs_statfs(nmp
->nm_mountp
)->f_mntfromname
[0]; 
2146         while (*path 
&& (*path 
!= '/')) 
2148         slen 
= strlen(path
); 
2149         nfsm_chain_build_alloc_init(error
, &nmreq
, 3 * NFSX_UNSIGNED 
+ nfsm_rndup(slen
)); 
2150         nfsm_chain_add_string(error
, &nmreq
, path
, slen
); 
2151         if (type 
== GRPQUOTA
) 
2152                 nfsm_chain_add_32(error
, &nmreq
, type
); 
2153         nfsm_chain_add_32(error
, &nmreq
, id
); 
2154         nfsm_chain_build_done(error
, &nmreq
); 
2156         error 
= nfsm_rpchead2(SOCK_DGRAM
, RPCPROG_RQUOTA
, rqvers
, RPCRQUOTA_GET
, 
2157                         RPCAUTH_SYS
, auth_len
, cred
, NULL
, nmreq
.nmc_mhead
, &xid
, &mreq
); 
2159         nmreq
.nmc_mhead 
= NULL
; 
2160         error 
= nfs_aux_request(nmp
, thd
, &saddr
, mreq
, R_XID32(xid
), timeo
, &nmrep
); 
2163         /* parse rquota response */ 
2164         nfsm_chain_get_32(error
, &nmrep
, val
); 
2165         if (!error 
&& (val 
!= RQUOTA_STAT_OK
)) { 
2166                 if (val 
== RQUOTA_STAT_NOQUOTA
) 
2168                 else if (val 
== RQUOTA_STAT_EPERM
) 
2173         nfsm_chain_get_32(error
, &nmrep
, bsize
); 
2174         nfsm_chain_adv(error
, &nmrep
, NFSX_UNSIGNED
); 
2175         nfsm_chain_get_32(error
, &nmrep
, val
); 
2177         dqb
->dqb_bhardlimit 
= (uint64_t)val 
* bsize
; 
2178         nfsm_chain_get_32(error
, &nmrep
, val
); 
2180         dqb
->dqb_bsoftlimit 
= (uint64_t)val 
* bsize
; 
2181         nfsm_chain_get_32(error
, &nmrep
, val
); 
2183         dqb
->dqb_curbytes 
= (uint64_t)val 
* bsize
; 
2184         nfsm_chain_get_32(error
, &nmrep
, dqb
->dqb_ihardlimit
); 
2185         nfsm_chain_get_32(error
, &nmrep
, dqb
->dqb_isoftlimit
); 
2186         nfsm_chain_get_32(error
, &nmrep
, dqb
->dqb_curinodes
); 
2187         nfsm_chain_get_32(error
, &nmrep
, dqb
->dqb_btime
); 
2188         nfsm_chain_get_32(error
, &nmrep
, dqb
->dqb_itime
); 
2192         nfsm_chain_cleanup(&nmreq
); 
2193         nfsm_chain_cleanup(&nmrep
); 
2198 nfs4_getquota(struct nfsmount 
*nmp
, vfs_context_t ctx
, u_long id
, int type
, struct dqblk 
*dqb
) 
2201         int error 
= 0, status
, nfsvers
, numops
; 
2203         struct nfsm_chain nmreq
, nmrep
; 
2204         uint32_t bitmap
[NFS_ATTR_BITMAP_LEN
]; 
2205         thread_t thd 
= vfs_context_thread(ctx
); 
2206         kauth_cred_t cred 
= vfs_context_ucred(ctx
); 
2208         if (type 
!= USRQUOTA
)  /* NFSv4 only supports user quotas */ 
2211         /* first check that the server supports any of the quota attributes */ 
2212         if (!NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_supp_attr
, NFS_FATTR_QUOTA_AVAIL_HARD
) && 
2213             !NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_supp_attr
, NFS_FATTR_QUOTA_AVAIL_SOFT
) && 
2214             !NFS_BITMAP_ISSET(nmp
->nm_fsattr
.nfsa_supp_attr
, NFS_FATTR_QUOTA_USED
)) 
2218          * The credential passed to the server needs to have 
2219          * an effective uid that matches the given uid. 
2221         if (id 
!= kauth_cred_getuid(cred
)) { 
2222                 struct ucred temp_cred
; 
2223                 bzero(&temp_cred
, sizeof(temp_cred
)); 
2224                 temp_cred
.cr_uid 
= id
; 
2225                 temp_cred
.cr_ngroups 
= cred
->cr_ngroups
; 
2226                 bcopy(cred
->cr_groups
, temp_cred
.cr_groups
, sizeof(temp_cred
.cr_groups
)); 
2227                 cred 
= kauth_cred_create(&temp_cred
); 
2228                 if (!IS_VALID_CRED(cred
)) 
2231                 kauth_cred_ref(cred
); 
2234         nfsvers 
= nmp
->nm_vers
; 
2236         if ((error 
= vnode_get(NFSTOV(np
)))) { 
2237                 kauth_cred_unref(&cred
); 
2241         nfsm_chain_null(&nmreq
); 
2242         nfsm_chain_null(&nmrep
); 
2246         nfsm_chain_build_alloc_init(error
, &nmreq
, 15 * NFSX_UNSIGNED
); 
2247         nfsm_chain_add_compound_header(error
, &nmreq
, "quota", numops
); 
2249         nfsm_chain_add_32(error
, &nmreq
, NFS_OP_PUTFH
); 
2250         nfsm_chain_add_fh(error
, &nmreq
, nfsvers
, np
->n_fhp
, np
->n_fhsize
); 
2252         nfsm_chain_add_32(error
, &nmreq
, NFS_OP_GETATTR
); 
2253         NFS_CLEAR_ATTRIBUTES(bitmap
); 
2254         NFS_BITMAP_SET(bitmap
, NFS_FATTR_QUOTA_AVAIL_HARD
); 
2255         NFS_BITMAP_SET(bitmap
, NFS_FATTR_QUOTA_AVAIL_SOFT
); 
2256         NFS_BITMAP_SET(bitmap
, NFS_FATTR_QUOTA_USED
); 
2257         nfsm_chain_add_bitmap_masked(error
, &nmreq
, bitmap
, 
2258                 NFS_ATTR_BITMAP_LEN
, nmp
->nm_fsattr
.nfsa_supp_attr
); 
2259         nfsm_chain_build_done(error
, &nmreq
); 
2260         nfsm_assert(error
, (numops 
== 0), EPROTO
); 
2262         error 
= nfs_request2(np
, NULL
, &nmreq
, NFSPROC4_COMPOUND
, thd
, cred
, 0, &nmrep
, &xid
, &status
); 
2263         nfsm_chain_skip_tag(error
, &nmrep
); 
2264         nfsm_chain_get_32(error
, &nmrep
, numops
); 
2265         nfsm_chain_op_check(error
, &nmrep
, NFS_OP_PUTFH
); 
2266         nfsm_chain_op_check(error
, &nmrep
, NFS_OP_GETATTR
); 
2267         nfsm_assert(error
, NFSTONMP(np
), ENXIO
); 
2269         error 
= nfs4_parsefattr(&nmrep
, NULL
, NULL
, NULL
, dqb
); 
2271         nfsm_assert(error
, NFSTONMP(np
), ENXIO
); 
2273         nfsm_chain_cleanup(&nmreq
); 
2274         nfsm_chain_cleanup(&nmrep
); 
2275         vnode_put(NFSTOV(np
)); 
2276         kauth_cred_unref(&cred
); 
2281 nfs_vfs_quotactl(mount_t mp
, int cmds
, uid_t uid
, caddr_t datap
, vfs_context_t ctx
) 
2283         struct nfsmount 
*nmp
; 
2284         int cmd
, type
, error
, nfsvers
; 
2285         uid_t ruid 
= vfs_context_ucred(ctx
)->cr_ruid
; 
2286         struct dqblk 
*dqb 
= (struct dqblk
*)datap
; 
2288         if (!(nmp 
= VFSTONFS(mp
))) 
2290         nfsvers 
= nmp
->nm_vers
; 
2295         /* we can only support Q_GETQUOTA */ 
2296         cmd 
= cmds 
>> SUBCMDSHIFT
; 
2311         type 
= cmds 
& SUBCMDMASK
; 
2312         if ((u_int
)type 
>= MAXQUOTAS
) 
2314         if ((uid 
!= ruid
) && ((error 
= vfs_context_suser(ctx
)))) 
2317         if (vfs_busy(mp
, LK_NOWAIT
)) 
2319         bzero(dqb
, sizeof(*dqb
)); 
2320         error 
= nmp
->nm_funcs
->nf_getquota(nmp
, ctx
, uid
, type
, dqb
); 
2327  * Flush out the buffer cache 
2330 struct nfs_sync_cargs 
{ 
2337 nfs_sync_callout(vnode_t vp
, void *arg
) 
2339         struct nfs_sync_cargs 
*cargs 
= (struct nfs_sync_cargs
*)arg
; 
2342         if (LIST_EMPTY(&VTONFS(vp
)->n_dirtyblkhd
)) 
2343                 return (VNODE_RETURNED
); 
2344         if (VTONFS(vp
)->n_wrbusy 
> 0) 
2345                 return (VNODE_RETURNED
); 
2346         if (VTONFS(vp
)->n_bflag 
& (NBFLUSHINPROG
|NBINVALINPROG
)) 
2347                 return (VNODE_RETURNED
); 
2349         error 
= nfs_flush(VTONFS(vp
), cargs
->waitfor
, cargs
->thd
, 0); 
2351                 cargs
->error 
= error
; 
2353         return (VNODE_RETURNED
); 
2357 nfs_vfs_sync(mount_t mp
, int waitfor
, vfs_context_t ctx
) 
2359         struct nfs_sync_cargs cargs
; 
2361         cargs
.waitfor 
= waitfor
; 
2362         cargs
.thd 
= vfs_context_thread(ctx
); 
2365         vnode_iterate(mp
, 0, nfs_sync_callout
, &cargs
); 
2367         return (cargs
.error
); 
2371  * NFS flat namespace lookup. 
2372  * Currently unsupported. 
2377         __unused mount_t mp
, 
2378         __unused ino64_t ino
, 
2379         __unused vnode_t 
*vpp
, 
2380         __unused vfs_context_t ctx
) 
2387  * At this point, this should never happen 
2392         __unused mount_t mp
, 
2394         __unused 
unsigned char *fhp
, 
2395         __unused vnode_t 
*vpp
, 
2396         __unused vfs_context_t ctx
) 
2403  * Vnode pointer to File handle, should never happen either 
2408         __unused vnode_t vp
, 
2409         __unused 
int *fhlenp
, 
2410         __unused 
unsigned char *fhp
, 
2411         __unused vfs_context_t ctx
) 
2418  * Vfs start routine, a no-op. 
2423         __unused mount_t mp
, 
2425         __unused vfs_context_t ctx
) 
2432  * Do that sysctl thang... 
2435 nfs_vfs_sysctl(int *name
, u_int namelen
, user_addr_t oldp
, size_t *oldlenp
, 
2436            user_addr_t newp
, size_t newlen
, vfs_context_t ctx
) 
2438         int error 
= 0, val
, softnobrowse
; 
2439         struct sysctl_req 
*req 
= NULL
; 
2441         struct user_vfsidctl user_vc
; 
2443         struct nfsmount 
*nmp 
= NULL
; 
2445         boolean_t is_64_bit
; 
2447         struct nfs_exportfs 
*nxfs
; 
2448         struct nfs_export 
*nx
; 
2449         struct nfs_active_user_list 
*ulist
; 
2450         struct nfs_export_stat_desc stat_desc
; 
2451         struct nfs_export_stat_rec statrec
; 
2452         struct nfs_user_stat_node 
*unode
, *unode_next
; 
2453         struct nfs_user_stat_desc ustat_desc
; 
2454         struct nfs_user_stat_user_rec ustat_rec
; 
2455         struct nfs_user_stat_path_rec upath_rec
; 
2456         uint bytes_avail
, bytes_total
, recs_copied
; 
2457         uint numExports
, totlen
, pos
, numRecs
, count
; 
2458 #endif /* NFSSERVER */ 
2461          * All names at this level are terminal. 
2464                 return (ENOTDIR
);       /* overloaded */ 
2466         is_64_bit 
= vfs_context_is64bit(ctx
); 
2468         /* common code for "new style" VFS_CTL sysctl, get the mount. */ 
2472         case VFS_CTL_NOLOCKS
: 
2473                 req 
= CAST_DOWN(struct sysctl_req 
*, oldp
); 
2475                         error 
= SYSCTL_IN(req
, &user_vc
, sizeof(user_vc
)); 
2478                         mp 
= vfs_getvfs(&user_vc
.vc_fsid
); 
2480                         error 
= SYSCTL_IN(req
, &vc
, sizeof(vc
)); 
2483                         mp 
= vfs_getvfs(&vc
.vc_fsid
); 
2490                 bzero(&vq
, sizeof(vq
)); 
2493                         req
->newptr 
= user_vc
.vc_ptr
; 
2494                         req
->newlen 
= (size_t)user_vc
.vc_len
; 
2496                         req
->newptr 
= CAST_USER_ADDR_T(vc
.vc_ptr
); 
2497                         req
->newlen 
= vc
.vc_len
; 
2504                         *oldlenp 
= sizeof nfsstats
; 
2508                 if (*oldlenp 
< sizeof nfsstats
) { 
2509                         *oldlenp 
= sizeof nfsstats
; 
2513                 error 
= copyout(&nfsstats
, oldp
, sizeof nfsstats
); 
2517                 if (newp 
&& newlen 
!= sizeof nfsstats
) 
2521                         return copyin(newp
, &nfsstats
, sizeof nfsstats
); 
2524         case NFS_EXPORTSTATS
: 
2525                 /* setup export stat descriptor */ 
2526                 stat_desc
.rec_vers 
= NFS_EXPORT_STAT_REC_VERSION
; 
2528                 if (!nfsrv_is_initialized()) { 
2529                         stat_desc
.rec_count 
= 0; 
2530                         if (oldp 
&& (*oldlenp 
>= sizeof(struct nfs_export_stat_desc
))) 
2531                                 error 
= copyout(&stat_desc
, oldp
, sizeof(struct nfs_export_stat_desc
)); 
2532                         *oldlenp 
= sizeof(struct nfs_export_stat_desc
); 
2536                 /* Count the number of exported directories */ 
2537                 lck_rw_lock_shared(&nfsrv_export_rwlock
); 
2539                 LIST_FOREACH(nxfs
, &nfsrv_exports
, nxfs_next
) 
2540                         LIST_FOREACH(nx
, &nxfs
->nxfs_exports
, nx_next
) 
2543                 /* update stat descriptor's export record count */ 
2544                 stat_desc
.rec_count 
= numExports
; 
2546                 /* calculate total size of required buffer */ 
2547                 totlen 
= sizeof(struct nfs_export_stat_desc
) + (numExports 
* sizeof(struct nfs_export_stat_rec
)); 
2549                 /* Check caller's buffer */ 
2551                         lck_rw_done(&nfsrv_export_rwlock
); 
2552                         /* indicate required buffer len */ 
2557                 /* We require the caller's buffer to be at least large enough to hold the descriptor */ 
2558                 if (*oldlenp 
< sizeof(struct nfs_export_stat_desc
)) { 
2559                         lck_rw_done(&nfsrv_export_rwlock
); 
2560                         /* indicate required buffer len */ 
2565                 /* indicate required buffer len */ 
2568                 /* check if export table is empty */ 
2570                         lck_rw_done(&nfsrv_export_rwlock
); 
2571                         error 
= copyout(&stat_desc
, oldp
, sizeof(struct nfs_export_stat_desc
)); 
2575                 /* calculate how many actual export stat records fit into caller's buffer */ 
2576                 numRecs 
= (*oldlenp 
- sizeof(struct nfs_export_stat_desc
)) / sizeof(struct nfs_export_stat_rec
); 
2579                         /* caller's buffer can only accomodate descriptor */ 
2580                         lck_rw_done(&nfsrv_export_rwlock
); 
2581                         stat_desc
.rec_count 
= 0; 
2582                         error 
= copyout(&stat_desc
, oldp
, sizeof(struct nfs_export_stat_desc
)); 
2586                 /* adjust to actual number of records to copyout to caller's buffer */ 
2587                 if (numRecs 
> numExports
) 
2588                         numRecs 
= numExports
; 
2590                 /* set actual number of records we are returning */ 
2591                 stat_desc
.rec_count 
= numRecs
; 
2593                 /* first copy out the stat descriptor */ 
2595                 error 
= copyout(&stat_desc
, oldp 
+ pos
, sizeof(struct nfs_export_stat_desc
)); 
2597                         lck_rw_done(&nfsrv_export_rwlock
); 
2600                 pos 
+= sizeof(struct nfs_export_stat_desc
); 
2602                 /* Loop through exported directories */ 
2604                 LIST_FOREACH(nxfs
, &nfsrv_exports
, nxfs_next
) { 
2605                         LIST_FOREACH(nx
, &nxfs
->nxfs_exports
, nx_next
) { 
2607                                 if (count 
>= numRecs
) 
2610                                 /* build exported filesystem path */ 
2611                                 snprintf(statrec
.path
, sizeof(statrec
.path
), "%s%s%s", 
2612                                         nxfs
->nxfs_path
, ((nxfs
->nxfs_path
[1] && nx
->nx_path
[0]) ? "/" : ""), 
2615                                 /* build the 64-bit export stat counters */ 
2616                                 statrec
.ops 
= ((uint64_t)nx
->nx_stats
.ops
.hi 
<< 32) | 
2617                                                 nx
->nx_stats
.ops
.lo
; 
2618                                 statrec
.bytes_read 
= ((uint64_t)nx
->nx_stats
.bytes_read
.hi 
<< 32) | 
2619                                                 nx
->nx_stats
.bytes_read
.lo
; 
2620                                 statrec
.bytes_written 
= ((uint64_t)nx
->nx_stats
.bytes_written
.hi 
<< 32) | 
2621                                                 nx
->nx_stats
.bytes_written
.lo
; 
2622                                 error 
= copyout(&statrec
, oldp 
+ pos
, sizeof(statrec
)); 
2624                                         lck_rw_done(&nfsrv_export_rwlock
); 
2627                                 /* advance buffer position */ 
2628                                 pos 
+= sizeof(statrec
); 
2631                 lck_rw_done(&nfsrv_export_rwlock
); 
2634                 /* init structures used for copying out of kernel */ 
2635                 ustat_desc
.rec_vers 
= NFS_USER_STAT_REC_VERSION
; 
2636                 ustat_rec
.rec_type 
= NFS_USER_STAT_USER_REC
; 
2637                 upath_rec
.rec_type 
= NFS_USER_STAT_PATH_REC
; 
2639                 /* initialize counters */ 
2640                 bytes_total 
= sizeof(struct nfs_user_stat_desc
); 
2641                 bytes_avail  
= *oldlenp
; 
2644                 if (!nfsrv_is_initialized()) /* NFS server not initialized, so no stats */ 
2647                 /* reclaim old expired user nodes */ 
2648                 nfsrv_active_user_list_reclaim(); 
2650                 /* reserve space for the buffer descriptor */ 
2651                 if (bytes_avail 
>= sizeof(struct nfs_user_stat_desc
)) 
2652                         bytes_avail 
-= sizeof(struct nfs_user_stat_desc
); 
2656                 /* put buffer position past the buffer descriptor */ 
2657                 pos 
= sizeof(struct nfs_user_stat_desc
); 
2659                 /* Loop through exported directories */ 
2660                 lck_rw_lock_shared(&nfsrv_export_rwlock
); 
2661                 LIST_FOREACH(nxfs
, &nfsrv_exports
, nxfs_next
) { 
2662                         LIST_FOREACH(nx
, &nxfs
->nxfs_exports
, nx_next
) { 
2664                                 if (bytes_avail 
>= sizeof(struct nfs_user_stat_path_rec
)) { 
2665                                         snprintf(upath_rec
.path
, sizeof(upath_rec
.path
), "%s%s%s", 
2666                                             nxfs
->nxfs_path
, ((nxfs
->nxfs_path
[1] && nx
->nx_path
[0]) ? "/" : ""), 
2669                                         error 
= copyout(&upath_rec
, oldp 
+ pos
, sizeof(struct nfs_user_stat_path_rec
)); 
2675                                         pos 
+= sizeof(struct nfs_user_stat_path_rec
); 
2676                                         bytes_avail 
-= sizeof(struct nfs_user_stat_path_rec
); 
2680                                         /* Caller's buffer is exhausted */ 
2684                                 bytes_total 
+= sizeof(struct nfs_user_stat_path_rec
); 
2686                                 /* Scan through all user nodes of this export */ 
2687                                 ulist 
= &nx
->nx_user_list
; 
2688                                 lck_mtx_lock(&ulist
->user_mutex
); 
2689                                 for (unode 
= TAILQ_FIRST(&ulist
->user_lru
); unode
; unode 
= unode_next
) { 
2690                                         unode_next 
= TAILQ_NEXT(unode
, lru_link
); 
2692                                         /* copy out node if there is space */ 
2693                                         if (bytes_avail 
>= sizeof(struct nfs_user_stat_user_rec
)) { 
2694                                                 /* prepare a user stat rec for copying out */ 
2695                                                 ustat_rec
.uid 
= unode
->uid
; 
2696                                                 bcopy(&unode
->sock
, &ustat_rec
.sock
, unode
->sock
.ss_len
); 
2697                                                 ustat_rec
.ops 
= unode
->ops
; 
2698                                                 ustat_rec
.bytes_read 
= unode
->bytes_read
; 
2699                                                 ustat_rec
.bytes_written 
= unode
->bytes_written
; 
2700                                                 ustat_rec
.tm_start 
= unode
->tm_start
; 
2701                                                 ustat_rec
.tm_last 
= unode
->tm_last
; 
2703                                                 error 
= copyout(&ustat_rec
, oldp 
+ pos
, sizeof(struct nfs_user_stat_user_rec
)); 
2707                                                         lck_mtx_unlock(&ulist
->user_mutex
); 
2711                                                 pos 
+= sizeof(struct nfs_user_stat_user_rec
); 
2712                                                 bytes_avail 
-= sizeof(struct nfs_user_stat_user_rec
); 
2716                                                 /* Caller's buffer is exhausted */ 
2719                                         bytes_total 
+= sizeof(struct nfs_user_stat_user_rec
); 
2721                                 /* can unlock this export's list now */ 
2722                                 lck_mtx_unlock(&ulist
->user_mutex
); 
2727                 /* unlock the export table */ 
2728                 lck_rw_done(&nfsrv_export_rwlock
); 
2731                 /* indicate number of actual records copied */ 
2732                 ustat_desc
.rec_count 
= recs_copied
; 
2735                         /* check if there was enough room for the buffer descriptor */ 
2736                         if (*oldlenp 
>= sizeof(struct nfs_user_stat_desc
)) 
2737                                 error 
= copyout(&ustat_desc
, oldp
, sizeof(struct nfs_user_stat_desc
)); 
2741                         /* always indicate required buffer size */ 
2742                         *oldlenp 
= bytes_total
; 
2747                         *oldlenp 
= sizeof(nfsrv_user_stat_node_count
); 
2751                 if (*oldlenp 
< sizeof(nfsrv_user_stat_node_count
)) { 
2752                         *oldlenp 
= sizeof(nfsrv_user_stat_node_count
); 
2756                 if (nfsrv_is_initialized()) { 
2757                         /* reclaim old expired user nodes */ 
2758                         nfsrv_active_user_list_reclaim(); 
2761                 error 
= copyout(&nfsrv_user_stat_node_count
, oldp
, sizeof(nfsrv_user_stat_node_count
)); 
2763 #endif /* NFSSERVER */ 
2764         case VFS_CTL_NOLOCKS
: 
2765                 if (req
->oldptr 
!= USER_ADDR_NULL
) { 
2766                         lck_mtx_lock(&nmp
->nm_lock
); 
2767                         val 
= (nmp
->nm_flag 
& NFSMNT_NOLOCKS
) ? 1 : 0; 
2768                         lck_mtx_unlock(&nmp
->nm_lock
); 
2769                         error 
= SYSCTL_OUT(req
, &val
, sizeof(val
)); 
2773                 if (req
->newptr 
!= USER_ADDR_NULL
) { 
2774                         error 
= SYSCTL_IN(req
, &val
, sizeof(val
)); 
2777                         lck_mtx_lock(&nmp
->nm_lock
); 
2778                         if (nmp
->nm_flag 
& NFSMNT_LOCALLOCKS
) { 
2779                                 /* can't toggle locks when using local locks */ 
2782                                 if (!(nmp
->nm_flag 
& NFSMNT_NOLOCKS
)) 
2783                                         nfs_lockd_mount_change(-1); 
2784                                 nmp
->nm_flag 
|= NFSMNT_NOLOCKS
; 
2785                                 nmp
->nm_state 
&= ~NFSSTA_LOCKTIMEO
; 
2787                                 if (nmp
->nm_flag 
& NFSMNT_NOLOCKS
) 
2788                                         nfs_lockd_mount_change(1); 
2789                                 nmp
->nm_flag 
&= ~NFSMNT_NOLOCKS
; 
2791                         lck_mtx_unlock(&nmp
->nm_lock
); 
2795                 lck_mtx_lock(&nmp
->nm_lock
); 
2796                 /* XXX don't allow users to know about/disconnect unresponsive, soft, nobrowse mounts */ 
2797                 softnobrowse 
= ((nmp
->nm_flag 
& NFSMNT_SOFT
) && (vfs_flags(nmp
->nm_mountp
) & MNT_DONTBROWSE
)); 
2798                 if (!softnobrowse 
&& (nmp
->nm_state 
& (NFSSTA_TIMEO
|NFSSTA_JUKEBOXTIMEO
))) 
2799                         vq
.vq_flags 
|= VQ_NOTRESP
; 
2800                 if (!softnobrowse 
&& !(nmp
->nm_flag 
& (NFSMNT_NOLOCKS
|NFSMNT_LOCALLOCKS
)) && 
2801                     (nmp
->nm_state 
& NFSSTA_LOCKTIMEO
)) 
2802                         vq
.vq_flags 
|= VQ_NOTRESP
; 
2803                 lck_mtx_unlock(&nmp
->nm_lock
); 
2804                 error 
= SYSCTL_OUT(req
, &vq
, sizeof(vq
)); 
2807                 if (req
->oldptr 
!= USER_ADDR_NULL
) { 
2808                         lck_mtx_lock(&nmp
->nm_lock
); 
2809                         val 
= nmp
->nm_tprintf_initial_delay
; 
2810                         lck_mtx_unlock(&nmp
->nm_lock
); 
2811                         error 
= SYSCTL_OUT(req
, &val
, sizeof(val
)); 
2815                 if (req
->newptr 
!= USER_ADDR_NULL
) { 
2816                         error 
= SYSCTL_IN(req
, &val
, sizeof(val
)); 
2819                         lck_mtx_lock(&nmp
->nm_lock
); 
2821                                 nmp
->nm_tprintf_initial_delay 
= 0; 
2823                                 nmp
->nm_tprintf_initial_delay 
= val
; 
2824                         lck_mtx_unlock(&nmp
->nm_lock
);