1/*
2 * Copyright (c) 2000-2008 Apple Inc.  All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
29/*
30 * Copyright (c) 1989, 1993, 1995
31 *	The Regents of the University of California.  All rights reserved.
32 *
33 * This code is derived from software contributed to Berkeley by
34 * Rick Macklem at The University of Guelph.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
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.
51 *
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
62 * SUCH DAMAGE.
63 *
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 $
66 */
67/*
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,
71 * Version 2.0.
72 */
73
74#include <sys/param.h>
75#include <sys/systm.h>
76#include <sys/conf.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>
92
93#include <sys/vm.h>
94#include <sys/vmparam.h>
95
96#if !defined(NO_MOUNT_PRIVATE)
97#include <sys/filedesc.h>
98#endif /* NO_MOUNT_PRIVATE */
99
100#include <net/if.h>
101#include <net/route.h>
102#include <netinet/in.h>
103
104#include <nfs/rpcv2.h>
105#include <nfs/krpc.h>
106#include <nfs/nfsproto.h>
107#include <nfs/nfs.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>
115#if CONFIG_MACF
116#include <security/mac_framework.h>
117#endif
118
119#include <pexpert/pexpert.h>
120
121/*
122 * NFS client globals
123 */
124
125int nfs_ticks;
126static lck_grp_t *nfs_mount_grp;
127uint32_t nfs_fs_attr_bitmap[NFS_ATTR_BITMAP_LEN];
128uint32_t nfs_object_attr_bitmap[NFS_ATTR_BITMAP_LEN];
129uint32_t nfs_getattr_bitmap[NFS_ATTR_BITMAP_LEN];
130
131/* NFS requests */
132struct nfs_reqqhead nfs_reqq;
133lck_grp_t *nfs_request_grp;
134lck_mtx_t *nfs_request_mutex;
135thread_call_t nfs_request_timer_call;
136int nfs_request_timer_on;
137u_long nfs_xid = 0;
138u_long nfs_xidwrap = 0;		/* to build a (non-wrapping) 64 bit xid */
139
140thread_call_t nfs_buf_timer_call;
141
142/* nfsiod */
143lck_grp_t *nfsiod_lck_grp;
144lck_mtx_t *nfsiod_mutex;
145struct nfsiodlist nfsiodfree, nfsiodwork;
146struct nfsiodmountlist nfsiodmounts;
147int nfsiod_thread_count = 0;
148int nfsiod_thread_max = NFS_DEFASYNCTHREAD;
149int nfs_max_async_writes = NFS_DEFMAXASYNCWRITES;
150
151int nfs_iosize = NFS_IOSIZE;
152int nfs_access_cache_timeout = NFS_MAXATTRTIMO;
153int nfs_allow_async = 0;
154int nfs_statfs_rate_limit = NFS_DEFSTATFSRATELIMIT;
155int nfs_lockd_mounts = 0;
156int nfs_lockd_request_sent = 0;
157
158int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
159int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
160
161
162static int	mountnfs(struct user_nfs_args *,mount_t,mbuf_t,vfs_context_t,vnode_t *);
163static int	nfs_mount_diskless(struct nfs_dlmount *, const char *, int, vnode_t *, mount_t *, vfs_context_t);
164#if !defined(NO_MOUNT_PRIVATE)
165static int	nfs_mount_diskless_private(struct nfs_dlmount *, const char *, int, vnode_t *, mount_t *, vfs_context_t);
166#endif /* NO_MOUNT_PRIVATE */
167
168/*
169 * NFS VFS operations.
170 */
171static int	nfs_vfs_mount(mount_t, vnode_t, user_addr_t, vfs_context_t);
172static int	nfs_vfs_start(mount_t, int, vfs_context_t);
173static int	nfs_vfs_unmount(mount_t, int, vfs_context_t);
174static int	nfs_vfs_root(mount_t, vnode_t *, vfs_context_t);
175static int	nfs_vfs_quotactl(mount_t, int, uid_t, caddr_t, vfs_context_t);
176static int	nfs_vfs_getattr(mount_t, struct vfs_attr *, vfs_context_t);
177static int	nfs_vfs_sync(mount_t, int, vfs_context_t);
178static int	nfs_vfs_vget(mount_t, ino64_t, vnode_t *, vfs_context_t);
179static int	nfs_vfs_vptofh(vnode_t, int *, unsigned char *, vfs_context_t);
180static int	nfs_vfs_fhtovp(mount_t, int, unsigned char *, vnode_t *, vfs_context_t);
181static int	nfs_vfs_init(struct vfsconf *);
182static int	nfs_vfs_sysctl(int *, u_int, user_addr_t, size_t *, user_addr_t, size_t, vfs_context_t);
183
184struct vfsops nfs_vfsops = {
185	nfs_vfs_mount,
186	nfs_vfs_start,
187	nfs_vfs_unmount,
188	nfs_vfs_root,
189	nfs_vfs_quotactl,
190	nfs_vfs_getattr,
191	nfs_vfs_sync,
192	nfs_vfs_vget,
193	nfs_vfs_fhtovp,
194	nfs_vfs_vptofh,
195	nfs_vfs_init,
196	nfs_vfs_sysctl,
197	NULL,		/* setattr */
198	{ NULL,		/* reserved */
199	  NULL,		/* reserved */
200	  NULL,		/* reserved */
201	  NULL,		/* reserved */
202	  NULL,		/* reserved */
203	  NULL,		/* reserved */
204	  NULL }	/* reserved */
205};
206
207
208/*
209 * version-specific NFS functions
210 */
211static int nfs3_mount(struct nfsmount *, vfs_context_t, struct user_nfs_args *, nfsnode_t *);
212static int nfs4_mount(struct nfsmount *, vfs_context_t, struct user_nfs_args *, nfsnode_t *);
213static int nfs3_update_statfs(struct nfsmount *, vfs_context_t);
214static int nfs4_update_statfs(struct nfsmount *, vfs_context_t);
215#if !QUOTA
216#define nfs3_getquota	NULL
217#define nfs4_getquota	NULL
218#else
219static int nfs3_getquota(struct nfsmount *, vfs_context_t, u_long, int, struct dqblk *);
220static int nfs4_getquota(struct nfsmount *, vfs_context_t, u_long, int, struct dqblk *);
221#endif
222
223struct nfs_funcs nfs3_funcs = {
224	nfs3_mount,
225	nfs3_update_statfs,
226	nfs3_getquota,
227	nfs3_access_rpc,
228	nfs3_getattr_rpc,
229	nfs3_setattr_rpc,
230	nfs3_read_rpc_async,
231	nfs3_read_rpc_async_finish,
232	nfs3_readlink_rpc,
233	nfs3_write_rpc_async,
234	nfs3_write_rpc_async_finish,
235	nfs3_commit_rpc,
236	nfs3_lookup_rpc_async,
237	nfs3_lookup_rpc_async_finish,
238	nfs3_remove_rpc,
239	nfs3_rename_rpc
240	};
241struct nfs_funcs nfs4_funcs = {
242	nfs4_mount,
243	nfs4_update_statfs,
244	nfs4_getquota,
245	nfs4_access_rpc,
246	nfs4_getattr_rpc,
247	nfs4_setattr_rpc,
248	nfs4_read_rpc_async,
249	nfs4_read_rpc_async_finish,
250	nfs4_readlink_rpc,
251	nfs4_write_rpc_async,
252	nfs4_write_rpc_async_finish,
253	nfs4_commit_rpc,
254	nfs4_lookup_rpc_async,
255	nfs4_lookup_rpc_async_finish,
256	nfs4_remove_rpc,
257	nfs4_rename_rpc
258	};
259
260/*
261 * Called once to initialize data structures...
262 */
263static int
264nfs_vfs_init(struct vfsconf *vfsp)
265{
266	int i;
267
268	/*
269	 * Check to see if major data structures haven't bloated.
270	 */
271	if (sizeof (struct nfsnode) > NFS_NODEALLOC) {
272		printf("struct nfsnode bloated (> %dbytes)\n", NFS_NODEALLOC);
273		printf("Try reducing NFS_SMALLFH\n");
274	}
275	if (sizeof (struct nfsmount) > NFS_MNTALLOC) {
276		printf("struct nfsmount bloated (> %dbytes)\n", NFS_MNTALLOC);
277		printf("Try reducing NFS_MUIDHASHSIZ\n");
278	}
279
280	nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
281	if (nfs_ticks < 1)
282		nfs_ticks = 1;
283
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);
290
291	/* init mount lock group */
292	nfs_mount_grp = lck_grp_alloc_init("nfs_mount", LCK_GRP_ATTR_NULL);
293
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);
297
298	/* initialize NFS request list */
299	TAILQ_INIT(&nfs_reqq);
300
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 */
305
306	/* NFSv4 stuff */
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];
312
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);
316
317	vfsp->vfc_refcount++; /* make us non-unloadable */
318	return (0);
319}
320
321/*
322 * nfs statfs call
323 */
324static int
325nfs3_update_statfs(struct nfsmount *nmp, vfs_context_t ctx)
326{
327	nfsnode_t np;
328	int error = 0, lockerror, status, nfsvers;
329	u_int64_t xid;
330	struct nfsm_chain nmreq, nmrep;
331	uint32_t val;
332
333	nfsvers = nmp->nm_vers;
334	np = nmp->nm_dnp;
335	if ((error = vnode_get(NFSTOV(np))))
336		return(error);
337
338	nfsm_chain_null(&nmreq);
339	nfsm_chain_null(&nmrep);
340
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);
344	nfsmout_if(error);
345	error = nfs_request(np, NULL, &nmreq, NFSPROC_FSSTAT, ctx,
346		   &nmrep, &xid, &status);
347	if ((lockerror = nfs_lock(np, NFS_NODE_LOCK_EXCLUSIVE)))
348		error = lockerror;
349	if (nfsvers == NFS_VER3)
350		nfsm_chain_postop_attr_update(error, &nmrep, np, &xid);
351	if (!lockerror)
352		nfs_unlock(np);
353	if (!error)
354		error = status;
355	nfsm_assert(error, NFSTONMP(np), ENXIO);
356	nfsmout_if(error);
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);
372		// skip invarsec
373	} else {
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);
377		nfsmout_if(error);
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);
382		nfsmout_if(error);
383		nmp->nm_fsattr.nfsa_space_free = (uint64_t)val * nmp->nm_fsattr.nfsa_bsize;
384		nfsm_chain_get_32(error, &nmrep, val);
385		nfsmout_if(error);
386		nmp->nm_fsattr.nfsa_space_avail = (uint64_t)val * nmp->nm_fsattr.nfsa_bsize;
387	}
388	lck_mtx_unlock(&nmp->nm_lock);
389nfsmout:
390	nfsm_chain_cleanup(&nmreq);
391	nfsm_chain_cleanup(&nmrep);
392	vnode_put(NFSTOV(np));
393	return (error);
394}
395
396static int
397nfs4_update_statfs(struct nfsmount *nmp, vfs_context_t ctx)
398{
399	nfsnode_t np;
400	int error = 0, lockerror, status, nfsvers, numops;
401	u_int64_t xid;
402	struct nfsm_chain nmreq, nmrep;
403	uint32_t bitmap[NFS_ATTR_BITMAP_LEN];
404	struct nfs_vattr nvattr;
405
406	nfsvers = nmp->nm_vers;
407	np = nmp->nm_dnp;
408	if ((error = vnode_get(NFSTOV(np))))
409		return(error);
410
411	nfsm_chain_null(&nmreq);
412	nfsm_chain_null(&nmrep);
413
414	// PUTFH + GETATTR
415	numops = 2;
416	nfsm_chain_build_alloc_init(error, &nmreq, 15 * NFSX_UNSIGNED);
417	nfsm_chain_add_compound_header(error, &nmreq, "statfs", numops);
418	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);
421	numops--;
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);
429	nfsmout_if(error);
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);
436	nfsmout_if(error);
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);
441	nfsmout_if(error);
442	if ((lockerror = nfs_lock(np, NFS_NODE_LOCK_EXCLUSIVE)))
443		error = lockerror;
444	if (!error)
445		nfs_loadattrcache(np, &nvattr, &xid, 0);
446	if (!lockerror)
447		nfs_unlock(np);
448	nfsm_assert(error, NFSTONMP(np), ENXIO);
449	nfsmout_if(error);
450	nmp->nm_fsattr.nfsa_bsize = NFS_FABLKSIZE;
451nfsmout:
452	nfsm_chain_cleanup(&nmreq);
453	nfsm_chain_cleanup(&nmrep);
454	vnode_put(NFSTOV(np));
455	return (error);
456}
457
458
459/*
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).
463 */
464static int
465nfs_vfs_getattr(mount_t mp, struct vfs_attr *fsap, vfs_context_t ctx)
466{
467	struct nfsmount *nmp;
468	uint32_t bsize;
469	int error = 0, nfsvers;
470
471	if (!(nmp = VFSTONFS(mp)))
472		return (ENXIO);
473	nfsvers = nmp->nm_vers;
474
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;
484		int refresh = 1;
485
486		/*
487		 * Are we rate-limiting statfs RPCs?
488		 * (Treat values less than 1 or greater than 1,000,000 as no limit.)
489		 */
490		if ((statfsrate > 0) && (statfsrate < 1000000)) {
491			struct timeval now;
492			uint32_t stamp;
493
494			microuptime(&now);
495			lck_mtx_lock(&nmp->nm_lock);
496			stamp = (now.tv_sec * statfsrate) + (now.tv_usec / (1000000/statfsrate));
497			if (stamp != nmp->nm_fsattrstamp) {
498				refresh = 1;
499				nmp->nm_fsattrstamp = stamp;
500			} else {
501				refresh = 0;
502			}
503			lck_mtx_unlock(&nmp->nm_lock);
504		}
505
506		if (refresh)
507			error = nmp->nm_funcs->nf_update_statfs(nmp, ctx);
508		if ((error == ESTALE) || (error == ETIMEDOUT))
509			error = 0;
510		if (error)
511			return (error);
512
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);
533	}
534
535	if (VFSATTR_IS_ACTIVE(fsap, f_capabilities)) {
536		u_int32_t caps, valid;
537		nfsnode_t np;
538
539		nfsm_assert(error, VFSTONFS(mp), ENXIO);
540		if (error)
541			return (error);
542		np = nmp->nm_dnp;
543		lck_mtx_lock(&nmp->nm_lock);
544
545		/*
546		 * The capabilities[] array defines what this volume supports.
547		 *
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
552		 * present or not.
553		 */
554		caps = valid = 0;
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;
559		}
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;
564		}
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;
569		}
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;
574		}
575		/* Note: VOL_CAP_FMT_2TB_FILESIZE is actually used to test for "large file support" */
576		if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXFILESIZE)) {
577			/* Is server's max file size at least 4GB? */
578			if (nmp->nm_fsattr.nfsa_maxfilesize >= 0x100000000ULL)
579				caps |= VOL_CAP_FMT_2TB_FILESIZE;
580		} else if (nfsvers >= NFS_VER3) {
581			/*
582			 * NFSv3 and up supports 64 bits of file size.
583			 * So, we'll just assume maxfilesize >= 4GB
584			 */
585			caps |= VOL_CAP_FMT_2TB_FILESIZE;
586		}
587		if (nfsvers >= NFS_VER4) {
588			caps |= VOL_CAP_FMT_HIDDEN_FILES;
589			valid |= VOL_CAP_FMT_HIDDEN_FILES;
590			// VOL_CAP_FMT_OPENDENYMODES
591		}
592		fsap->f_capabilities.capabilities[VOL_CAPABILITIES_FORMAT] =
593			// VOL_CAP_FMT_PERSISTENTOBJECTIDS |
594			// VOL_CAP_FMT_SYMBOLICLINKS |
595			// VOL_CAP_FMT_HARDLINKS |
596			// VOL_CAP_FMT_JOURNAL |
597			// VOL_CAP_FMT_JOURNAL_ACTIVE |
598			// VOL_CAP_FMT_NO_ROOT_TIMES |
599			// VOL_CAP_FMT_SPARSE_FILES |
600			// VOL_CAP_FMT_ZERO_RUNS |
601			// VOL_CAP_FMT_CASE_SENSITIVE |
602			// VOL_CAP_FMT_CASE_PRESERVING |
603			// VOL_CAP_FMT_FAST_STATFS |
604			// VOL_CAP_FMT_2TB_FILESIZE |
605			// VOL_CAP_FMT_OPENDENYMODES |
606			// VOL_CAP_FMT_HIDDEN_FILES |
607			caps;
608		fsap->f_capabilities.valid[VOL_CAPABILITIES_FORMAT] =
609			VOL_CAP_FMT_PERSISTENTOBJECTIDS |
610			// VOL_CAP_FMT_SYMBOLICLINKS |
611			// VOL_CAP_FMT_HARDLINKS |
612			// VOL_CAP_FMT_JOURNAL |
613			// VOL_CAP_FMT_JOURNAL_ACTIVE |
614			// VOL_CAP_FMT_NO_ROOT_TIMES |
615			// VOL_CAP_FMT_SPARSE_FILES |
616			// VOL_CAP_FMT_ZERO_RUNS |
617			// VOL_CAP_FMT_CASE_SENSITIVE |
618			// VOL_CAP_FMT_CASE_PRESERVING |
619			VOL_CAP_FMT_FAST_STATFS |
620			VOL_CAP_FMT_2TB_FILESIZE |
621			// VOL_CAP_FMT_OPENDENYMODES |
622			// VOL_CAP_FMT_HIDDEN_FILES |
623			valid;
624
625		/*
626		 * We don't support most of the interfaces.
627		 *
628		 * We MAY support locking, but we don't have any easy way of probing.
629		 * We can tell if there's no lockd running or if locks have been
630		 * disabled for a mount, so we can definitely answer NO in that case.
631		 * Any attempt to send a request to lockd to test for locking support
632		 * may cause the lazily-launched locking daemons to be started
633		 * unnecessarily.  So we avoid that.  However, we do record if we ever
634		 * successfully perform a lock operation on a mount point, so if it
635		 * looks like lock ops have worked, we do report that we support them.
636		 */
637		caps = valid = 0;
638		if (nfsvers >= NFS_VER4) {
639			caps = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
640			valid = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
641			// VOL_CAP_INT_EXTENDED_SECURITY
642			// VOL_CAP_INT_NAMEDSTREAMS
643			// VOL_CAP_INT_EXTENDED_ATTR
644		} else if ((nmp->nm_flag & NFSMNT_NOLOCKS)) {
645			/* locks disabled on this mount, so they definitely won't work */
646			valid = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
647		} else if (nmp->nm_state & NFSSTA_LOCKSWORK) {
648			caps = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
649			valid = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
650		}
651		fsap->f_capabilities.capabilities[VOL_CAPABILITIES_INTERFACES] =
652			// VOL_CAP_INT_SEARCHFS |
653			// VOL_CAP_INT_ATTRLIST |
654			// VOL_CAP_INT_NFSEXPORT |
655			// VOL_CAP_INT_READDIRATTR |
656			// VOL_CAP_INT_EXCHANGEDATA |
657			// VOL_CAP_INT_COPYFILE |
658			// VOL_CAP_INT_ALLOCATE |
659			// VOL_CAP_INT_VOL_RENAME |
660			// VOL_CAP_INT_ADVLOCK |
661			// VOL_CAP_INT_FLOCK |
662			// VOL_CAP_INT_EXTENDED_SECURITY |
663			// VOL_CAP_INT_USERACCESS |
664			// VOL_CAP_INT_MANLOCK |
665			// VOL_CAP_INT_NAMEDSTREAMS |
666			// VOL_CAP_INT_EXTENDED_ATTR |
667			caps;
668		fsap->f_capabilities.valid[VOL_CAPABILITIES_INTERFACES] =
669			VOL_CAP_INT_SEARCHFS |
670			VOL_CAP_INT_ATTRLIST |
671			VOL_CAP_INT_NFSEXPORT |
672			VOL_CAP_INT_READDIRATTR |
673			VOL_CAP_INT_EXCHANGEDATA |
674			VOL_CAP_INT_COPYFILE |
675			VOL_CAP_INT_ALLOCATE |
676			VOL_CAP_INT_VOL_RENAME |
677			// VOL_CAP_INT_ADVLOCK |
678			// VOL_CAP_INT_FLOCK |
679			// VOL_CAP_INT_EXTENDED_SECURITY |
680			// VOL_CAP_INT_USERACCESS |
681			// VOL_CAP_INT_MANLOCK |
682			// VOL_CAP_INT_NAMEDSTREAMS |
683			// VOL_CAP_INT_EXTENDED_ATTR |
684			valid;
685
686		fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED1] = 0;
687		fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED1] = 0;
688
689		fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED2] = 0;
690		fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED2] = 0;
691
692		VFSATTR_SET_SUPPORTED(fsap, f_capabilities);
693		lck_mtx_unlock(&nmp->nm_lock);
694	}
695
696	if (VFSATTR_IS_ACTIVE(fsap, f_attributes)) {
697		fsap->f_attributes.validattr.commonattr = 0;
698		fsap->f_attributes.validattr.volattr =
699			ATTR_VOL_CAPABILITIES | ATTR_VOL_ATTRIBUTES;
700		fsap->f_attributes.validattr.dirattr = 0;
701		fsap->f_attributes.validattr.fileattr = 0;
702		fsap->f_attributes.validattr.forkattr = 0;
703
704		fsap->f_attributes.nativeattr.commonattr = 0;
705		fsap->f_attributes.nativeattr.volattr =
706			ATTR_VOL_CAPABILITIES | ATTR_VOL_ATTRIBUTES;
707		fsap->f_attributes.nativeattr.dirattr = 0;
708		fsap->f_attributes.nativeattr.fileattr = 0;
709		fsap->f_attributes.nativeattr.forkattr = 0;
710
711		VFSATTR_SET_SUPPORTED(fsap, f_attributes);
712	}
713
714	return (error);
715}
716
717/*
718 * nfs version 3 fsinfo rpc call
719 */
720static int
721nfs3_fsinfo(struct nfsmount *nmp, nfsnode_t np, vfs_context_t ctx)
722{
723	int error = 0, lockerror, status, prefsize, maxsize, nmlocked = 0;
724	u_int64_t xid;
725	uint32_t val;
726	struct nfsm_chain nmreq, nmrep;
727
728	nfsm_chain_null(&nmreq);
729	nfsm_chain_null(&nmrep);
730
731	nfsm_chain_build_alloc_init(error, &nmreq, NFSX_FH(nmp->nm_vers));
732	nfsm_chain_add_fh(error, &nmreq, nmp->nm_vers, np->n_fhp, np->n_fhsize);
733	nfsm_chain_build_done(error, &nmreq);
734	nfsmout_if(error);
735	error = nfs_request(np, NULL, &nmreq, NFSPROC_FSINFO, ctx,
736			&nmrep, &xid, &status);
737	if ((lockerror = nfs_lock(np, NFS_NODE_LOCK_EXCLUSIVE)))
738		error = lockerror;
739	nfsm_chain_postop_attr_update(error, &nmrep, np, &xid);
740	if (!lockerror)
741		nfs_unlock(np);
742	if (!error)
743		error = status;
744	nfsmout_if(error);
745
746	lck_mtx_lock(&nmp->nm_lock);
747	nmlocked = 1;
748
749	nfsm_chain_get_32(error, &nmrep, maxsize);
750	nfsm_chain_get_32(error, &nmrep, prefsize);
751	nfsmout_if(error);
752	nmp->nm_fsattr.nfsa_maxread = maxsize;
753	if (prefsize < nmp->nm_rsize)
754		nmp->nm_rsize = (prefsize + NFS_FABLKSIZE - 1) &
755			~(NFS_FABLKSIZE - 1);
756	if (maxsize < nmp->nm_rsize) {
757		nmp->nm_rsize = maxsize & ~(NFS_FABLKSIZE - 1);
758		if (nmp->nm_rsize == 0)
759			nmp->nm_rsize = maxsize;
760	}
761	nfsm_chain_adv(error, &nmrep, NFSX_UNSIGNED); // skip rtmult
762
763	nfsm_chain_get_32(error, &nmrep, maxsize);
764	nfsm_chain_get_32(error, &nmrep, prefsize);
765	nfsmout_if(error);
766	nmp->nm_fsattr.nfsa_maxwrite = maxsize;
767	if (prefsize < nmp->nm_wsize)
768		nmp->nm_wsize = (prefsize + NFS_FABLKSIZE - 1) &
769			~(NFS_FABLKSIZE - 1);
770	if (maxsize < nmp->nm_wsize) {
771		nmp->nm_wsize = maxsize & ~(NFS_FABLKSIZE - 1);
772		if (nmp->nm_wsize == 0)
773			nmp->nm_wsize = maxsize;
774	}
775	nfsm_chain_adv(error, &nmrep, NFSX_UNSIGNED); // skip wtmult
776
777	nfsm_chain_get_32(error, &nmrep, prefsize);
778	nfsmout_if(error);
779	if (prefsize < nmp->nm_readdirsize)
780		nmp->nm_readdirsize = prefsize;
781	if (maxsize < nmp->nm_readdirsize)
782		nmp->nm_readdirsize = maxsize;
783
784	nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_maxfilesize);
785
786	nfsm_chain_adv(error, &nmrep, 2 * NFSX_UNSIGNED); // skip time_delta
787
788	/* convert FS properties to our own flags */
789	nfsm_chain_get_32(error, &nmrep, val);
790	nfsmout_if(error);
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);
807nfsmout:
808	if (nmlocked)
809		lck_mtx_unlock(&nmp->nm_lock);
810	nfsm_chain_cleanup(&nmreq);
811	nfsm_chain_cleanup(&nmrep);
812	return (error);
813}
814
815/*
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
818 * bootstrap.
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
823 *   a default gateway.
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.
827 */
828int
829nfs_mountroot(void)
830{
831	struct nfs_diskless nd;
832	struct nfs_vattr nvattr;
833	mount_t mp = NULL;
834	vnode_t vp = NULL;
835	vfs_context_t ctx;
836	int error;
837#if !defined(NO_MOUNT_PRIVATE)
838	mount_t mppriv = NULL;
839	vnode_t vppriv = NULL;
840#endif /* NO_MOUNT_PRIVATE */
841	int v3, sotype;
842
843	/*
844	 * Call nfs_boot_init() to fill in the nfs_diskless struct.
845	 * Note: networking must already have been configured before
846	 * we're called.
847	 */
848	bzero((caddr_t) &nd, sizeof(nd));
849	error = nfs_boot_init(&nd);
850	if (error) {
851		panic("nfs_boot_init failed with %d\n", error);
852	}
853
854	/*
855	 * Try NFSv3 first, then fallback to NFSv2.
856	 * Likewise, try TCP first, then fall back to UDP.
857	 */
858	v3 = 1;
859	sotype = SOCK_STREAM;
860
861tryagain:
862	error = nfs_boot_getfh(&nd, v3, sotype);
863	if (error) {
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);
871			return (error);
872		}
873		if (v3) {
874			if (sotype == SOCK_STREAM) {
875				printf("nfs_boot_getfh(v3,TCP) failed with %d, trying UDP...\n", error);
876				sotype = SOCK_DGRAM;
877				goto tryagain;
878			}
879			printf("nfs_boot_getfh(v3,UDP) failed with %d, trying v2...\n", error);
880			v3 = 0;
881			sotype = SOCK_STREAM;
882			goto tryagain;
883		} else if (sotype == SOCK_STREAM) {
884			printf("nfs_boot_getfh(v2,TCP) failed with %d, trying UDP...\n", error);
885			sotype = SOCK_DGRAM;
886			goto tryagain;
887		}
888		switch(error) {
889		case EPROGUNAVAIL:
890			panic("nfs_boot_getfh(v2,UDP) failed: NFS server mountd not responding - check server configuration: %s", PE_boot_args());
891		case EACCES:
892		case EPERM:
893			panic("nfs_boot_getfh(v2,UDP) failed: NFS server refused mount - check server configuration: %s", PE_boot_args());
894		default:
895			panic("nfs_boot_getfh(v2,UDP) failed with %d: %s", error, PE_boot_args());
896		}
897	}
898
899	ctx = vfs_context_kernel();
900
901	/*
902	 * Create the root mount point.
903	 */
904#if !defined(NO_MOUNT_PRIVATE)
905	{
906		//PWC hack until we have a real "mount" tool to remount root rw
907		int rw_root=0;
908		int flags = MNT_ROOTFS|MNT_RDONLY;
909		PE_parse_boot_argn("-rwroot_hack", &rw_root, sizeof (rw_root));
910		if(rw_root)
911		{
912			flags = MNT_ROOTFS;
913			kprintf("-rwroot_hack in effect: mounting root fs read/write\n");
914		}
915
916	if ((error = nfs_mount_diskless(&nd.nd_root, "/", flags, &vp, &mp, ctx)))
917#else
918	if ((error = nfs_mount_diskless(&nd.nd_root, "/", MNT_ROOTFS, &vp, &mp, ctx)))
919#endif /* NO_MOUNT_PRIVATE */
920	{
921		if (v3) {
922			if (sotype == SOCK_STREAM) {
923				printf("nfs_mount_diskless(v3,TCP) failed with %d, trying UDP...\n", error);
924				sotype = SOCK_DGRAM;
925				goto tryagain;
926			}
927			printf("nfs_mount_diskless(v3,UDP) failed with %d, trying v2...\n", error);
928			v3 = 0;
929			sotype = SOCK_STREAM;
930			goto tryagain;
931		} else if (sotype == SOCK_STREAM) {
932			printf("nfs_mount_diskless(v2,TCP) failed with %d, trying UDP...\n", error);
933			sotype = SOCK_DGRAM;
934			goto tryagain;
935		}
936		panic("nfs_mount_diskless(v2,UDP) root failed with %d: %s\n", error, PE_boot_args());
937	}
938	}
939	printf("root on %s\n", (char *)&nd.nd_root.ndm_host);
940
941	vfs_unbusy(mp);
942	mount_list_add(mp);
943	rootvp = vp;
944
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);
949	    if (error) {
950		panic("nfs_mount_diskless private failed with %d\n", error);
951	    }
952	    printf("private on %s\n", (char *)&nd.nd_private.ndm_host);
953
954	    vfs_unbusy(mppriv);
955	    mount_list_add(mppriv);
956	}
957
958#endif /* NO_MOUNT_PRIVATE */
959
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);
964
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");
968	return (0);
969}
970
971/*
972 * Internal version of mount system call for diskless setup.
973 */
974static int
975nfs_mount_diskless(
976	struct nfs_dlmount *ndmntp,
977	const char *mntname,
978	int mntflag,
979	vnode_t *vpp,
980	mount_t *mpp,
981	vfs_context_t ctx)
982{
983	struct user_nfs_args args;
984	mount_t mp;
985	mbuf_t m;
986	int error;
987
988	if ((error = vfs_rootmountalloc("nfs", ndmntp->ndm_host, &mp))) {
989		printf("nfs_mount_diskless: NFS not configured");
990		return (error);
991	}
992
993	mp->mnt_flag |= mntflag;
994	if (!(mntflag & MNT_RDONLY))
995		mp->mnt_flag &= ~MNT_RDONLY;
996
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;
1008
1009	error = mbuf_get(MBUF_WAITOK, MBUF_TYPE_SONAME, &m);
1010	if (error) {
1011		printf("nfs_mount_diskless: mbuf_get(soname) failed");
1012		return (error);
1013	}
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);
1019		mount_list_lock();
1020		mp->mnt_vtable->vfc_refcount--;
1021		mount_list_unlock();
1022		vfs_unbusy(mp);
1023		mount_lock_destroy(mp);
1024#if CONFIG_MACF
1025		mac_mount_label_destroy(mp);
1026#endif
1027		FREE_ZONE(mp, sizeof(struct mount), M_MOUNT);
1028		return (error);
1029	}
1030	*mpp = mp;
1031	return (0);
1032}
1033
1034#if !defined(NO_MOUNT_PRIVATE)
1035/*
1036 * Internal version of mount system call to mount "/private"
1037 * separately in diskless setup
1038 */
1039static int
1040nfs_mount_diskless_private(
1041	struct nfs_dlmount *ndmntp,
1042	const char *mntname,
1043	int mntflag,
1044	vnode_t *vpp,
1045	mount_t *mpp,
1046	vfs_context_t ctx)
1047{
1048	struct user_nfs_args args;
1049	mount_t mp;
1050	mbuf_t m;
1051	int error;
1052	proc_t procp;
1053	struct vfstable *vfsp;
1054	struct nameidata nd;
1055	vnode_t vp;
1056
1057	procp = current_proc(); /* XXX */
1058
1059	{
1060	/*
1061	 * mimic main()!. Temporarily set up rootvnode and other stuff so
1062	 * that namei works. Need to undo this because main() does it, too
1063	 */
1064		struct filedesc *fdp;	/* pointer to file descriptor state */
1065		fdp = procp->p_fd;
1066		mountlist.tqh_first->mnt_flag |= MNT_ROOTFS;
1067
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);
1072		if (error) {
1073			printf("nfs_mountroot: vnode_ref() failed on root vnode!\n");
1074			goto out;
1075		}
1076		fdp->fd_cdir = rootvnode;
1077		fdp->fd_rdir = NULL;
1078	}
1079
1080	/*
1081	 * Get vnode to be covered
1082	 */
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");
1087		goto out;
1088	}
1089	{
1090		/* undo vnode_ref() in mimic main()! */
1091		vnode_rele(rootvnode);
1092	}
1093	nameidone(&nd);
1094	vp = nd.ni_vp;
1095
1096	if ((error = VNOP_FSYNC(vp, MNT_WAIT, ctx)) ||
1097	    (error = buf_invalidateblks(vp, BUF_WRITE_DATA, 0, 0))) {
1098		vnode_put(vp);
1099		goto out;
1100	}
1101	if (vnode_vtype(vp) != VDIR) {
1102		vnode_put(vp);
1103		error = ENOTDIR;
1104		goto out;
1105	}
1106	for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
1107		if (!strncmp(vfsp->vfc_name, "nfs", sizeof(vfsp->vfc_name)))
1108			break;
1109	if (vfsp == NULL) {
1110		printf("nfs_mountroot: private NFS not configured\n");
1111		vnode_put(vp);
1112		error = ENODEV;
1113		goto out;
1114	}
1115	if (vnode_mountedhere(vp) != NULL) {
1116		vnode_put(vp);
1117		error = EBUSY;
1118		goto out;
1119	}
1120
1121	/*
1122	 * Allocate and initialize the filesystem.
1123	 */
1124	mp = _MALLOC_ZONE((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
1125	if (!mp) {
1126		printf("nfs_mountroot: unable to allocate mount structure\n");
1127		vnode_put(vp);
1128		error = ENOMEM;
1129		goto out;
1130	}
1131	bzero((char *)mp, (u_long)sizeof(struct mount));
1132
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;
1139
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);
1146	mount_list_lock();
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);
1160#if CONFIG_MACF
1161	mac_mount_label_init(mp);
1162	mac_mount_label_associate(ctx, mp);
1163#endif
1164
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;
1176
1177	error = mbuf_get(MBUF_WAITOK, MBUF_TYPE_SONAME, &m);
1178	if (error) {
1179		printf("nfs_mount_diskless_private: mbuf_get(soname) failed");
1180		goto out;
1181	}
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);
1186		mount_list_lock();
1187		vfsp->vfc_refcount--;
1188		mount_list_unlock();
1189		vfs_unbusy(mp);
1190		mount_lock_destroy(mp);
1191#if CONFIG_MACF
1192		mac_mount_label_destroy(mp);
1193#endif
1194		FREE_ZONE(mp, sizeof (struct mount), M_MOUNT);
1195		goto out;
1196	}
1197
1198	*mpp = mp;
1199	*vpp = vp;
1200out:
1201	return (error);
1202}
1203#endif /* NO_MOUNT_PRIVATE */
1204
1205/*
1206 * VFS Operations.
1207 *
1208 * mount system call
1209 */
1210static int
1211nfs_vfs_mount(mount_t mp, vnode_t vp, user_addr_t data, vfs_context_t ctx)
1212{
1213	int error, argsvers;
1214	struct user_nfs_args args;
1215	struct nfs_args tempargs;
1216	mbuf_t nam;
1217	size_t len;
1218	u_char nfh[NFSX_V3FHMAX];
1219	char *mntfrom;
1220
1221	error = copyin(data, (caddr_t)&argsvers, sizeof (argsvers));
1222	if (error)
1223		return (error);
1224
1225	switch (argsvers) {
1226	case 3:
1227		if (vfs_context_is64bit(ctx))
1228			error = copyin(data, (caddr_t)&args, sizeof (struct user_nfs_args3));
1229		else
1230			error = copyin(data, (caddr_t)&tempargs, sizeof (struct nfs_args3));
1231		break;
1232	case 4:
1233		if (vfs_context_is64bit(ctx))
1234			error = copyin(data, (caddr_t)&args, sizeof (struct user_nfs_args4));
1235		else
1236			error = copyin(data, (caddr_t)&tempargs, sizeof (struct nfs_args4));
1237		break;
1238	case 5:
1239		if (vfs_context_is64bit(ctx))
1240			error = copyin(data, (caddr_t)&args, sizeof (args));
1241		else
1242			error = copyin(data, (caddr_t)&tempargs, sizeof (tempargs));
1243		break;
1244	default:
1245		return (EPROGMISMATCH);
1246	}
1247	if (error)
1248		return (error);
1249
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;
1274		}
1275		if (argsvers >= 5)
1276			args.auth = tempargs.auth;
1277	}
1278
1279	if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX)
1280		return (EINVAL);
1281	if (args.fhsize > 0) {
1282		error = copyin(args.fh, (caddr_t)nfh, args.fhsize);
1283		if (error)
1284			return (error);
1285	}
1286
1287	mntfrom = &vfs_statfs(mp)->f_mntfromname[0];
1288	error = copyinstr(args.hostname, mntfrom, MAXPATHLEN-1, &len);
1289	if (error)
1290		return (error);
1291	bzero(&mntfrom[len], MAXPATHLEN - len);
1292
1293	/* sockargs() call must be after above copyin() calls */
1294	error = sockargs(&nam, args.addr, args.addrlen, MBUF_TYPE_SONAME);
1295	if (error)
1296		return (error);
1297
1298	args.fh = CAST_USER_ADDR_T(&nfh[0]);
1299	error = mountnfs(&args, mp, nam, ctx, &vp);
1300	return (error);
1301}
1302
1303/*
1304 * Common code for mount and mountroot
1305 */
1306
1307static int
1308nfs3_mount(
1309	struct nfsmount *nmp,
1310	vfs_context_t ctx,
1311	struct user_nfs_args *argp,
1312	nfsnode_t *npp)
1313{
1314	int error = 0;
1315	struct nfs_vattr nvattr;
1316	u_int64_t xid;
1317	u_char *fhp;
1318
1319	*npp = NULL;
1320
1321	/*
1322	 * Get file attributes for the mountpoint.  These are needed
1323	 * in order to properly create the root vnode.
1324	 */
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);
1329	if (error)
1330		goto out;
1331
1332	error = nfs_nget(nmp->nm_mountp, NULL, NULL, fhp, argp->fhsize,
1333			&nvattr, &xid, NG_MARKROOT, npp);
1334	if (*npp)
1335		nfs_unlock(*npp);
1336	if (error)
1337		goto out;
1338
1339	/*
1340	 * Try to make sure we have all the general info from the server.
1341	 */
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);
1348		if (error)
1349			goto out;
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);
1360			}
1361		}
1362	}
1363out:
1364	if (*npp && error) {
1365		vnode_put(NFSTOV(*npp));
1366		*npp = NULL;
1367	}
1368	return (error);
1369}
1370
1371static int
1372nfs4_mount(
1373	struct nfsmount *nmp,
1374	vfs_context_t ctx,
1375	__unused struct user_nfs_args *argp,
1376	nfsnode_t *npp)
1377{
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;
1382	fhandle_t fh;
1383	struct nfs_vattr nvattr;
1384	u_int64_t xid;
1385	struct timeval now;
1386
1387	*npp = NULL;
1388	fh.fh_len = 0;
1389	microtime(&now);
1390	nmp->nm_mounttime = ((uint64_t)now.tv_sec << 32) | now.tv_usec;
1391
1392	/* look up path to get fh and attrs for mount point root */
1393	numops = 2; // PUTROOTFH + LOOKUP* + GETATTR
1394	while (*path && (*path != '/'))
1395		path++;
1396	name = path;
1397	while (*name) {
1398		while (*name && (*name == '/'))
1399			name++;
1400		if (!*name)
1401			break;
1402		nextname = name;
1403		while (*nextname && (*nextname != '/'))
1404			nextname++;
1405		numops++;
1406		name = nextname;
1407	}
1408	nfsm_chain_build_alloc_init(error, &nmreq, 25 * NFSX_UNSIGNED);
1409	nfsm_chain_add_compound_header(error, &nmreq, "mount", numops);
1410	numops--;
1411	nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTROOTFH);
1412	// (LOOKUP)*
1413	name = path;
1414	while (*name) {
1415		while (*name && (*name == '/'))
1416			name++;
1417		if (!*name)
1418			break;
1419		nextname = name;
1420		while (*nextname && (*nextname != '/'))
1421			nextname++;
1422		numops--;
1423		nfsm_chain_add_32(error, &nmreq, NFS_OP_LOOKUP);
1424		nfsm_chain_add_string(error, &nmreq, name, nextname - name);
1425		name = nextname;
1426	}
1427	numops--;
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);
1434	nfsmout_if(error);
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);
1439	name = path;
1440	while (*name) {
1441		while (*name && (*name == '/'))
1442			name++;
1443		if (!*name)
1444			break;
1445		nextname = name;
1446		while (*nextname && (*nextname != '/'))
1447			nextname++;
1448		nfsm_chain_op_check(error, &nmrep, NFS_OP_LOOKUP);
1449		name = nextname;
1450	}
1451	nfsm_chain_op_check(error, &nmrep, NFS_OP_GETATTR);
1452	nfsmout_if(error);
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");
1458		error = EBADRPC;
1459	}
1460	nfsmout_if(error);
1461
1462	error = nfs_nget(nmp->nm_mountp, NULL, NULL, fh.fh_data, fh.fh_len, &nvattr, &xid, NG_MARKROOT, npp);
1463	nfsmout_if(error);
1464
1465	/* XXX local locking for now */
1466	vfs_setlocklocal(nmp->nm_mountp);
1467
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;
1474		}
1475	}
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;
1481		}
1482	}
1483
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;
1487	if (interval < 1)
1488		interval = 1;
1489	nfs_interval_timer_start(nmp->nm_renew_timer, interval * 1000);
1490
1491nfsmout:
1492	if (*npp)
1493		nfs_unlock(*npp);
1494	return (error);
1495}
1496
1497static int
1498mountnfs(
1499	struct user_nfs_args *argp,
1500	mount_t mp,
1501	mbuf_t nam,
1502	vfs_context_t ctx,
1503	vnode_t *vpp)
1504{
1505	struct nfsmount *nmp;
1506	nfsnode_t np;
1507	int error, maxio, iosize;
1508	struct vfsstatfs *sbp;
1509	struct timespec ts = { 1, 0 };
1510
1511	/*
1512	 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
1513	 * no sense in that context.
1514	 */
1515	if (argp->sotype == SOCK_STREAM)
1516		argp->flags &= ~NFSMNT_NOCONN;
1517
1518	if (vfs_flags(mp) & MNT_UPDATE) {
1519		nmp = VFSTONFS(mp);
1520		/* update paths, file handles, etc, here	XXX */
1521		mbuf_freem(nam);
1522		return (0);
1523	} else {
1524		MALLOC_ZONE(nmp, struct nfsmount *,
1525				sizeof (struct nfsmount), M_NFSMNT, M_WAITOK);
1526		if (!nmp) {
1527			mbuf_freem(nam);
1528			return (ENOMEM);
1529		}
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);
1536
1537		nfs_nhinit_finish();
1538	}
1539	lck_mtx_lock(&nmp->nm_lock);
1540
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;
1548	} else {
1549		nmp->nm_wsize = NFS_WSIZE;
1550		nmp->nm_rsize = NFS_RSIZE;
1551	}
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;
1566
1567	vfs_getnewfsid(mp);
1568	nmp->nm_mountp = mp;
1569	vfs_setauthopaque(mp);
1570	nmp->nm_flag = argp->flags;
1571	nmp->nm_nam = nam;
1572
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) {
1577			error = EINVAL;
1578			goto bad;
1579		}
1580	} else if (argp->flags & NFSMNT_NFSV3)
1581		nmp->nm_vers = NFS_VER3;
1582
1583	if (nmp->nm_vers == NFS_VER2)
1584		nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
1585
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;
1592	}
1593
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;
1598	}
1599
1600	if (nmp->nm_vers != NFS_VER2) {
1601		if (argp->sotype == SOCK_DGRAM)
1602			maxio = NFS_MAXDGRAMDATA;
1603		else
1604			maxio = NFS_MAXDATA;
1605	} else
1606		maxio = NFS_V2MAXDATA;
1607
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;
1614	}
1615	if (nmp->nm_wsize > maxio)
1616		nmp->nm_wsize = maxio;
1617	if (nmp->nm_wsize > NFS_MAXBSIZE)
1618		nmp->nm_wsize = NFS_MAXBSIZE;
1619
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;
1626	}
1627	if (nmp->nm_rsize > maxio)
1628		nmp->nm_rsize = maxio;
1629	if (nmp->nm_rsize > NFS_MAXBSIZE)
1630		nmp->nm_rsize = NFS_MAXBSIZE;
1631
1632	if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
1633		nmp->nm_readdirsize = argp->readdirsize;
1634	}
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;
1639
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;
1652
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;
1666	}
1667	if (argp->version >= 5) {
1668		if (argp->flags & NFSMNT_SECFLAVOR) {
1669			/*
1670			 * Check for valid security flavor
1671			 */
1672			switch (argp->auth) {
1673			case RPCAUTH_SYS:
1674			case RPCAUTH_KRB5:
1675			case RPCAUTH_KRB5I:
1676			case RPCAUTH_KRB5P:
1677				nmp->nm_auth = argp->auth;
1678				break;
1679			default:
1680				error = EINVAL;
1681				goto bad;
1682			}
1683		}
1684	}
1685
1686	/* set up the version-specific function tables */
1687	if (nmp->nm_vers < NFS_VER4)
1688		nmp->nm_funcs = &nfs3_funcs;
1689	else
1690		nmp->nm_funcs = &nfs4_funcs;
1691
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);
1697
1698	lck_mtx_unlock(&nmp->nm_lock);
1699
1700	/* make sure mbuf constants are set up */
1701	if (!nfs_mbuf_mhlen)
1702		nfs_mbuf_init();
1703
1704	/* NFS does its own node locking */
1705	mp->mnt_vtable->vfc_threadsafe = TRUE;
1706
1707	/* set up the socket */
1708	if ((error = nfs_connect(nmp)))
1709		goto bad;
1710
1711	/*
1712	 * Get the root node/attributes from the NFS server and
1713	 * do any basic, version-specific setup.
1714	 */
1715	error = nmp->nm_funcs->nf_mount(nmp, ctx, argp, &np);
1716	if (error)
1717		goto bad;
1718
1719	/*
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.
1724	 */
1725	nmp->nm_dnp = np;
1726	*vpp = NFSTOV(np);
1727	/* get usecount and drop iocount */
1728	error = vnode_ref(*vpp);
1729	vnode_put(*vpp);
1730	if (error)
1731		goto bad;
1732
1733	/*
1734	 * Do statfs to ensure static info gets set to reasonable values.
1735	 */
1736	if ((error = nmp->nm_funcs->nf_update_statfs(nmp, ctx)))
1737		goto bad;
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;
1748
1749	/*
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.
1757	 */
1758	iosize = max(nmp->nm_rsize, nmp->nm_wsize);
1759	if (iosize < PAGE_SIZE)
1760		iosize = PAGE_SIZE;
1761	nmp->nm_biosize = trunc_page_32(iosize);
1762
1763	/*
1764	 * V3 mounts give us a (relatively) reliable remote access(2)
1765	 * call, so advertise the fact.
1766	 *
1767	 * XXX this may not be the best way to go, as the granularity
1768	 *     offered isn't a good match to our needs.
1769	 */
1770	if (nmp->nm_vers != NFS_VER2)
1771		vfs_setauthopaqueaccess(mp);
1772
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);
1777
1778	lck_mtx_lock(&nmp->nm_lock);
1779	nmp->nm_state |= NFSSTA_MOUNTED;
1780	lck_mtx_unlock(&nmp->nm_lock);
1781	return (0);
1782bad:
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);
1793	}
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);
1800	}
1801	lck_mtx_destroy(&nmp->nm_lock, nfs_mount_grp);
1802	FREE_ZONE((caddr_t)nmp, sizeof (struct nfsmount), M_NFSMNT);
1803	mbuf_freem(nam);
1804	return (error);
1805}
1806
1807
1808/*
1809 * unmount system call
1810 */
1811static int
1812nfs_vfs_unmount(
1813	mount_t mp,
1814	int mntflags,
1815	__unused vfs_context_t ctx)
1816{
1817	struct nfsmount *nmp;
1818	vnode_t vp;
1819	int error, flags = 0, docallback;
1820	struct nfsreq *req, *treq;
1821	struct nfs_reqqhead iodq;
1822	struct timespec ts = { 1, 0 };
1823
1824	nmp = VFSTONFS(mp);
1825	lck_mtx_lock(&nmp->nm_lock);
1826	/*
1827	 * During a force unmount we want to...
1828	 *   Mark that we are doing a force unmount.
1829	 *   Make the mountpoint soft.
1830	 */
1831	if (mntflags & MNT_FORCE) {
1832		flags |= FORCECLOSE;
1833		nmp->nm_state |= NFSSTA_FORCE;
1834		nmp->nm_flag |= NFSMNT_SOFT;
1835	}
1836	/*
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
1843	 */
1844	vp = NFSTOV(nmp->nm_dnp);
1845	lck_mtx_unlock(&nmp->nm_lock);
1846
1847	/*
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.
1851	 */
1852	error = vflush(mp, vp, SKIPSWAP | flags);
1853	if (mntflags & MNT_FORCE) {
1854		error = vflush(mp, NULLVP, flags); /* locks vp in the process */
1855	} else {
1856		if (vnode_isinuse(vp, 1))
1857			return (EBUSY);
1858		error = vflush(mp, vp, flags);
1859	}
1860	if (error)
1861		return (error);
1862
1863	lck_mtx_lock(&nmp->nm_lock);
1864	nmp->nm_state &= ~NFSSTA_MOUNTED;
1865	lck_mtx_unlock(&nmp->nm_lock);
1866
1867	/*
1868	 * Release the root vnode reference held by mountnfs()
1869	 */
1870	vnode_rele(vp);
1871
1872	vflush(mp, NULLVP, FORCECLOSE);
1873
1874	/*
1875	 * Destroy any RPCSEC_GSS contexts
1876	 */
1877	if (!TAILQ_EMPTY(&nmp->nm_gsscl))
1878		nfs_gss_clnt_ctx_unmount(nmp, mntflags);
1879
1880	vfs_setfsprivate(mp, 0); /* don't want to end up using stale vp */
1881
1882	/* mark the socket for termination */
1883	lck_mtx_lock(&nmp->nm_lock);
1884	nmp->nm_sockflags |= NMSOCK_UNMOUNT;
1885
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);
1889
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);
1894	}
1895
1896	/* tear down the socket */
1897	lck_mtx_unlock(&nmp->nm_lock);
1898	nfs_disconnect(nmp);
1899	lck_mtx_lock(&nmp->nm_lock);
1900
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);
1905	}
1906
1907	mbuf_freem(nmp->nm_nam);
1908	lck_mtx_unlock(&nmp->nm_lock);
1909
1910	if (!(nmp->nm_flag & (NFSMNT_NOLOCKS|NFSMNT_LOCALLOCKS)))
1911		nfs_lockd_mount_change(-1);
1912
1913	/*
1914	 * Loop through outstanding request list and remove dangling
1915	 * references to defunct nfsmount struct
1916	 */
1917	TAILQ_INIT(&iodq);
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);
1922			req->r_nmp = NULL;
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);
1930			}
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;
1936			}
1937			lck_mtx_unlock(&nmp->nm_lock);
1938			wakeup(req);
1939		}
1940	}
1941	lck_mtx_unlock(nfs_request_mutex);
1942
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);
1954		if (docallback)
1955			req->r_callback.rcb_func(req);
1956	}
1957
1958	lck_mtx_destroy(&nmp->nm_lock, nfs_mount_grp);
1959	FREE_ZONE((caddr_t)nmp, sizeof (struct nfsmount), M_NFSMNT);
1960	return (0);
1961}
1962
1963/*
1964 * Return root of a filesystem
1965 */
1966static int
1967nfs_vfs_root(mount_t mp, vnode_t *vpp, __unused vfs_context_t ctx)
1968{
1969	vnode_t vp;
1970	struct nfsmount *nmp;
1971	int error;
1972	u_long vpid;
1973
1974	nmp = VFSTONFS(mp);
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))
1981			return (error);
1982		vpid = vnode_vid(vp);
1983	}
1984	*vpp = vp;
1985	return (0);
1986}
1987
1988/*
1989 * Do operations associated with quotas
1990 */
1991#if !QUOTA
1992static int
1993nfs_vfs_quotactl(
1994	__unused mount_t mp,
1995	__unused int cmds,
1996	__unused uid_t uid,
1997	__unused caddr_t datap,
1998	__unused vfs_context_t context)
1999{
2000	return (ENOTSUP);
2001}
2002#else
2003static int
2004nfs_aux_request(
2005	struct nfsmount *nmp,
2006	thread_t thd,
2007	struct sockaddr_in *saddr,
2008	mbuf_t mreq,
2009	uint32_t xid,
2010	int timeo,
2011	struct nfsm_chain *nmrep)
2012{
2013	int error = 0, on = 1, try, sendat = 2;
2014	socket_t so = NULL;
2015	struct timeval tv = { 1, 0 };
2016	mbuf_t m, mrep = NULL;
2017	struct msghdr msg;
2018	uint32_t rxid, reply, reply_status, rejected_status;
2019	uint32_t verf_type, verf_len, accepted_status;
2020	size_t readlen;
2021
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)))))
2027		goto nfsmout;
2028
2029	for (try=0; try < timeo; try++) {
2030		if ((error = nfs_sigintr(nmp, NULL, thd, 0)))
2031			break;
2032		if (!try || (try == sendat)) {
2033			/* send the request (resending periodically) */
2034			if ((error = mbuf_copym(mreq, 0, MBUF_COPYALL, MBUF_WAITOK, &m)))
2035				goto nfsmout;
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)))
2040				goto nfsmout;
2041			sendat *= 2;
2042			if (sendat > 30)
2043				sendat = 30;
2044		}
2045		/* wait for the response */
2046		readlen = 1<<18;
2047		bzero(&msg, sizeof(msg));
2048		error = sock_receivembuf(so, &msg, &mrep, 0, &readlen);
2049		if (error == EWOULDBLOCK)
2050			continue;
2051		nfsmout_if(error);
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);
2056		nfsmout_if(error);
2057		if ((rxid != xid) || (reply != RPC_REPLY))
2058			error = EBADRPC;
2059		nfsm_chain_get_32(error, nmrep, reply_status);
2060		nfsmout_if(error);
2061		if (reply_status == RPC_MSGDENIED) {
2062			nfsm_chain_get_32(error, nmrep, rejected_status);
2063			nfsmout_if(error);
2064			error = (rejected_status == RPC_MISMATCH) ? ENOTSUP : EACCES;
2065			goto nfsmout;
2066		}
2067		nfsm_chain_get_32(error, nmrep, verf_type); /* verifier flavor */
2068		nfsm_chain_get_32(error, nmrep, verf_len); /* verifier length */
2069		nfsmout_if(error);
2070		if (verf_len)
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);
2074		break;
2075	}
2076nfsmout:
2077	if (so) {
2078		sock_shutdown(so, SHUT_RDWR);
2079		sock_close(so);
2080	}
2081	mbuf_freem(mreq);
2082	return (error);
2083}
2084
2085static int
2086nfs3_getquota(struct nfsmount *nmp, vfs_context_t ctx, u_long id, int type, struct dqblk *dqb)
2087{
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);
2092	char *path;
2093	uint64_t xid = 0;
2094	struct nfsm_chain nmreq, nmrep;
2095	mbuf_t mreq;
2096	uint32_t val = 0, bsize;
2097	struct sockaddr *nam = mbuf_data(nmp->nm_nam);
2098	struct sockaddr_in saddr;
2099	struct timeval now;
2100
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) +
2104			5 * NFSX_UNSIGNED;
2105	timeo = (nmp->nm_flag & NFSMNT_SOFT) ? 10 : 60;
2106	nfsm_chain_null(&nmreq);
2107	nfsm_chain_null(&nmrep);
2108
2109	/* check if we have a recently cached rquota port */
2110	if (nmp->nm_rqport) {
2111		microuptime(&now);
2112		if ((nmp->nm_rqportstamp + 60) >= (uint32_t)now.tv_sec)
2113			goto got_rqport;
2114	}
2115
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);
2124	nfsmout_if(error);
2125	error = nfsm_rpchead2(SOCK_DGRAM, PMAPPROG, PMAPVERS, PMAPPROC_GETPORT,
2126			RPCAUTH_SYS, auth_len, cred, NULL, nmreq.nmc_mhead, &xid, &mreq);
2127	nfsmout_if(error);
2128	nmreq.nmc_mhead = NULL;
2129	error = nfs_aux_request(nmp, thd, &saddr, mreq, R_XID32(xid), timeo, &nmrep);
2130	nfsmout_if(error);
2131
2132	/* grab rquota port from portmap response */
2133	nfsm_chain_get_32(error, &nmrep, val);
2134	nfsmout_if(error);
2135	nmp->nm_rqport = val;
2136	microuptime(&now);
2137	nmp->nm_rqportstamp = now.tv_sec;
2138	nfsm_chain_cleanup(&nmreq);
2139	nfsm_chain_cleanup(&nmrep);
2140	xid = 0;
2141
2142got_rqport:
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 != '/'))
2147		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);
2155	nfsmout_if(error);
2156	error = nfsm_rpchead2(SOCK_DGRAM, RPCPROG_RQUOTA, rqvers, RPCRQUOTA_GET,
2157			RPCAUTH_SYS, auth_len, cred, NULL, nmreq.nmc_mhead, &xid, &mreq);
2158	nfsmout_if(error);
2159	nmreq.nmc_mhead = NULL;
2160	error = nfs_aux_request(nmp, thd, &saddr, mreq, R_XID32(xid), timeo, &nmrep);
2161	nfsmout_if(error);
2162
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)
2167			error = ENOENT;
2168		else if (val == RQUOTA_STAT_EPERM)
2169			error = EPERM;
2170		else
2171			error = EIO;
2172	}
2173	nfsm_chain_get_32(error, &nmrep, bsize);
2174	nfsm_chain_adv(error, &nmrep, NFSX_UNSIGNED);
2175	nfsm_chain_get_32(error, &nmrep, val);
2176	nfsmout_if(error);
2177	dqb->dqb_bhardlimit = (uint64_t)val * bsize;
2178	nfsm_chain_get_32(error, &nmrep, val);
2179	nfsmout_if(error);
2180	dqb->dqb_bsoftlimit = (uint64_t)val * bsize;
2181	nfsm_chain_get_32(error, &nmrep, val);
2182	nfsmout_if(error);
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);
2189	nfsmout_if(error);
2190	dqb->dqb_id = id;
2191nfsmout:
2192	nfsm_chain_cleanup(&nmreq);
2193	nfsm_chain_cleanup(&nmrep);
2194	return (error);
2195}
2196
2197static int
2198nfs4_getquota(struct nfsmount *nmp, vfs_context_t ctx, u_long id, int type, struct dqblk *dqb)
2199{
2200	nfsnode_t np;
2201	int error = 0, status, nfsvers, numops;
2202	u_int64_t xid;
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);
2207
2208	if (type != USRQUOTA)  /* NFSv4 only supports user quotas */
2209		return (ENOTSUP);
2210
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))
2215		return (ENOTSUP);
2216
2217	/*
2218	 * The credential passed to the server needs to have
2219	 * an effective uid that matches the given uid.
2220	 */
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))
2229			return (ENOMEM);
2230	} else {
2231		kauth_cred_ref(cred);
2232	}
2233
2234	nfsvers = nmp->nm_vers;
2235	np = nmp->nm_dnp;
2236	if ((error = vnode_get(NFSTOV(np)))) {
2237		kauth_cred_unref(&cred);
2238		return(error);
2239	}
2240
2241	nfsm_chain_null(&nmreq);
2242	nfsm_chain_null(&nmrep);
2243
2244	// PUTFH + GETATTR
2245	numops = 2;
2246	nfsm_chain_build_alloc_init(error, &nmreq, 15 * NFSX_UNSIGNED);
2247	nfsm_chain_add_compound_header(error, &nmreq, "quota", numops);
2248	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);
2251	numops--;
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);
2261	nfsmout_if(error);
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);
2268	nfsmout_if(error);
2269	error = nfs4_parsefattr(&nmrep, NULL, NULL, NULL, dqb);
2270	nfsmout_if(error);
2271	nfsm_assert(error, NFSTONMP(np), ENXIO);
2272nfsmout:
2273	nfsm_chain_cleanup(&nmreq);
2274	nfsm_chain_cleanup(&nmrep);
2275	vnode_put(NFSTOV(np));
2276	kauth_cred_unref(&cred);
2277	return (error);
2278}
2279
2280static int
2281nfs_vfs_quotactl(mount_t mp, int cmds, uid_t uid, caddr_t datap, vfs_context_t ctx)
2282{
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;
2287
2288	if (!(nmp = VFSTONFS(mp)))
2289		return (ENXIO);
2290	nfsvers = nmp->nm_vers;
2291
2292	if (uid == ~0U)
2293		uid = ruid;
2294
2295	/* we can only support Q_GETQUOTA */
2296	cmd = cmds >> SUBCMDSHIFT;
2297	switch (cmd) {
2298	case Q_GETQUOTA:
2299		break;
2300	case Q_QUOTAON:
2301	case Q_QUOTAOFF:
2302	case Q_SETQUOTA:
2303	case Q_SETUSE:
2304	case Q_SYNC:
2305	case Q_QUOTASTAT:
2306		return (ENOTSUP);
2307	default:
2308		return (EINVAL);
2309	}
2310
2311	type = cmds & SUBCMDMASK;
2312	if ((u_int)type >= MAXQUOTAS)
2313		return (EINVAL);
2314	if ((uid != ruid) && ((error = vfs_context_suser(ctx))))
2315		return (error);
2316
2317	if (vfs_busy(mp, LK_NOWAIT))
2318		return (0);
2319	bzero(dqb, sizeof(*dqb));
2320	error = nmp->nm_funcs->nf_getquota(nmp, ctx, uid, type, dqb);
2321	vfs_unbusy(mp);
2322	return (error);
2323}
2324#endif
2325
2326/*
2327 * Flush out the buffer cache
2328 */
2329
2330struct nfs_sync_cargs {
2331	thread_t	thd;
2332	int		waitfor;
2333	int		error;
2334};
2335
2336static int
2337nfs_sync_callout(vnode_t vp, void *arg)
2338{
2339	struct nfs_sync_cargs *cargs = (struct nfs_sync_cargs*)arg;
2340	int error;
2341
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);
2348
2349	error = nfs_flush(VTONFS(vp), cargs->waitfor, cargs->thd, 0);
2350	if (error)
2351		cargs->error = error;
2352
2353	return (VNODE_RETURNED);
2354}
2355
2356static int
2357nfs_vfs_sync(mount_t mp, int waitfor, vfs_context_t ctx)
2358{
2359	struct nfs_sync_cargs cargs;
2360
2361	cargs.waitfor = waitfor;
2362	cargs.thd = vfs_context_thread(ctx);
2363	cargs.error = 0;
2364
2365	vnode_iterate(mp, 0, nfs_sync_callout, &cargs);
2366
2367	return (cargs.error);
2368}
2369
2370/*
2371 * NFS flat namespace lookup.
2372 * Currently unsupported.
2373 */
2374/*ARGSUSED*/
2375static int
2376nfs_vfs_vget(
2377	__unused mount_t mp,
2378	__unused ino64_t ino,
2379	__unused vnode_t *vpp,
2380	__unused vfs_context_t ctx)
2381{
2382
2383	return (ENOTSUP);
2384}
2385
2386/*
2387 * At this point, this should never happen
2388 */
2389/*ARGSUSED*/
2390static int
2391nfs_vfs_fhtovp(
2392	__unused mount_t mp,
2393	__unused int fhlen,
2394	__unused unsigned char *fhp,
2395	__unused vnode_t *vpp,
2396	__unused vfs_context_t ctx)
2397{
2398
2399	return (ENOTSUP);
2400}
2401
2402/*
2403 * Vnode pointer to File handle, should never happen either
2404 */
2405/*ARGSUSED*/
2406static int
2407nfs_vfs_vptofh(
2408	__unused vnode_t vp,
2409	__unused int *fhlenp,
2410	__unused unsigned char *fhp,
2411	__unused vfs_context_t ctx)
2412{
2413
2414	return (ENOTSUP);
2415}
2416
2417/*
2418 * Vfs start routine, a no-op.
2419 */
2420/*ARGSUSED*/
2421static int
2422nfs_vfs_start(
2423	__unused mount_t mp,
2424	__unused int flags,
2425	__unused vfs_context_t ctx)
2426{
2427
2428	return (0);
2429}
2430
2431/*
2432 * Do that sysctl thang...
2433 */
2434static int
2435nfs_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)
2437{
2438	int error = 0, val, softnobrowse;
2439	struct sysctl_req *req = NULL;
2440	struct vfsidctl vc;
2441	struct user_vfsidctl user_vc;
2442	mount_t mp;
2443	struct nfsmount *nmp = NULL;
2444	struct vfsquery vq;
2445	boolean_t is_64_bit;
2446#if NFSSERVER
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 */
2459
2460	/*
2461	 * All names at this level are terminal.
2462	 */
2463	if (namelen > 1)
2464		return (ENOTDIR);	/* overloaded */
2465
2466	is_64_bit = vfs_context_is64bit(ctx);
2467
2468	/* common code for "new style" VFS_CTL sysctl, get the mount. */
2469	switch (name[0]) {
2470	case VFS_CTL_TIMEO:
2471	case VFS_CTL_QUERY:
2472	case VFS_CTL_NOLOCKS:
2473		req = CAST_DOWN(struct sysctl_req *, oldp);
2474		if (is_64_bit) {
2475			error = SYSCTL_IN(req, &user_vc, sizeof(user_vc));
2476			if (error)
2477				 return (error);
2478			mp = vfs_getvfs(&user_vc.vc_fsid);
2479		} else {
2480			error = SYSCTL_IN(req, &vc, sizeof(vc));
2481			if (error)
2482				return (error);
2483			mp = vfs_getvfs(&vc.vc_fsid);
2484		}
2485		if (mp == NULL)
2486			return (ENOENT);
2487		nmp = VFSTONFS(mp);
2488		if (nmp == NULL)
2489			return (ENOENT);
2490		bzero(&vq, sizeof(vq));
2491		req->newidx = 0;
2492		if (is_64_bit) {
2493			req->newptr = user_vc.vc_ptr;
2494			req->newlen = (size_t)user_vc.vc_len;
2495		} else {
2496			req->newptr = CAST_USER_ADDR_T(vc.vc_ptr);
2497			req->newlen = vc.vc_len;
2498		}
2499	}
2500
2501	switch(name[0]) {
2502	case NFS_NFSSTATS:
2503		if (!oldp) {
2504			*oldlenp = sizeof nfsstats;
2505			return (0);
2506		}
2507
2508		if (*oldlenp < sizeof nfsstats) {
2509			*oldlenp = sizeof nfsstats;
2510			return (ENOMEM);
2511		}
2512
2513		error = copyout(&nfsstats, oldp, sizeof nfsstats);
2514		if (error)
2515			return (error);
2516
2517		if (newp && newlen != sizeof nfsstats)
2518			return (EINVAL);
2519
2520		if (newp)
2521			return copyin(newp, &nfsstats, sizeof nfsstats);
2522		return (0);
2523#if NFSSERVER
2524	case NFS_EXPORTSTATS:
2525		/* setup export stat descriptor */
2526		stat_desc.rec_vers = NFS_EXPORT_STAT_REC_VERSION;
2527
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);
2533			return (error);
2534		}
2535
2536		/* Count the number of exported directories */
2537		lck_rw_lock_shared(&nfsrv_export_rwlock);
2538		numExports = 0;
2539		LIST_FOREACH(nxfs, &nfsrv_exports, nxfs_next)
2540			LIST_FOREACH(nx, &nxfs->nxfs_exports, nx_next)
2541					numExports += 1;
2542
2543		/* update stat descriptor's export record count */
2544		stat_desc.rec_count = numExports;
2545
2546		/* calculate total size of required buffer */
2547		totlen = sizeof(struct nfs_export_stat_desc) + (numExports * sizeof(struct nfs_export_stat_rec));
2548
2549		/* Check caller's buffer */
2550		if (oldp == 0) {
2551			lck_rw_done(&nfsrv_export_rwlock);
2552			/* indicate required buffer len */
2553			*oldlenp = totlen;
2554			return (0);
2555		}
2556
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 */
2561			*oldlenp = totlen;
2562			return (ENOMEM);
2563		}
2564
2565		/* indicate required buffer len */
2566		*oldlenp = totlen;
2567
2568		/* check if export table is empty */
2569		if (!numExports) {
2570			lck_rw_done(&nfsrv_export_rwlock);
2571			error = copyout(&stat_desc, oldp, sizeof(struct nfs_export_stat_desc));
2572			return (error);
2573		}
2574
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);
2577
2578		if (!numRecs) {
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));
2583			return (error);
2584		}
2585
2586		/* adjust to actual number of records to copyout to caller's buffer */
2587		if (numRecs > numExports)
2588			numRecs = numExports;
2589
2590		/* set actual number of records we are returning */
2591		stat_desc.rec_count = numRecs;
2592
2593		/* first copy out the stat descriptor */
2594		pos = 0;
2595		error = copyout(&stat_desc, oldp + pos, sizeof(struct nfs_export_stat_desc));
2596		if (error) {
2597			lck_rw_done(&nfsrv_export_rwlock);
2598			return (error);
2599		}
2600		pos += sizeof(struct nfs_export_stat_desc);
2601
2602		/* Loop through exported directories */
2603		count = 0;
2604		LIST_FOREACH(nxfs, &nfsrv_exports, nxfs_next) {
2605			LIST_FOREACH(nx, &nxfs->nxfs_exports, nx_next) {
2606
2607				if (count >= numRecs)
2608					break;
2609
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]) ? "/" : ""),
2613					nx->nx_path);
2614
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));
2623				if (error) {
2624					lck_rw_done(&nfsrv_export_rwlock);
2625					return (error);
2626				}
2627				/* advance buffer position */
2628				pos += sizeof(statrec);
2629			}
2630		}
2631		lck_rw_done(&nfsrv_export_rwlock);
2632		break;
2633	case NFS_USERSTATS:
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;
2638
2639		/* initialize counters */
2640		bytes_total = sizeof(struct nfs_user_stat_desc);
2641		bytes_avail  = *oldlenp;
2642		recs_copied = 0;
2643
2644		if (!nfsrv_is_initialized()) /* NFS server not initialized, so no stats */
2645			goto ustat_skip;
2646
2647		/* reclaim old expired user nodes */
2648		nfsrv_active_user_list_reclaim();
2649
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);
2653		else
2654			bytes_avail = 0;
2655
2656		/* put buffer position past the buffer descriptor */
2657		pos = sizeof(struct nfs_user_stat_desc);
2658
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) {
2663				/* copy out path */
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]) ? "/" : ""),
2667					    nx->nx_path);
2668
2669					error = copyout(&upath_rec, oldp + pos, sizeof(struct nfs_user_stat_path_rec));
2670					if (error) {
2671						/* punt */
2672						goto ustat_done;
2673					}
2674
2675					pos += sizeof(struct nfs_user_stat_path_rec);
2676					bytes_avail -= sizeof(struct nfs_user_stat_path_rec);
2677					recs_copied++;
2678				}
2679				else {
2680					/* Caller's buffer is exhausted */
2681					bytes_avail = 0;
2682				}
2683
2684				bytes_total += sizeof(struct nfs_user_stat_path_rec);
2685
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);
2691
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;
2702
2703						error = copyout(&ustat_rec, oldp + pos, sizeof(struct nfs_user_stat_user_rec));
2704
2705						if (error) {
2706							/* punt */
2707							lck_mtx_unlock(&ulist->user_mutex);
2708							goto ustat_done;
2709						}
2710
2711						pos += sizeof(struct nfs_user_stat_user_rec);
2712						bytes_avail -= sizeof(struct nfs_user_stat_user_rec);
2713						recs_copied++;
2714					}
2715					else {
2716						/* Caller's buffer is exhausted */
2717						bytes_avail = 0;
2718					}
2719					bytes_total += sizeof(struct nfs_user_stat_user_rec);
2720				}
2721				/* can unlock this export's list now */
2722				lck_mtx_unlock(&ulist->user_mutex);
2723			}
2724		}
2725
2726ustat_done:
2727		/* unlock the export table */
2728		lck_rw_done(&nfsrv_export_rwlock);
2729
2730ustat_skip:
2731		/* indicate number of actual records copied */
2732		ustat_desc.rec_count = recs_copied;
2733
2734		if (!error) {
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));
2738			else
2739				error = ENOMEM;
2740
2741			/* always indicate required buffer size */
2742			*oldlenp = bytes_total;
2743		}
2744		break;
2745	case NFS_USERCOUNT:
2746		if (!oldp) {
2747			*oldlenp = sizeof(nfsrv_user_stat_node_count);
2748			return (0);
2749		}
2750
2751		if (*oldlenp < sizeof(nfsrv_user_stat_node_count)) {
2752			*oldlenp = sizeof(nfsrv_user_stat_node_count);
2753			return (ENOMEM);
2754		}
2755
2756		if (nfsrv_is_initialized()) {
2757			/* reclaim old expired user nodes */
2758			nfsrv_active_user_list_reclaim();
2759		}
2760
2761		error = copyout(&nfsrv_user_stat_node_count, oldp, sizeof(nfsrv_user_stat_node_count));
2762		break;
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));
2770 			if (error)
2771 				return (error);
2772 		}
2773 		if (req->newptr != USER_ADDR_NULL) {
2774 			error = SYSCTL_IN(req, &val, sizeof(val));
2775 			if (error)
2776 				return (error);
2777			lck_mtx_lock(&nmp->nm_lock);
2778			if (nmp->nm_flag & NFSMNT_LOCALLOCKS) {
2779				/* can't toggle locks when using local locks */
2780				error = EINVAL;
2781			} else if (val) {
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;
2786			} else {
2787				if (nmp->nm_flag & NFSMNT_NOLOCKS)
2788					nfs_lockd_mount_change(1);
2789				nmp->nm_flag &= ~NFSMNT_NOLOCKS;
2790			}
2791			lck_mtx_unlock(&nmp->nm_lock);
2792 		}
2793		break;
2794	case VFS_CTL_QUERY:
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));
2805		break;
2806 	case VFS_CTL_TIMEO:
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));
2812 			if (error)
2813 				return (error);
2814 		}
2815 		if (req->newptr != USER_ADDR_NULL) {
2816 			error = SYSCTL_IN(req, &val, sizeof(val));
2817 			if (error)
2818 				return (error);
2819			lck_mtx_lock(&nmp->nm_lock);
2820 			if (val < 0)
2821 				nmp->nm_tprintf_initial_delay = 0;
2822			else
2823				nmp->nm_tprintf_initial_delay = val;
2824			lck_mtx_unlock(&nmp->nm_lock);
2825 		}
2826		break;
2827	default:
2828		return (ENOTSUP);
2829	}
2830	return (error);
2831}
2832