]> git.saurik.com Git - apple/xnu.git/blob - bsd/nfs/nfs_vfsops.c
xnu-1228.5.18.tar.gz
[apple/xnu.git] / bsd / nfs / nfs_vfsops.c
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
125 int nfs_ticks;
126 static lck_grp_t *nfs_mount_grp;
127 uint32_t nfs_fs_attr_bitmap[NFS_ATTR_BITMAP_LEN];
128 uint32_t nfs_object_attr_bitmap[NFS_ATTR_BITMAP_LEN];
129 uint32_t nfs_getattr_bitmap[NFS_ATTR_BITMAP_LEN];
130
131 /* NFS requests */
132 struct nfs_reqqhead nfs_reqq;
133 lck_grp_t *nfs_request_grp;
134 lck_mtx_t *nfs_request_mutex;
135 thread_call_t nfs_request_timer_call;
136 int nfs_request_timer_on;
137 u_long nfs_xid = 0;
138 u_long nfs_xidwrap = 0; /* to build a (non-wrapping) 64 bit xid */
139
140 thread_call_t nfs_buf_timer_call;
141
142 /* nfsiod */
143 lck_grp_t *nfsiod_lck_grp;
144 lck_mtx_t *nfsiod_mutex;
145 struct nfsiodlist nfsiodfree, nfsiodwork;
146 struct nfsiodmountlist nfsiodmounts;
147 int nfsiod_thread_count = 0;
148 int nfsiod_thread_max = NFS_DEFASYNCTHREAD;
149 int nfs_max_async_writes = NFS_DEFMAXASYNCWRITES;
150
151 int nfs_iosize = NFS_IOSIZE;
152 int nfs_access_cache_timeout = NFS_MAXATTRTIMO;
153 int nfs_allow_async = 0;
154 int nfs_statfs_rate_limit = NFS_DEFSTATFSRATELIMIT;
155 int nfs_lockd_mounts = 0;
156 int nfs_lockd_request_sent = 0;
157
158 int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
159 int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
160
161
162 static int mountnfs(struct user_nfs_args *,mount_t,mbuf_t,vfs_context_t,vnode_t *);
163 static int nfs_mount_diskless(struct nfs_dlmount *, const char *, int, vnode_t *, mount_t *, vfs_context_t);
164 #if !defined(NO_MOUNT_PRIVATE)
165 static int nfs_mount_diskless_private(struct nfs_dlmount *, const char *, int, vnode_t *, mount_t *, vfs_context_t);
166 #endif /* NO_MOUNT_PRIVATE */
167
168 /*
169 * NFS VFS operations.
170 */
171 static int nfs_vfs_mount(mount_t, vnode_t, user_addr_t, vfs_context_t);
172 static int nfs_vfs_start(mount_t, int, vfs_context_t);
173 static int nfs_vfs_unmount(mount_t, int, vfs_context_t);
174 static int nfs_vfs_root(mount_t, vnode_t *, vfs_context_t);
175 static int nfs_vfs_quotactl(mount_t, int, uid_t, caddr_t, vfs_context_t);
176 static int nfs_vfs_getattr(mount_t, struct vfs_attr *, vfs_context_t);
177 static int nfs_vfs_sync(mount_t, int, vfs_context_t);
178 static int nfs_vfs_vget(mount_t, ino64_t, vnode_t *, vfs_context_t);
179 static int nfs_vfs_vptofh(vnode_t, int *, unsigned char *, vfs_context_t);
180 static int nfs_vfs_fhtovp(mount_t, int, unsigned char *, vnode_t *, vfs_context_t);
181 static int nfs_vfs_init(struct vfsconf *);
182 static int nfs_vfs_sysctl(int *, u_int, user_addr_t, size_t *, user_addr_t, size_t, vfs_context_t);
183
184 struct 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 */
211 static int nfs3_mount(struct nfsmount *, vfs_context_t, struct user_nfs_args *, nfsnode_t *);
212 static int nfs4_mount(struct nfsmount *, vfs_context_t, struct user_nfs_args *, nfsnode_t *);
213 static int nfs3_update_statfs(struct nfsmount *, vfs_context_t);
214 static int nfs4_update_statfs(struct nfsmount *, vfs_context_t);
215 #if !QUOTA
216 #define nfs3_getquota NULL
217 #define nfs4_getquota NULL
218 #else
219 static int nfs3_getquota(struct nfsmount *, vfs_context_t, u_long, int, struct dqblk *);
220 static int nfs4_getquota(struct nfsmount *, vfs_context_t, u_long, int, struct dqblk *);
221 #endif
222
223 struct 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 };
241 struct 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 */
263 static int
264 nfs_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 */
324 static int
325 nfs3_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);
389 nfsmout:
390 nfsm_chain_cleanup(&nmreq);
391 nfsm_chain_cleanup(&nmrep);
392 vnode_put(NFSTOV(np));
393 return (error);
394 }
395
396 static int
397 nfs4_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;
451 nfsmout:
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 */
464 static int
465 nfs_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 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXFILESIZE)) {
576 /* Is server's max file size at least 2TB? */
577 if (nmp->nm_fsattr.nfsa_maxfilesize >= 0x20000000000ULL)
578 caps |= VOL_CAP_FMT_2TB_FILESIZE;
579 } else if (nfsvers >= NFS_VER3) {
580 /*
581 * NFSv3 and up supports 64 bits of file size.
582 * So, we'll just assume maxfilesize >= 2TB
583 */
584 caps |= VOL_CAP_FMT_2TB_FILESIZE;
585 }
586 if (nfsvers >= NFS_VER4) {
587 caps |= VOL_CAP_FMT_HIDDEN_FILES;
588 valid |= VOL_CAP_FMT_HIDDEN_FILES;
589 // VOL_CAP_FMT_OPENDENYMODES
590 }
591 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_FORMAT] =
592 // VOL_CAP_FMT_PERSISTENTOBJECTIDS |
593 // VOL_CAP_FMT_SYMBOLICLINKS |
594 // VOL_CAP_FMT_HARDLINKS |
595 // VOL_CAP_FMT_JOURNAL |
596 // VOL_CAP_FMT_JOURNAL_ACTIVE |
597 // VOL_CAP_FMT_NO_ROOT_TIMES |
598 // VOL_CAP_FMT_SPARSE_FILES |
599 // VOL_CAP_FMT_ZERO_RUNS |
600 // VOL_CAP_FMT_CASE_SENSITIVE |
601 // VOL_CAP_FMT_CASE_PRESERVING |
602 // VOL_CAP_FMT_FAST_STATFS |
603 // VOL_CAP_FMT_2TB_FILESIZE |
604 // VOL_CAP_FMT_OPENDENYMODES |
605 // VOL_CAP_FMT_HIDDEN_FILES |
606 caps;
607 fsap->f_capabilities.valid[VOL_CAPABILITIES_FORMAT] =
608 VOL_CAP_FMT_PERSISTENTOBJECTIDS |
609 // VOL_CAP_FMT_SYMBOLICLINKS |
610 // VOL_CAP_FMT_HARDLINKS |
611 // VOL_CAP_FMT_JOURNAL |
612 // VOL_CAP_FMT_JOURNAL_ACTIVE |
613 // VOL_CAP_FMT_NO_ROOT_TIMES |
614 // VOL_CAP_FMT_SPARSE_FILES |
615 // VOL_CAP_FMT_ZERO_RUNS |
616 // VOL_CAP_FMT_CASE_SENSITIVE |
617 // VOL_CAP_FMT_CASE_PRESERVING |
618 VOL_CAP_FMT_FAST_STATFS |
619 VOL_CAP_FMT_2TB_FILESIZE |
620 // VOL_CAP_FMT_OPENDENYMODES |
621 // VOL_CAP_FMT_HIDDEN_FILES |
622 valid;
623
624 /*
625 * We don't support most of the interfaces.
626 *
627 * We MAY support locking, but we don't have any easy way of probing.
628 * We can tell if there's no lockd running or if locks have been
629 * disabled for a mount, so we can definitely answer NO in that case.
630 * Any attempt to send a request to lockd to test for locking support
631 * may cause the lazily-launched locking daemons to be started
632 * unnecessarily. So we avoid that. However, we do record if we ever
633 * successfully perform a lock operation on a mount point, so if it
634 * looks like lock ops have worked, we do report that we support them.
635 */
636 caps = valid = 0;
637 if (nfsvers >= NFS_VER4) {
638 caps = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
639 valid = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
640 // VOL_CAP_INT_EXTENDED_SECURITY
641 // VOL_CAP_INT_NAMEDSTREAMS
642 // VOL_CAP_INT_EXTENDED_ATTR
643 } else if ((nmp->nm_flag & NFSMNT_NOLOCKS)) {
644 /* locks disabled on this mount, so they definitely won't work */
645 valid = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
646 } else if (nmp->nm_state & NFSSTA_LOCKSWORK) {
647 caps = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
648 valid = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
649 }
650 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_INTERFACES] =
651 // VOL_CAP_INT_SEARCHFS |
652 // VOL_CAP_INT_ATTRLIST |
653 // VOL_CAP_INT_NFSEXPORT |
654 // VOL_CAP_INT_READDIRATTR |
655 // VOL_CAP_INT_EXCHANGEDATA |
656 // VOL_CAP_INT_COPYFILE |
657 // VOL_CAP_INT_ALLOCATE |
658 // VOL_CAP_INT_VOL_RENAME |
659 // VOL_CAP_INT_ADVLOCK |
660 // VOL_CAP_INT_FLOCK |
661 // VOL_CAP_INT_EXTENDED_SECURITY |
662 // VOL_CAP_INT_USERACCESS |
663 // VOL_CAP_INT_MANLOCK |
664 // VOL_CAP_INT_NAMEDSTREAMS |
665 // VOL_CAP_INT_EXTENDED_ATTR |
666 caps;
667 fsap->f_capabilities.valid[VOL_CAPABILITIES_INTERFACES] =
668 VOL_CAP_INT_SEARCHFS |
669 VOL_CAP_INT_ATTRLIST |
670 VOL_CAP_INT_NFSEXPORT |
671 VOL_CAP_INT_READDIRATTR |
672 VOL_CAP_INT_EXCHANGEDATA |
673 VOL_CAP_INT_COPYFILE |
674 VOL_CAP_INT_ALLOCATE |
675 VOL_CAP_INT_VOL_RENAME |
676 // VOL_CAP_INT_ADVLOCK |
677 // VOL_CAP_INT_FLOCK |
678 // VOL_CAP_INT_EXTENDED_SECURITY |
679 // VOL_CAP_INT_USERACCESS |
680 // VOL_CAP_INT_MANLOCK |
681 // VOL_CAP_INT_NAMEDSTREAMS |
682 // VOL_CAP_INT_EXTENDED_ATTR |
683 valid;
684
685 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED1] = 0;
686 fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED1] = 0;
687
688 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED2] = 0;
689 fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED2] = 0;
690
691 VFSATTR_SET_SUPPORTED(fsap, f_capabilities);
692 lck_mtx_unlock(&nmp->nm_lock);
693 }
694
695 if (VFSATTR_IS_ACTIVE(fsap, f_attributes)) {
696 fsap->f_attributes.validattr.commonattr = 0;
697 fsap->f_attributes.validattr.volattr =
698 ATTR_VOL_CAPABILITIES | ATTR_VOL_ATTRIBUTES;
699 fsap->f_attributes.validattr.dirattr = 0;
700 fsap->f_attributes.validattr.fileattr = 0;
701 fsap->f_attributes.validattr.forkattr = 0;
702
703 fsap->f_attributes.nativeattr.commonattr = 0;
704 fsap->f_attributes.nativeattr.volattr =
705 ATTR_VOL_CAPABILITIES | ATTR_VOL_ATTRIBUTES;
706 fsap->f_attributes.nativeattr.dirattr = 0;
707 fsap->f_attributes.nativeattr.fileattr = 0;
708 fsap->f_attributes.nativeattr.forkattr = 0;
709
710 VFSATTR_SET_SUPPORTED(fsap, f_attributes);
711 }
712
713 return (error);
714 }
715
716 /*
717 * nfs version 3 fsinfo rpc call
718 */
719 static int
720 nfs3_fsinfo(struct nfsmount *nmp, nfsnode_t np, vfs_context_t ctx)
721 {
722 int error = 0, lockerror, status, prefsize, maxsize, nmlocked = 0;
723 u_int64_t xid;
724 uint32_t val;
725 struct nfsm_chain nmreq, nmrep;
726
727 nfsm_chain_null(&nmreq);
728 nfsm_chain_null(&nmrep);
729
730 nfsm_chain_build_alloc_init(error, &nmreq, NFSX_FH(nmp->nm_vers));
731 nfsm_chain_add_fh(error, &nmreq, nmp->nm_vers, np->n_fhp, np->n_fhsize);
732 nfsm_chain_build_done(error, &nmreq);
733 nfsmout_if(error);
734 error = nfs_request(np, NULL, &nmreq, NFSPROC_FSINFO, ctx,
735 &nmrep, &xid, &status);
736 if ((lockerror = nfs_lock(np, NFS_NODE_LOCK_EXCLUSIVE)))
737 error = lockerror;
738 nfsm_chain_postop_attr_update(error, &nmrep, np, &xid);
739 if (!lockerror)
740 nfs_unlock(np);
741 if (!error)
742 error = status;
743 nfsmout_if(error);
744
745 lck_mtx_lock(&nmp->nm_lock);
746 nmlocked = 1;
747
748 nfsm_chain_get_32(error, &nmrep, maxsize);
749 nfsm_chain_get_32(error, &nmrep, prefsize);
750 nfsmout_if(error);
751 nmp->nm_fsattr.nfsa_maxread = maxsize;
752 if (prefsize < nmp->nm_rsize)
753 nmp->nm_rsize = (prefsize + NFS_FABLKSIZE - 1) &
754 ~(NFS_FABLKSIZE - 1);
755 if (maxsize < nmp->nm_rsize) {
756 nmp->nm_rsize = maxsize & ~(NFS_FABLKSIZE - 1);
757 if (nmp->nm_rsize == 0)
758 nmp->nm_rsize = maxsize;
759 }
760 nfsm_chain_adv(error, &nmrep, NFSX_UNSIGNED); // skip rtmult
761
762 nfsm_chain_get_32(error, &nmrep, maxsize);
763 nfsm_chain_get_32(error, &nmrep, prefsize);
764 nfsmout_if(error);
765 nmp->nm_fsattr.nfsa_maxwrite = maxsize;
766 if (prefsize < nmp->nm_wsize)
767 nmp->nm_wsize = (prefsize + NFS_FABLKSIZE - 1) &
768 ~(NFS_FABLKSIZE - 1);
769 if (maxsize < nmp->nm_wsize) {
770 nmp->nm_wsize = maxsize & ~(NFS_FABLKSIZE - 1);
771 if (nmp->nm_wsize == 0)
772 nmp->nm_wsize = maxsize;
773 }
774 nfsm_chain_adv(error, &nmrep, NFSX_UNSIGNED); // skip wtmult
775
776 nfsm_chain_get_32(error, &nmrep, prefsize);
777 nfsmout_if(error);
778 if (prefsize < nmp->nm_readdirsize)
779 nmp->nm_readdirsize = prefsize;
780 if (maxsize < nmp->nm_readdirsize)
781 nmp->nm_readdirsize = maxsize;
782
783 nfsm_chain_get_64(error, &nmrep, maxsize);
784 nmp->nm_fsattr.nfsa_maxfilesize = maxsize;
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);
807 nfsmout:
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 */
828 int
829 nfs_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
861 tryagain:
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_arg("-rwroot_hack", &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 */
974 static int
975 nfs_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 */
1039 static int
1040 nfs_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;
1200 out:
1201 return (error);
1202 }
1203 #endif /* NO_MOUNT_PRIVATE */
1204
1205 /*
1206 * VFS Operations.
1207 *
1208 * mount system call
1209 */
1210 static int
1211 nfs_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
1307 static int
1308 nfs3_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 }
1363 out:
1364 if (*npp && error) {
1365 vnode_put(NFSTOV(*npp));
1366 *npp = NULL;
1367 }
1368 return (error);
1369 }
1370
1371 static int
1372 nfs4_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
1491 nfsmout:
1492 if (*npp)
1493 nfs_unlock(*npp);
1494 return (error);
1495 }
1496
1497 static int
1498 mountnfs(
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);
1782 bad:
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 */
1811 static int
1812 nfs_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 */
1966 static int
1967 nfs_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
1992 static int
1993 nfs_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
2003 static int
2004 nfs_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 }
2076 nfsmout:
2077 if (so) {
2078 sock_shutdown(so, SHUT_RDWR);
2079 sock_close(so);
2080 }
2081 mbuf_freem(mreq);
2082 return (error);
2083 }
2084
2085 static int
2086 nfs3_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
2142 got_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;
2191 nfsmout:
2192 nfsm_chain_cleanup(&nmreq);
2193 nfsm_chain_cleanup(&nmrep);
2194 return (error);
2195 }
2196
2197 static int
2198 nfs4_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);
2272 nfsmout:
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
2280 static int
2281 nfs_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
2330 struct nfs_sync_cargs {
2331 thread_t thd;
2332 int waitfor;
2333 int error;
2334 };
2335
2336 static int
2337 nfs_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
2356 static int
2357 nfs_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*/
2375 static int
2376 nfs_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*/
2390 static int
2391 nfs_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*/
2406 static int
2407 nfs_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*/
2421 static int
2422 nfs_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 */
2434 static int
2435 nfs_vfs_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp,
2436 user_addr_t newp, size_t newlen, vfs_context_t ctx)
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
2726 ustat_done:
2727 /* unlock the export table */
2728 lck_rw_done(&nfsrv_export_rwlock);
2729
2730 ustat_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 }