]> git.saurik.com Git - apple/xnu.git/blob - bsd/nfs/nfs_vfsops.c
xnu-3789.51.2.tar.gz
[apple/xnu.git] / bsd / nfs / nfs_vfsops.c
1 /*
2 * Copyright (c) 2000-2014 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 <sys/priv.h>
92 #include <libkern/OSAtomic.h>
93
94 #include <sys/vm.h>
95 #include <sys/vmparam.h>
96
97 #if !defined(NO_MOUNT_PRIVATE)
98 #include <sys/filedesc.h>
99 #endif /* NO_MOUNT_PRIVATE */
100
101 #include <net/if.h>
102 #include <net/route.h>
103 #include <netinet/in.h>
104
105 #include <nfs/rpcv2.h>
106 #include <nfs/krpc.h>
107 #include <nfs/nfsproto.h>
108 #include <nfs/nfs.h>
109 #include <nfs/nfsnode.h>
110 #include <nfs/nfs_gss.h>
111 #include <nfs/nfsmount.h>
112 #include <nfs/xdr_subs.h>
113 #include <nfs/nfsm_subs.h>
114 #include <nfs/nfsdiskless.h>
115 #include <nfs/nfs_lock.h>
116 #if CONFIG_MACF
117 #include <security/mac_framework.h>
118 #endif
119
120 #include <pexpert/pexpert.h>
121
122 #define NFS_VFS_DBG(...) NFS_DBG(NFS_FAC_VFS, 7, ## __VA_ARGS__)
123
124 /*
125 * NFS client globals
126 */
127
128 int nfs_ticks;
129 static lck_grp_t *nfs_global_grp, *nfs_mount_grp;
130 lck_mtx_t *nfs_global_mutex;
131 uint32_t nfs_fs_attr_bitmap[NFS_ATTR_BITMAP_LEN];
132 uint32_t nfs_object_attr_bitmap[NFS_ATTR_BITMAP_LEN];
133 uint32_t nfs_getattr_bitmap[NFS_ATTR_BITMAP_LEN];
134 struct nfsclientidlist nfsclientids;
135
136 /* NFS requests */
137 struct nfs_reqqhead nfs_reqq;
138 lck_grp_t *nfs_request_grp;
139 lck_mtx_t *nfs_request_mutex;
140 thread_call_t nfs_request_timer_call;
141 int nfs_request_timer_on;
142 u_int32_t nfs_xid = 0;
143 u_int32_t nfs_xidwrap = 0; /* to build a (non-wrapping) 64 bit xid */
144
145 thread_call_t nfs_buf_timer_call;
146
147 /* NFSv4 */
148 lck_grp_t *nfs_open_grp;
149 uint32_t nfs_open_owner_seqnum = 0;
150 uint32_t nfs_lock_owner_seqnum = 0;
151 thread_call_t nfs4_callback_timer_call;
152 int nfs4_callback_timer_on = 0;
153 char nfs4_domain[MAXPATHLEN];
154
155 /* nfsiod */
156 lck_grp_t *nfsiod_lck_grp;
157 lck_mtx_t *nfsiod_mutex;
158 struct nfsiodlist nfsiodfree, nfsiodwork;
159 struct nfsiodmountlist nfsiodmounts;
160 int nfsiod_thread_count = 0;
161 int nfsiod_thread_max = NFS_DEFASYNCTHREAD;
162 int nfs_max_async_writes = NFS_DEFMAXASYNCWRITES;
163
164 int nfs_iosize = NFS_IOSIZE;
165 int nfs_access_cache_timeout = NFS_MAXATTRTIMO;
166 int nfs_access_delete = 1; /* too many servers get this wrong - workaround on by default */
167 int nfs_access_dotzfs = 1;
168 int nfs_access_for_getattr = 0;
169 int nfs_allow_async = 0;
170 int nfs_statfs_rate_limit = NFS_DEFSTATFSRATELIMIT;
171 int nfs_lockd_mounts = 0;
172 int nfs_lockd_request_sent = 0;
173 int nfs_idmap_ctrl = NFS_IDMAP_CTRL_USE_IDMAP_SERVICE;
174 int nfs_callback_port = 0;
175
176 int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
177 int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
178
179
180 int mountnfs(char *, mount_t, vfs_context_t, vnode_t *);
181 static int nfs_mount_diskless(struct nfs_dlmount *, const char *, int, vnode_t *, mount_t *, vfs_context_t);
182 #if !defined(NO_MOUNT_PRIVATE)
183 static int nfs_mount_diskless_private(struct nfs_dlmount *, const char *, int, vnode_t *, mount_t *, vfs_context_t);
184 #endif /* NO_MOUNT_PRIVATE */
185 int nfs_mount_connect(struct nfsmount *);
186 void nfs_mount_drain_and_cleanup(struct nfsmount *);
187 void nfs_mount_cleanup(struct nfsmount *);
188 int nfs_mountinfo_assemble(struct nfsmount *, struct xdrbuf *);
189 int nfs4_mount_update_path_with_symlink(struct nfsmount *, struct nfs_fs_path *, uint32_t, fhandle_t *, int *, fhandle_t *, vfs_context_t);
190
191 /*
192 * NFS VFS operations.
193 */
194 int nfs_vfs_mount(mount_t, vnode_t, user_addr_t, vfs_context_t);
195 int nfs_vfs_start(mount_t, int, vfs_context_t);
196 int nfs_vfs_unmount(mount_t, int, vfs_context_t);
197 int nfs_vfs_root(mount_t, vnode_t *, vfs_context_t);
198 int nfs_vfs_quotactl(mount_t, int, uid_t, caddr_t, vfs_context_t);
199 int nfs_vfs_getattr(mount_t, struct vfs_attr *, vfs_context_t);
200 int nfs_vfs_sync(mount_t, int, vfs_context_t);
201 int nfs_vfs_vget(mount_t, ino64_t, vnode_t *, vfs_context_t);
202 int nfs_vfs_vptofh(vnode_t, int *, unsigned char *, vfs_context_t);
203 int nfs_vfs_fhtovp(mount_t, int, unsigned char *, vnode_t *, vfs_context_t);
204 int nfs_vfs_init(struct vfsconf *);
205 int nfs_vfs_sysctl(int *, u_int, user_addr_t, size_t *, user_addr_t, size_t, vfs_context_t);
206
207 struct vfsops nfs_vfsops = {
208 .vfs_mount = nfs_vfs_mount,
209 .vfs_start = nfs_vfs_start,
210 .vfs_unmount = nfs_vfs_unmount,
211 .vfs_root = nfs_vfs_root,
212 .vfs_quotactl = nfs_vfs_quotactl,
213 .vfs_getattr = nfs_vfs_getattr,
214 .vfs_sync = nfs_vfs_sync,
215 .vfs_vget = nfs_vfs_vget,
216 .vfs_fhtovp = nfs_vfs_fhtovp,
217 .vfs_vptofh = nfs_vfs_vptofh,
218 .vfs_init = nfs_vfs_init,
219 .vfs_sysctl = nfs_vfs_sysctl,
220 // We do not support the remaining VFS ops
221 };
222
223
224 /*
225 * version-specific NFS functions
226 */
227 int nfs3_mount(struct nfsmount *, vfs_context_t, nfsnode_t *);
228 int nfs4_mount(struct nfsmount *, vfs_context_t, nfsnode_t *);
229 int nfs3_fsinfo(struct nfsmount *, nfsnode_t, vfs_context_t);
230 int nfs3_update_statfs(struct nfsmount *, vfs_context_t);
231 int nfs4_update_statfs(struct nfsmount *, vfs_context_t);
232 #if !QUOTA
233 #define nfs3_getquota NULL
234 #define nfs4_getquota NULL
235 #else
236 int nfs3_getquota(struct nfsmount *, vfs_context_t, uid_t, int, struct dqblk *);
237 int nfs4_getquota(struct nfsmount *, vfs_context_t, uid_t, int, struct dqblk *);
238 #endif
239
240 struct nfs_funcs nfs3_funcs = {
241 nfs3_mount,
242 nfs3_update_statfs,
243 nfs3_getquota,
244 nfs3_access_rpc,
245 nfs3_getattr_rpc,
246 nfs3_setattr_rpc,
247 nfs3_read_rpc_async,
248 nfs3_read_rpc_async_finish,
249 nfs3_readlink_rpc,
250 nfs3_write_rpc_async,
251 nfs3_write_rpc_async_finish,
252 nfs3_commit_rpc,
253 nfs3_lookup_rpc_async,
254 nfs3_lookup_rpc_async_finish,
255 nfs3_remove_rpc,
256 nfs3_rename_rpc,
257 nfs3_setlock_rpc,
258 nfs3_unlock_rpc,
259 nfs3_getlock_rpc
260 };
261 struct nfs_funcs nfs4_funcs = {
262 nfs4_mount,
263 nfs4_update_statfs,
264 nfs4_getquota,
265 nfs4_access_rpc,
266 nfs4_getattr_rpc,
267 nfs4_setattr_rpc,
268 nfs4_read_rpc_async,
269 nfs4_read_rpc_async_finish,
270 nfs4_readlink_rpc,
271 nfs4_write_rpc_async,
272 nfs4_write_rpc_async_finish,
273 nfs4_commit_rpc,
274 nfs4_lookup_rpc_async,
275 nfs4_lookup_rpc_async_finish,
276 nfs4_remove_rpc,
277 nfs4_rename_rpc,
278 nfs4_setlock_rpc,
279 nfs4_unlock_rpc,
280 nfs4_getlock_rpc
281 };
282
283 /*
284 * Called once to initialize data structures...
285 */
286 int
287 nfs_vfs_init(__unused struct vfsconf *vfsp)
288 {
289 int i;
290
291 /*
292 * Check to see if major data structures haven't bloated.
293 */
294 if (sizeof (struct nfsnode) > NFS_NODEALLOC) {
295 printf("struct nfsnode bloated (> %dbytes)\n", NFS_NODEALLOC);
296 printf("Try reducing NFS_SMALLFH\n");
297 }
298 if (sizeof (struct nfsmount) > NFS_MNTALLOC)
299 printf("struct nfsmount bloated (> %dbytes)\n", NFS_MNTALLOC);
300
301 nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
302 if (nfs_ticks < 1)
303 nfs_ticks = 1;
304
305 /* init async I/O thread pool state */
306 TAILQ_INIT(&nfsiodfree);
307 TAILQ_INIT(&nfsiodwork);
308 TAILQ_INIT(&nfsiodmounts);
309 nfsiod_lck_grp = lck_grp_alloc_init("nfsiod", LCK_GRP_ATTR_NULL);
310 nfsiod_mutex = lck_mtx_alloc_init(nfsiod_lck_grp, LCK_ATTR_NULL);
311
312 /* init lock groups, etc. */
313 nfs_mount_grp = lck_grp_alloc_init("nfs_mount", LCK_GRP_ATTR_NULL);
314 nfs_open_grp = lck_grp_alloc_init("nfs_open", LCK_GRP_ATTR_NULL);
315 nfs_global_grp = lck_grp_alloc_init("nfs_global", LCK_GRP_ATTR_NULL);
316
317 nfs_global_mutex = lck_mtx_alloc_init(nfs_global_grp, LCK_ATTR_NULL);
318
319 /* init request list mutex */
320 nfs_request_grp = lck_grp_alloc_init("nfs_request", LCK_GRP_ATTR_NULL);
321 nfs_request_mutex = lck_mtx_alloc_init(nfs_request_grp, LCK_ATTR_NULL);
322
323 /* initialize NFS request list */
324 TAILQ_INIT(&nfs_reqq);
325
326 nfs_nbinit(); /* Init the nfsbuf table */
327 nfs_nhinit(); /* Init the nfsnode table */
328 nfs_lockinit(); /* Init the nfs lock state */
329 nfs_gss_init(); /* Init RPCSEC_GSS security */
330
331 /* NFSv4 stuff */
332 NFS4_PER_FS_ATTRIBUTES(nfs_fs_attr_bitmap);
333 NFS4_PER_OBJECT_ATTRIBUTES(nfs_object_attr_bitmap);
334 NFS4_DEFAULT_ATTRIBUTES(nfs_getattr_bitmap);
335 for (i=0; i < NFS_ATTR_BITMAP_LEN; i++)
336 nfs_getattr_bitmap[i] &= nfs_object_attr_bitmap[i];
337 TAILQ_INIT(&nfsclientids);
338
339 /* initialize NFS timer callouts */
340 nfs_request_timer_call = thread_call_allocate(nfs_request_timer, NULL);
341 nfs_buf_timer_call = thread_call_allocate(nfs_buf_timer, NULL);
342 nfs4_callback_timer_call = thread_call_allocate(nfs4_callback_timer, NULL);
343
344 return (0);
345 }
346
347 /*
348 * nfs statfs call
349 */
350 int
351 nfs3_update_statfs(struct nfsmount *nmp, vfs_context_t ctx)
352 {
353 nfsnode_t np;
354 int error = 0, lockerror, status, nfsvers;
355 u_int64_t xid;
356 struct nfsm_chain nmreq, nmrep;
357 uint32_t val = 0;
358
359 nfsvers = nmp->nm_vers;
360 np = nmp->nm_dnp;
361 if (!np)
362 return (ENXIO);
363 if ((error = vnode_get(NFSTOV(np))))
364 return (error);
365
366 nfsm_chain_null(&nmreq);
367 nfsm_chain_null(&nmrep);
368
369 nfsm_chain_build_alloc_init(error, &nmreq, NFSX_FH(nfsvers));
370 nfsm_chain_add_fh(error, &nmreq, nfsvers, np->n_fhp, np->n_fhsize);
371 nfsm_chain_build_done(error, &nmreq);
372 nfsmout_if(error);
373 error = nfs_request2(np, NULL, &nmreq, NFSPROC_FSSTAT, vfs_context_thread(ctx),
374 vfs_context_ucred(ctx), NULL, R_SOFT, &nmrep, &xid, &status);
375 if (error == ETIMEDOUT)
376 goto nfsmout;
377 if ((lockerror = nfs_node_lock(np)))
378 error = lockerror;
379 if (nfsvers == NFS_VER3)
380 nfsm_chain_postop_attr_update(error, &nmrep, np, &xid);
381 if (!lockerror)
382 nfs_node_unlock(np);
383 if (!error)
384 error = status;
385 nfsm_assert(error, NFSTONMP(np), ENXIO);
386 nfsmout_if(error);
387 lck_mtx_lock(&nmp->nm_lock);
388 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_TOTAL);
389 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_FREE);
390 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_AVAIL);
391 if (nfsvers == NFS_VER3) {
392 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_FILES_AVAIL);
393 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_FILES_TOTAL);
394 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_FILES_FREE);
395 nmp->nm_fsattr.nfsa_bsize = NFS_FABLKSIZE;
396 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_space_total);
397 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_space_free);
398 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_space_avail);
399 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_files_total);
400 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_files_free);
401 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_files_avail);
402 // skip invarsec
403 } else {
404 nfsm_chain_adv(error, &nmrep, NFSX_UNSIGNED); // skip tsize?
405 nfsm_chain_get_32(error, &nmrep, nmp->nm_fsattr.nfsa_bsize);
406 nfsm_chain_get_32(error, &nmrep, val);
407 nfsmout_if(error);
408 if (nmp->nm_fsattr.nfsa_bsize <= 0)
409 nmp->nm_fsattr.nfsa_bsize = NFS_FABLKSIZE;
410 nmp->nm_fsattr.nfsa_space_total = (uint64_t)val * nmp->nm_fsattr.nfsa_bsize;
411 nfsm_chain_get_32(error, &nmrep, val);
412 nfsmout_if(error);
413 nmp->nm_fsattr.nfsa_space_free = (uint64_t)val * nmp->nm_fsattr.nfsa_bsize;
414 nfsm_chain_get_32(error, &nmrep, val);
415 nfsmout_if(error);
416 nmp->nm_fsattr.nfsa_space_avail = (uint64_t)val * nmp->nm_fsattr.nfsa_bsize;
417 }
418 lck_mtx_unlock(&nmp->nm_lock);
419 nfsmout:
420 nfsm_chain_cleanup(&nmreq);
421 nfsm_chain_cleanup(&nmrep);
422 vnode_put(NFSTOV(np));
423 return (error);
424 }
425
426 int
427 nfs4_update_statfs(struct nfsmount *nmp, vfs_context_t ctx)
428 {
429 nfsnode_t np;
430 int error = 0, lockerror, status, nfsvers, numops;
431 u_int64_t xid;
432 struct nfsm_chain nmreq, nmrep;
433 uint32_t bitmap[NFS_ATTR_BITMAP_LEN];
434 struct nfs_vattr nvattr;
435 struct nfsreq_secinfo_args si;
436
437 nfsvers = nmp->nm_vers;
438 np = nmp->nm_dnp;
439 if (!np)
440 return (ENXIO);
441 if ((error = vnode_get(NFSTOV(np))))
442 return (error);
443
444 NFSREQ_SECINFO_SET(&si, np, NULL, 0, NULL, 0);
445 NVATTR_INIT(&nvattr);
446 nfsm_chain_null(&nmreq);
447 nfsm_chain_null(&nmrep);
448
449 // PUTFH + GETATTR
450 numops = 2;
451 nfsm_chain_build_alloc_init(error, &nmreq, 15 * NFSX_UNSIGNED);
452 nfsm_chain_add_compound_header(error, &nmreq, "statfs", nmp->nm_minor_vers, numops);
453 numops--;
454 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTFH);
455 nfsm_chain_add_fh(error, &nmreq, nfsvers, np->n_fhp, np->n_fhsize);
456 numops--;
457 nfsm_chain_add_32(error, &nmreq, NFS_OP_GETATTR);
458 NFS_COPY_ATTRIBUTES(nfs_getattr_bitmap, bitmap);
459 NFS4_STATFS_ATTRIBUTES(bitmap);
460 nfsm_chain_add_bitmap_supported(error, &nmreq, bitmap, nmp, np);
461 nfsm_chain_build_done(error, &nmreq);
462 nfsm_assert(error, (numops == 0), EPROTO);
463 nfsmout_if(error);
464 error = nfs_request2(np, NULL, &nmreq, NFSPROC4_COMPOUND,
465 vfs_context_thread(ctx), vfs_context_ucred(ctx),
466 NULL, R_SOFT, &nmrep, &xid, &status);
467 nfsm_chain_skip_tag(error, &nmrep);
468 nfsm_chain_get_32(error, &nmrep, numops);
469 nfsm_chain_op_check(error, &nmrep, NFS_OP_PUTFH);
470 nfsm_chain_op_check(error, &nmrep, NFS_OP_GETATTR);
471 nfsm_assert(error, NFSTONMP(np), ENXIO);
472 nfsmout_if(error);
473 lck_mtx_lock(&nmp->nm_lock);
474 error = nfs4_parsefattr(&nmrep, &nmp->nm_fsattr, &nvattr, NULL, NULL, NULL);
475 lck_mtx_unlock(&nmp->nm_lock);
476 nfsmout_if(error);
477 if ((lockerror = nfs_node_lock(np)))
478 error = lockerror;
479 if (!error)
480 nfs_loadattrcache(np, &nvattr, &xid, 0);
481 if (!lockerror)
482 nfs_node_unlock(np);
483 nfsm_assert(error, NFSTONMP(np), ENXIO);
484 nfsmout_if(error);
485 nmp->nm_fsattr.nfsa_bsize = NFS_FABLKSIZE;
486 nfsmout:
487 NVATTR_CLEANUP(&nvattr);
488 nfsm_chain_cleanup(&nmreq);
489 nfsm_chain_cleanup(&nmrep);
490 vnode_put(NFSTOV(np));
491 return (error);
492 }
493
494
495 /*
496 * The NFS VFS_GETATTR function: "statfs"-type information is retrieved
497 * using the nf_update_statfs() function, and other attributes are cobbled
498 * together from whatever sources we can (getattr, fsinfo, pathconf).
499 */
500 int
501 nfs_vfs_getattr(mount_t mp, struct vfs_attr *fsap, vfs_context_t ctx)
502 {
503 struct nfsmount *nmp;
504 uint32_t bsize;
505 int error = 0, nfsvers;
506
507 nmp = VFSTONFS(mp);
508 if (nfs_mount_gone(nmp))
509 return (ENXIO);
510 nfsvers = nmp->nm_vers;
511
512 if (VFSATTR_IS_ACTIVE(fsap, f_bsize) ||
513 VFSATTR_IS_ACTIVE(fsap, f_iosize) ||
514 VFSATTR_IS_ACTIVE(fsap, f_blocks) ||
515 VFSATTR_IS_ACTIVE(fsap, f_bfree) ||
516 VFSATTR_IS_ACTIVE(fsap, f_bavail) ||
517 VFSATTR_IS_ACTIVE(fsap, f_bused) ||
518 VFSATTR_IS_ACTIVE(fsap, f_files) ||
519 VFSATTR_IS_ACTIVE(fsap, f_ffree)) {
520 int statfsrate = nfs_statfs_rate_limit;
521 int refresh = 1;
522
523 /*
524 * Are we rate-limiting statfs RPCs?
525 * (Treat values less than 1 or greater than 1,000,000 as no limit.)
526 */
527 if ((statfsrate > 0) && (statfsrate < 1000000)) {
528 struct timeval now;
529 uint32_t stamp;
530
531 microuptime(&now);
532 lck_mtx_lock(&nmp->nm_lock);
533 stamp = (now.tv_sec * statfsrate) + (now.tv_usec / (1000000/statfsrate));
534 if (stamp != nmp->nm_fsattrstamp) {
535 refresh = 1;
536 nmp->nm_fsattrstamp = stamp;
537 } else {
538 refresh = 0;
539 }
540 lck_mtx_unlock(&nmp->nm_lock);
541 }
542
543 if (refresh && !nfs_use_cache(nmp))
544 error = nmp->nm_funcs->nf_update_statfs(nmp, ctx);
545 if ((error == ESTALE) || (error == ETIMEDOUT))
546 error = 0;
547 if (error)
548 return (error);
549
550 lck_mtx_lock(&nmp->nm_lock);
551 VFSATTR_RETURN(fsap, f_iosize, nfs_iosize);
552 VFSATTR_RETURN(fsap, f_bsize, nmp->nm_fsattr.nfsa_bsize);
553 bsize = nmp->nm_fsattr.nfsa_bsize;
554 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_TOTAL))
555 VFSATTR_RETURN(fsap, f_blocks, nmp->nm_fsattr.nfsa_space_total / bsize);
556 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_FREE))
557 VFSATTR_RETURN(fsap, f_bfree, nmp->nm_fsattr.nfsa_space_free / bsize);
558 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_AVAIL))
559 VFSATTR_RETURN(fsap, f_bavail, nmp->nm_fsattr.nfsa_space_avail / bsize);
560 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_TOTAL) &&
561 NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_FREE))
562 VFSATTR_RETURN(fsap, f_bused,
563 (nmp->nm_fsattr.nfsa_space_total / bsize) -
564 (nmp->nm_fsattr.nfsa_space_free / bsize));
565 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_FILES_TOTAL))
566 VFSATTR_RETURN(fsap, f_files, nmp->nm_fsattr.nfsa_files_total);
567 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_FILES_FREE))
568 VFSATTR_RETURN(fsap, f_ffree, nmp->nm_fsattr.nfsa_files_free);
569 lck_mtx_unlock(&nmp->nm_lock);
570 }
571
572 if (VFSATTR_IS_ACTIVE(fsap, f_capabilities)) {
573 u_int32_t caps, valid;
574 nfsnode_t np = nmp->nm_dnp;
575
576 nfsm_assert(error, VFSTONFS(mp) && np, ENXIO);
577 if (error)
578 return (error);
579 lck_mtx_lock(&nmp->nm_lock);
580
581 /*
582 * The capabilities[] array defines what this volume supports.
583 *
584 * The valid[] array defines which bits this code understands
585 * the meaning of (whether the volume has that capability or not).
586 * Any zero bits here means "I don't know what you're asking about"
587 * and the caller cannot tell whether that capability is
588 * present or not.
589 */
590 caps = valid = 0;
591 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SYMLINK_SUPPORT)) {
592 valid |= VOL_CAP_FMT_SYMBOLICLINKS;
593 if (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_SYMLINK)
594 caps |= VOL_CAP_FMT_SYMBOLICLINKS;
595 }
596 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_LINK_SUPPORT)) {
597 valid |= VOL_CAP_FMT_HARDLINKS;
598 if (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_LINK)
599 caps |= VOL_CAP_FMT_HARDLINKS;
600 }
601 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_CASE_INSENSITIVE)) {
602 valid |= VOL_CAP_FMT_CASE_SENSITIVE;
603 if (!(nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_CASE_INSENSITIVE))
604 caps |= VOL_CAP_FMT_CASE_SENSITIVE;
605 }
606 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_CASE_PRESERVING)) {
607 valid |= VOL_CAP_FMT_CASE_PRESERVING;
608 if (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_CASE_PRESERVING)
609 caps |= VOL_CAP_FMT_CASE_PRESERVING;
610 }
611 /* Note: VOL_CAP_FMT_2TB_FILESIZE is actually used to test for "large file support" */
612 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXFILESIZE)) {
613 /* Is server's max file size at least 4GB? */
614 if (nmp->nm_fsattr.nfsa_maxfilesize >= 0x100000000ULL)
615 caps |= VOL_CAP_FMT_2TB_FILESIZE;
616 } else if (nfsvers >= NFS_VER3) {
617 /*
618 * NFSv3 and up supports 64 bits of file size.
619 * So, we'll just assume maxfilesize >= 4GB
620 */
621 caps |= VOL_CAP_FMT_2TB_FILESIZE;
622 }
623 if (nfsvers >= NFS_VER4) {
624 caps |= VOL_CAP_FMT_HIDDEN_FILES;
625 valid |= VOL_CAP_FMT_HIDDEN_FILES;
626 // VOL_CAP_FMT_OPENDENYMODES
627 // caps |= VOL_CAP_FMT_OPENDENYMODES;
628 // valid |= VOL_CAP_FMT_OPENDENYMODES;
629 }
630 // no version of nfs supports immutable files
631 caps |= VOL_CAP_FMT_NO_IMMUTABLE_FILES;
632 valid |= VOL_CAP_FMT_NO_IMMUTABLE_FILES;
633
634 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_FORMAT] =
635 // VOL_CAP_FMT_PERSISTENTOBJECTIDS |
636 // VOL_CAP_FMT_SYMBOLICLINKS |
637 // VOL_CAP_FMT_HARDLINKS |
638 // VOL_CAP_FMT_JOURNAL |
639 // VOL_CAP_FMT_JOURNAL_ACTIVE |
640 // VOL_CAP_FMT_NO_ROOT_TIMES |
641 // VOL_CAP_FMT_SPARSE_FILES |
642 // VOL_CAP_FMT_ZERO_RUNS |
643 // VOL_CAP_FMT_CASE_SENSITIVE |
644 // VOL_CAP_FMT_CASE_PRESERVING |
645 // VOL_CAP_FMT_FAST_STATFS |
646 // VOL_CAP_FMT_2TB_FILESIZE |
647 // VOL_CAP_FMT_OPENDENYMODES |
648 // VOL_CAP_FMT_HIDDEN_FILES |
649 caps;
650 fsap->f_capabilities.valid[VOL_CAPABILITIES_FORMAT] =
651 VOL_CAP_FMT_PERSISTENTOBJECTIDS |
652 // VOL_CAP_FMT_SYMBOLICLINKS |
653 // VOL_CAP_FMT_HARDLINKS |
654 // VOL_CAP_FMT_JOURNAL |
655 // VOL_CAP_FMT_JOURNAL_ACTIVE |
656 // VOL_CAP_FMT_NO_ROOT_TIMES |
657 // VOL_CAP_FMT_SPARSE_FILES |
658 // VOL_CAP_FMT_ZERO_RUNS |
659 // VOL_CAP_FMT_CASE_SENSITIVE |
660 // VOL_CAP_FMT_CASE_PRESERVING |
661 VOL_CAP_FMT_FAST_STATFS |
662 VOL_CAP_FMT_2TB_FILESIZE |
663 // VOL_CAP_FMT_OPENDENYMODES |
664 // VOL_CAP_FMT_HIDDEN_FILES |
665 valid;
666
667 /*
668 * We don't support most of the interfaces.
669 *
670 * We MAY support locking, but we don't have any easy way of probing.
671 * We can tell if there's no lockd running or if locks have been
672 * disabled for a mount, so we can definitely answer NO in that case.
673 * Any attempt to send a request to lockd to test for locking support
674 * may cause the lazily-launched locking daemons to be started
675 * unnecessarily. So we avoid that. However, we do record if we ever
676 * successfully perform a lock operation on a mount point, so if it
677 * looks like lock ops have worked, we do report that we support them.
678 */
679 caps = valid = 0;
680 if (nfsvers >= NFS_VER4) {
681 caps = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
682 valid = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
683 if (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_ACL)
684 caps |= VOL_CAP_INT_EXTENDED_SECURITY;
685 valid |= VOL_CAP_INT_EXTENDED_SECURITY;
686 if (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR)
687 caps |= VOL_CAP_INT_EXTENDED_ATTR;
688 valid |= VOL_CAP_INT_EXTENDED_ATTR;
689 #if NAMEDSTREAMS
690 if (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_NAMED_ATTR)
691 caps |= VOL_CAP_INT_NAMEDSTREAMS;
692 valid |= VOL_CAP_INT_NAMEDSTREAMS;
693 #endif
694 } else if (nmp->nm_lockmode == NFS_LOCK_MODE_DISABLED) {
695 /* locks disabled on this mount, so they definitely won't work */
696 valid = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
697 } else if (nmp->nm_state & NFSSTA_LOCKSWORK) {
698 caps = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
699 valid = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK;
700 }
701 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_INTERFACES] =
702 // VOL_CAP_INT_SEARCHFS |
703 // VOL_CAP_INT_ATTRLIST |
704 // VOL_CAP_INT_NFSEXPORT |
705 // VOL_CAP_INT_READDIRATTR |
706 // VOL_CAP_INT_EXCHANGEDATA |
707 // VOL_CAP_INT_COPYFILE |
708 // VOL_CAP_INT_ALLOCATE |
709 // VOL_CAP_INT_VOL_RENAME |
710 // VOL_CAP_INT_ADVLOCK |
711 // VOL_CAP_INT_FLOCK |
712 // VOL_CAP_INT_EXTENDED_SECURITY |
713 // VOL_CAP_INT_USERACCESS |
714 // VOL_CAP_INT_MANLOCK |
715 // VOL_CAP_INT_NAMEDSTREAMS |
716 // VOL_CAP_INT_EXTENDED_ATTR |
717 VOL_CAP_INT_REMOTE_EVENT |
718 caps;
719 fsap->f_capabilities.valid[VOL_CAPABILITIES_INTERFACES] =
720 VOL_CAP_INT_SEARCHFS |
721 VOL_CAP_INT_ATTRLIST |
722 VOL_CAP_INT_NFSEXPORT |
723 VOL_CAP_INT_READDIRATTR |
724 VOL_CAP_INT_EXCHANGEDATA |
725 VOL_CAP_INT_COPYFILE |
726 VOL_CAP_INT_ALLOCATE |
727 VOL_CAP_INT_VOL_RENAME |
728 // VOL_CAP_INT_ADVLOCK |
729 // VOL_CAP_INT_FLOCK |
730 // VOL_CAP_INT_EXTENDED_SECURITY |
731 // VOL_CAP_INT_USERACCESS |
732 // VOL_CAP_INT_MANLOCK |
733 // VOL_CAP_INT_NAMEDSTREAMS |
734 // VOL_CAP_INT_EXTENDED_ATTR |
735 VOL_CAP_INT_REMOTE_EVENT |
736 valid;
737
738 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED1] = 0;
739 fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED1] = 0;
740
741 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED2] = 0;
742 fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED2] = 0;
743
744 VFSATTR_SET_SUPPORTED(fsap, f_capabilities);
745 lck_mtx_unlock(&nmp->nm_lock);
746 }
747
748 if (VFSATTR_IS_ACTIVE(fsap, f_attributes)) {
749 fsap->f_attributes.validattr.commonattr = 0;
750 fsap->f_attributes.validattr.volattr =
751 ATTR_VOL_CAPABILITIES | ATTR_VOL_ATTRIBUTES;
752 fsap->f_attributes.validattr.dirattr = 0;
753 fsap->f_attributes.validattr.fileattr = 0;
754 fsap->f_attributes.validattr.forkattr = 0;
755
756 fsap->f_attributes.nativeattr.commonattr = 0;
757 fsap->f_attributes.nativeattr.volattr =
758 ATTR_VOL_CAPABILITIES | ATTR_VOL_ATTRIBUTES;
759 fsap->f_attributes.nativeattr.dirattr = 0;
760 fsap->f_attributes.nativeattr.fileattr = 0;
761 fsap->f_attributes.nativeattr.forkattr = 0;
762
763 VFSATTR_SET_SUPPORTED(fsap, f_attributes);
764 }
765
766 return (error);
767 }
768
769 /*
770 * nfs version 3 fsinfo rpc call
771 */
772 int
773 nfs3_fsinfo(struct nfsmount *nmp, nfsnode_t np, vfs_context_t ctx)
774 {
775 int error = 0, lockerror, status, nmlocked = 0;
776 u_int64_t xid;
777 uint32_t val, prefsize, maxsize;
778 struct nfsm_chain nmreq, nmrep;
779
780 nfsm_chain_null(&nmreq);
781 nfsm_chain_null(&nmrep);
782
783 nfsm_chain_build_alloc_init(error, &nmreq, NFSX_FH(nmp->nm_vers));
784 nfsm_chain_add_fh(error, &nmreq, nmp->nm_vers, np->n_fhp, np->n_fhsize);
785 nfsm_chain_build_done(error, &nmreq);
786 nfsmout_if(error);
787 error = nfs_request(np, NULL, &nmreq, NFSPROC_FSINFO, ctx, NULL, &nmrep, &xid, &status);
788 if ((lockerror = nfs_node_lock(np)))
789 error = lockerror;
790 nfsm_chain_postop_attr_update(error, &nmrep, np, &xid);
791 if (!lockerror)
792 nfs_node_unlock(np);
793 if (!error)
794 error = status;
795 nfsmout_if(error);
796
797 lck_mtx_lock(&nmp->nm_lock);
798 nmlocked = 1;
799
800 nfsm_chain_get_32(error, &nmrep, maxsize);
801 nfsm_chain_get_32(error, &nmrep, prefsize);
802 nfsmout_if(error);
803 nmp->nm_fsattr.nfsa_maxread = maxsize;
804 if (prefsize < nmp->nm_rsize)
805 nmp->nm_rsize = (prefsize + NFS_FABLKSIZE - 1) &
806 ~(NFS_FABLKSIZE - 1);
807 if ((maxsize > 0) && (maxsize < nmp->nm_rsize)) {
808 nmp->nm_rsize = maxsize & ~(NFS_FABLKSIZE - 1);
809 if (nmp->nm_rsize == 0)
810 nmp->nm_rsize = maxsize;
811 }
812 nfsm_chain_adv(error, &nmrep, NFSX_UNSIGNED); // skip rtmult
813
814 nfsm_chain_get_32(error, &nmrep, maxsize);
815 nfsm_chain_get_32(error, &nmrep, prefsize);
816 nfsmout_if(error);
817 nmp->nm_fsattr.nfsa_maxwrite = maxsize;
818 if (prefsize < nmp->nm_wsize)
819 nmp->nm_wsize = (prefsize + NFS_FABLKSIZE - 1) &
820 ~(NFS_FABLKSIZE - 1);
821 if ((maxsize > 0) && (maxsize < nmp->nm_wsize)) {
822 nmp->nm_wsize = maxsize & ~(NFS_FABLKSIZE - 1);
823 if (nmp->nm_wsize == 0)
824 nmp->nm_wsize = maxsize;
825 }
826 nfsm_chain_adv(error, &nmrep, NFSX_UNSIGNED); // skip wtmult
827
828 nfsm_chain_get_32(error, &nmrep, prefsize);
829 nfsmout_if(error);
830 if ((prefsize > 0) && (prefsize < nmp->nm_readdirsize))
831 nmp->nm_readdirsize = prefsize;
832 if ((nmp->nm_fsattr.nfsa_maxread > 0) &&
833 (nmp->nm_fsattr.nfsa_maxread < nmp->nm_readdirsize))
834 nmp->nm_readdirsize = nmp->nm_fsattr.nfsa_maxread;
835
836 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_maxfilesize);
837
838 nfsm_chain_adv(error, &nmrep, 2 * NFSX_UNSIGNED); // skip time_delta
839
840 /* convert FS properties to our own flags */
841 nfsm_chain_get_32(error, &nmrep, val);
842 nfsmout_if(error);
843 if (val & NFSV3FSINFO_LINK)
844 nmp->nm_fsattr.nfsa_flags |= NFS_FSFLAG_LINK;
845 if (val & NFSV3FSINFO_SYMLINK)
846 nmp->nm_fsattr.nfsa_flags |= NFS_FSFLAG_SYMLINK;
847 if (val & NFSV3FSINFO_HOMOGENEOUS)
848 nmp->nm_fsattr.nfsa_flags |= NFS_FSFLAG_HOMOGENEOUS;
849 if (val & NFSV3FSINFO_CANSETTIME)
850 nmp->nm_fsattr.nfsa_flags |= NFS_FSFLAG_SET_TIME;
851 nmp->nm_state |= NFSSTA_GOTFSINFO;
852 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXREAD);
853 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXWRITE);
854 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXFILESIZE);
855 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_LINK_SUPPORT);
856 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SYMLINK_SUPPORT);
857 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_HOMOGENEOUS);
858 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_CANSETTIME);
859 nfsmout:
860 if (nmlocked)
861 lck_mtx_unlock(&nmp->nm_lock);
862 nfsm_chain_cleanup(&nmreq);
863 nfsm_chain_cleanup(&nmrep);
864 return (error);
865 }
866
867 /*
868 * Mount a remote root fs via. nfs. This depends on the info in the
869 * nfs_diskless structure that has been filled in properly by some primary
870 * bootstrap.
871 * It goes something like this:
872 * - do enough of "ifconfig" by calling ifioctl() so that the system
873 * can talk to the server
874 * - If nfs_diskless.mygateway is filled in, use that address as
875 * a default gateway.
876 * - hand craft the swap nfs vnode hanging off a fake mount point
877 * if swdevt[0].sw_dev == NODEV
878 * - build the rootfs mount point and call mountnfs() to do the rest.
879 */
880 int
881 nfs_mountroot(void)
882 {
883 struct nfs_diskless nd;
884 mount_t mp = NULL;
885 vnode_t vp = NULL;
886 vfs_context_t ctx;
887 int error;
888 #if !defined(NO_MOUNT_PRIVATE)
889 mount_t mppriv = NULL;
890 vnode_t vppriv = NULL;
891 #endif /* NO_MOUNT_PRIVATE */
892 int v3, sotype;
893
894 /*
895 * Call nfs_boot_init() to fill in the nfs_diskless struct.
896 * Note: networking must already have been configured before
897 * we're called.
898 */
899 bzero((caddr_t) &nd, sizeof(nd));
900 error = nfs_boot_init(&nd);
901 if (error)
902 panic("nfs_boot_init: unable to initialize NFS root system information, "
903 "error %d, check configuration: %s\n", error, PE_boot_args());
904
905 /*
906 * Try NFSv3 first, then fallback to NFSv2.
907 * Likewise, try TCP first, then fall back to UDP.
908 */
909 v3 = 1;
910 sotype = SOCK_STREAM;
911
912 tryagain:
913 error = nfs_boot_getfh(&nd, v3, sotype);
914 if (error) {
915 if (error == EHOSTDOWN || error == EHOSTUNREACH) {
916 if (nd.nd_root.ndm_mntfrom)
917 FREE_ZONE(nd.nd_root.ndm_mntfrom,
918 MAXPATHLEN, M_NAMEI);
919 if (nd.nd_root.ndm_path)
920 FREE_ZONE(nd.nd_root.ndm_path,
921 MAXPATHLEN, M_NAMEI);
922 if (nd.nd_private.ndm_mntfrom)
923 FREE_ZONE(nd.nd_private.ndm_mntfrom,
924 MAXPATHLEN, M_NAMEI);
925 if (nd.nd_private.ndm_path)
926 FREE_ZONE(nd.nd_private.ndm_path,
927 MAXPATHLEN, M_NAMEI);
928 return (error);
929 }
930 if (v3) {
931 if (sotype == SOCK_STREAM) {
932 printf("NFS mount (v3,TCP) failed with error %d, trying UDP...\n", error);
933 sotype = SOCK_DGRAM;
934 goto tryagain;
935 }
936 printf("NFS mount (v3,UDP) failed with error %d, trying v2...\n", error);
937 v3 = 0;
938 sotype = SOCK_STREAM;
939 goto tryagain;
940 } else if (sotype == SOCK_STREAM) {
941 printf("NFS mount (v2,TCP) failed with error %d, trying UDP...\n", error);
942 sotype = SOCK_DGRAM;
943 goto tryagain;
944 } else {
945 printf("NFS mount (v2,UDP) failed with error %d, giving up...\n", error);
946 }
947 switch(error) {
948 case EPROGUNAVAIL:
949 panic("NFS mount failed: NFS server mountd not responding, check server configuration: %s", PE_boot_args());
950 case EACCES:
951 case EPERM:
952 panic("NFS mount failed: NFS server refused mount, check server configuration: %s", PE_boot_args());
953 default:
954 panic("NFS mount failed with error %d, check configuration: %s", error, PE_boot_args());
955 }
956 }
957
958 ctx = vfs_context_kernel();
959
960 /*
961 * Create the root mount point.
962 */
963 #if !defined(NO_MOUNT_PRIVATE)
964 {
965 //PWC hack until we have a real "mount" tool to remount root rw
966 int rw_root=0;
967 int flags = MNT_ROOTFS|MNT_RDONLY;
968 PE_parse_boot_argn("-rwroot_hack", &rw_root, sizeof (rw_root));
969 if(rw_root)
970 {
971 flags = MNT_ROOTFS;
972 kprintf("-rwroot_hack in effect: mounting root fs read/write\n");
973 }
974
975 if ((error = nfs_mount_diskless(&nd.nd_root, "/", flags, &vp, &mp, ctx)))
976 #else
977 if ((error = nfs_mount_diskless(&nd.nd_root, "/", MNT_ROOTFS, &vp, &mp, ctx)))
978 #endif /* NO_MOUNT_PRIVATE */
979 {
980 if (v3) {
981 if (sotype == SOCK_STREAM) {
982 printf("NFS root mount (v3,TCP) failed with %d, trying UDP...\n", error);
983 sotype = SOCK_DGRAM;
984 goto tryagain;
985 }
986 printf("NFS root mount (v3,UDP) failed with %d, trying v2...\n", error);
987 v3 = 0;
988 sotype = SOCK_STREAM;
989 goto tryagain;
990 } else if (sotype == SOCK_STREAM) {
991 printf("NFS root mount (v2,TCP) failed with %d, trying UDP...\n", error);
992 sotype = SOCK_DGRAM;
993 goto tryagain;
994 } else {
995 printf("NFS root mount (v2,UDP) failed with error %d, giving up...\n", error);
996 }
997 panic("NFS root mount failed with error %d, check configuration: %s\n", error, PE_boot_args());
998 }
999 }
1000 printf("root on %s\n", nd.nd_root.ndm_mntfrom);
1001
1002 vfs_unbusy(mp);
1003 mount_list_add(mp);
1004 rootvp = vp;
1005
1006 #if !defined(NO_MOUNT_PRIVATE)
1007 if (nd.nd_private.ndm_saddr.sin_addr.s_addr) {
1008 error = nfs_mount_diskless_private(&nd.nd_private, "/private",
1009 0, &vppriv, &mppriv, ctx);
1010 if (error)
1011 panic("NFS /private mount failed with error %d, check configuration: %s\n", error, PE_boot_args());
1012 printf("private on %s\n", nd.nd_private.ndm_mntfrom);
1013
1014 vfs_unbusy(mppriv);
1015 mount_list_add(mppriv);
1016 }
1017
1018 #endif /* NO_MOUNT_PRIVATE */
1019
1020 if (nd.nd_root.ndm_mntfrom)
1021 FREE_ZONE(nd.nd_root.ndm_mntfrom, MAXPATHLEN, M_NAMEI);
1022 if (nd.nd_root.ndm_path)
1023 FREE_ZONE(nd.nd_root.ndm_path, MAXPATHLEN, M_NAMEI);
1024 if (nd.nd_private.ndm_mntfrom)
1025 FREE_ZONE(nd.nd_private.ndm_mntfrom, MAXPATHLEN, M_NAMEI);
1026 if (nd.nd_private.ndm_path)
1027 FREE_ZONE(nd.nd_private.ndm_path, MAXPATHLEN, M_NAMEI);
1028
1029 /* Get root attributes (for the time). */
1030 error = nfs_getattr(VTONFS(vp), NULL, ctx, NGA_UNCACHED);
1031 if (error)
1032 panic("NFS mount: failed to get attributes for root directory, error %d, check server", error);
1033 return (0);
1034 }
1035
1036 /*
1037 * Internal version of mount system call for diskless setup.
1038 */
1039 static int
1040 nfs_mount_diskless(
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 mount_t mp;
1049 int error, numcomps;
1050 char *xdrbuf, *p, *cp, *frompath, *endserverp;
1051 char uaddr[MAX_IPv4_STR_LEN];
1052 struct xdrbuf xb;
1053 uint32_t mattrs[NFS_MATTR_BITMAP_LEN];
1054 uint32_t mflags_mask[NFS_MFLAG_BITMAP_LEN];
1055 uint32_t mflags[NFS_MFLAG_BITMAP_LEN];
1056 uint32_t argslength_offset, attrslength_offset, end_offset;
1057
1058 if ((error = vfs_rootmountalloc("nfs", ndmntp->ndm_mntfrom, &mp))) {
1059 printf("nfs_mount_diskless: NFS not configured\n");
1060 return (error);
1061 }
1062
1063 mp->mnt_flag |= mntflag;
1064 if (!(mntflag & MNT_RDONLY))
1065 mp->mnt_flag &= ~MNT_RDONLY;
1066
1067 /* find the server-side path being mounted */
1068 frompath = ndmntp->ndm_mntfrom;
1069 if (*frompath == '[') { /* skip IPv6 literal address */
1070 while (*frompath && (*frompath != ']'))
1071 frompath++;
1072 if (*frompath == ']')
1073 frompath++;
1074 }
1075 while (*frompath && (*frompath != ':'))
1076 frompath++;
1077 endserverp = frompath;
1078 while (*frompath && (*frompath == ':'))
1079 frompath++;
1080 /* count fs location path components */
1081 p = frompath;
1082 while (*p && (*p == '/'))
1083 p++;
1084 numcomps = 0;
1085 while (*p) {
1086 numcomps++;
1087 while (*p && (*p != '/'))
1088 p++;
1089 while (*p && (*p == '/'))
1090 p++;
1091 }
1092
1093 /* convert address to universal address string */
1094 if (inet_ntop(AF_INET, &ndmntp->ndm_saddr.sin_addr, uaddr, sizeof(uaddr)) != uaddr) {
1095 printf("nfs_mount_diskless: bad address\n");
1096 return (EINVAL);
1097 }
1098
1099 /* prepare mount attributes */
1100 NFS_BITMAP_ZERO(mattrs, NFS_MATTR_BITMAP_LEN);
1101 NFS_BITMAP_SET(mattrs, NFS_MATTR_NFS_VERSION);
1102 NFS_BITMAP_SET(mattrs, NFS_MATTR_SOCKET_TYPE);
1103 NFS_BITMAP_SET(mattrs, NFS_MATTR_NFS_PORT);
1104 NFS_BITMAP_SET(mattrs, NFS_MATTR_FH);
1105 NFS_BITMAP_SET(mattrs, NFS_MATTR_FS_LOCATIONS);
1106 NFS_BITMAP_SET(mattrs, NFS_MATTR_MNTFLAGS);
1107
1108 /* prepare mount flags */
1109 NFS_BITMAP_ZERO(mflags_mask, NFS_MFLAG_BITMAP_LEN);
1110 NFS_BITMAP_ZERO(mflags, NFS_MFLAG_BITMAP_LEN);
1111 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_RESVPORT);
1112 NFS_BITMAP_SET(mflags, NFS_MFLAG_RESVPORT);
1113
1114 /* build xdr buffer */
1115 xb_init_buffer(&xb, NULL, 0);
1116 xb_add_32(error, &xb, NFS_ARGSVERSION_XDR);
1117 argslength_offset = xb_offset(&xb);
1118 xb_add_32(error, &xb, 0); // args length
1119 xb_add_32(error, &xb, NFS_XDRARGS_VERSION_0);
1120 xb_add_bitmap(error, &xb, mattrs, NFS_MATTR_BITMAP_LEN);
1121 attrslength_offset = xb_offset(&xb);
1122 xb_add_32(error, &xb, 0); // attrs length
1123 xb_add_32(error, &xb, ndmntp->ndm_nfsv3 ? 3 : 2); // NFS version
1124 xb_add_string(error, &xb, ((ndmntp->ndm_sotype == SOCK_DGRAM) ? "udp" : "tcp"), 3);
1125 xb_add_32(error, &xb, ntohs(ndmntp->ndm_saddr.sin_port)); // NFS port
1126 xb_add_fh(error, &xb, &ndmntp->ndm_fh[0], ndmntp->ndm_fhlen);
1127 /* fs location */
1128 xb_add_32(error, &xb, 1); /* fs location count */
1129 xb_add_32(error, &xb, 1); /* server count */
1130 xb_add_string(error, &xb, ndmntp->ndm_mntfrom, (endserverp - ndmntp->ndm_mntfrom)); /* server name */
1131 xb_add_32(error, &xb, 1); /* address count */
1132 xb_add_string(error, &xb, uaddr, strlen(uaddr)); /* address */
1133 xb_add_32(error, &xb, 0); /* empty server info */
1134 xb_add_32(error, &xb, numcomps); /* pathname component count */
1135 p = frompath;
1136 while (*p && (*p == '/'))
1137 p++;
1138 while (*p) {
1139 cp = p;
1140 while (*p && (*p != '/'))
1141 p++;
1142 xb_add_string(error, &xb, cp, (p - cp)); /* component */
1143 if (error)
1144 break;
1145 while (*p && (*p == '/'))
1146 p++;
1147 }
1148 xb_add_32(error, &xb, 0); /* empty fsl info */
1149 xb_add_32(error, &xb, mntflag); /* MNT flags */
1150 xb_build_done(error, &xb);
1151
1152 /* update opaque counts */
1153 end_offset = xb_offset(&xb);
1154 if (!error) {
1155 error = xb_seek(&xb, argslength_offset);
1156 xb_add_32(error, &xb, end_offset - argslength_offset + XDRWORD/*version*/);
1157 }
1158 if (!error) {
1159 error = xb_seek(&xb, attrslength_offset);
1160 xb_add_32(error, &xb, end_offset - attrslength_offset - XDRWORD/*don't include length field*/);
1161 }
1162 if (error) {
1163 printf("nfs_mount_diskless: error %d assembling mount args\n", error);
1164 xb_cleanup(&xb);
1165 return (error);
1166 }
1167 /* grab the assembled buffer */
1168 xdrbuf = xb_buffer_base(&xb);
1169 xb.xb_flags &= ~XB_CLEANUP;
1170
1171 /* do the mount */
1172 if ((error = mountnfs(xdrbuf, mp, ctx, vpp))) {
1173 printf("nfs_mountroot: mount %s failed: %d\n", mntname, error);
1174 // XXX vfs_rootmountfailed(mp);
1175 mount_list_lock();
1176 mp->mnt_vtable->vfc_refcount--;
1177 mount_list_unlock();
1178 vfs_unbusy(mp);
1179 mount_lock_destroy(mp);
1180 #if CONFIG_MACF
1181 mac_mount_label_destroy(mp);
1182 #endif
1183 FREE_ZONE(mp, sizeof(struct mount), M_MOUNT);
1184 } else {
1185 *mpp = mp;
1186 }
1187 xb_cleanup(&xb);
1188 return (error);
1189 }
1190
1191 #if !defined(NO_MOUNT_PRIVATE)
1192 /*
1193 * Internal version of mount system call to mount "/private"
1194 * separately in diskless setup
1195 */
1196 static int
1197 nfs_mount_diskless_private(
1198 struct nfs_dlmount *ndmntp,
1199 const char *mntname,
1200 int mntflag,
1201 vnode_t *vpp,
1202 mount_t *mpp,
1203 vfs_context_t ctx)
1204 {
1205 mount_t mp;
1206 int error, numcomps;
1207 proc_t procp;
1208 struct vfstable *vfsp;
1209 struct nameidata nd;
1210 vnode_t vp;
1211 char *xdrbuf = NULL, *p, *cp, *frompath, *endserverp;
1212 char uaddr[MAX_IPv4_STR_LEN];
1213 struct xdrbuf xb;
1214 uint32_t mattrs[NFS_MATTR_BITMAP_LEN];
1215 uint32_t mflags_mask[NFS_MFLAG_BITMAP_LEN], mflags[NFS_MFLAG_BITMAP_LEN];
1216 uint32_t argslength_offset, attrslength_offset, end_offset;
1217
1218 procp = current_proc(); /* XXX */
1219 xb_init(&xb, 0);
1220
1221 {
1222 /*
1223 * mimic main()!. Temporarily set up rootvnode and other stuff so
1224 * that namei works. Need to undo this because main() does it, too
1225 */
1226 struct filedesc *fdp; /* pointer to file descriptor state */
1227 fdp = procp->p_fd;
1228 mountlist.tqh_first->mnt_flag |= MNT_ROOTFS;
1229
1230 /* Get the vnode for '/'. Set fdp->fd_cdir to reference it. */
1231 if (VFS_ROOT(mountlist.tqh_first, &rootvnode, NULL))
1232 panic("cannot find root vnode");
1233 error = vnode_ref(rootvnode);
1234 if (error) {
1235 printf("nfs_mountroot: vnode_ref() failed on root vnode!\n");
1236 goto out;
1237 }
1238 fdp->fd_cdir = rootvnode;
1239 fdp->fd_rdir = NULL;
1240 }
1241
1242 /*
1243 * Get vnode to be covered
1244 */
1245 NDINIT(&nd, LOOKUP, OP_LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
1246 CAST_USER_ADDR_T(mntname), ctx);
1247 if ((error = namei(&nd))) {
1248 printf("nfs_mountroot: private namei failed!\n");
1249 goto out;
1250 }
1251 {
1252 /* undo vnode_ref() in mimic main()! */
1253 vnode_rele(rootvnode);
1254 }
1255 nameidone(&nd);
1256 vp = nd.ni_vp;
1257
1258 if ((error = VNOP_FSYNC(vp, MNT_WAIT, ctx)) ||
1259 (error = buf_invalidateblks(vp, BUF_WRITE_DATA, 0, 0))) {
1260 vnode_put(vp);
1261 goto out;
1262 }
1263 if (vnode_vtype(vp) != VDIR) {
1264 vnode_put(vp);
1265 error = ENOTDIR;
1266 goto out;
1267 }
1268 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
1269 if (!strncmp(vfsp->vfc_name, "nfs", sizeof(vfsp->vfc_name)))
1270 break;
1271 if (vfsp == NULL) {
1272 printf("nfs_mountroot: private NFS not configured\n");
1273 vnode_put(vp);
1274 error = ENODEV;
1275 goto out;
1276 }
1277 if (vnode_mountedhere(vp) != NULL) {
1278 vnode_put(vp);
1279 error = EBUSY;
1280 goto out;
1281 }
1282
1283 /*
1284 * Allocate and initialize the filesystem.
1285 */
1286 mp = _MALLOC_ZONE((u_int32_t)sizeof(struct mount), M_MOUNT, M_WAITOK);
1287 if (!mp) {
1288 printf("nfs_mountroot: unable to allocate mount structure\n");
1289 vnode_put(vp);
1290 error = ENOMEM;
1291 goto out;
1292 }
1293 bzero((char *)mp, sizeof(struct mount));
1294
1295 /* Initialize the default IO constraints */
1296 mp->mnt_maxreadcnt = mp->mnt_maxwritecnt = MAXPHYS;
1297 mp->mnt_segreadcnt = mp->mnt_segwritecnt = 32;
1298 mp->mnt_ioflags = 0;
1299 mp->mnt_realrootvp = NULLVP;
1300 mp->mnt_authcache_ttl = CACHED_LOOKUP_RIGHT_TTL;
1301
1302 mount_lock_init(mp);
1303 TAILQ_INIT(&mp->mnt_vnodelist);
1304 TAILQ_INIT(&mp->mnt_workerqueue);
1305 TAILQ_INIT(&mp->mnt_newvnodes);
1306 (void)vfs_busy(mp, LK_NOWAIT);
1307 TAILQ_INIT(&mp->mnt_vnodelist);
1308 mount_list_lock();
1309 vfsp->vfc_refcount++;
1310 mount_list_unlock();
1311 mp->mnt_vtable = vfsp;
1312 mp->mnt_op = vfsp->vfc_vfsops;
1313 // mp->mnt_stat.f_type = vfsp->vfc_typenum;
1314 mp->mnt_flag = mntflag;
1315 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
1316 strncpy(mp->mnt_vfsstat.f_fstypename, vfsp->vfc_name, MFSNAMELEN-1);
1317 vp->v_mountedhere = mp;
1318 mp->mnt_vnodecovered = vp;
1319 vp = NULLVP;
1320 mp->mnt_vfsstat.f_owner = kauth_cred_getuid(kauth_cred_get());
1321 (void) copystr(mntname, mp->mnt_vfsstat.f_mntonname, MAXPATHLEN - 1, 0);
1322 (void) copystr(ndmntp->ndm_mntfrom, mp->mnt_vfsstat.f_mntfromname, MAXPATHLEN - 1, 0);
1323 #if CONFIG_MACF
1324 mac_mount_label_init(mp);
1325 mac_mount_label_associate(ctx, mp);
1326 #endif
1327
1328 /* find the server-side path being mounted */
1329 frompath = ndmntp->ndm_mntfrom;
1330 if (*frompath == '[') { /* skip IPv6 literal address */
1331 while (*frompath && (*frompath != ']'))
1332 frompath++;
1333 if (*frompath == ']')
1334 frompath++;
1335 }
1336 while (*frompath && (*frompath != ':'))
1337 frompath++;
1338 endserverp = frompath;
1339 while (*frompath && (*frompath == ':'))
1340 frompath++;
1341 /* count fs location path components */
1342 p = frompath;
1343 while (*p && (*p == '/'))
1344 p++;
1345 numcomps = 0;
1346 while (*p) {
1347 numcomps++;
1348 while (*p && (*p != '/'))
1349 p++;
1350 while (*p && (*p == '/'))
1351 p++;
1352 }
1353
1354 /* convert address to universal address string */
1355 if (inet_ntop(AF_INET, &ndmntp->ndm_saddr.sin_addr, uaddr, sizeof(uaddr)) != uaddr) {
1356 printf("nfs_mountroot: bad address\n");
1357 error = EINVAL;
1358 goto out;
1359 }
1360
1361 /* prepare mount attributes */
1362 NFS_BITMAP_ZERO(mattrs, NFS_MATTR_BITMAP_LEN);
1363 NFS_BITMAP_SET(mattrs, NFS_MATTR_NFS_VERSION);
1364 NFS_BITMAP_SET(mattrs, NFS_MATTR_SOCKET_TYPE);
1365 NFS_BITMAP_SET(mattrs, NFS_MATTR_NFS_PORT);
1366 NFS_BITMAP_SET(mattrs, NFS_MATTR_FH);
1367 NFS_BITMAP_SET(mattrs, NFS_MATTR_FS_LOCATIONS);
1368 NFS_BITMAP_SET(mattrs, NFS_MATTR_MNTFLAGS);
1369
1370 /* prepare mount flags */
1371 NFS_BITMAP_ZERO(mflags_mask, NFS_MFLAG_BITMAP_LEN);
1372 NFS_BITMAP_ZERO(mflags, NFS_MFLAG_BITMAP_LEN);
1373 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_RESVPORT);
1374 NFS_BITMAP_SET(mflags, NFS_MFLAG_RESVPORT);
1375
1376 /* build xdr buffer */
1377 xb_init_buffer(&xb, NULL, 0);
1378 xb_add_32(error, &xb, NFS_ARGSVERSION_XDR);
1379 argslength_offset = xb_offset(&xb);
1380 xb_add_32(error, &xb, 0); // args length
1381 xb_add_32(error, &xb, NFS_XDRARGS_VERSION_0);
1382 xb_add_bitmap(error, &xb, mattrs, NFS_MATTR_BITMAP_LEN);
1383 attrslength_offset = xb_offset(&xb);
1384 xb_add_32(error, &xb, 0); // attrs length
1385 xb_add_32(error, &xb, ndmntp->ndm_nfsv3 ? 3 : 2); // NFS version
1386 xb_add_string(error, &xb, ((ndmntp->ndm_sotype == SOCK_DGRAM) ? "udp" : "tcp"), 3);
1387 xb_add_32(error, &xb, ntohs(ndmntp->ndm_saddr.sin_port)); // NFS port
1388 xb_add_fh(error, &xb, &ndmntp->ndm_fh[0], ndmntp->ndm_fhlen);
1389 /* fs location */
1390 xb_add_32(error, &xb, 1); /* fs location count */
1391 xb_add_32(error, &xb, 1); /* server count */
1392 xb_add_string(error, &xb, ndmntp->ndm_mntfrom, (endserverp - ndmntp->ndm_mntfrom)); /* server name */
1393 xb_add_32(error, &xb, 1); /* address count */
1394 xb_add_string(error, &xb, uaddr, strlen(uaddr)); /* address */
1395 xb_add_32(error, &xb, 0); /* empty server info */
1396 xb_add_32(error, &xb, numcomps); /* pathname component count */
1397 p = frompath;
1398 while (*p && (*p == '/'))
1399 p++;
1400 while (*p) {
1401 cp = p;
1402 while (*p && (*p != '/'))
1403 p++;
1404 xb_add_string(error, &xb, cp, (p - cp)); /* component */
1405 if (error)
1406 break;
1407 while (*p && (*p == '/'))
1408 p++;
1409 }
1410 xb_add_32(error, &xb, 0); /* empty fsl info */
1411 xb_add_32(error, &xb, mntflag); /* MNT flags */
1412 xb_build_done(error, &xb);
1413
1414 /* update opaque counts */
1415 end_offset = xb_offset(&xb);
1416 if (!error) {
1417 error = xb_seek(&xb, argslength_offset);
1418 xb_add_32(error, &xb, end_offset - argslength_offset + XDRWORD/*version*/);
1419 }
1420 if (!error) {
1421 error = xb_seek(&xb, attrslength_offset);
1422 xb_add_32(error, &xb, end_offset - attrslength_offset - XDRWORD/*don't include length field*/);
1423 }
1424 if (error) {
1425 printf("nfs_mountroot: error %d assembling mount args\n", error);
1426 goto out;
1427 }
1428 /* grab the assembled buffer */
1429 xdrbuf = xb_buffer_base(&xb);
1430 xb.xb_flags &= ~XB_CLEANUP;
1431
1432 /* do the mount */
1433 if ((error = mountnfs(xdrbuf, mp, ctx, &vp))) {
1434 printf("nfs_mountroot: mount %s failed: %d\n", mntname, error);
1435 vnode_put(mp->mnt_vnodecovered);
1436 mount_list_lock();
1437 vfsp->vfc_refcount--;
1438 mount_list_unlock();
1439 vfs_unbusy(mp);
1440 mount_lock_destroy(mp);
1441 #if CONFIG_MACF
1442 mac_mount_label_destroy(mp);
1443 #endif
1444 FREE_ZONE(mp, sizeof (struct mount), M_MOUNT);
1445 goto out;
1446 }
1447
1448 *mpp = mp;
1449 *vpp = vp;
1450 out:
1451 xb_cleanup(&xb);
1452 return (error);
1453 }
1454 #endif /* NO_MOUNT_PRIVATE */
1455
1456 /*
1457 * Convert old style NFS mount args to XDR.
1458 */
1459 static int
1460 nfs_convert_old_nfs_args(mount_t mp, user_addr_t data, vfs_context_t ctx, int argsversion, int inkernel, char **xdrbufp)
1461 {
1462 int error = 0, args64bit, argsize, numcomps;
1463 struct user_nfs_args args;
1464 struct nfs_args tempargs;
1465 caddr_t argsp;
1466 size_t len;
1467 u_char nfh[NFS4_FHSIZE];
1468 char *mntfrom, *endserverp, *frompath, *p, *cp;
1469 struct sockaddr_storage ss;
1470 void *sinaddr;
1471 char uaddr[MAX_IPv6_STR_LEN];
1472 uint32_t mattrs[NFS_MATTR_BITMAP_LEN];
1473 uint32_t mflags_mask[NFS_MFLAG_BITMAP_LEN], mflags[NFS_MFLAG_BITMAP_LEN];
1474 uint32_t nfsvers, nfslockmode = 0, argslength_offset, attrslength_offset, end_offset;
1475 struct xdrbuf xb;
1476
1477 *xdrbufp = NULL;
1478
1479 /* allocate a temporary buffer for mntfrom */
1480 MALLOC_ZONE(mntfrom, char*, MAXPATHLEN, M_NAMEI, M_WAITOK);
1481 if (!mntfrom)
1482 return (ENOMEM);
1483
1484 args64bit = (inkernel || vfs_context_is64bit(ctx));
1485 argsp = args64bit ? (void*)&args : (void*)&tempargs;
1486
1487 argsize = args64bit ? sizeof(args) : sizeof(tempargs);
1488 switch (argsversion) {
1489 case 3:
1490 argsize -= NFS_ARGSVERSION4_INCSIZE;
1491 case 4:
1492 argsize -= NFS_ARGSVERSION5_INCSIZE;
1493 case 5:
1494 argsize -= NFS_ARGSVERSION6_INCSIZE;
1495 case 6:
1496 break;
1497 default:
1498 error = EPROGMISMATCH;
1499 goto nfsmout;
1500 }
1501
1502 /* read in the structure */
1503 if (inkernel)
1504 bcopy(CAST_DOWN(void *, data), argsp, argsize);
1505 else
1506 error = copyin(data, argsp, argsize);
1507 nfsmout_if(error);
1508
1509 if (!args64bit) {
1510 args.addrlen = tempargs.addrlen;
1511 args.sotype = tempargs.sotype;
1512 args.proto = tempargs.proto;
1513 args.fhsize = tempargs.fhsize;
1514 args.flags = tempargs.flags;
1515 args.wsize = tempargs.wsize;
1516 args.rsize = tempargs.rsize;
1517 args.readdirsize = tempargs.readdirsize;
1518 args.timeo = tempargs.timeo;
1519 args.retrans = tempargs.retrans;
1520 args.maxgrouplist = tempargs.maxgrouplist;
1521 args.readahead = tempargs.readahead;
1522 args.leaseterm = tempargs.leaseterm;
1523 args.deadthresh = tempargs.deadthresh;
1524 args.addr = CAST_USER_ADDR_T(tempargs.addr);
1525 args.fh = CAST_USER_ADDR_T(tempargs.fh);
1526 args.hostname = CAST_USER_ADDR_T(tempargs.hostname);
1527 if (args.version >= 4) {
1528 args.acregmin = tempargs.acregmin;
1529 args.acregmax = tempargs.acregmax;
1530 args.acdirmin = tempargs.acdirmin;
1531 args.acdirmax = tempargs.acdirmax;
1532 }
1533 if (args.version >= 5)
1534 args.auth = tempargs.auth;
1535 if (args.version >= 6)
1536 args.deadtimeout = tempargs.deadtimeout;
1537 }
1538
1539 if ((args.fhsize < 0) || (args.fhsize > NFS4_FHSIZE)) {
1540 error = EINVAL;
1541 goto nfsmout;
1542 }
1543 if (args.fhsize > 0) {
1544 if (inkernel)
1545 bcopy(CAST_DOWN(void *, args.fh), (caddr_t)nfh, args.fhsize);
1546 else
1547 error = copyin(args.fh, (caddr_t)nfh, args.fhsize);
1548 nfsmout_if(error);
1549 }
1550
1551 if (inkernel)
1552 error = copystr(CAST_DOWN(void *, args.hostname), mntfrom, MAXPATHLEN-1, &len);
1553 else
1554 error = copyinstr(args.hostname, mntfrom, MAXPATHLEN-1, &len);
1555 nfsmout_if(error);
1556 bzero(&mntfrom[len], MAXPATHLEN - len);
1557
1558 /* find the server-side path being mounted */
1559 frompath = mntfrom;
1560 if (*frompath == '[') { /* skip IPv6 literal address */
1561 while (*frompath && (*frompath != ']'))
1562 frompath++;
1563 if (*frompath == ']')
1564 frompath++;
1565 }
1566 while (*frompath && (*frompath != ':'))
1567 frompath++;
1568 endserverp = frompath;
1569 while (*frompath && (*frompath == ':'))
1570 frompath++;
1571 /* count fs location path components */
1572 p = frompath;
1573 while (*p && (*p == '/'))
1574 p++;
1575 numcomps = 0;
1576 while (*p) {
1577 numcomps++;
1578 while (*p && (*p != '/'))
1579 p++;
1580 while (*p && (*p == '/'))
1581 p++;
1582 }
1583
1584 /* copy socket address */
1585 if (inkernel)
1586 bcopy(CAST_DOWN(void *, args.addr), &ss, args.addrlen);
1587 else {
1588 if ((size_t)args.addrlen > sizeof (struct sockaddr_storage))
1589 error = EINVAL;
1590 else
1591 error = copyin(args.addr, &ss, args.addrlen);
1592 }
1593 nfsmout_if(error);
1594 ss.ss_len = args.addrlen;
1595
1596 /* convert address to universal address string */
1597 if (ss.ss_family == AF_INET)
1598 sinaddr = &((struct sockaddr_in*)&ss)->sin_addr;
1599 else if (ss.ss_family == AF_INET6)
1600 sinaddr = &((struct sockaddr_in6*)&ss)->sin6_addr;
1601 else
1602 sinaddr = NULL;
1603 if (!sinaddr || (inet_ntop(ss.ss_family, sinaddr, uaddr, sizeof(uaddr)) != uaddr)) {
1604 error = EINVAL;
1605 goto nfsmout;
1606 }
1607
1608 /* prepare mount flags */
1609 NFS_BITMAP_ZERO(mflags_mask, NFS_MFLAG_BITMAP_LEN);
1610 NFS_BITMAP_ZERO(mflags, NFS_MFLAG_BITMAP_LEN);
1611 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_SOFT);
1612 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_INTR);
1613 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_RESVPORT);
1614 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NOCONNECT);
1615 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_DUMBTIMER);
1616 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_CALLUMNT);
1617 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_RDIRPLUS);
1618 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NONEGNAMECACHE);
1619 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_MUTEJUKEBOX);
1620 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NOQUOTA);
1621 if (args.flags & NFSMNT_SOFT)
1622 NFS_BITMAP_SET(mflags, NFS_MFLAG_SOFT);
1623 if (args.flags & NFSMNT_INT)
1624 NFS_BITMAP_SET(mflags, NFS_MFLAG_INTR);
1625 if (args.flags & NFSMNT_RESVPORT)
1626 NFS_BITMAP_SET(mflags, NFS_MFLAG_RESVPORT);
1627 if (args.flags & NFSMNT_NOCONN)
1628 NFS_BITMAP_SET(mflags, NFS_MFLAG_NOCONNECT);
1629 if (args.flags & NFSMNT_DUMBTIMR)
1630 NFS_BITMAP_SET(mflags, NFS_MFLAG_DUMBTIMER);
1631 if (args.flags & NFSMNT_CALLUMNT)
1632 NFS_BITMAP_SET(mflags, NFS_MFLAG_CALLUMNT);
1633 if (args.flags & NFSMNT_RDIRPLUS)
1634 NFS_BITMAP_SET(mflags, NFS_MFLAG_RDIRPLUS);
1635 if (args.flags & NFSMNT_NONEGNAMECACHE)
1636 NFS_BITMAP_SET(mflags, NFS_MFLAG_NONEGNAMECACHE);
1637 if (args.flags & NFSMNT_MUTEJUKEBOX)
1638 NFS_BITMAP_SET(mflags, NFS_MFLAG_MUTEJUKEBOX);
1639 if (args.flags & NFSMNT_NOQUOTA)
1640 NFS_BITMAP_SET(mflags, NFS_MFLAG_NOQUOTA);
1641
1642 /* prepare mount attributes */
1643 NFS_BITMAP_ZERO(mattrs, NFS_MATTR_BITMAP_LEN);
1644 NFS_BITMAP_SET(mattrs, NFS_MATTR_FLAGS);
1645 NFS_BITMAP_SET(mattrs, NFS_MATTR_NFS_VERSION);
1646 NFS_BITMAP_SET(mattrs, NFS_MATTR_SOCKET_TYPE);
1647 NFS_BITMAP_SET(mattrs, NFS_MATTR_NFS_PORT);
1648 NFS_BITMAP_SET(mattrs, NFS_MATTR_FH);
1649 NFS_BITMAP_SET(mattrs, NFS_MATTR_FS_LOCATIONS);
1650 NFS_BITMAP_SET(mattrs, NFS_MATTR_MNTFLAGS);
1651 NFS_BITMAP_SET(mattrs, NFS_MATTR_MNTFROM);
1652 if (args.flags & NFSMNT_NFSV4)
1653 nfsvers = 4;
1654 else if (args.flags & NFSMNT_NFSV3)
1655 nfsvers = 3;
1656 else
1657 nfsvers = 2;
1658 if ((args.flags & NFSMNT_RSIZE) && (args.rsize > 0))
1659 NFS_BITMAP_SET(mattrs, NFS_MATTR_READ_SIZE);
1660 if ((args.flags & NFSMNT_WSIZE) && (args.wsize > 0))
1661 NFS_BITMAP_SET(mattrs, NFS_MATTR_WRITE_SIZE);
1662 if ((args.flags & NFSMNT_TIMEO) && (args.timeo > 0))
1663 NFS_BITMAP_SET(mattrs, NFS_MATTR_REQUEST_TIMEOUT);
1664 if ((args.flags & NFSMNT_RETRANS) && (args.retrans > 0))
1665 NFS_BITMAP_SET(mattrs, NFS_MATTR_SOFT_RETRY_COUNT);
1666 if ((args.flags & NFSMNT_MAXGRPS) && (args.maxgrouplist > 0))
1667 NFS_BITMAP_SET(mattrs, NFS_MATTR_MAX_GROUP_LIST);
1668 if ((args.flags & NFSMNT_READAHEAD) && (args.readahead > 0))
1669 NFS_BITMAP_SET(mattrs, NFS_MATTR_READAHEAD);
1670 if ((args.flags & NFSMNT_READDIRSIZE) && (args.readdirsize > 0))
1671 NFS_BITMAP_SET(mattrs, NFS_MATTR_READDIR_SIZE);
1672 if ((args.flags & NFSMNT_NOLOCKS) ||
1673 (args.flags & NFSMNT_LOCALLOCKS)) {
1674 NFS_BITMAP_SET(mattrs, NFS_MATTR_LOCK_MODE);
1675 if (args.flags & NFSMNT_NOLOCKS)
1676 nfslockmode = NFS_LOCK_MODE_DISABLED;
1677 else if (args.flags & NFSMNT_LOCALLOCKS)
1678 nfslockmode = NFS_LOCK_MODE_LOCAL;
1679 else
1680 nfslockmode = NFS_LOCK_MODE_ENABLED;
1681 }
1682 if (args.version >= 4) {
1683 if ((args.flags & NFSMNT_ACREGMIN) && (args.acregmin > 0))
1684 NFS_BITMAP_SET(mattrs, NFS_MATTR_ATTRCACHE_REG_MIN);
1685 if ((args.flags & NFSMNT_ACREGMAX) && (args.acregmax > 0))
1686 NFS_BITMAP_SET(mattrs, NFS_MATTR_ATTRCACHE_REG_MAX);
1687 if ((args.flags & NFSMNT_ACDIRMIN) && (args.acdirmin > 0))
1688 NFS_BITMAP_SET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MIN);
1689 if ((args.flags & NFSMNT_ACDIRMAX) && (args.acdirmax > 0))
1690 NFS_BITMAP_SET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MAX);
1691 }
1692 if (args.version >= 5) {
1693 if ((args.flags & NFSMNT_SECFLAVOR) || (args.flags & NFSMNT_SECSYSOK))
1694 NFS_BITMAP_SET(mattrs, NFS_MATTR_SECURITY);
1695 }
1696 if (args.version >= 6) {
1697 if ((args.flags & NFSMNT_DEADTIMEOUT) && (args.deadtimeout > 0))
1698 NFS_BITMAP_SET(mattrs, NFS_MATTR_DEAD_TIMEOUT);
1699 }
1700
1701 /* build xdr buffer */
1702 xb_init_buffer(&xb, NULL, 0);
1703 xb_add_32(error, &xb, args.version);
1704 argslength_offset = xb_offset(&xb);
1705 xb_add_32(error, &xb, 0); // args length
1706 xb_add_32(error, &xb, NFS_XDRARGS_VERSION_0);
1707 xb_add_bitmap(error, &xb, mattrs, NFS_MATTR_BITMAP_LEN);
1708 attrslength_offset = xb_offset(&xb);
1709 xb_add_32(error, &xb, 0); // attrs length
1710 xb_add_bitmap(error, &xb, mflags_mask, NFS_MFLAG_BITMAP_LEN); /* mask */
1711 xb_add_bitmap(error, &xb, mflags, NFS_MFLAG_BITMAP_LEN); /* value */
1712 xb_add_32(error, &xb, nfsvers);
1713 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READ_SIZE))
1714 xb_add_32(error, &xb, args.rsize);
1715 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_WRITE_SIZE))
1716 xb_add_32(error, &xb, args.wsize);
1717 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READDIR_SIZE))
1718 xb_add_32(error, &xb, args.readdirsize);
1719 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READAHEAD))
1720 xb_add_32(error, &xb, args.readahead);
1721 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_REG_MIN)) {
1722 xb_add_32(error, &xb, args.acregmin);
1723 xb_add_32(error, &xb, 0);
1724 }
1725 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_REG_MAX)) {
1726 xb_add_32(error, &xb, args.acregmax);
1727 xb_add_32(error, &xb, 0);
1728 }
1729 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MIN)) {
1730 xb_add_32(error, &xb, args.acdirmin);
1731 xb_add_32(error, &xb, 0);
1732 }
1733 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MAX)) {
1734 xb_add_32(error, &xb, args.acdirmax);
1735 xb_add_32(error, &xb, 0);
1736 }
1737 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_LOCK_MODE))
1738 xb_add_32(error, &xb, nfslockmode);
1739 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SECURITY)) {
1740 uint32_t flavors[2], i=0;
1741 if (args.flags & NFSMNT_SECFLAVOR)
1742 flavors[i++] = args.auth;
1743 if ((args.flags & NFSMNT_SECSYSOK) && ((i == 0) || (flavors[0] != RPCAUTH_SYS)))
1744 flavors[i++] = RPCAUTH_SYS;
1745 xb_add_word_array(error, &xb, flavors, i);
1746 }
1747 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MAX_GROUP_LIST))
1748 xb_add_32(error, &xb, args.maxgrouplist);
1749 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SOCKET_TYPE))
1750 xb_add_string(error, &xb, ((args.sotype == SOCK_DGRAM) ? "udp" : "tcp"), 3);
1751 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_PORT))
1752 xb_add_32(error, &xb, ((ss.ss_family == AF_INET) ?
1753 ntohs(((struct sockaddr_in*)&ss)->sin_port) :
1754 ntohs(((struct sockaddr_in6*)&ss)->sin6_port)));
1755 /* NFS_MATTR_MOUNT_PORT (not available in old args) */
1756 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_REQUEST_TIMEOUT)) {
1757 /* convert from .1s increments to time */
1758 xb_add_32(error, &xb, args.timeo/10);
1759 xb_add_32(error, &xb, (args.timeo%10)*100000000);
1760 }
1761 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SOFT_RETRY_COUNT))
1762 xb_add_32(error, &xb, args.retrans);
1763 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_DEAD_TIMEOUT)) {
1764 xb_add_32(error, &xb, args.deadtimeout);
1765 xb_add_32(error, &xb, 0);
1766 }
1767 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_FH))
1768 xb_add_fh(error, &xb, &nfh[0], args.fhsize);
1769 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_FS_LOCATIONS)) {
1770 xb_add_32(error, &xb, 1); /* fs location count */
1771 xb_add_32(error, &xb, 1); /* server count */
1772 xb_add_string(error, &xb, mntfrom, (endserverp - mntfrom)); /* server name */
1773 xb_add_32(error, &xb, 1); /* address count */
1774 xb_add_string(error, &xb, uaddr, strlen(uaddr)); /* address */
1775 xb_add_32(error, &xb, 0); /* empty server info */
1776 xb_add_32(error, &xb, numcomps); /* pathname component count */
1777 nfsmout_if(error);
1778 p = frompath;
1779 while (*p && (*p == '/'))
1780 p++;
1781 while (*p) {
1782 cp = p;
1783 while (*p && (*p != '/'))
1784 p++;
1785 xb_add_string(error, &xb, cp, (p - cp)); /* component */
1786 nfsmout_if(error);
1787 while (*p && (*p == '/'))
1788 p++;
1789 }
1790 xb_add_32(error, &xb, 0); /* empty fsl info */
1791 }
1792 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MNTFLAGS))
1793 xb_add_32(error, &xb, (vfs_flags(mp) & MNT_VISFLAGMASK)); /* VFS MNT_* flags */
1794 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MNTFROM))
1795 xb_add_string(error, &xb, mntfrom, strlen(mntfrom)); /* fixed f_mntfromname */
1796 xb_build_done(error, &xb);
1797
1798 /* update opaque counts */
1799 end_offset = xb_offset(&xb);
1800 error = xb_seek(&xb, argslength_offset);
1801 xb_add_32(error, &xb, end_offset - argslength_offset + XDRWORD/*version*/);
1802 nfsmout_if(error);
1803 error = xb_seek(&xb, attrslength_offset);
1804 xb_add_32(error, &xb, end_offset - attrslength_offset - XDRWORD/*don't include length field*/);
1805
1806 if (!error) {
1807 /* grab the assembled buffer */
1808 *xdrbufp = xb_buffer_base(&xb);
1809 xb.xb_flags &= ~XB_CLEANUP;
1810 }
1811 nfsmout:
1812 xb_cleanup(&xb);
1813 FREE_ZONE(mntfrom, MAXPATHLEN, M_NAMEI);
1814 return (error);
1815 }
1816
1817 /*
1818 * VFS Operations.
1819 *
1820 * mount system call
1821 */
1822 int
1823 nfs_vfs_mount(mount_t mp, vnode_t vp, user_addr_t data, vfs_context_t ctx)
1824 {
1825 int error = 0, inkernel = vfs_iskernelmount(mp);
1826 uint32_t argsversion, argslength;
1827 char *xdrbuf = NULL;
1828
1829 /* read in version */
1830 if (inkernel)
1831 bcopy(CAST_DOWN(void *, data), &argsversion, sizeof(argsversion));
1832 else if ((error = copyin(data, &argsversion, sizeof(argsversion))))
1833 return (error);
1834
1835 /* If we have XDR args, then all values in the buffer are in network order */
1836 if (argsversion == htonl(NFS_ARGSVERSION_XDR))
1837 argsversion = NFS_ARGSVERSION_XDR;
1838
1839 switch (argsversion) {
1840 case 3:
1841 case 4:
1842 case 5:
1843 case 6:
1844 /* convert old-style args to xdr */
1845 error = nfs_convert_old_nfs_args(mp, data, ctx, argsversion, inkernel, &xdrbuf);
1846 break;
1847 case NFS_ARGSVERSION_XDR:
1848 /* copy in xdr buffer */
1849 if (inkernel)
1850 bcopy(CAST_DOWN(void *, (data + XDRWORD)), &argslength, XDRWORD);
1851 else
1852 error = copyin((data + XDRWORD), &argslength, XDRWORD);
1853 if (error)
1854 break;
1855 argslength = ntohl(argslength);
1856 /* put a reasonable limit on the size of the XDR args */
1857 if (argslength > 16*1024) {
1858 error = E2BIG;
1859 break;
1860 }
1861 /* allocate xdr buffer */
1862 xdrbuf = xb_malloc(xdr_rndup(argslength));
1863 if (!xdrbuf) {
1864 error = ENOMEM;
1865 break;
1866 }
1867 if (inkernel)
1868 bcopy(CAST_DOWN(void *, data), xdrbuf, argslength);
1869 else
1870 error = copyin(data, xdrbuf, argslength);
1871 break;
1872 default:
1873 error = EPROGMISMATCH;
1874 }
1875
1876 if (error) {
1877 if (xdrbuf)
1878 xb_free(xdrbuf);
1879 return (error);
1880 }
1881 error = mountnfs(xdrbuf, mp, ctx, &vp);
1882 return (error);
1883 }
1884
1885 /*
1886 * Common code for mount and mountroot
1887 */
1888
1889 /* Set up an NFSv2/v3 mount */
1890 int
1891 nfs3_mount(
1892 struct nfsmount *nmp,
1893 vfs_context_t ctx,
1894 nfsnode_t *npp)
1895 {
1896 int error = 0;
1897 struct nfs_vattr nvattr;
1898 u_int64_t xid;
1899
1900 *npp = NULL;
1901
1902 if (!nmp->nm_fh)
1903 return (EINVAL);
1904
1905 /*
1906 * Get file attributes for the mountpoint. These are needed
1907 * in order to properly create the root vnode.
1908 */
1909 error = nfs3_getattr_rpc(NULL, nmp->nm_mountp, nmp->nm_fh->fh_data, nmp->nm_fh->fh_len, 0,
1910 ctx, &nvattr, &xid);
1911 if (error)
1912 goto out;
1913
1914 error = nfs_nget(nmp->nm_mountp, NULL, NULL, nmp->nm_fh->fh_data, nmp->nm_fh->fh_len,
1915 &nvattr, &xid, RPCAUTH_UNKNOWN, NG_MARKROOT, npp);
1916 if (*npp)
1917 nfs_node_unlock(*npp);
1918 if (error)
1919 goto out;
1920
1921 /*
1922 * Try to make sure we have all the general info from the server.
1923 */
1924 if (nmp->nm_vers == NFS_VER2) {
1925 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXNAME);
1926 nmp->nm_fsattr.nfsa_maxname = NFS_MAXNAMLEN;
1927 } else if (nmp->nm_vers == NFS_VER3) {
1928 /* get the NFSv3 FSINFO */
1929 error = nfs3_fsinfo(nmp, *npp, ctx);
1930 if (error)
1931 goto out;
1932 /* If the server indicates all pathconf info is */
1933 /* the same, grab a copy of that info now */
1934 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_HOMOGENEOUS) &&
1935 (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_HOMOGENEOUS)) {
1936 struct nfs_fsattr nfsa;
1937 if (!nfs3_pathconf_rpc(*npp, &nfsa, ctx)) {
1938 /* cache a copy of the results */
1939 lck_mtx_lock(&nmp->nm_lock);
1940 nfs3_pathconf_cache(nmp, &nfsa);
1941 lck_mtx_unlock(&nmp->nm_lock);
1942 }
1943 }
1944 }
1945 out:
1946 if (*npp && error) {
1947 vnode_put(NFSTOV(*npp));
1948 vnode_recycle(NFSTOV(*npp));
1949 *npp = NULL;
1950 }
1951 return (error);
1952 }
1953
1954 /*
1955 * Update an NFSv4 mount path with the contents of the symlink.
1956 *
1957 * Read the link for the given file handle.
1958 * Insert the link's components into the path.
1959 */
1960 int
1961 nfs4_mount_update_path_with_symlink(struct nfsmount *nmp, struct nfs_fs_path *nfsp, uint32_t curcomp, fhandle_t *dirfhp, int *depthp, fhandle_t *fhp, vfs_context_t ctx)
1962 {
1963 int error = 0, status, numops;
1964 uint32_t len = 0, comp, newcomp, linkcompcount;
1965 u_int64_t xid;
1966 struct nfsm_chain nmreq, nmrep;
1967 struct nfsreq rq, *req = &rq;
1968 struct nfsreq_secinfo_args si;
1969 char *link = NULL, *p, *q, ch;
1970 struct nfs_fs_path nfsp2;
1971
1972 bzero(&nfsp2, sizeof(nfsp2));
1973 if (dirfhp->fh_len)
1974 NFSREQ_SECINFO_SET(&si, NULL, dirfhp->fh_data, dirfhp->fh_len, nfsp->np_components[curcomp], 0);
1975 else
1976 NFSREQ_SECINFO_SET(&si, NULL, NULL, 0, nfsp->np_components[curcomp], 0);
1977 nfsm_chain_null(&nmreq);
1978 nfsm_chain_null(&nmrep);
1979
1980 MALLOC_ZONE(link, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
1981 if (!link)
1982 error = ENOMEM;
1983
1984 // PUTFH, READLINK
1985 numops = 2;
1986 nfsm_chain_build_alloc_init(error, &nmreq, 12 * NFSX_UNSIGNED);
1987 nfsm_chain_add_compound_header(error, &nmreq, "readlink", nmp->nm_minor_vers, numops);
1988 numops--;
1989 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTFH);
1990 nfsm_chain_add_fh(error, &nmreq, NFS_VER4, fhp->fh_data, fhp->fh_len);
1991 numops--;
1992 nfsm_chain_add_32(error, &nmreq, NFS_OP_READLINK);
1993 nfsm_chain_build_done(error, &nmreq);
1994 nfsm_assert(error, (numops == 0), EPROTO);
1995 nfsmout_if(error);
1996
1997 error = nfs_request_async(NULL, nmp->nm_mountp, &nmreq, NFSPROC4_COMPOUND,
1998 vfs_context_thread(ctx), vfs_context_ucred(ctx), &si, 0, NULL, &req);
1999 if (!error)
2000 error = nfs_request_async_finish(req, &nmrep, &xid, &status);
2001
2002 nfsm_chain_skip_tag(error, &nmrep);
2003 nfsm_chain_get_32(error, &nmrep, numops);
2004 nfsm_chain_op_check(error, &nmrep, NFS_OP_PUTFH);
2005 nfsm_chain_op_check(error, &nmrep, NFS_OP_READLINK);
2006 nfsm_chain_get_32(error, &nmrep, len);
2007 nfsmout_if(error);
2008 if (len == 0)
2009 error = ENOENT;
2010 else if (len >= MAXPATHLEN)
2011 len = MAXPATHLEN - 1;
2012 nfsm_chain_get_opaque(error, &nmrep, len, link);
2013 nfsmout_if(error);
2014 /* make sure link string is terminated properly */
2015 link[len] = '\0';
2016
2017 /* count the number of components in link */
2018 p = link;
2019 while (*p && (*p == '/'))
2020 p++;
2021 linkcompcount = 0;
2022 while (*p) {
2023 linkcompcount++;
2024 while (*p && (*p != '/'))
2025 p++;
2026 while (*p && (*p == '/'))
2027 p++;
2028 }
2029
2030 /* free up used components */
2031 for (comp=0; comp <= curcomp; comp++) {
2032 if (nfsp->np_components[comp]) {
2033 FREE(nfsp->np_components[comp], M_TEMP);
2034 nfsp->np_components[comp] = NULL;
2035 }
2036 }
2037
2038 /* set up new path */
2039 nfsp2.np_compcount = nfsp->np_compcount - curcomp - 1 + linkcompcount;
2040 MALLOC(nfsp2.np_components, char **, nfsp2.np_compcount*sizeof(char*), M_TEMP, M_WAITOK|M_ZERO);
2041 if (!nfsp2.np_components) {
2042 error = ENOMEM;
2043 goto nfsmout;
2044 }
2045
2046 /* add link components */
2047 p = link;
2048 while (*p && (*p == '/'))
2049 p++;
2050 for (newcomp=0; newcomp < linkcompcount; newcomp++) {
2051 /* find end of component */
2052 q = p;
2053 while (*q && (*q != '/'))
2054 q++;
2055 MALLOC(nfsp2.np_components[newcomp], char *, q-p+1, M_TEMP, M_WAITOK|M_ZERO);
2056 if (!nfsp2.np_components[newcomp]) {
2057 error = ENOMEM;
2058 break;
2059 }
2060 ch = *q;
2061 *q = '\0';
2062 strlcpy(nfsp2.np_components[newcomp], p, q-p+1);
2063 *q = ch;
2064 p = q;
2065 while (*p && (*p == '/'))
2066 p++;
2067 }
2068 nfsmout_if(error);
2069
2070 /* add remaining components */
2071 for(comp = curcomp + 1; comp < nfsp->np_compcount; comp++,newcomp++) {
2072 nfsp2.np_components[newcomp] = nfsp->np_components[comp];
2073 nfsp->np_components[comp] = NULL;
2074 }
2075
2076 /* move new path into place */
2077 FREE(nfsp->np_components, M_TEMP);
2078 nfsp->np_components = nfsp2.np_components;
2079 nfsp->np_compcount = nfsp2.np_compcount;
2080 nfsp2.np_components = NULL;
2081
2082 /* for absolute link, let the caller now that the next dirfh is root */
2083 if (link[0] == '/') {
2084 dirfhp->fh_len = 0;
2085 *depthp = 0;
2086 }
2087 nfsmout:
2088 if (link)
2089 FREE_ZONE(link, MAXPATHLEN, M_NAMEI);
2090 if (nfsp2.np_components) {
2091 for (comp=0; comp < nfsp2.np_compcount; comp++)
2092 if (nfsp2.np_components[comp])
2093 FREE(nfsp2.np_components[comp], M_TEMP);
2094 FREE(nfsp2.np_components, M_TEMP);
2095 }
2096 nfsm_chain_cleanup(&nmreq);
2097 nfsm_chain_cleanup(&nmrep);
2098 return (error);
2099 }
2100
2101 /* Set up an NFSv4 mount */
2102 int
2103 nfs4_mount(
2104 struct nfsmount *nmp,
2105 vfs_context_t ctx,
2106 nfsnode_t *npp)
2107 {
2108 struct nfsm_chain nmreq, nmrep;
2109 int error = 0, numops, status, interval, isdotdot, loopcnt = 0, depth = 0;
2110 struct nfs_fs_path fspath, *nfsp, fspath2;
2111 uint32_t bitmap[NFS_ATTR_BITMAP_LEN], comp, comp2;
2112 fhandle_t fh, dirfh;
2113 struct nfs_vattr nvattr;
2114 u_int64_t xid;
2115 struct nfsreq rq, *req = &rq;
2116 struct nfsreq_secinfo_args si;
2117 struct nfs_sec sec;
2118 struct nfs_fs_locations nfsls;
2119
2120 *npp = NULL;
2121 fh.fh_len = dirfh.fh_len = 0;
2122 TAILQ_INIT(&nmp->nm_open_owners);
2123 TAILQ_INIT(&nmp->nm_delegations);
2124 TAILQ_INIT(&nmp->nm_dreturnq);
2125 nmp->nm_stategenid = 1;
2126 NVATTR_INIT(&nvattr);
2127 bzero(&nfsls, sizeof(nfsls));
2128 nfsm_chain_null(&nmreq);
2129 nfsm_chain_null(&nmrep);
2130
2131 /*
2132 * If no security flavors were specified we'll want to default to the server's
2133 * preferred flavor. For NFSv4.0 we need a file handle and name to get that via
2134 * SECINFO, so we'll do that on the last component of the server path we are
2135 * mounting. If we are mounting the server's root, we'll need to defer the
2136 * SECINFO call to the first successful LOOKUP request.
2137 */
2138 if (!nmp->nm_sec.count)
2139 nmp->nm_state |= NFSSTA_NEEDSECINFO;
2140
2141 /* make a copy of the current location's path */
2142 nfsp = &nmp->nm_locations.nl_locations[nmp->nm_locations.nl_current.nli_loc]->nl_path;
2143 bzero(&fspath, sizeof(fspath));
2144 fspath.np_compcount = nfsp->np_compcount;
2145 if (fspath.np_compcount > 0) {
2146 MALLOC(fspath.np_components, char **, fspath.np_compcount*sizeof(char*), M_TEMP, M_WAITOK|M_ZERO);
2147 if (!fspath.np_components) {
2148 error = ENOMEM;
2149 goto nfsmout;
2150 }
2151 for (comp=0; comp < nfsp->np_compcount; comp++) {
2152 int slen = strlen(nfsp->np_components[comp]);
2153 MALLOC(fspath.np_components[comp], char *, slen+1, M_TEMP, M_WAITOK|M_ZERO);
2154 if (!fspath.np_components[comp]) {
2155 error = ENOMEM;
2156 break;
2157 }
2158 strlcpy(fspath.np_components[comp], nfsp->np_components[comp], slen+1);
2159 }
2160 if (error)
2161 goto nfsmout;
2162 }
2163
2164 /* for mirror mounts, we can just use the file handle passed in */
2165 if (nmp->nm_fh) {
2166 dirfh.fh_len = nmp->nm_fh->fh_len;
2167 bcopy(nmp->nm_fh->fh_data, dirfh.fh_data, dirfh.fh_len);
2168 NFSREQ_SECINFO_SET(&si, NULL, dirfh.fh_data, dirfh.fh_len, NULL, 0);
2169 goto gotfh;
2170 }
2171
2172 /* otherwise, we need to get the fh for the directory we are mounting */
2173
2174 /* if no components, just get root */
2175 if (fspath.np_compcount == 0) {
2176 nocomponents:
2177 // PUTROOTFH + GETATTR(FH)
2178 NFSREQ_SECINFO_SET(&si, NULL, NULL, 0, NULL, 0);
2179 numops = 2;
2180 nfsm_chain_build_alloc_init(error, &nmreq, 9 * NFSX_UNSIGNED);
2181 nfsm_chain_add_compound_header(error, &nmreq, "mount", nmp->nm_minor_vers, numops);
2182 numops--;
2183 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTROOTFH);
2184 numops--;
2185 nfsm_chain_add_32(error, &nmreq, NFS_OP_GETATTR);
2186 NFS_CLEAR_ATTRIBUTES(bitmap);
2187 NFS4_DEFAULT_ATTRIBUTES(bitmap);
2188 NFS_BITMAP_SET(bitmap, NFS_FATTR_FILEHANDLE);
2189 nfsm_chain_add_bitmap(error, &nmreq, bitmap, NFS_ATTR_BITMAP_LEN);
2190 nfsm_chain_build_done(error, &nmreq);
2191 nfsm_assert(error, (numops == 0), EPROTO);
2192 nfsmout_if(error);
2193 error = nfs_request_async(NULL, nmp->nm_mountp, &nmreq, NFSPROC4_COMPOUND,
2194 vfs_context_thread(ctx), vfs_context_ucred(ctx), &si, 0, NULL, &req);
2195 if (!error)
2196 error = nfs_request_async_finish(req, &nmrep, &xid, &status);
2197 nfsm_chain_skip_tag(error, &nmrep);
2198 nfsm_chain_get_32(error, &nmrep, numops);
2199 nfsm_chain_op_check(error, &nmrep, NFS_OP_PUTROOTFH);
2200 nfsm_chain_op_check(error, &nmrep, NFS_OP_GETATTR);
2201 nfsmout_if(error);
2202 NFS_CLEAR_ATTRIBUTES(nmp->nm_fsattr.nfsa_bitmap);
2203 error = nfs4_parsefattr(&nmrep, &nmp->nm_fsattr, &nvattr, &dirfh, NULL, NULL);
2204 if (!error && !NFS_BITMAP_ISSET(&nvattr.nva_bitmap, NFS_FATTR_FILEHANDLE)) {
2205 printf("nfs: mount didn't return filehandle?\n");
2206 error = EBADRPC;
2207 }
2208 nfsmout_if(error);
2209 nfsm_chain_cleanup(&nmrep);
2210 nfsm_chain_null(&nmreq);
2211 NVATTR_CLEANUP(&nvattr);
2212 goto gotfh;
2213 }
2214
2215 /* look up each path component */
2216 for (comp=0; comp < fspath.np_compcount; ) {
2217 isdotdot = 0;
2218 if (fspath.np_components[comp][0] == '.') {
2219 if (fspath.np_components[comp][1] == '\0') {
2220 /* skip "." */
2221 comp++;
2222 continue;
2223 }
2224 /* treat ".." specially */
2225 if ((fspath.np_components[comp][1] == '.') &&
2226 (fspath.np_components[comp][2] == '\0'))
2227 isdotdot = 1;
2228 if (isdotdot && (dirfh.fh_len == 0)) {
2229 /* ".." in root directory is same as "." */
2230 comp++;
2231 continue;
2232 }
2233 }
2234 // PUT(ROOT)FH + LOOKUP(P) + GETFH + GETATTR
2235 if (dirfh.fh_len == 0)
2236 NFSREQ_SECINFO_SET(&si, NULL, NULL, 0, isdotdot ? NULL : fspath.np_components[comp], 0);
2237 else
2238 NFSREQ_SECINFO_SET(&si, NULL, dirfh.fh_data, dirfh.fh_len, isdotdot ? NULL : fspath.np_components[comp], 0);
2239 numops = 4;
2240 nfsm_chain_build_alloc_init(error, &nmreq, 18 * NFSX_UNSIGNED);
2241 nfsm_chain_add_compound_header(error, &nmreq, "mount", nmp->nm_minor_vers, numops);
2242 numops--;
2243 if (dirfh.fh_len) {
2244 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTFH);
2245 nfsm_chain_add_fh(error, &nmreq, NFS_VER4, dirfh.fh_data, dirfh.fh_len);
2246 } else {
2247 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTROOTFH);
2248 }
2249 numops--;
2250 if (isdotdot) {
2251 nfsm_chain_add_32(error, &nmreq, NFS_OP_LOOKUPP);
2252 } else {
2253 nfsm_chain_add_32(error, &nmreq, NFS_OP_LOOKUP);
2254 nfsm_chain_add_name(error, &nmreq,
2255 fspath.np_components[comp], strlen(fspath.np_components[comp]), nmp);
2256 }
2257 numops--;
2258 nfsm_chain_add_32(error, &nmreq, NFS_OP_GETFH);
2259 numops--;
2260 nfsm_chain_add_32(error, &nmreq, NFS_OP_GETATTR);
2261 NFS_CLEAR_ATTRIBUTES(bitmap);
2262 NFS4_DEFAULT_ATTRIBUTES(bitmap);
2263 /* if no namedattr support or component is ".zfs", clear NFS_FATTR_NAMED_ATTR */
2264 if (NMFLAG(nmp, NONAMEDATTR) || !strcmp(fspath.np_components[comp], ".zfs"))
2265 NFS_BITMAP_CLR(bitmap, NFS_FATTR_NAMED_ATTR);
2266 nfsm_chain_add_bitmap(error, &nmreq, bitmap, NFS_ATTR_BITMAP_LEN);
2267 nfsm_chain_build_done(error, &nmreq);
2268 nfsm_assert(error, (numops == 0), EPROTO);
2269 nfsmout_if(error);
2270 error = nfs_request_async(NULL, nmp->nm_mountp, &nmreq, NFSPROC4_COMPOUND,
2271 vfs_context_thread(ctx), vfs_context_ucred(ctx), &si, 0, NULL, &req);
2272 if (!error)
2273 error = nfs_request_async_finish(req, &nmrep, &xid, &status);
2274 nfsm_chain_skip_tag(error, &nmrep);
2275 nfsm_chain_get_32(error, &nmrep, numops);
2276 nfsm_chain_op_check(error, &nmrep, dirfh.fh_len ? NFS_OP_PUTFH : NFS_OP_PUTROOTFH);
2277 nfsm_chain_op_check(error, &nmrep, isdotdot ? NFS_OP_LOOKUPP : NFS_OP_LOOKUP);
2278 nfsmout_if(error);
2279 nfsm_chain_op_check(error, &nmrep, NFS_OP_GETFH);
2280 nfsm_chain_get_32(error, &nmrep, fh.fh_len);
2281 nfsm_chain_get_opaque(error, &nmrep, fh.fh_len, fh.fh_data);
2282 nfsm_chain_op_check(error, &nmrep, NFS_OP_GETATTR);
2283 if (!error) {
2284 NFS_CLEAR_ATTRIBUTES(nmp->nm_fsattr.nfsa_bitmap);
2285 error = nfs4_parsefattr(&nmrep, &nmp->nm_fsattr, &nvattr, NULL, NULL, &nfsls);
2286 }
2287 nfsm_chain_cleanup(&nmrep);
2288 nfsm_chain_null(&nmreq);
2289 if (error) {
2290 /* LOOKUP succeeded but GETATTR failed? This could be a referral. */
2291 /* Try the lookup again with a getattr for fs_locations. */
2292 nfs_fs_locations_cleanup(&nfsls);
2293 error = nfs4_get_fs_locations(nmp, NULL, dirfh.fh_data, dirfh.fh_len, fspath.np_components[comp], ctx, &nfsls);
2294 if (!error && (nfsls.nl_numlocs < 1))
2295 error = ENOENT;
2296 nfsmout_if(error);
2297 if (++loopcnt > MAXSYMLINKS) {
2298 /* too many symlink/referral redirections */
2299 error = ELOOP;
2300 goto nfsmout;
2301 }
2302 /* tear down the current connection */
2303 nfs_disconnect(nmp);
2304 /* replace fs locations */
2305 nfs_fs_locations_cleanup(&nmp->nm_locations);
2306 nmp->nm_locations = nfsls;
2307 bzero(&nfsls, sizeof(nfsls));
2308 /* initiate a connection using the new fs locations */
2309 error = nfs_mount_connect(nmp);
2310 if (!error && !(nmp->nm_locations.nl_current.nli_flags & NLI_VALID))
2311 error = EIO;
2312 nfsmout_if(error);
2313 /* add new server's remote path to beginning of our path and continue */
2314 nfsp = &nmp->nm_locations.nl_locations[nmp->nm_locations.nl_current.nli_loc]->nl_path;
2315 bzero(&fspath2, sizeof(fspath2));
2316 fspath2.np_compcount = (fspath.np_compcount - comp - 1) + nfsp->np_compcount;
2317 if (fspath2.np_compcount > 0) {
2318 MALLOC(fspath2.np_components, char **, fspath2.np_compcount*sizeof(char*), M_TEMP, M_WAITOK|M_ZERO);
2319 if (!fspath2.np_components) {
2320 error = ENOMEM;
2321 goto nfsmout;
2322 }
2323 for (comp2=0; comp2 < nfsp->np_compcount; comp2++) {
2324 int slen = strlen(nfsp->np_components[comp2]);
2325 MALLOC(fspath2.np_components[comp2], char *, slen+1, M_TEMP, M_WAITOK|M_ZERO);
2326 if (!fspath2.np_components[comp2]) {
2327 /* clean up fspath2, then error out */
2328 while (comp2 > 0) {
2329 comp2--;
2330 FREE(fspath2.np_components[comp2], M_TEMP);
2331 }
2332 FREE(fspath2.np_components, M_TEMP);
2333 error = ENOMEM;
2334 goto nfsmout;
2335 }
2336 strlcpy(fspath2.np_components[comp2], nfsp->np_components[comp2], slen+1);
2337 }
2338 if ((fspath.np_compcount - comp - 1) > 0)
2339 bcopy(&fspath.np_components[comp+1], &fspath2.np_components[nfsp->np_compcount], (fspath.np_compcount - comp - 1)*sizeof(char*));
2340 /* free up unused parts of old path (prior components and component array) */
2341 do {
2342 FREE(fspath.np_components[comp], M_TEMP);
2343 } while (comp-- > 0);
2344 FREE(fspath.np_components, M_TEMP);
2345 /* put new path in place */
2346 fspath = fspath2;
2347 }
2348 /* reset dirfh and component index */
2349 dirfh.fh_len = 0;
2350 comp = 0;
2351 NVATTR_CLEANUP(&nvattr);
2352 if (fspath.np_compcount == 0)
2353 goto nocomponents;
2354 continue;
2355 }
2356 nfsmout_if(error);
2357 /* if file handle is for a symlink, then update the path with the symlink contents */
2358 if (NFS_BITMAP_ISSET(&nvattr.nva_bitmap, NFS_FATTR_TYPE) && (nvattr.nva_type == VLNK)) {
2359 if (++loopcnt > MAXSYMLINKS)
2360 error = ELOOP;
2361 else
2362 error = nfs4_mount_update_path_with_symlink(nmp, &fspath, comp, &dirfh, &depth, &fh, ctx);
2363 nfsmout_if(error);
2364 /* directory file handle is either left the same or reset to root (if link was absolute) */
2365 /* path traversal starts at beginning of the path again */
2366 comp = 0;
2367 NVATTR_CLEANUP(&nvattr);
2368 nfs_fs_locations_cleanup(&nfsls);
2369 continue;
2370 }
2371 NVATTR_CLEANUP(&nvattr);
2372 nfs_fs_locations_cleanup(&nfsls);
2373 /* not a symlink... */
2374 if ((nmp->nm_state & NFSSTA_NEEDSECINFO) && (comp == (fspath.np_compcount-1)) && !isdotdot) {
2375 /* need to get SECINFO for the directory being mounted */
2376 if (dirfh.fh_len == 0)
2377 NFSREQ_SECINFO_SET(&si, NULL, NULL, 0, isdotdot ? NULL : fspath.np_components[comp], 0);
2378 else
2379 NFSREQ_SECINFO_SET(&si, NULL, dirfh.fh_data, dirfh.fh_len, isdotdot ? NULL : fspath.np_components[comp], 0);
2380 sec.count = NX_MAX_SEC_FLAVORS;
2381 error = nfs4_secinfo_rpc(nmp, &si, vfs_context_ucred(ctx), sec.flavors, &sec.count);
2382 /* [sigh] some implementations return "illegal" error for unsupported ops */
2383 if (error == NFSERR_OP_ILLEGAL)
2384 error = 0;
2385 nfsmout_if(error);
2386 /* set our default security flavor to the first in the list */
2387 if (sec.count)
2388 nmp->nm_auth = sec.flavors[0];
2389 nmp->nm_state &= ~NFSSTA_NEEDSECINFO;
2390 }
2391 /* advance directory file handle, component index, & update depth */
2392 dirfh = fh;
2393 comp++;
2394 if (!isdotdot) /* going down the hierarchy */
2395 depth++;
2396 else if (--depth <= 0) /* going up the hierarchy */
2397 dirfh.fh_len = 0; /* clear dirfh when we hit root */
2398 }
2399
2400 gotfh:
2401 /* get attrs for mount point root */
2402 numops = NMFLAG(nmp, NONAMEDATTR) ? 2 : 3; // PUTFH + GETATTR + OPENATTR
2403 nfsm_chain_build_alloc_init(error, &nmreq, 25 * NFSX_UNSIGNED);
2404 nfsm_chain_add_compound_header(error, &nmreq, "mount", nmp->nm_minor_vers, numops);
2405 numops--;
2406 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTFH);
2407 nfsm_chain_add_fh(error, &nmreq, NFS_VER4, dirfh.fh_data, dirfh.fh_len);
2408 numops--;
2409 nfsm_chain_add_32(error, &nmreq, NFS_OP_GETATTR);
2410 NFS_CLEAR_ATTRIBUTES(bitmap);
2411 NFS4_DEFAULT_ATTRIBUTES(bitmap);
2412 /* if no namedattr support or last component is ".zfs", clear NFS_FATTR_NAMED_ATTR */
2413 if (NMFLAG(nmp, NONAMEDATTR) || ((fspath.np_compcount > 0) && !strcmp(fspath.np_components[fspath.np_compcount-1], ".zfs")))
2414 NFS_BITMAP_CLR(bitmap, NFS_FATTR_NAMED_ATTR);
2415 nfsm_chain_add_bitmap(error, &nmreq, bitmap, NFS_ATTR_BITMAP_LEN);
2416 if (!NMFLAG(nmp, NONAMEDATTR)) {
2417 numops--;
2418 nfsm_chain_add_32(error, &nmreq, NFS_OP_OPENATTR);
2419 nfsm_chain_add_32(error, &nmreq, 0);
2420 }
2421 nfsm_chain_build_done(error, &nmreq);
2422 nfsm_assert(error, (numops == 0), EPROTO);
2423 nfsmout_if(error);
2424 error = nfs_request_async(NULL, nmp->nm_mountp, &nmreq, NFSPROC4_COMPOUND,
2425 vfs_context_thread(ctx), vfs_context_ucred(ctx), &si, 0, NULL, &req);
2426 if (!error)
2427 error = nfs_request_async_finish(req, &nmrep, &xid, &status);
2428 nfsm_chain_skip_tag(error, &nmrep);
2429 nfsm_chain_get_32(error, &nmrep, numops);
2430 nfsm_chain_op_check(error, &nmrep, NFS_OP_PUTFH);
2431 nfsm_chain_op_check(error, &nmrep, NFS_OP_GETATTR);
2432 nfsmout_if(error);
2433 NFS_CLEAR_ATTRIBUTES(nmp->nm_fsattr.nfsa_bitmap);
2434 error = nfs4_parsefattr(&nmrep, &nmp->nm_fsattr, &nvattr, NULL, NULL, NULL);
2435 nfsmout_if(error);
2436 if (!NMFLAG(nmp, NONAMEDATTR)) {
2437 nfsm_chain_op_check(error, &nmrep, NFS_OP_OPENATTR);
2438 if (error == ENOENT)
2439 error = 0;
2440 /* [sigh] some implementations return "illegal" error for unsupported ops */
2441 if (error || !NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_NAMED_ATTR)) {
2442 nmp->nm_fsattr.nfsa_flags &= ~NFS_FSFLAG_NAMED_ATTR;
2443 } else {
2444 nmp->nm_fsattr.nfsa_flags |= NFS_FSFLAG_NAMED_ATTR;
2445 }
2446 } else {
2447 nmp->nm_fsattr.nfsa_flags &= ~NFS_FSFLAG_NAMED_ATTR;
2448 }
2449 if (NMFLAG(nmp, NOACL)) /* make sure ACL support is turned off */
2450 nmp->nm_fsattr.nfsa_flags &= ~NFS_FSFLAG_ACL;
2451 if (NMFLAG(nmp, ACLONLY) && !(nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_ACL))
2452 NFS_BITMAP_CLR(nmp->nm_flags, NFS_MFLAG_ACLONLY);
2453 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_FH_EXPIRE_TYPE)) {
2454 uint32_t fhtype = ((nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_FHTYPE_MASK) >> NFS_FSFLAG_FHTYPE_SHIFT);
2455 if (fhtype != NFS_FH_PERSISTENT)
2456 printf("nfs: warning: non-persistent file handles! for %s\n", vfs_statfs(nmp->nm_mountp)->f_mntfromname);
2457 }
2458
2459 /* make sure it's a directory */
2460 if (!NFS_BITMAP_ISSET(&nvattr.nva_bitmap, NFS_FATTR_TYPE) || (nvattr.nva_type != VDIR)) {
2461 error = ENOTDIR;
2462 goto nfsmout;
2463 }
2464
2465 /* save the NFS fsid */
2466 nmp->nm_fsid = nvattr.nva_fsid;
2467
2468 /* create the root node */
2469 error = nfs_nget(nmp->nm_mountp, NULL, NULL, dirfh.fh_data, dirfh.fh_len, &nvattr, &xid, rq.r_auth, NG_MARKROOT, npp);
2470 nfsmout_if(error);
2471
2472 if (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_ACL)
2473 vfs_setextendedsecurity(nmp->nm_mountp);
2474
2475 /* adjust I/O sizes to server limits */
2476 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXREAD) && (nmp->nm_fsattr.nfsa_maxread > 0)) {
2477 if (nmp->nm_fsattr.nfsa_maxread < (uint64_t)nmp->nm_rsize) {
2478 nmp->nm_rsize = nmp->nm_fsattr.nfsa_maxread & ~(NFS_FABLKSIZE - 1);
2479 if (nmp->nm_rsize == 0)
2480 nmp->nm_rsize = nmp->nm_fsattr.nfsa_maxread;
2481 }
2482 }
2483 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXWRITE) && (nmp->nm_fsattr.nfsa_maxwrite > 0)) {
2484 if (nmp->nm_fsattr.nfsa_maxwrite < (uint64_t)nmp->nm_wsize) {
2485 nmp->nm_wsize = nmp->nm_fsattr.nfsa_maxwrite & ~(NFS_FABLKSIZE - 1);
2486 if (nmp->nm_wsize == 0)
2487 nmp->nm_wsize = nmp->nm_fsattr.nfsa_maxwrite;
2488 }
2489 }
2490
2491 /* set up lease renew timer */
2492 nmp->nm_renew_timer = thread_call_allocate(nfs4_renew_timer, nmp);
2493 interval = nmp->nm_fsattr.nfsa_lease / 2;
2494 if (interval < 1)
2495 interval = 1;
2496 nfs_interval_timer_start(nmp->nm_renew_timer, interval * 1000);
2497
2498 nfsmout:
2499 if (fspath.np_components) {
2500 for (comp=0; comp < fspath.np_compcount; comp++)
2501 if (fspath.np_components[comp])
2502 FREE(fspath.np_components[comp], M_TEMP);
2503 FREE(fspath.np_components, M_TEMP);
2504 }
2505 NVATTR_CLEANUP(&nvattr);
2506 nfs_fs_locations_cleanup(&nfsls);
2507 if (*npp)
2508 nfs_node_unlock(*npp);
2509 nfsm_chain_cleanup(&nmreq);
2510 nfsm_chain_cleanup(&nmrep);
2511 return (error);
2512 }
2513
2514 /*
2515 * Thread to handle initial NFS mount connection.
2516 */
2517 void
2518 nfs_mount_connect_thread(void *arg, __unused wait_result_t wr)
2519 {
2520 struct nfsmount *nmp = arg;
2521 int error = 0, savederror = 0, slpflag = (NMFLAG(nmp, INTR) ? PCATCH : 0);
2522 int done = 0, timeo, tries, maxtries;
2523
2524 if (NM_OMFLAG(nmp, MNTQUICK)) {
2525 timeo = 8;
2526 maxtries = 1;
2527 } else {
2528 timeo = 30;
2529 maxtries = 2;
2530 }
2531
2532 for (tries = 0; tries < maxtries; tries++) {
2533 error = nfs_connect(nmp, 1, timeo);
2534 switch (error) {
2535 case ETIMEDOUT:
2536 case EAGAIN:
2537 case EPIPE:
2538 case EADDRNOTAVAIL:
2539 case ENETDOWN:
2540 case ENETUNREACH:
2541 case ENETRESET:
2542 case ECONNABORTED:
2543 case ECONNRESET:
2544 case EISCONN:
2545 case ENOTCONN:
2546 case ESHUTDOWN:
2547 case ECONNREFUSED:
2548 case EHOSTDOWN:
2549 case EHOSTUNREACH:
2550 /* just keep retrying on any of these errors */
2551 break;
2552 case 0:
2553 default:
2554 /* looks like we got an answer... */
2555 done = 1;
2556 break;
2557 }
2558
2559 /* save the best error */
2560 if (nfs_connect_error_class(error) >= nfs_connect_error_class(savederror))
2561 savederror = error;
2562 if (done) {
2563 error = savederror;
2564 break;
2565 }
2566
2567 /* pause before next attempt */
2568 if ((error = nfs_sigintr(nmp, NULL, current_thread(), 0)))
2569 break;
2570 error = tsleep(nmp, PSOCK|slpflag, "nfs_mount_connect_retry", 2*hz);
2571 if (error && (error != EWOULDBLOCK))
2572 break;
2573 error = savederror;
2574 }
2575
2576 /* update status of mount connect */
2577 lck_mtx_lock(&nmp->nm_lock);
2578 if (!nmp->nm_mounterror)
2579 nmp->nm_mounterror = error;
2580 nmp->nm_state &= ~NFSSTA_MOUNT_THREAD;
2581 lck_mtx_unlock(&nmp->nm_lock);
2582 wakeup(&nmp->nm_nss);
2583 }
2584
2585 int
2586 nfs_mount_connect(struct nfsmount *nmp)
2587 {
2588 int error = 0, slpflag;
2589 thread_t thd;
2590 struct timespec ts = { 2, 0 };
2591
2592 /*
2593 * Set up the socket. Perform initial search for a location/server/address to
2594 * connect to and negotiate any unspecified mount parameters. This work is
2595 * done on a kernel thread to satisfy reserved port usage needs.
2596 */
2597 slpflag = NMFLAG(nmp, INTR) ? PCATCH : 0;
2598 lck_mtx_lock(&nmp->nm_lock);
2599 /* set flag that the thread is running */
2600 nmp->nm_state |= NFSSTA_MOUNT_THREAD;
2601 if (kernel_thread_start(nfs_mount_connect_thread, nmp, &thd) != KERN_SUCCESS) {
2602 nmp->nm_state &= ~NFSSTA_MOUNT_THREAD;
2603 nmp->nm_mounterror = EIO;
2604 printf("nfs mount %s start socket connect thread failed\n", vfs_statfs(nmp->nm_mountp)->f_mntfromname);
2605 } else {
2606 thread_deallocate(thd);
2607 }
2608
2609 /* wait until mount connect thread is finished/gone */
2610 while (nmp->nm_state & NFSSTA_MOUNT_THREAD) {
2611 error = msleep(&nmp->nm_nss, &nmp->nm_lock, slpflag|PSOCK, "nfsconnectthread", &ts);
2612 if ((error && (error != EWOULDBLOCK)) || ((error = nfs_sigintr(nmp, NULL, current_thread(), 1)))) {
2613 /* record error */
2614 if (!nmp->nm_mounterror)
2615 nmp->nm_mounterror = error;
2616 /* signal the thread that we are aborting */
2617 nmp->nm_sockflags |= NMSOCK_UNMOUNT;
2618 if (nmp->nm_nss)
2619 wakeup(nmp->nm_nss);
2620 /* and continue waiting on it to finish */
2621 slpflag = 0;
2622 }
2623 }
2624 lck_mtx_unlock(&nmp->nm_lock);
2625
2626 /* grab mount connect status */
2627 error = nmp->nm_mounterror;
2628
2629 return (error);
2630 }
2631
2632 /* Table of maximum minor version for a given version */
2633 uint32_t maxminorverstab[] = {
2634 0, /* Version 0 (does not exist) */
2635 0, /* Version 1 (does not exist) */
2636 0, /* Version 2 */
2637 0, /* Version 3 */
2638 0, /* Version 4 */
2639 };
2640
2641 #define NFS_MAX_SUPPORTED_VERSION ((long)(sizeof (maxminorverstab) / sizeof (uint32_t) - 1))
2642 #define NFS_MAX_SUPPORTED_MINOR_VERSION(v) ((long)(maxminorverstab[(v)]))
2643
2644 #define DEFAULT_NFS_MIN_VERS VER2PVER(2, 0)
2645 #define DEFAULT_NFS_MAX_VERS VER2PVER(3, 0)
2646
2647 /*
2648 * Common code to mount an NFS file system.
2649 */
2650 int
2651 mountnfs(
2652 char *xdrbuf,
2653 mount_t mp,
2654 vfs_context_t ctx,
2655 vnode_t *vpp)
2656 {
2657 struct nfsmount *nmp;
2658 nfsnode_t np;
2659 int error = 0;
2660 struct vfsstatfs *sbp;
2661 struct xdrbuf xb;
2662 uint32_t i, val, maxio, iosize, len;
2663 uint32_t *mattrs;
2664 uint32_t *mflags_mask;
2665 uint32_t *mflags;
2666 uint32_t argslength, attrslength;
2667 struct nfs_location_index firstloc = { NLI_VALID, 0, 0, 0 };
2668 static const struct nfs_etype nfs_default_etypes = {
2669 .count = NFS_MAX_ETYPES,
2670 .selected = NFS_MAX_ETYPES,
2671 .etypes = { NFS_AES256_CTS_HMAC_SHA1_96,
2672 NFS_AES128_CTS_HMAC_SHA1_96,
2673 NFS_DES3_CBC_SHA1_KD
2674 }
2675 };
2676 /* make sure mbuf constants are set up */
2677 if (!nfs_mbuf_mhlen)
2678 nfs_mbuf_init();
2679
2680 if (vfs_flags(mp) & MNT_UPDATE) {
2681 nmp = VFSTONFS(mp);
2682 /* update paths, file handles, etc, here XXX */
2683 xb_free(xdrbuf);
2684 return (0);
2685 } else {
2686 /* allocate an NFS mount structure for this mount */
2687 MALLOC_ZONE(nmp, struct nfsmount *,
2688 sizeof (struct nfsmount), M_NFSMNT, M_WAITOK);
2689 if (!nmp) {
2690 xb_free(xdrbuf);
2691 return (ENOMEM);
2692 }
2693 bzero((caddr_t)nmp, sizeof (struct nfsmount));
2694 lck_mtx_init(&nmp->nm_lock, nfs_mount_grp, LCK_ATTR_NULL);
2695 TAILQ_INIT(&nmp->nm_resendq);
2696 TAILQ_INIT(&nmp->nm_iodq);
2697 TAILQ_INIT(&nmp->nm_gsscl);
2698 LIST_INIT(&nmp->nm_monlist);
2699 vfs_setfsprivate(mp, nmp);
2700 vfs_getnewfsid(mp);
2701 nmp->nm_mountp = mp;
2702 vfs_setauthopaque(mp);
2703
2704 nfs_nhinit_finish();
2705
2706 nmp->nm_args = xdrbuf;
2707
2708 /* set up defaults */
2709 nmp->nm_ref = 0;
2710 nmp->nm_vers = 0;
2711 nmp->nm_min_vers = DEFAULT_NFS_MIN_VERS;
2712 nmp->nm_max_vers = DEFAULT_NFS_MAX_VERS;
2713 nmp->nm_timeo = NFS_TIMEO;
2714 nmp->nm_retry = NFS_RETRANS;
2715 nmp->nm_sotype = 0;
2716 nmp->nm_sofamily = 0;
2717 nmp->nm_nfsport = 0;
2718 nmp->nm_wsize = NFS_WSIZE;
2719 nmp->nm_rsize = NFS_RSIZE;
2720 nmp->nm_readdirsize = NFS_READDIRSIZE;
2721 nmp->nm_numgrps = NFS_MAXGRPS;
2722 nmp->nm_readahead = NFS_DEFRAHEAD;
2723 nmp->nm_tprintf_delay = nfs_tprintf_delay;
2724 if (nmp->nm_tprintf_delay < 0)
2725 nmp->nm_tprintf_delay = 0;
2726 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
2727 if (nmp->nm_tprintf_initial_delay < 0)
2728 nmp->nm_tprintf_initial_delay = 0;
2729 nmp->nm_acregmin = NFS_MINATTRTIMO;
2730 nmp->nm_acregmax = NFS_MAXATTRTIMO;
2731 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
2732 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
2733 nmp->nm_etype = nfs_default_etypes;
2734 nmp->nm_auth = RPCAUTH_SYS;
2735 nmp->nm_iodlink.tqe_next = NFSNOLIST;
2736 nmp->nm_deadtimeout = 0;
2737 nmp->nm_curdeadtimeout = 0;
2738 NFS_BITMAP_SET(nmp->nm_flags, NFS_MFLAG_NOACL);
2739 nmp->nm_realm = NULL;
2740 nmp->nm_principal = NULL;
2741 nmp->nm_sprinc = NULL;
2742 }
2743
2744 mattrs = nmp->nm_mattrs;
2745 mflags = nmp->nm_mflags;
2746 mflags_mask = nmp->nm_mflags_mask;
2747
2748 /* set up NFS mount with args */
2749 xb_init_buffer(&xb, xdrbuf, 2*XDRWORD);
2750 xb_get_32(error, &xb, val); /* version */
2751 xb_get_32(error, &xb, argslength); /* args length */
2752 nfsmerr_if(error);
2753 xb_init_buffer(&xb, xdrbuf, argslength); /* restart parsing with actual buffer length */
2754 xb_get_32(error, &xb, val); /* version */
2755 xb_get_32(error, &xb, argslength); /* args length */
2756 xb_get_32(error, &xb, val); /* XDR args version */
2757 if (val != NFS_XDRARGS_VERSION_0)
2758 error = EINVAL;
2759 len = NFS_MATTR_BITMAP_LEN;
2760 xb_get_bitmap(error, &xb, mattrs, len); /* mount attribute bitmap */
2761 attrslength = 0;
2762 xb_get_32(error, &xb, attrslength); /* attrs length */
2763 if (!error && (attrslength > (argslength - ((4+NFS_MATTR_BITMAP_LEN+1)*XDRWORD))))
2764 error = EINVAL;
2765 nfsmerr_if(error);
2766 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_FLAGS)) {
2767 len = NFS_MFLAG_BITMAP_LEN;
2768 xb_get_bitmap(error, &xb, mflags_mask, len); /* mount flag mask */
2769 len = NFS_MFLAG_BITMAP_LEN;
2770 xb_get_bitmap(error, &xb, mflags, len); /* mount flag values */
2771 if (!error) {
2772 /* clear all mask bits and OR in all the ones that are set */
2773 nmp->nm_flags[0] &= ~mflags_mask[0];
2774 nmp->nm_flags[0] |= (mflags_mask[0] & mflags[0]);
2775 }
2776 }
2777 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_VERSION)) {
2778 /* Can't specify a single version and a range */
2779 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_VERSION_RANGE))
2780 error = EINVAL;
2781 xb_get_32(error, &xb, nmp->nm_vers);
2782 if (nmp->nm_vers > NFS_MAX_SUPPORTED_VERSION ||
2783 nmp->nm_vers < NFS_VER2)
2784 error = EINVAL;
2785 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_MINOR_VERSION))
2786 xb_get_32(error, &xb, nmp->nm_minor_vers);
2787 else
2788 nmp->nm_minor_vers = maxminorverstab[nmp->nm_vers];
2789 if (nmp->nm_minor_vers > maxminorverstab[nmp->nm_vers])
2790 error = EINVAL;
2791 nmp->nm_max_vers = nmp->nm_min_vers =
2792 VER2PVER(nmp->nm_vers, nmp->nm_minor_vers);
2793 }
2794 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_MINOR_VERSION)) {
2795 /* should have also gotten NFS version (and already gotten minor version) */
2796 if (!NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_VERSION))
2797 error = EINVAL;
2798 }
2799 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_VERSION_RANGE)) {
2800 xb_get_32(error, &xb, nmp->nm_min_vers);
2801 xb_get_32(error, &xb, nmp->nm_max_vers);
2802 if ((nmp->nm_min_vers > nmp->nm_max_vers) ||
2803 (PVER2MAJOR(nmp->nm_max_vers) > NFS_MAX_SUPPORTED_VERSION) ||
2804 (PVER2MINOR(nmp->nm_min_vers) > maxminorverstab[PVER2MAJOR(nmp->nm_min_vers)]) ||
2805 (PVER2MINOR(nmp->nm_max_vers) > maxminorverstab[PVER2MAJOR(nmp->nm_max_vers)]))
2806 error = EINVAL;
2807 }
2808 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READ_SIZE))
2809 xb_get_32(error, &xb, nmp->nm_rsize);
2810 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_WRITE_SIZE))
2811 xb_get_32(error, &xb, nmp->nm_wsize);
2812 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READDIR_SIZE))
2813 xb_get_32(error, &xb, nmp->nm_readdirsize);
2814 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READAHEAD))
2815 xb_get_32(error, &xb, nmp->nm_readahead);
2816 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_REG_MIN)) {
2817 xb_get_32(error, &xb, nmp->nm_acregmin);
2818 xb_skip(error, &xb, XDRWORD);
2819 }
2820 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_REG_MAX)) {
2821 xb_get_32(error, &xb, nmp->nm_acregmax);
2822 xb_skip(error, &xb, XDRWORD);
2823 }
2824 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MIN)) {
2825 xb_get_32(error, &xb, nmp->nm_acdirmin);
2826 xb_skip(error, &xb, XDRWORD);
2827 }
2828 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MAX)) {
2829 xb_get_32(error, &xb, nmp->nm_acdirmax);
2830 xb_skip(error, &xb, XDRWORD);
2831 }
2832 nfsmerr_if(error);
2833 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_LOCK_MODE)) {
2834 xb_get_32(error, &xb, val);
2835 switch (val) {
2836 case NFS_LOCK_MODE_DISABLED:
2837 case NFS_LOCK_MODE_LOCAL:
2838 if (nmp->nm_vers >= NFS_VER4) {
2839 /* disabled/local lock mode only allowed on v2/v3 */
2840 error = EINVAL;
2841 break;
2842 }
2843 /* FALLTHROUGH */
2844 case NFS_LOCK_MODE_ENABLED:
2845 nmp->nm_lockmode = val;
2846 break;
2847 default:
2848 error = EINVAL;
2849 }
2850 }
2851 nfsmerr_if(error);
2852 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SECURITY)) {
2853 uint32_t seccnt;
2854 xb_get_32(error, &xb, seccnt);
2855 if (!error && ((seccnt < 1) || (seccnt > NX_MAX_SEC_FLAVORS)))
2856 error = EINVAL;
2857 nfsmerr_if(error);
2858 nmp->nm_sec.count = seccnt;
2859 for (i=0; i < seccnt; i++) {
2860 xb_get_32(error, &xb, nmp->nm_sec.flavors[i]);
2861 /* Check for valid security flavor */
2862 switch (nmp->nm_sec.flavors[i]) {
2863 case RPCAUTH_NONE:
2864 case RPCAUTH_SYS:
2865 case RPCAUTH_KRB5:
2866 case RPCAUTH_KRB5I:
2867 case RPCAUTH_KRB5P:
2868 break;
2869 default:
2870 error = EINVAL;
2871 }
2872 }
2873 /* start with the first flavor */
2874 nmp->nm_auth = nmp->nm_sec.flavors[0];
2875 }
2876 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_KERB_ETYPE)) {
2877 uint32_t etypecnt;
2878 xb_get_32(error, &xb, etypecnt);
2879 if (!error && ((etypecnt < 1) || (etypecnt > NFS_MAX_ETYPES)))
2880 error = EINVAL;
2881 nfsmerr_if(error);
2882 nmp->nm_etype.count = etypecnt;
2883 xb_get_32(error, &xb, nmp->nm_etype.selected);
2884 nfsmerr_if(error);
2885 if (etypecnt) {
2886 nmp->nm_etype.selected = etypecnt; /* Nothing is selected yet, so set selected to count */
2887 for (i=0; i < etypecnt; i++) {
2888 xb_get_32(error, &xb, nmp->nm_etype.etypes[i]);
2889 /* Check for valid encryption type */
2890 switch (nmp->nm_etype.etypes[i]) {
2891 case NFS_DES3_CBC_SHA1_KD:
2892 case NFS_AES128_CTS_HMAC_SHA1_96:
2893 case NFS_AES256_CTS_HMAC_SHA1_96:
2894 break;
2895 default:
2896 error = EINVAL;
2897 }
2898 }
2899 }
2900 }
2901 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MAX_GROUP_LIST))
2902 xb_get_32(error, &xb, nmp->nm_numgrps);
2903 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SOCKET_TYPE)) {
2904 char sotype[6];
2905
2906 xb_get_32(error, &xb, val);
2907 if (!error && ((val < 3) || (val > 5)))
2908 error = EINVAL;
2909 nfsmerr_if(error);
2910 error = xb_get_bytes(&xb, sotype, val, 0);
2911 nfsmerr_if(error);
2912 sotype[val] = '\0';
2913 if (!strcmp(sotype, "tcp")) {
2914 nmp->nm_sotype = SOCK_STREAM;
2915 } else if (!strcmp(sotype, "udp")) {
2916 nmp->nm_sotype = SOCK_DGRAM;
2917 } else if (!strcmp(sotype, "tcp4")) {
2918 nmp->nm_sotype = SOCK_STREAM;
2919 nmp->nm_sofamily = AF_INET;
2920 } else if (!strcmp(sotype, "udp4")) {
2921 nmp->nm_sotype = SOCK_DGRAM;
2922 nmp->nm_sofamily = AF_INET;
2923 } else if (!strcmp(sotype, "tcp6")) {
2924 nmp->nm_sotype = SOCK_STREAM;
2925 nmp->nm_sofamily = AF_INET6;
2926 } else if (!strcmp(sotype, "udp6")) {
2927 nmp->nm_sotype = SOCK_DGRAM;
2928 nmp->nm_sofamily = AF_INET6;
2929 } else if (!strcmp(sotype, "inet4")) {
2930 nmp->nm_sofamily = AF_INET;
2931 } else if (!strcmp(sotype, "inet6")) {
2932 nmp->nm_sofamily = AF_INET6;
2933 } else if (!strcmp(sotype, "inet")) {
2934 nmp->nm_sofamily = 0; /* ok */
2935 } else {
2936 error = EINVAL;
2937 }
2938 if (!error && (nmp->nm_vers >= NFS_VER4) && nmp->nm_sotype &&
2939 (nmp->nm_sotype != SOCK_STREAM))
2940 error = EINVAL; /* NFSv4 is only allowed over TCP. */
2941 nfsmerr_if(error);
2942 }
2943 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_PORT))
2944 xb_get_32(error, &xb, nmp->nm_nfsport);
2945 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MOUNT_PORT))
2946 xb_get_32(error, &xb, nmp->nm_mountport);
2947 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_REQUEST_TIMEOUT)) {
2948 /* convert from time to 0.1s units */
2949 xb_get_32(error, &xb, nmp->nm_timeo);
2950 xb_get_32(error, &xb, val);
2951 nfsmerr_if(error);
2952 if (val >= 1000000000)
2953 error = EINVAL;
2954 nfsmerr_if(error);
2955 nmp->nm_timeo *= 10;
2956 nmp->nm_timeo += (val+100000000-1)/100000000;
2957 /* now convert to ticks */
2958 nmp->nm_timeo = (nmp->nm_timeo * NFS_HZ + 5) / 10;
2959 }
2960 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SOFT_RETRY_COUNT)) {
2961 xb_get_32(error, &xb, val);
2962 if (!error && (val > 1))
2963 nmp->nm_retry = val;
2964 }
2965 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_DEAD_TIMEOUT)) {
2966 xb_get_32(error, &xb, nmp->nm_deadtimeout);
2967 xb_skip(error, &xb, XDRWORD);
2968 }
2969 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_FH)) {
2970 nfsmerr_if(error);
2971 MALLOC(nmp->nm_fh, fhandle_t *, sizeof(fhandle_t), M_TEMP, M_WAITOK|M_ZERO);
2972 if (!nmp->nm_fh)
2973 error = ENOMEM;
2974 xb_get_32(error, &xb, nmp->nm_fh->fh_len);
2975 nfsmerr_if(error);
2976 if (nmp->nm_fh->fh_len < 0 ||
2977 (size_t)nmp->nm_fh->fh_len > sizeof(nmp->nm_fh->fh_data))
2978 error = EINVAL;
2979 else
2980 error = xb_get_bytes(&xb, (char*)&nmp->nm_fh->fh_data[0], nmp->nm_fh->fh_len, 0);
2981 }
2982 nfsmerr_if(error);
2983 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_FS_LOCATIONS)) {
2984 uint32_t loc, serv, addr, comp;
2985 struct nfs_fs_location *fsl;
2986 struct nfs_fs_server *fss;
2987 struct nfs_fs_path *fsp;
2988
2989 xb_get_32(error, &xb, nmp->nm_locations.nl_numlocs); /* fs location count */
2990 /* sanity check location count */
2991 if (!error && ((nmp->nm_locations.nl_numlocs < 1) || (nmp->nm_locations.nl_numlocs > 256)))
2992 error = EINVAL;
2993 nfsmerr_if(error);
2994 MALLOC(nmp->nm_locations.nl_locations, struct nfs_fs_location **, nmp->nm_locations.nl_numlocs * sizeof(struct nfs_fs_location*), M_TEMP, M_WAITOK|M_ZERO);
2995 if (!nmp->nm_locations.nl_locations)
2996 error = ENOMEM;
2997 for (loc = 0; loc < nmp->nm_locations.nl_numlocs; loc++) {
2998 nfsmerr_if(error);
2999 MALLOC(fsl, struct nfs_fs_location *, sizeof(struct nfs_fs_location), M_TEMP, M_WAITOK|M_ZERO);
3000 if (!fsl)
3001 error = ENOMEM;
3002 nmp->nm_locations.nl_locations[loc] = fsl;
3003 xb_get_32(error, &xb, fsl->nl_servcount); /* server count */
3004 /* sanity check server count */
3005 if (!error && ((fsl->nl_servcount < 1) || (fsl->nl_servcount > 256)))
3006 error = EINVAL;
3007 nfsmerr_if(error);
3008 MALLOC(fsl->nl_servers, struct nfs_fs_server **, fsl->nl_servcount * sizeof(struct nfs_fs_server*), M_TEMP, M_WAITOK|M_ZERO);
3009 if (!fsl->nl_servers)
3010 error = ENOMEM;
3011 for (serv = 0; serv < fsl->nl_servcount; serv++) {
3012 nfsmerr_if(error);
3013 MALLOC(fss, struct nfs_fs_server *, sizeof(struct nfs_fs_server), M_TEMP, M_WAITOK|M_ZERO);
3014 if (!fss)
3015 error = ENOMEM;
3016 fsl->nl_servers[serv] = fss;
3017 xb_get_32(error, &xb, val); /* server name length */
3018 /* sanity check server name length */
3019 if (!error && ((val < 1) || (val > MAXPATHLEN)))
3020 error = EINVAL;
3021 nfsmerr_if(error);
3022 MALLOC(fss->ns_name, char *, val+1, M_TEMP, M_WAITOK|M_ZERO);
3023 if (!fss->ns_name)
3024 error = ENOMEM;
3025 nfsmerr_if(error);
3026 error = xb_get_bytes(&xb, fss->ns_name, val, 0); /* server name */
3027 xb_get_32(error, &xb, fss->ns_addrcount); /* address count */
3028 /* sanity check address count (OK to be zero) */
3029 if (!error && (fss->ns_addrcount > 256))
3030 error = EINVAL;
3031 nfsmerr_if(error);
3032 if (fss->ns_addrcount > 0) {
3033 MALLOC(fss->ns_addresses, char **, fss->ns_addrcount * sizeof(char *), M_TEMP, M_WAITOK|M_ZERO);
3034 if (!fss->ns_addresses)
3035 error = ENOMEM;
3036 for (addr = 0; addr < fss->ns_addrcount; addr++) {
3037 xb_get_32(error, &xb, val); /* address length */
3038 /* sanity check address length */
3039 if (!error && ((val < 1) || (val > 128)))
3040 error = EINVAL;
3041 nfsmerr_if(error);
3042 MALLOC(fss->ns_addresses[addr], char *, val+1, M_TEMP, M_WAITOK|M_ZERO);
3043 if (!fss->ns_addresses[addr])
3044 error = ENOMEM;
3045 nfsmerr_if(error);
3046 error = xb_get_bytes(&xb, fss->ns_addresses[addr], val, 0); /* address */
3047 }
3048 }
3049 xb_get_32(error, &xb, val); /* server info length */
3050 xb_skip(error, &xb, val); /* skip server info */
3051 }
3052 /* get pathname */
3053 fsp = &fsl->nl_path;
3054 xb_get_32(error, &xb, fsp->np_compcount); /* component count */
3055 /* sanity check component count */
3056 if (!error && (fsp->np_compcount > MAXPATHLEN))
3057 error = EINVAL;
3058 nfsmerr_if(error);
3059 if (fsp->np_compcount) {
3060 MALLOC(fsp->np_components, char **, fsp->np_compcount * sizeof(char*), M_TEMP, M_WAITOK|M_ZERO);
3061 if (!fsp->np_components)
3062 error = ENOMEM;
3063 }
3064 for (comp = 0; comp < fsp->np_compcount; comp++) {
3065 xb_get_32(error, &xb, val); /* component length */
3066 /* sanity check component length */
3067 if (!error && (val == 0)) {
3068 /*
3069 * Apparently some people think a path with zero components should
3070 * be encoded with one zero-length component. So, just ignore any
3071 * zero length components.
3072 */
3073 comp--;
3074 fsp->np_compcount--;
3075 if (fsp->np_compcount == 0) {
3076 FREE(fsp->np_components, M_TEMP);
3077 fsp->np_components = NULL;
3078 }
3079 continue;
3080 }
3081 if (!error && ((val < 1) || (val > MAXPATHLEN)))
3082 error = EINVAL;
3083 nfsmerr_if(error);
3084 MALLOC(fsp->np_components[comp], char *, val+1, M_TEMP, M_WAITOK|M_ZERO);
3085 if (!fsp->np_components[comp])
3086 error = ENOMEM;
3087 nfsmerr_if(error);
3088 error = xb_get_bytes(&xb, fsp->np_components[comp], val, 0); /* component */
3089 }
3090 xb_get_32(error, &xb, val); /* fs location info length */
3091 xb_skip(error, &xb, val); /* skip fs location info */
3092 }
3093 }
3094 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MNTFLAGS))
3095 xb_skip(error, &xb, XDRWORD);
3096 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MNTFROM)) {
3097 xb_get_32(error, &xb, len);
3098 nfsmerr_if(error);
3099 val = len;
3100 if (val >= sizeof(vfs_statfs(mp)->f_mntfromname))
3101 val = sizeof(vfs_statfs(mp)->f_mntfromname) - 1;
3102 error = xb_get_bytes(&xb, vfs_statfs(mp)->f_mntfromname, val, 0);
3103 if ((len - val) > 0)
3104 xb_skip(error, &xb, len - val);
3105 nfsmerr_if(error);
3106 vfs_statfs(mp)->f_mntfromname[val] = '\0';
3107 }
3108 nfsmerr_if(error);
3109
3110 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_REALM)) {
3111 xb_get_32(error, &xb, len);
3112 if (!error && ((len < 1) || (len > MAXPATHLEN)))
3113 error=EINVAL;
3114 nfsmerr_if(error);
3115 /* allocate an extra byte for a leading '@' if its not already prepended to the realm */
3116 MALLOC(nmp->nm_realm, char *, len+2, M_TEMP, M_WAITOK|M_ZERO);
3117 if (!nmp->nm_realm)
3118 error = ENOMEM;
3119 nfsmerr_if(error);
3120 error = xb_get_bytes(&xb, nmp->nm_realm, len, 0);
3121 if (error == 0 && *nmp->nm_realm != '@') {
3122 bcopy(nmp->nm_realm, &nmp->nm_realm[1], len);
3123 nmp->nm_realm[0] = '@';
3124 }
3125 }
3126 nfsmerr_if(error);
3127
3128 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_PRINCIPAL)) {
3129 xb_get_32(error, &xb, len);
3130 if (!error && ((len < 1) || (len > MAXPATHLEN)))
3131 error=EINVAL;
3132 nfsmerr_if(error);
3133 MALLOC(nmp->nm_principal, char *, len+1, M_TEMP, M_WAITOK|M_ZERO);
3134 if (!nmp->nm_principal)
3135 error = ENOMEM;
3136 nfsmerr_if(error);
3137 error = xb_get_bytes(&xb, nmp->nm_principal, len, 0);
3138 }
3139 nfsmerr_if(error);
3140
3141 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SVCPRINCIPAL)) {
3142 xb_get_32(error, &xb, len);
3143 if (!error && ((len < 1) || (len > MAXPATHLEN)))
3144 error=EINVAL;
3145 nfsmerr_if(error);
3146 MALLOC(nmp->nm_sprinc, char *, len+1, M_TEMP, M_WAITOK|M_ZERO);
3147 if (!nmp->nm_sprinc)
3148 error = ENOMEM;
3149 nfsmerr_if(error);
3150 error = xb_get_bytes(&xb, nmp->nm_sprinc, len, 0);
3151 }
3152 nfsmerr_if(error);
3153
3154 /*
3155 * Sanity check/finalize settings.
3156 */
3157
3158 if (nmp->nm_timeo < NFS_MINTIMEO)
3159 nmp->nm_timeo = NFS_MINTIMEO;
3160 else if (nmp->nm_timeo > NFS_MAXTIMEO)
3161 nmp->nm_timeo = NFS_MAXTIMEO;
3162 if (nmp->nm_retry > NFS_MAXREXMIT)
3163 nmp->nm_retry = NFS_MAXREXMIT;
3164
3165 if (nmp->nm_numgrps > NFS_MAXGRPS)
3166 nmp->nm_numgrps = NFS_MAXGRPS;
3167 if (nmp->nm_readahead > NFS_MAXRAHEAD)
3168 nmp->nm_readahead = NFS_MAXRAHEAD;
3169 if (nmp->nm_acregmin > nmp->nm_acregmax)
3170 nmp->nm_acregmin = nmp->nm_acregmax;
3171 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
3172 nmp->nm_acdirmin = nmp->nm_acdirmax;
3173
3174 /* need at least one fs location */
3175 if (nmp->nm_locations.nl_numlocs < 1)
3176 error = EINVAL;
3177 nfsmerr_if(error);
3178
3179 /* init mount's mntfromname to first location */
3180 if (!NM_OMATTR_GIVEN(nmp, MNTFROM))
3181 nfs_location_mntfromname(&nmp->nm_locations, firstloc,
3182 vfs_statfs(mp)->f_mntfromname, sizeof(vfs_statfs(mp)->f_mntfromname), 0);
3183
3184 /* Need to save the mounting credential for v4. */
3185 nmp->nm_mcred = vfs_context_ucred(ctx);
3186 if (IS_VALID_CRED(nmp->nm_mcred))
3187 kauth_cred_ref(nmp->nm_mcred);
3188
3189 /*
3190 * If a reserved port is required, check for that privilege.
3191 * (Note that mirror mounts are exempt because the privilege was
3192 * already checked for the original mount.)
3193 */
3194 if (NMFLAG(nmp, RESVPORT) && !vfs_iskernelmount(mp))
3195 error = priv_check_cred(nmp->nm_mcred, PRIV_NETINET_RESERVEDPORT, 0);
3196 nfsmerr_if(error);
3197
3198 /* do mount's initial socket connection */
3199 error = nfs_mount_connect(nmp);
3200 nfsmerr_if(error);
3201
3202 /* set up the version-specific function tables */
3203 if (nmp->nm_vers < NFS_VER4)
3204 nmp->nm_funcs = &nfs3_funcs;
3205 else
3206 nmp->nm_funcs = &nfs4_funcs;
3207
3208 /* sanity check settings now that version/connection is set */
3209 if (nmp->nm_vers == NFS_VER2) /* ignore RDIRPLUS on NFSv2 */
3210 NFS_BITMAP_CLR(nmp->nm_flags, NFS_MFLAG_RDIRPLUS);
3211 if (nmp->nm_vers >= NFS_VER4) {
3212 if (NFS_BITMAP_ISSET(nmp->nm_flags, NFS_MFLAG_ACLONLY)) /* aclonly trumps noacl */
3213 NFS_BITMAP_CLR(nmp->nm_flags, NFS_MFLAG_NOACL);
3214 NFS_BITMAP_CLR(nmp->nm_flags, NFS_MFLAG_CALLUMNT);
3215 if (nmp->nm_lockmode != NFS_LOCK_MODE_ENABLED)
3216 error = EINVAL; /* disabled/local lock mode only allowed on v2/v3 */
3217 } else {
3218 /* ignore these if not v4 */
3219 NFS_BITMAP_CLR(nmp->nm_flags, NFS_MFLAG_NOCALLBACK);
3220 NFS_BITMAP_CLR(nmp->nm_flags, NFS_MFLAG_NONAMEDATTR);
3221 NFS_BITMAP_CLR(nmp->nm_flags, NFS_MFLAG_NOACL);
3222 NFS_BITMAP_CLR(nmp->nm_flags, NFS_MFLAG_ACLONLY);
3223 }
3224 nfsmerr_if(error);
3225
3226 if (nmp->nm_sotype == SOCK_DGRAM) {
3227 /* I/O size defaults for UDP are different */
3228 if (!NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READ_SIZE))
3229 nmp->nm_rsize = NFS_DGRAM_RSIZE;
3230 if (!NFS_BITMAP_ISSET(mattrs, NFS_MATTR_WRITE_SIZE))
3231 nmp->nm_wsize = NFS_DGRAM_WSIZE;
3232 }
3233
3234 /* round down I/O sizes to multiple of NFS_FABLKSIZE */
3235 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
3236 if (nmp->nm_rsize <= 0)
3237 nmp->nm_rsize = NFS_FABLKSIZE;
3238 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
3239 if (nmp->nm_wsize <= 0)
3240 nmp->nm_wsize = NFS_FABLKSIZE;
3241
3242 /* and limit I/O sizes to maximum allowed */
3243 maxio = (nmp->nm_vers == NFS_VER2) ? NFS_V2MAXDATA :
3244 (nmp->nm_sotype == SOCK_DGRAM) ? NFS_MAXDGRAMDATA : NFS_MAXDATA;
3245 if (maxio > NFS_MAXBSIZE)
3246 maxio = NFS_MAXBSIZE;
3247 if (nmp->nm_rsize > maxio)
3248 nmp->nm_rsize = maxio;
3249 if (nmp->nm_wsize > maxio)
3250 nmp->nm_wsize = maxio;
3251
3252 if (nmp->nm_readdirsize > maxio)
3253 nmp->nm_readdirsize = maxio;
3254 if (nmp->nm_readdirsize > nmp->nm_rsize)
3255 nmp->nm_readdirsize = nmp->nm_rsize;
3256
3257 /* Set up the sockets and related info */
3258 if (nmp->nm_sotype == SOCK_DGRAM)
3259 TAILQ_INIT(&nmp->nm_cwndq);
3260
3261 /*
3262 * Get the root node/attributes from the NFS server and
3263 * do any basic, version-specific setup.
3264 */
3265 error = nmp->nm_funcs->nf_mount(nmp, ctx, &np);
3266 nfsmerr_if(error);
3267
3268 /*
3269 * A reference count is needed on the node representing the
3270 * remote root. If this object is not persistent, then backward
3271 * traversals of the mount point (i.e. "..") will not work if
3272 * the node gets flushed out of the cache.
3273 */
3274 nmp->nm_dnp = np;
3275 *vpp = NFSTOV(np);
3276 /* get usecount and drop iocount */
3277 error = vnode_ref(*vpp);
3278 vnode_put(*vpp);
3279 if (error) {
3280 vnode_recycle(*vpp);
3281 goto nfsmerr;
3282 }
3283
3284 /*
3285 * Do statfs to ensure static info gets set to reasonable values.
3286 */
3287 if ((error = nmp->nm_funcs->nf_update_statfs(nmp, ctx))) {
3288 int error2 = vnode_getwithref(*vpp);
3289 vnode_rele(*vpp);
3290 if (!error2)
3291 vnode_put(*vpp);
3292 vnode_recycle(*vpp);
3293 goto nfsmerr;
3294 }
3295 sbp = vfs_statfs(mp);
3296 sbp->f_bsize = nmp->nm_fsattr.nfsa_bsize;
3297 sbp->f_blocks = nmp->nm_fsattr.nfsa_space_total / sbp->f_bsize;
3298 sbp->f_bfree = nmp->nm_fsattr.nfsa_space_free / sbp->f_bsize;
3299 sbp->f_bavail = nmp->nm_fsattr.nfsa_space_avail / sbp->f_bsize;
3300 sbp->f_bused = (nmp->nm_fsattr.nfsa_space_total / sbp->f_bsize) -
3301 (nmp->nm_fsattr.nfsa_space_free / sbp->f_bsize);
3302 sbp->f_files = nmp->nm_fsattr.nfsa_files_total;
3303 sbp->f_ffree = nmp->nm_fsattr.nfsa_files_free;
3304 sbp->f_iosize = nfs_iosize;
3305
3306 /*
3307 * Calculate the size used for I/O buffers. Use the larger
3308 * of the two sizes to minimise NFS requests but make sure
3309 * that it is at least one VM page to avoid wasting buffer
3310 * space and to allow easy mmapping of I/O buffers.
3311 * The read/write RPC calls handle the splitting up of
3312 * buffers into multiple requests if the buffer size is
3313 * larger than the I/O size.
3314 */
3315 iosize = max(nmp->nm_rsize, nmp->nm_wsize);
3316 if (iosize < PAGE_SIZE)
3317 iosize = PAGE_SIZE;
3318 nmp->nm_biosize = trunc_page_32(iosize);
3319
3320 /* For NFSv3 and greater, there is a (relatively) reliable ACCESS call. */
3321 if (nmp->nm_vers > NFS_VER2)
3322 vfs_setauthopaqueaccess(mp);
3323
3324 switch (nmp->nm_lockmode) {
3325 case NFS_LOCK_MODE_DISABLED:
3326 break;
3327 case NFS_LOCK_MODE_LOCAL:
3328 vfs_setlocklocal(nmp->nm_mountp);
3329 break;
3330 case NFS_LOCK_MODE_ENABLED:
3331 default:
3332 if (nmp->nm_vers <= NFS_VER3)
3333 nfs_lockd_mount_register(nmp);
3334 break;
3335 }
3336
3337 /* success! */
3338 lck_mtx_lock(&nmp->nm_lock);
3339 nmp->nm_state |= NFSSTA_MOUNTED;
3340 lck_mtx_unlock(&nmp->nm_lock);
3341 return (0);
3342 nfsmerr:
3343 nfs_mount_drain_and_cleanup(nmp);
3344 return (error);
3345 }
3346
3347 #if CONFIG_TRIGGERS
3348
3349 /*
3350 * We've detected a file system boundary on the server and
3351 * need to mount a new file system so that our file systems
3352 * MIRROR the file systems on the server.
3353 *
3354 * Build the mount arguments for the new mount and call kernel_mount().
3355 */
3356 int
3357 nfs_mirror_mount_domount(vnode_t dvp, vnode_t vp, vfs_context_t ctx)
3358 {
3359 nfsnode_t np = VTONFS(vp);
3360 nfsnode_t dnp = VTONFS(dvp);
3361 struct nfsmount *nmp = NFSTONMP(np);
3362 char fstype[MFSTYPENAMELEN], *mntfromname = NULL, *path = NULL, *relpath, *p, *cp;
3363 int error = 0, pathbuflen = MAXPATHLEN, i, mntflags = 0, referral, skipcopy = 0;
3364 size_t nlen;
3365 struct xdrbuf xb, xbnew;
3366 uint32_t mattrs[NFS_MATTR_BITMAP_LEN];
3367 uint32_t newmattrs[NFS_MATTR_BITMAP_LEN];
3368 uint32_t newmflags[NFS_MFLAG_BITMAP_LEN];
3369 uint32_t newmflags_mask[NFS_MFLAG_BITMAP_LEN];
3370 uint32_t argslength = 0, val, count, mlen, mlen2, rlen, relpathcomps;
3371 uint32_t argslength_offset, attrslength_offset, end_offset;
3372 uint32_t numlocs, loc, numserv, serv, numaddr, addr, numcomp, comp;
3373 char buf[XDRWORD];
3374 struct nfs_fs_locations nfsls;
3375
3376 referral = (np->n_vattr.nva_flags & NFS_FFLAG_TRIGGER_REFERRAL);
3377 if (referral)
3378 bzero(&nfsls, sizeof(nfsls));
3379
3380 xb_init(&xbnew, 0);
3381
3382 if (!nmp || (nmp->nm_state & (NFSSTA_FORCE|NFSSTA_DEAD)))
3383 return (ENXIO);
3384
3385 /* allocate a couple path buffers we need */
3386 MALLOC_ZONE(mntfromname, char *, pathbuflen, M_NAMEI, M_WAITOK);
3387 if (!mntfromname) {
3388 error = ENOMEM;
3389 goto nfsmerr;
3390 }
3391 MALLOC_ZONE(path, char *, pathbuflen, M_NAMEI, M_WAITOK);
3392 if (!path) {
3393 error = ENOMEM;
3394 goto nfsmerr;
3395 }
3396
3397 /* get the path for the directory being mounted on */
3398 error = vn_getpath(vp, path, &pathbuflen);
3399 if (error) {
3400 error = ENOMEM;
3401 goto nfsmerr;
3402 }
3403
3404 /*
3405 * Set up the mntfromname for the new mount based on the
3406 * current mount's mntfromname and the directory's path
3407 * relative to the current mount's mntonname.
3408 * Set up relpath to point at the relative path on the current mount.
3409 * Also, count the number of components in relpath.
3410 * We'll be adding those to each fs location path in the new args.
3411 */
3412 nlen = strlcpy(mntfromname, vfs_statfs(nmp->nm_mountp)->f_mntfromname, MAXPATHLEN);
3413 if ((nlen > 0) && (mntfromname[nlen-1] == '/')) { /* avoid double '/' in new name */
3414 mntfromname[nlen-1] = '\0';
3415 nlen--;
3416 }
3417 relpath = mntfromname + nlen;
3418 nlen = strlcat(mntfromname, path + strlen(vfs_statfs(nmp->nm_mountp)->f_mntonname), MAXPATHLEN);
3419 if (nlen >= MAXPATHLEN) {
3420 error = ENAMETOOLONG;
3421 goto nfsmerr;
3422 }
3423 /* count the number of components in relpath */
3424 p = relpath;
3425 while (*p && (*p == '/'))
3426 p++;
3427 relpathcomps = 0;
3428 while (*p) {
3429 relpathcomps++;
3430 while (*p && (*p != '/'))
3431 p++;
3432 while (*p && (*p == '/'))
3433 p++;
3434 }
3435
3436 /* grab a copy of the file system type */
3437 vfs_name(vnode_mount(vp), fstype);
3438
3439 /* for referrals, fetch the fs locations */
3440 if (referral) {
3441 const char *vname = vnode_getname(NFSTOV(np));
3442 if (!vname) {
3443 error = ENOENT;
3444 } else {
3445 error = nfs4_get_fs_locations(nmp, dnp, NULL, 0, vname, ctx, &nfsls);
3446 vnode_putname(vname);
3447 if (!error && (nfsls.nl_numlocs < 1))
3448 error = ENOENT;
3449 }
3450 nfsmerr_if(error);
3451 }
3452
3453 /* set up NFS mount args based on current mount args */
3454
3455 #define xb_copy_32(E, XBSRC, XBDST, V) \
3456 do { \
3457 if (E) break; \
3458 xb_get_32((E), (XBSRC), (V)); \
3459 if (skipcopy) break; \
3460 xb_add_32((E), (XBDST), (V)); \
3461 } while (0)
3462 #define xb_copy_opaque(E, XBSRC, XBDST) \
3463 do { \
3464 uint32_t __count, __val; \
3465 xb_copy_32((E), (XBSRC), (XBDST), __count); \
3466 if (E) break; \
3467 __count = nfsm_rndup(__count); \
3468 __count /= XDRWORD; \
3469 while (__count-- > 0) \
3470 xb_copy_32((E), (XBSRC), (XBDST), __val); \
3471 } while (0)
3472
3473 xb_init_buffer(&xb, nmp->nm_args, 2*XDRWORD);
3474 xb_get_32(error, &xb, val); /* version */
3475 xb_get_32(error, &xb, argslength); /* args length */
3476 xb_init_buffer(&xb, nmp->nm_args, argslength);
3477
3478 xb_init_buffer(&xbnew, NULL, 0);
3479 xb_copy_32(error, &xb, &xbnew, val); /* version */
3480 argslength_offset = xb_offset(&xbnew);
3481 xb_copy_32(error, &xb, &xbnew, val); /* args length */
3482 xb_copy_32(error, &xb, &xbnew, val); /* XDR args version */
3483 count = NFS_MATTR_BITMAP_LEN;
3484 xb_get_bitmap(error, &xb, mattrs, count); /* mount attribute bitmap */
3485 nfsmerr_if(error);
3486 for (i = 0; i < NFS_MATTR_BITMAP_LEN; i++)
3487 newmattrs[i] = mattrs[i];
3488 if (referral)
3489 NFS_BITMAP_SET(newmattrs, NFS_MATTR_FS_LOCATIONS);
3490 else
3491 NFS_BITMAP_SET(newmattrs, NFS_MATTR_FH);
3492 NFS_BITMAP_SET(newmattrs, NFS_MATTR_FLAGS);
3493 NFS_BITMAP_SET(newmattrs, NFS_MATTR_MNTFLAGS);
3494 NFS_BITMAP_CLR(newmattrs, NFS_MATTR_MNTFROM);
3495 xb_add_bitmap(error, &xbnew, newmattrs, NFS_MATTR_BITMAP_LEN);
3496 attrslength_offset = xb_offset(&xbnew);
3497 xb_copy_32(error, &xb, &xbnew, val); /* attrs length */
3498 NFS_BITMAP_ZERO(newmflags_mask, NFS_MFLAG_BITMAP_LEN);
3499 NFS_BITMAP_ZERO(newmflags, NFS_MFLAG_BITMAP_LEN);
3500 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_FLAGS)) {
3501 count = NFS_MFLAG_BITMAP_LEN;
3502 xb_get_bitmap(error, &xb, newmflags_mask, count); /* mount flag mask bitmap */
3503 count = NFS_MFLAG_BITMAP_LEN;
3504 xb_get_bitmap(error, &xb, newmflags, count); /* mount flag bitmap */
3505 }
3506 NFS_BITMAP_SET(newmflags_mask, NFS_MFLAG_EPHEMERAL);
3507 NFS_BITMAP_SET(newmflags, NFS_MFLAG_EPHEMERAL);
3508 xb_add_bitmap(error, &xbnew, newmflags_mask, NFS_MFLAG_BITMAP_LEN);
3509 xb_add_bitmap(error, &xbnew, newmflags, NFS_MFLAG_BITMAP_LEN);
3510 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_VERSION))
3511 xb_copy_32(error, &xb, &xbnew, val);
3512 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_MINOR_VERSION))
3513 xb_copy_32(error, &xb, &xbnew, val);
3514 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_VERSION_RANGE)) {
3515 xb_copy_32(error, &xb, &xbnew, val);
3516 xb_copy_32(error, &xb, &xbnew, val);
3517 }
3518 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READ_SIZE))
3519 xb_copy_32(error, &xb, &xbnew, val);
3520 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_WRITE_SIZE))
3521 xb_copy_32(error, &xb, &xbnew, val);
3522 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READDIR_SIZE))
3523 xb_copy_32(error, &xb, &xbnew, val);
3524 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_READAHEAD))
3525 xb_copy_32(error, &xb, &xbnew, val);
3526 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_REG_MIN)) {
3527 xb_copy_32(error, &xb, &xbnew, val);
3528 xb_copy_32(error, &xb, &xbnew, val);
3529 }
3530 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_REG_MAX)) {
3531 xb_copy_32(error, &xb, &xbnew, val);
3532 xb_copy_32(error, &xb, &xbnew, val);
3533 }
3534 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MIN)) {
3535 xb_copy_32(error, &xb, &xbnew, val);
3536 xb_copy_32(error, &xb, &xbnew, val);
3537 }
3538 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MAX)) {
3539 xb_copy_32(error, &xb, &xbnew, val);
3540 xb_copy_32(error, &xb, &xbnew, val);
3541 }
3542 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_LOCK_MODE))
3543 xb_copy_32(error, &xb, &xbnew, val);
3544 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SECURITY)) {
3545 xb_copy_32(error, &xb, &xbnew, count);
3546 while (!error && (count-- > 0))
3547 xb_copy_32(error, &xb, &xbnew, val);
3548 }
3549 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_KERB_ETYPE)) {
3550 xb_copy_32(error, &xb, &xbnew, count);
3551 xb_add_32(error, &xbnew, -1);
3552 while (!error && (count-- > 0))
3553 xb_copy_32(error, &xb, &xbnew, val);
3554 }
3555 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MAX_GROUP_LIST))
3556 xb_copy_32(error, &xb, &xbnew, val);
3557 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SOCKET_TYPE))
3558 xb_copy_opaque(error, &xb, &xbnew);
3559 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_NFS_PORT))
3560 xb_copy_32(error, &xb, &xbnew, val);
3561 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MOUNT_PORT))
3562 xb_copy_32(error, &xb, &xbnew, val);
3563 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_REQUEST_TIMEOUT)) {
3564 xb_copy_32(error, &xb, &xbnew, val);
3565 xb_copy_32(error, &xb, &xbnew, val);
3566 }
3567 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SOFT_RETRY_COUNT))
3568 xb_copy_32(error, &xb, &xbnew, val);
3569 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_DEAD_TIMEOUT)) {
3570 xb_copy_32(error, &xb, &xbnew, val);
3571 xb_copy_32(error, &xb, &xbnew, val);
3572 }
3573 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_FH)) {
3574 xb_get_32(error, &xb, count);
3575 xb_skip(error, &xb, count);
3576 }
3577 if (!referral) {
3578 /* set the initial file handle to the directory's file handle */
3579 xb_add_fh(error, &xbnew, np->n_fhp, np->n_fhsize);
3580 }
3581 /* copy/extend/skip fs locations */
3582 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_FS_LOCATIONS)) {
3583 numlocs = numserv = numaddr = numcomp = 0;
3584 if (referral) /* don't copy the fs locations for a referral */
3585 skipcopy = 1;
3586 xb_copy_32(error, &xb, &xbnew, numlocs); /* location count */
3587 for (loc = 0; !error && (loc < numlocs); loc++) {
3588 xb_copy_32(error, &xb, &xbnew, numserv); /* server count */
3589 for (serv = 0; !error && (serv < numserv); serv++) {
3590 xb_copy_opaque(error, &xb, &xbnew); /* server name */
3591 xb_copy_32(error, &xb, &xbnew, numaddr); /* address count */
3592 for (addr = 0; !error && (addr < numaddr); addr++)
3593 xb_copy_opaque(error, &xb, &xbnew); /* address */
3594 xb_copy_opaque(error, &xb, &xbnew); /* server info */
3595 }
3596 /* pathname */
3597 xb_get_32(error, &xb, numcomp); /* component count */
3598 if (!skipcopy)
3599 xb_add_32(error, &xbnew, numcomp+relpathcomps); /* new component count */
3600 for (comp = 0; !error && (comp < numcomp); comp++)
3601 xb_copy_opaque(error, &xb, &xbnew); /* component */
3602 /* add additional components */
3603 for (comp = 0; !skipcopy && !error && (comp < relpathcomps); comp++) {
3604 p = relpath;
3605 while (*p && (*p == '/'))
3606 p++;
3607 while (*p && !error) {
3608 cp = p;
3609 while (*p && (*p != '/'))
3610 p++;
3611 xb_add_string(error, &xbnew, cp, (p - cp)); /* component */
3612 while (*p && (*p == '/'))
3613 p++;
3614 }
3615 }
3616 xb_copy_opaque(error, &xb, &xbnew); /* fs location info */
3617 }
3618 if (referral)
3619 skipcopy = 0;
3620 }
3621 if (referral) {
3622 /* add referral's fs locations */
3623 xb_add_32(error, &xbnew, nfsls.nl_numlocs); /* FS_LOCATIONS */
3624 for (loc = 0; !error && (loc < nfsls.nl_numlocs); loc++) {
3625 xb_add_32(error, &xbnew, nfsls.nl_locations[loc]->nl_servcount);
3626 for (serv = 0; !error && (serv < nfsls.nl_locations[loc]->nl_servcount); serv++) {
3627 xb_add_string(error, &xbnew, nfsls.nl_locations[loc]->nl_servers[serv]->ns_name,
3628 strlen(nfsls.nl_locations[loc]->nl_servers[serv]->ns_name));
3629 xb_add_32(error, &xbnew, nfsls.nl_locations[loc]->nl_servers[serv]->ns_addrcount);
3630 for (addr = 0; !error && (addr < nfsls.nl_locations[loc]->nl_servers[serv]->ns_addrcount); addr++)
3631 xb_add_string(error, &xbnew, nfsls.nl_locations[loc]->nl_servers[serv]->ns_addresses[addr],
3632 strlen(nfsls.nl_locations[loc]->nl_servers[serv]->ns_addresses[addr]));
3633 xb_add_32(error, &xbnew, 0); /* empty server info */
3634 }
3635 xb_add_32(error, &xbnew, nfsls.nl_locations[loc]->nl_path.np_compcount);
3636 for (comp = 0; !error && (comp < nfsls.nl_locations[loc]->nl_path.np_compcount); comp++)
3637 xb_add_string(error, &xbnew, nfsls.nl_locations[loc]->nl_path.np_components[comp],
3638 strlen(nfsls.nl_locations[loc]->nl_path.np_components[comp]));
3639 xb_add_32(error, &xbnew, 0); /* empty fs location info */
3640 }
3641 }
3642 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MNTFLAGS))
3643 xb_get_32(error, &xb, mntflags);
3644 /*
3645 * We add the following mount flags to the ones for the mounted-on mount:
3646 * MNT_DONTBROWSE - to keep the mount from showing up as a separate volume
3647 * MNT_AUTOMOUNTED - to keep DiskArb from retriggering the mount after
3648 * an unmount (looking for /.autodiskmounted)
3649 */
3650 mntflags |= (MNT_AUTOMOUNTED | MNT_DONTBROWSE);
3651 xb_add_32(error, &xbnew, mntflags);
3652 if (!referral && NFS_BITMAP_ISSET(mattrs, NFS_MATTR_MNTFROM)) {
3653 /* copy mntfrom string and add relpath */
3654 rlen = strlen(relpath);
3655 xb_get_32(error, &xb, mlen);
3656 nfsmerr_if(error);
3657 mlen2 = mlen + ((relpath[0] != '/') ? 1 : 0) + rlen;
3658 xb_add_32(error, &xbnew, mlen2);
3659 count = mlen/XDRWORD;
3660 /* copy the original string */
3661 while (count-- > 0)
3662 xb_copy_32(error, &xb, &xbnew, val);
3663 if (!error && (mlen % XDRWORD)) {
3664 error = xb_get_bytes(&xb, buf, mlen%XDRWORD, 0);
3665 if (!error)
3666 error = xb_add_bytes(&xbnew, buf, mlen%XDRWORD, 1);
3667 }
3668 /* insert a '/' if the relative path doesn't start with one */
3669 if (!error && (relpath[0] != '/')) {
3670 buf[0] = '/';
3671 error = xb_add_bytes(&xbnew, buf, 1, 1);
3672 }
3673 /* add the additional relative path */
3674 if (!error)
3675 error = xb_add_bytes(&xbnew, relpath, rlen, 1);
3676 /* make sure the resulting string has the right number of pad bytes */
3677 if (!error && (mlen2 != nfsm_rndup(mlen2))) {
3678 bzero(buf, sizeof(buf));
3679 count = nfsm_rndup(mlen2) - mlen2;
3680 error = xb_add_bytes(&xbnew, buf, count, 1);
3681 }
3682 }
3683 xb_build_done(error, &xbnew);
3684
3685 /* update opaque counts */
3686 end_offset = xb_offset(&xbnew);
3687 if (!error) {
3688 error = xb_seek(&xbnew, argslength_offset);
3689 argslength = end_offset - argslength_offset + XDRWORD/*version*/;
3690 xb_add_32(error, &xbnew, argslength);
3691 }
3692 if (!error) {
3693 error = xb_seek(&xbnew, attrslength_offset);
3694 xb_add_32(error, &xbnew, end_offset - attrslength_offset - XDRWORD/*don't include length field*/);
3695 }
3696 nfsmerr_if(error);
3697
3698 /*
3699 * For kernel_mount() call, use the existing mount flags (instead of the
3700 * original flags) because flags like MNT_NOSUID and MNT_NODEV may have
3701 * been silently enforced.
3702 */
3703 mntflags = vnode_vfsvisflags(vp);
3704 mntflags |= (MNT_AUTOMOUNTED | MNT_DONTBROWSE);
3705
3706 /* do the mount */
3707 error = kernel_mount(fstype, dvp, vp, path, xb_buffer_base(&xbnew), argslength,
3708 mntflags, KERNEL_MOUNT_PERMIT_UNMOUNT | KERNEL_MOUNT_NOAUTH, ctx);
3709
3710 nfsmerr:
3711 if (error)
3712 printf("nfs: mirror mount of %s on %s failed (%d)\n",
3713 mntfromname, path, error);
3714 /* clean up */
3715 xb_cleanup(&xbnew);
3716 if (referral)
3717 nfs_fs_locations_cleanup(&nfsls);
3718 if (path)
3719 FREE_ZONE(path, MAXPATHLEN, M_NAMEI);
3720 if (mntfromname)
3721 FREE_ZONE(mntfromname, MAXPATHLEN, M_NAMEI);
3722 if (!error)
3723 nfs_ephemeral_mount_harvester_start();
3724 return (error);
3725 }
3726
3727 /*
3728 * trigger vnode functions
3729 */
3730
3731 resolver_result_t
3732 nfs_mirror_mount_trigger_resolve(
3733 vnode_t vp,
3734 const struct componentname *cnp,
3735 enum path_operation pop,
3736 __unused int flags,
3737 __unused void *data,
3738 vfs_context_t ctx)
3739 {
3740 nfsnode_t np = VTONFS(vp);
3741 vnode_t pvp = NULLVP;
3742 int error = 0;
3743 resolver_result_t result;
3744
3745 /*
3746 * We have a trigger node that doesn't have anything mounted on it yet.
3747 * We'll do the mount if either:
3748 * (a) this isn't the last component of the path OR
3749 * (b) this is an op that looks like it should trigger the mount.
3750 */
3751 if (cnp->cn_flags & ISLASTCN) {
3752 switch (pop) {
3753 case OP_MOUNT:
3754 case OP_UNMOUNT:
3755 case OP_STATFS:
3756 case OP_LINK:
3757 case OP_UNLINK:
3758 case OP_RENAME:
3759 case OP_MKNOD:
3760 case OP_MKFIFO:
3761 case OP_SYMLINK:
3762 case OP_ACCESS:
3763 case OP_GETATTR:
3764 case OP_MKDIR:
3765 case OP_RMDIR:
3766 case OP_REVOKE:
3767 case OP_GETXATTR:
3768 case OP_LISTXATTR:
3769 /* don't perform the mount for these operations */
3770 result = vfs_resolver_result(np->n_trigseq, RESOLVER_NOCHANGE, 0);
3771 #ifdef NFS_TRIGGER_DEBUG
3772 NP(np, "nfs trigger RESOLVE: no change, last %d nameiop %d, seq %d",
3773 (cnp->cn_flags & ISLASTCN) ? 1 : 0, cnp->cn_nameiop, np->n_trigseq);
3774 #endif
3775 return (result);
3776 case OP_OPEN:
3777 case OP_CHDIR:
3778 case OP_CHROOT:
3779 case OP_TRUNCATE:
3780 case OP_COPYFILE:
3781 case OP_PATHCONF:
3782 case OP_READLINK:
3783 case OP_SETATTR:
3784 case OP_EXCHANGEDATA:
3785 case OP_SEARCHFS:
3786 case OP_FSCTL:
3787 case OP_SETXATTR:
3788 case OP_REMOVEXATTR:
3789 default:
3790 /* go ahead and do the mount */
3791 break;
3792 }
3793 }
3794
3795 if (vnode_mountedhere(vp) != NULL) {
3796 /*
3797 * Um... there's already something mounted.
3798 * Been there. Done that. Let's just say it succeeded.
3799 */
3800 error = 0;
3801 goto skipmount;
3802 }
3803
3804 if ((error = nfs_node_set_busy(np, vfs_context_thread(ctx)))) {
3805 result = vfs_resolver_result(np->n_trigseq, RESOLVER_ERROR, error);
3806 #ifdef NFS_TRIGGER_DEBUG
3807 NP(np, "nfs trigger RESOLVE: busy error %d, last %d nameiop %d, seq %d",
3808 error, (cnp->cn_flags & ISLASTCN) ? 1 : 0, cnp->cn_nameiop, np->n_trigseq);
3809 #endif
3810 return (result);
3811 }
3812
3813 pvp = vnode_getparent(vp);
3814 if (pvp == NULLVP)
3815 error = EINVAL;
3816 if (!error)
3817 error = nfs_mirror_mount_domount(pvp, vp, ctx);
3818 skipmount:
3819 if (!error)
3820 np->n_trigseq++;
3821 result = vfs_resolver_result(np->n_trigseq, error ? RESOLVER_ERROR : RESOLVER_RESOLVED, error);
3822 #ifdef NFS_TRIGGER_DEBUG
3823 NP(np, "nfs trigger RESOLVE: %s %d, last %d nameiop %d, seq %d",
3824 error ? "error" : "resolved", error,
3825 (cnp->cn_flags & ISLASTCN) ? 1 : 0, cnp->cn_nameiop, np->n_trigseq);
3826 #endif
3827
3828 if (pvp != NULLVP)
3829 vnode_put(pvp);
3830 nfs_node_clear_busy(np);
3831 return (result);
3832 }
3833
3834 resolver_result_t
3835 nfs_mirror_mount_trigger_unresolve(
3836 vnode_t vp,
3837 int flags,
3838 __unused void *data,
3839 vfs_context_t ctx)
3840 {
3841 nfsnode_t np = VTONFS(vp);
3842 mount_t mp;
3843 int error;
3844 resolver_result_t result;
3845
3846 if ((error = nfs_node_set_busy(np, vfs_context_thread(ctx)))) {
3847 result = vfs_resolver_result(np->n_trigseq, RESOLVER_ERROR, error);
3848 #ifdef NFS_TRIGGER_DEBUG
3849 NP(np, "nfs trigger UNRESOLVE: busy error %d, seq %d", error, np->n_trigseq);
3850 #endif
3851 return (result);
3852 }
3853
3854 mp = vnode_mountedhere(vp);
3855 if (!mp)
3856 error = EINVAL;
3857 if (!error)
3858 error = vfs_unmountbyfsid(&(vfs_statfs(mp)->f_fsid), flags, ctx);
3859 if (!error)
3860 np->n_trigseq++;
3861 result = vfs_resolver_result(np->n_trigseq, error ? RESOLVER_ERROR : RESOLVER_UNRESOLVED, error);
3862 #ifdef NFS_TRIGGER_DEBUG
3863 NP(np, "nfs trigger UNRESOLVE: %s %d, seq %d",
3864 error ? "error" : "unresolved", error, np->n_trigseq);
3865 #endif
3866 nfs_node_clear_busy(np);
3867 return (result);
3868 }
3869
3870 resolver_result_t
3871 nfs_mirror_mount_trigger_rearm(
3872 vnode_t vp,
3873 __unused int flags,
3874 __unused void *data,
3875 vfs_context_t ctx)
3876 {
3877 nfsnode_t np = VTONFS(vp);
3878 int error;
3879 resolver_result_t result;
3880
3881 if ((error = nfs_node_set_busy(np, vfs_context_thread(ctx)))) {
3882 result = vfs_resolver_result(np->n_trigseq, RESOLVER_ERROR, error);
3883 #ifdef NFS_TRIGGER_DEBUG
3884 NP(np, "nfs trigger REARM: busy error %d, seq %d", error, np->n_trigseq);
3885 #endif
3886 return (result);
3887 }
3888
3889 np->n_trigseq++;
3890 result = vfs_resolver_result(np->n_trigseq,
3891 vnode_mountedhere(vp) ? RESOLVER_RESOLVED : RESOLVER_UNRESOLVED, 0);
3892 #ifdef NFS_TRIGGER_DEBUG
3893 NP(np, "nfs trigger REARM: %s, seq %d",
3894 vnode_mountedhere(vp) ? "resolved" : "unresolved", np->n_trigseq);
3895 #endif
3896 nfs_node_clear_busy(np);
3897 return (result);
3898 }
3899
3900 /*
3901 * Periodically attempt to unmount ephemeral (mirror) mounts in an attempt to limit
3902 * the number of unused mounts.
3903 */
3904
3905 #define NFS_EPHEMERAL_MOUNT_HARVEST_INTERVAL 120 /* how often the harvester runs */
3906 struct nfs_ephemeral_mount_harvester_info {
3907 fsid_t fsid; /* FSID that we need to try to unmount */
3908 uint32_t mountcount; /* count of ephemeral mounts seen in scan */
3909 };
3910 /* various globals for the harvester */
3911 static thread_call_t nfs_ephemeral_mount_harvester_timer = NULL;
3912 static int nfs_ephemeral_mount_harvester_on = 0;
3913
3914 kern_return_t thread_terminate(thread_t);
3915
3916 static int
3917 nfs_ephemeral_mount_harvester_callback(mount_t mp, void *arg)
3918 {
3919 struct nfs_ephemeral_mount_harvester_info *hinfo = arg;
3920 struct nfsmount *nmp;
3921 struct timeval now;
3922
3923 if (strcmp(mp->mnt_vfsstat.f_fstypename, "nfs"))
3924 return (VFS_RETURNED);
3925 nmp = VFSTONFS(mp);
3926 if (!nmp || !NMFLAG(nmp, EPHEMERAL))
3927 return (VFS_RETURNED);
3928 hinfo->mountcount++;
3929
3930 /* avoid unmounting mounts that have been triggered within the last harvest interval */
3931 microtime(&now);
3932 if ((nmp->nm_mounttime >> 32) > ((uint32_t)now.tv_sec - NFS_EPHEMERAL_MOUNT_HARVEST_INTERVAL))
3933 return (VFS_RETURNED);
3934
3935 if (hinfo->fsid.val[0] || hinfo->fsid.val[1]) {
3936 /* attempt to unmount previously-found ephemeral mount */
3937 vfs_unmountbyfsid(&hinfo->fsid, 0, vfs_context_kernel());
3938 hinfo->fsid.val[0] = hinfo->fsid.val[1] = 0;
3939 }
3940
3941 /*
3942 * We can't call unmount here since we hold a mount iter ref
3943 * on mp so save its fsid for the next call iteration to unmount.
3944 */
3945 hinfo->fsid.val[0] = mp->mnt_vfsstat.f_fsid.val[0];
3946 hinfo->fsid.val[1] = mp->mnt_vfsstat.f_fsid.val[1];
3947
3948 return (VFS_RETURNED);
3949 }
3950
3951 /*
3952 * Spawn a thread to do the ephemeral mount harvesting.
3953 */
3954 static void
3955 nfs_ephemeral_mount_harvester_timer_func(void)
3956 {
3957 thread_t thd;
3958
3959 if (kernel_thread_start(nfs_ephemeral_mount_harvester, NULL, &thd) == KERN_SUCCESS)
3960 thread_deallocate(thd);
3961 }
3962
3963 /*
3964 * Iterate all mounts looking for NFS ephemeral mounts to try to unmount.
3965 */
3966 void
3967 nfs_ephemeral_mount_harvester(__unused void *arg, __unused wait_result_t wr)
3968 {
3969 struct nfs_ephemeral_mount_harvester_info hinfo;
3970 uint64_t deadline;
3971
3972 hinfo.mountcount = 0;
3973 hinfo.fsid.val[0] = hinfo.fsid.val[1] = 0;
3974 vfs_iterate(VFS_ITERATE_TAIL_FIRST, nfs_ephemeral_mount_harvester_callback, &hinfo);
3975 if (hinfo.fsid.val[0] || hinfo.fsid.val[1]) {
3976 /* attempt to unmount last found ephemeral mount */
3977 vfs_unmountbyfsid(&hinfo.fsid, 0, vfs_context_kernel());
3978 }
3979
3980 lck_mtx_lock(nfs_global_mutex);
3981 if (!hinfo.mountcount) {
3982 /* no more ephemeral mounts - don't need timer */
3983 nfs_ephemeral_mount_harvester_on = 0;
3984 } else {
3985 /* re-arm the timer */
3986 clock_interval_to_deadline(NFS_EPHEMERAL_MOUNT_HARVEST_INTERVAL, NSEC_PER_SEC, &deadline);
3987 thread_call_enter_delayed(nfs_ephemeral_mount_harvester_timer, deadline);
3988 nfs_ephemeral_mount_harvester_on = 1;
3989 }
3990 lck_mtx_unlock(nfs_global_mutex);
3991
3992 /* thread done */
3993 thread_terminate(current_thread());
3994 }
3995
3996 /*
3997 * Make sure the NFS ephemeral mount harvester timer is running.
3998 */
3999 void
4000 nfs_ephemeral_mount_harvester_start(void)
4001 {
4002 uint64_t deadline;
4003
4004 lck_mtx_lock(nfs_global_mutex);
4005 if (nfs_ephemeral_mount_harvester_on) {
4006 lck_mtx_unlock(nfs_global_mutex);
4007 return;
4008 }
4009 if (nfs_ephemeral_mount_harvester_timer == NULL)
4010 nfs_ephemeral_mount_harvester_timer = thread_call_allocate((thread_call_func_t)nfs_ephemeral_mount_harvester_timer_func, NULL);
4011 clock_interval_to_deadline(NFS_EPHEMERAL_MOUNT_HARVEST_INTERVAL, NSEC_PER_SEC, &deadline);
4012 thread_call_enter_delayed(nfs_ephemeral_mount_harvester_timer, deadline);
4013 nfs_ephemeral_mount_harvester_on = 1;
4014 lck_mtx_unlock(nfs_global_mutex);
4015 }
4016
4017 #endif
4018
4019 /*
4020 * Send a MOUNT protocol MOUNT request to the server to get the initial file handle (and security).
4021 */
4022 int
4023 nfs3_mount_rpc(struct nfsmount *nmp, struct sockaddr *sa, int sotype, int nfsvers, char *path, vfs_context_t ctx, int timeo, fhandle_t *fh, struct nfs_sec *sec)
4024 {
4025 int error = 0, slen, mntproto;
4026 thread_t thd = vfs_context_thread(ctx);
4027 kauth_cred_t cred = vfs_context_ucred(ctx);
4028 uint64_t xid = 0;
4029 struct nfsm_chain nmreq, nmrep;
4030 mbuf_t mreq;
4031 uint32_t mntvers, mntport, val;
4032 struct sockaddr_storage ss;
4033 struct sockaddr *saddr = (struct sockaddr*)&ss;
4034
4035 nfsm_chain_null(&nmreq);
4036 nfsm_chain_null(&nmrep);
4037
4038 mntvers = (nfsvers == NFS_VER2) ? RPCMNT_VER1 : RPCMNT_VER3;
4039 mntproto = (NM_OMFLAG(nmp, MNTUDP) || (sotype == SOCK_DGRAM)) ? IPPROTO_UDP : IPPROTO_TCP;
4040 sec->count = 0;
4041
4042 bcopy(sa, saddr, min(sizeof(ss), sa->sa_len));
4043 if (saddr->sa_family == AF_INET) {
4044 if (nmp->nm_mountport)
4045 ((struct sockaddr_in*)saddr)->sin_port = htons(nmp->nm_mountport);
4046 mntport = ntohs(((struct sockaddr_in*)saddr)->sin_port);
4047 } else {
4048 if (nmp->nm_mountport)
4049 ((struct sockaddr_in6*)saddr)->sin6_port = htons(nmp->nm_mountport);
4050 mntport = ntohs(((struct sockaddr_in6*)saddr)->sin6_port);
4051 }
4052
4053 while (!mntport) {
4054 error = nfs_portmap_lookup(nmp, ctx, saddr, NULL, RPCPROG_MNT, mntvers, mntproto, timeo);
4055 nfsmout_if(error);
4056 if (saddr->sa_family == AF_INET)
4057 mntport = ntohs(((struct sockaddr_in*)saddr)->sin_port);
4058 else
4059 mntport = ntohs(((struct sockaddr_in6*)saddr)->sin6_port);
4060 if (!mntport) {
4061 /* if not found and TCP, then retry with UDP */
4062 if (mntproto == IPPROTO_UDP) {
4063 error = EPROGUNAVAIL;
4064 break;
4065 }
4066 mntproto = IPPROTO_UDP;
4067 bcopy(sa, saddr, min(sizeof(ss), sa->sa_len));
4068 }
4069 }
4070 nfsmout_if(error || !mntport);
4071
4072 /* MOUNT protocol MOUNT request */
4073 slen = strlen(path);
4074 nfsm_chain_build_alloc_init(error, &nmreq, NFSX_UNSIGNED + nfsm_rndup(slen));
4075 nfsm_chain_add_name(error, &nmreq, path, slen, nmp);
4076 nfsm_chain_build_done(error, &nmreq);
4077 nfsmout_if(error);
4078 error = nfsm_rpchead2(nmp, (mntproto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM,
4079 RPCPROG_MNT, mntvers, RPCMNT_MOUNT,
4080 RPCAUTH_SYS, cred, NULL, nmreq.nmc_mhead, &xid, &mreq);
4081 nfsmout_if(error);
4082 nmreq.nmc_mhead = NULL;
4083 error = nfs_aux_request(nmp, thd, saddr, NULL,
4084 ((mntproto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM),
4085 mreq, R_XID32(xid), 1, timeo, &nmrep);
4086 nfsmout_if(error);
4087 nfsm_chain_get_32(error, &nmrep, val);
4088 if (!error && val)
4089 error = val;
4090 nfsm_chain_get_fh(error, &nmrep, nfsvers, fh);
4091 if (!error && (nfsvers > NFS_VER2)) {
4092 sec->count = NX_MAX_SEC_FLAVORS;
4093 error = nfsm_chain_get_secinfo(&nmrep, &sec->flavors[0], &sec->count);
4094 }
4095 nfsmout:
4096 nfsm_chain_cleanup(&nmreq);
4097 nfsm_chain_cleanup(&nmrep);
4098 return (error);
4099 }
4100
4101
4102 /*
4103 * Send a MOUNT protocol UNMOUNT request to tell the server we've unmounted it.
4104 */
4105 void
4106 nfs3_umount_rpc(struct nfsmount *nmp, vfs_context_t ctx, int timeo)
4107 {
4108 int error = 0, slen, mntproto;
4109 thread_t thd = vfs_context_thread(ctx);
4110 kauth_cred_t cred = vfs_context_ucred(ctx);
4111 char *path;
4112 uint64_t xid = 0;
4113 struct nfsm_chain nmreq, nmrep;
4114 mbuf_t mreq;
4115 uint32_t mntvers, mntport;
4116 struct sockaddr_storage ss;
4117 struct sockaddr *saddr = (struct sockaddr*)&ss;
4118
4119 if (!nmp->nm_saddr)
4120 return;
4121
4122 nfsm_chain_null(&nmreq);
4123 nfsm_chain_null(&nmrep);
4124
4125 mntvers = (nmp->nm_vers == NFS_VER2) ? RPCMNT_VER1 : RPCMNT_VER3;
4126 mntproto = (NM_OMFLAG(nmp, MNTUDP) || (nmp->nm_sotype == SOCK_DGRAM)) ? IPPROTO_UDP : IPPROTO_TCP;
4127 mntport = nmp->nm_mountport;
4128
4129 bcopy(nmp->nm_saddr, saddr, min(sizeof(ss), nmp->nm_saddr->sa_len));
4130 if (saddr->sa_family == AF_INET)
4131 ((struct sockaddr_in*)saddr)->sin_port = htons(mntport);
4132 else
4133 ((struct sockaddr_in6*)saddr)->sin6_port = htons(mntport);
4134
4135 while (!mntport) {
4136 error = nfs_portmap_lookup(nmp, ctx, saddr, NULL, RPCPROG_MNT, mntvers, mntproto, timeo);
4137 nfsmout_if(error);
4138 if (saddr->sa_family == AF_INET)
4139 mntport = ntohs(((struct sockaddr_in*)saddr)->sin_port);
4140 else
4141 mntport = ntohs(((struct sockaddr_in6*)saddr)->sin6_port);
4142 /* if not found and mntvers > VER1, then retry with VER1 */
4143 if (!mntport) {
4144 if (mntvers > RPCMNT_VER1) {
4145 mntvers = RPCMNT_VER1;
4146 } else if (mntproto == IPPROTO_TCP) {
4147 mntproto = IPPROTO_UDP;
4148 mntvers = (nmp->nm_vers == NFS_VER2) ? RPCMNT_VER1 : RPCMNT_VER3;
4149 } else {
4150 break;
4151 }
4152 bcopy(nmp->nm_saddr, saddr, min(sizeof(ss), nmp->nm_saddr->sa_len));
4153 }
4154 }
4155 nfsmout_if(!mntport);
4156
4157 /* MOUNT protocol UNMOUNT request */
4158 path = &vfs_statfs(nmp->nm_mountp)->f_mntfromname[0];
4159 while (*path && (*path != '/'))
4160 path++;
4161 slen = strlen(path);
4162 nfsm_chain_build_alloc_init(error, &nmreq, NFSX_UNSIGNED + nfsm_rndup(slen));
4163 nfsm_chain_add_name(error, &nmreq, path, slen, nmp);
4164 nfsm_chain_build_done(error, &nmreq);
4165 nfsmout_if(error);
4166 error = nfsm_rpchead2(nmp, (mntproto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM,
4167 RPCPROG_MNT, RPCMNT_VER1, RPCMNT_UMOUNT,
4168 RPCAUTH_SYS, cred, NULL, nmreq.nmc_mhead, &xid, &mreq);
4169 nfsmout_if(error);
4170 nmreq.nmc_mhead = NULL;
4171 error = nfs_aux_request(nmp, thd, saddr, NULL,
4172 ((mntproto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM),
4173 mreq, R_XID32(xid), 1, timeo, &nmrep);
4174 nfsmout:
4175 nfsm_chain_cleanup(&nmreq);
4176 nfsm_chain_cleanup(&nmrep);
4177 }
4178
4179 /*
4180 * unmount system call
4181 */
4182 int
4183 nfs_vfs_unmount(
4184 mount_t mp,
4185 int mntflags,
4186 __unused vfs_context_t ctx)
4187 {
4188 struct nfsmount *nmp;
4189 vnode_t vp;
4190 int error, flags = 0;
4191 struct timespec ts = { 1, 0 };
4192
4193 nmp = VFSTONFS(mp);
4194 lck_mtx_lock(&nmp->nm_lock);
4195 /*
4196 * Set the flag indicating that an unmount attempt is in progress.
4197 */
4198 nmp->nm_state |= NFSSTA_UNMOUNTING;
4199 /*
4200 * During a force unmount we want to...
4201 * Mark that we are doing a force unmount.
4202 * Make the mountpoint soft.
4203 */
4204 if (mntflags & MNT_FORCE) {
4205 flags |= FORCECLOSE;
4206 nmp->nm_state |= NFSSTA_FORCE;
4207 NFS_BITMAP_SET(nmp->nm_flags, NFS_MFLAG_SOFT);
4208 }
4209 /*
4210 * Wait for any in-progress monitored node scan to complete.
4211 */
4212 while (nmp->nm_state & NFSSTA_MONITOR_SCAN)
4213 msleep(&nmp->nm_state, &nmp->nm_lock, PZERO-1, "nfswaitmonscan", &ts);
4214 /*
4215 * Goes something like this..
4216 * - Call vflush() to clear out vnodes for this file system,
4217 * except for the swap files. Deal with them in 2nd pass.
4218 * - Decrement reference on the vnode representing remote root.
4219 * - Clean up the NFS mount structure.
4220 */
4221 vp = NFSTOV(nmp->nm_dnp);
4222 lck_mtx_unlock(&nmp->nm_lock);
4223
4224 /*
4225 * vflush will check for busy vnodes on mountpoint.
4226 * Will do the right thing for MNT_FORCE. That is, we should
4227 * not get EBUSY back.
4228 */
4229 error = vflush(mp, vp, SKIPSWAP | flags);
4230 if (mntflags & MNT_FORCE) {
4231 error = vflush(mp, NULLVP, flags); /* locks vp in the process */
4232 } else {
4233 if (vnode_isinuse(vp, 1))
4234 error = EBUSY;
4235 else
4236 error = vflush(mp, vp, flags);
4237 }
4238 if (error) {
4239 lck_mtx_lock(&nmp->nm_lock);
4240 nmp->nm_state &= ~NFSSTA_UNMOUNTING;
4241 lck_mtx_unlock(&nmp->nm_lock);
4242 return (error);
4243 }
4244
4245 lck_mtx_lock(&nmp->nm_lock);
4246 nmp->nm_dnp = NULL;
4247 lck_mtx_unlock(&nmp->nm_lock);
4248
4249 /*
4250 * Release the root vnode reference held by mountnfs()
4251 */
4252 error = vnode_get(vp);
4253 vnode_rele(vp);
4254 if (!error)
4255 vnode_put(vp);
4256
4257 vflush(mp, NULLVP, FORCECLOSE);
4258
4259 /* Wait for all other references to be released and free the mount */
4260 nfs_mount_drain_and_cleanup(nmp);
4261
4262 return (0);
4263 }
4264
4265 /*
4266 * cleanup/destroy NFS fs locations structure
4267 */
4268 void
4269 nfs_fs_locations_cleanup(struct nfs_fs_locations *nfslsp)
4270 {
4271 struct nfs_fs_location *fsl;
4272 struct nfs_fs_server *fss;
4273 struct nfs_fs_path *fsp;
4274 uint32_t loc, serv, addr, comp;
4275
4276 /* free up fs locations */
4277 if (!nfslsp->nl_numlocs || !nfslsp->nl_locations)
4278 return;
4279
4280 for (loc = 0; loc < nfslsp->nl_numlocs; loc++) {
4281 fsl = nfslsp->nl_locations[loc];
4282 if (!fsl)
4283 continue;
4284 if ((fsl->nl_servcount > 0) && fsl->nl_servers) {
4285 for (serv = 0; serv < fsl->nl_servcount; serv++) {
4286 fss = fsl->nl_servers[serv];
4287 if (!fss)
4288 continue;
4289 if ((fss->ns_addrcount > 0) && fss->ns_addresses) {
4290 for (addr = 0; addr < fss->ns_addrcount; addr++)
4291 FREE(fss->ns_addresses[addr], M_TEMP);
4292 FREE(fss->ns_addresses, M_TEMP);
4293 }
4294 FREE(fss->ns_name, M_TEMP);
4295 FREE(fss, M_TEMP);
4296 }
4297 FREE(fsl->nl_servers, M_TEMP);
4298 }
4299 fsp = &fsl->nl_path;
4300 if (fsp->np_compcount && fsp->np_components) {
4301 for (comp = 0; comp < fsp->np_compcount; comp++)
4302 if (fsp->np_components[comp])
4303 FREE(fsp->np_components[comp], M_TEMP);
4304 FREE(fsp->np_components, M_TEMP);
4305 }
4306 FREE(fsl, M_TEMP);
4307 }
4308 FREE(nfslsp->nl_locations, M_TEMP);
4309 nfslsp->nl_numlocs = 0;
4310 nfslsp->nl_locations = NULL;
4311 }
4312
4313 void
4314 nfs_mount_rele(struct nfsmount *nmp)
4315 {
4316 int wup = 0;
4317
4318 lck_mtx_lock(&nmp->nm_lock);
4319 if (nmp->nm_ref < 1)
4320 panic("nfs zombie mount underflow\n");
4321 nmp->nm_ref--;
4322 if (nmp->nm_ref == 0)
4323 wup = nmp->nm_state & NFSSTA_MOUNT_DRAIN;
4324 lck_mtx_unlock(&nmp->nm_lock);
4325 if (wup)
4326 wakeup(&nmp->nm_ref);
4327 }
4328
4329 void
4330 nfs_mount_drain_and_cleanup(struct nfsmount *nmp)
4331 {
4332 lck_mtx_lock(&nmp->nm_lock);
4333 nmp->nm_state |= NFSSTA_MOUNT_DRAIN;
4334 while (nmp->nm_ref > 0) {
4335 msleep(&nmp->nm_ref, &nmp->nm_lock, PZERO-1, "nfs_mount_drain", NULL);
4336 }
4337 assert(nmp->nm_ref == 0);
4338 lck_mtx_unlock(&nmp->nm_lock);
4339 nfs_mount_cleanup(nmp);
4340 }
4341
4342 /*
4343 * nfs_mount_zombie
4344 */
4345 void
4346 nfs_mount_zombie(struct nfsmount *nmp, int nm_state_flags)
4347 {
4348 struct nfsreq *req, *treq;
4349 struct nfs_reqqhead iodq, resendq;
4350 struct timespec ts = { 1, 0 };
4351 struct nfs_open_owner *noop, *nextnoop;
4352 nfsnode_t np;
4353 int docallback;
4354
4355 lck_mtx_lock(&nmp->nm_lock);
4356 nmp->nm_state |= nm_state_flags;
4357 nmp->nm_ref++;
4358 lck_mtx_unlock(&nmp->nm_lock);
4359
4360 /* stop callbacks */
4361 if ((nmp->nm_vers >= NFS_VER4) && !NMFLAG(nmp, NOCALLBACK) && nmp->nm_cbid)
4362 nfs4_mount_callback_shutdown(nmp);
4363
4364 /* Destroy any RPCSEC_GSS contexts */
4365 nfs_gss_clnt_ctx_unmount(nmp);
4366
4367 /* mark the socket for termination */
4368 lck_mtx_lock(&nmp->nm_lock);
4369 nmp->nm_sockflags |= NMSOCK_UNMOUNT;
4370
4371 /* Have the socket thread send the unmount RPC, if requested/appropriate. */
4372 if ((nmp->nm_vers < NFS_VER4) && (nmp->nm_state & NFSSTA_MOUNTED) &&
4373 !(nmp->nm_state & (NFSSTA_FORCE|NFSSTA_DEAD)) && NMFLAG(nmp, CALLUMNT))
4374 nfs_mount_sock_thread_wake(nmp);
4375
4376 /* wait for the socket thread to terminate */
4377 while (nmp->nm_sockthd && current_thread() != nmp->nm_sockthd) {
4378 wakeup(&nmp->nm_sockthd);
4379 msleep(&nmp->nm_sockthd, &nmp->nm_lock, PZERO-1, "nfswaitsockthd", &ts);
4380 }
4381 lck_mtx_unlock(&nmp->nm_lock);
4382
4383 /* tear down the socket */
4384 nfs_disconnect(nmp);
4385
4386 lck_mtx_lock(&nmp->nm_lock);
4387
4388 if ((nmp->nm_vers >= NFS_VER4) && !NMFLAG(nmp, NOCALLBACK) && nmp->nm_cbid) {
4389 /* clear out any pending delegation return requests */
4390 while ((np = TAILQ_FIRST(&nmp->nm_dreturnq))) {
4391 TAILQ_REMOVE(&nmp->nm_dreturnq, np, n_dreturn);
4392 np->n_dreturn.tqe_next = NFSNOLIST;
4393 }
4394 }
4395
4396 /* cancel any renew timer */
4397 if ((nmp->nm_vers >= NFS_VER4) && nmp->nm_renew_timer) {
4398 thread_call_cancel(nmp->nm_renew_timer);
4399 thread_call_free(nmp->nm_renew_timer);
4400 }
4401
4402 lck_mtx_unlock(&nmp->nm_lock);
4403
4404 if (nmp->nm_state & NFSSTA_MOUNTED)
4405 switch (nmp->nm_lockmode) {
4406 case NFS_LOCK_MODE_DISABLED:
4407 case NFS_LOCK_MODE_LOCAL:
4408 break;
4409 case NFS_LOCK_MODE_ENABLED:
4410 default:
4411 if (nmp->nm_vers <= NFS_VER3) {
4412 nfs_lockd_mount_unregister(nmp);
4413 nmp->nm_lockmode = NFS_LOCK_MODE_DISABLED;
4414 }
4415 break;
4416 }
4417
4418 if ((nmp->nm_vers >= NFS_VER4) && nmp->nm_longid) {
4419 /* remove/deallocate the client ID data */
4420 lck_mtx_lock(nfs_global_mutex);
4421 TAILQ_REMOVE(&nfsclientids, nmp->nm_longid, nci_link);
4422 if (nmp->nm_longid->nci_id)
4423 FREE(nmp->nm_longid->nci_id, M_TEMP);
4424 FREE(nmp->nm_longid, M_TEMP);
4425 lck_mtx_unlock(nfs_global_mutex);
4426 }
4427
4428 /*
4429 * Be sure all requests for this mount are completed
4430 * and removed from the resend queue.
4431 */
4432 TAILQ_INIT(&resendq);
4433 lck_mtx_lock(nfs_request_mutex);
4434 TAILQ_FOREACH(req, &nfs_reqq, r_chain) {
4435 if (req->r_nmp == nmp) {
4436 lck_mtx_lock(&req->r_mtx);
4437 if (!req->r_error && req->r_nmrep.nmc_mhead == NULL)
4438 req->r_error = EIO;
4439 if (req->r_flags & R_RESENDQ) {
4440 lck_mtx_lock(&nmp->nm_lock);
4441 req->r_flags &= ~R_RESENDQ;
4442 if (req->r_rchain.tqe_next != NFSREQNOLIST) {
4443 TAILQ_REMOVE(&nmp->nm_resendq, req, r_rchain);
4444 /*
4445 * Queue up the request so that we can unreference them
4446 * with out holding nfs_request_mutex
4447 */
4448 TAILQ_INSERT_TAIL(&resendq, req, r_rchain);
4449 }
4450 lck_mtx_unlock(&nmp->nm_lock);
4451 }
4452 wakeup(req);
4453 lck_mtx_unlock(&req->r_mtx);
4454 }
4455 }
4456 lck_mtx_unlock(nfs_request_mutex);
4457
4458 /* Since we've drop the request mutex we can now safely unreference the request */
4459 TAILQ_FOREACH_SAFE(req, &resendq, r_rchain, treq) {
4460 TAILQ_REMOVE(&resendq, req, r_rchain);
4461 nfs_request_rele(req);
4462 }
4463
4464 /*
4465 * Now handle and outstanding async requests. We need to walk the
4466 * request queue again this time with the nfsiod_mutex held. No
4467 * other iods can grab our requests until we've put them on our own
4468 * local iod queue for processing.
4469 */
4470 TAILQ_INIT(&iodq);
4471 lck_mtx_lock(nfs_request_mutex);
4472 lck_mtx_lock(nfsiod_mutex);
4473 TAILQ_FOREACH(req, &nfs_reqq, r_chain) {
4474 if (req->r_nmp == nmp) {
4475 lck_mtx_lock(&req->r_mtx);
4476 if (req->r_callback.rcb_func
4477 && !(req->r_flags & R_WAITSENT) && !(req->r_flags & R_IOD)) {
4478 /*
4479 * Since R_IOD is not set then we need to handle it. If
4480 * we're not on a list add it to our iod queue. Otherwise
4481 * we must already be on nm_iodq which is added to our
4482 * local queue below.
4483 * %%% We should really keep a back pointer to our iod queue
4484 * that we're on.
4485 */
4486 req->r_flags |= R_IOD;
4487 if (req->r_achain.tqe_next == NFSREQNOLIST) {
4488 TAILQ_INSERT_TAIL(&iodq, req, r_achain);
4489 }
4490 }
4491 lck_mtx_unlock(&req->r_mtx);
4492 }
4493 }
4494
4495 /* finish any async I/O RPCs queued up */
4496 if (nmp->nm_iodlink.tqe_next != NFSNOLIST)
4497 TAILQ_REMOVE(&nfsiodmounts, nmp, nm_iodlink);
4498 TAILQ_CONCAT(&iodq, &nmp->nm_iodq, r_achain);
4499 lck_mtx_unlock(nfsiod_mutex);
4500 lck_mtx_unlock(nfs_request_mutex);
4501
4502 TAILQ_FOREACH_SAFE(req, &iodq, r_achain, treq) {
4503 TAILQ_REMOVE(&iodq, req, r_achain);
4504 req->r_achain.tqe_next = NFSREQNOLIST;
4505 lck_mtx_lock(&req->r_mtx);
4506 docallback = !(req->r_flags & R_WAITSENT);
4507 lck_mtx_unlock(&req->r_mtx);
4508 if (docallback)
4509 req->r_callback.rcb_func(req);
4510 }
4511
4512 /* clean up common state */
4513 lck_mtx_lock(&nmp->nm_lock);
4514 while ((np = LIST_FIRST(&nmp->nm_monlist))) {
4515 LIST_REMOVE(np, n_monlink);
4516 np->n_monlink.le_next = NFSNOLIST;
4517 }
4518 TAILQ_FOREACH_SAFE(noop, &nmp->nm_open_owners, noo_link, nextnoop) {
4519 TAILQ_REMOVE(&nmp->nm_open_owners, noop, noo_link);
4520 noop->noo_flags &= ~NFS_OPEN_OWNER_LINK;
4521 if (noop->noo_refcnt)
4522 continue;
4523 nfs_open_owner_destroy(noop);
4524 }
4525 lck_mtx_unlock(&nmp->nm_lock);
4526
4527 /* clean up NFSv4 state */
4528 if (nmp->nm_vers >= NFS_VER4) {
4529 lck_mtx_lock(&nmp->nm_lock);
4530 while ((np = TAILQ_FIRST(&nmp->nm_delegations))) {
4531 TAILQ_REMOVE(&nmp->nm_delegations, np, n_dlink);
4532 np->n_dlink.tqe_next = NFSNOLIST;
4533 }
4534 lck_mtx_unlock(&nmp->nm_lock);
4535 }
4536
4537 nfs_mount_rele(nmp);
4538 }
4539
4540 /*
4541 * cleanup/destroy an nfsmount
4542 */
4543 void
4544 nfs_mount_cleanup(struct nfsmount *nmp)
4545 {
4546 if (!nmp)
4547 return;
4548
4549 nfs_mount_zombie(nmp, 0);
4550
4551 NFS_VFS_DBG("Unmounting %s from %s\n",
4552 vfs_statfs(nmp->nm_mountp)->f_mntfromname,
4553 vfs_statfs(nmp->nm_mountp)->f_mntonname);
4554 NFS_VFS_DBG("nfs state = 0x%8.8x\n", nmp->nm_state);
4555 NFS_VFS_DBG("nfs socket flags = 0x%8.8x\n", nmp->nm_sockflags);
4556 NFS_VFS_DBG("nfs mount ref count is %d\n", nmp->nm_ref);
4557 NFS_VFS_DBG("mount ref count is %d\n", nmp->nm_mountp->mnt_count);
4558
4559 if (nmp->nm_mountp)
4560 vfs_setfsprivate(nmp->nm_mountp, NULL);
4561
4562 lck_mtx_lock(&nmp->nm_lock);
4563 if (nmp->nm_ref)
4564 panic("Some one has grabbed a ref %d state flags = 0x%8.8x\n", nmp->nm_ref, nmp->nm_state);
4565
4566 if (nmp->nm_saddr)
4567 FREE(nmp->nm_saddr, M_SONAME);
4568 if ((nmp->nm_vers < NFS_VER4) && nmp->nm_rqsaddr)
4569 FREE(nmp->nm_rqsaddr, M_SONAME);
4570
4571 if (IS_VALID_CRED(nmp->nm_mcred))
4572 kauth_cred_unref(&nmp->nm_mcred);
4573
4574 nfs_fs_locations_cleanup(&nmp->nm_locations);
4575
4576 if (nmp->nm_realm)
4577 FREE(nmp->nm_realm, M_TEMP);
4578 if (nmp->nm_principal)
4579 FREE(nmp->nm_principal, M_TEMP);
4580 if (nmp->nm_sprinc)
4581 FREE(nmp->nm_sprinc, M_TEMP);
4582
4583 if (nmp->nm_args)
4584 xb_free(nmp->nm_args);
4585
4586 lck_mtx_unlock(&nmp->nm_lock);
4587
4588 lck_mtx_destroy(&nmp->nm_lock, nfs_mount_grp);
4589 if (nmp->nm_fh)
4590 FREE(nmp->nm_fh, M_TEMP);
4591 FREE_ZONE((caddr_t)nmp, sizeof (struct nfsmount), M_NFSMNT);
4592 }
4593
4594 /*
4595 * Return root of a filesystem
4596 */
4597 int
4598 nfs_vfs_root(mount_t mp, vnode_t *vpp, __unused vfs_context_t ctx)
4599 {
4600 vnode_t vp;
4601 struct nfsmount *nmp;
4602 int error;
4603 u_int32_t vpid;
4604
4605 nmp = VFSTONFS(mp);
4606 if (!nmp || !nmp->nm_dnp)
4607 return (ENXIO);
4608 vp = NFSTOV(nmp->nm_dnp);
4609 vpid = vnode_vid(vp);
4610 while ((error = vnode_getwithvid(vp, vpid))) {
4611 /* vnode_get() may return ENOENT if the dir changes. */
4612 /* If that happens, just try it again, else return the error. */
4613 if ((error != ENOENT) || (vnode_vid(vp) == vpid))
4614 return (error);
4615 vpid = vnode_vid(vp);
4616 }
4617 *vpp = vp;
4618 return (0);
4619 }
4620
4621 /*
4622 * Do operations associated with quotas
4623 */
4624 #if !QUOTA
4625 int
4626 nfs_vfs_quotactl(
4627 __unused mount_t mp,
4628 __unused int cmds,
4629 __unused uid_t uid,
4630 __unused caddr_t datap,
4631 __unused vfs_context_t context)
4632 {
4633 return (ENOTSUP);
4634 }
4635 #else
4636
4637 int
4638 nfs3_getquota(struct nfsmount *nmp, vfs_context_t ctx, uid_t id, int type, struct dqblk *dqb)
4639 {
4640 int error = 0, slen, timeo;
4641 int rqport = 0, rqproto, rqvers = (type == GRPQUOTA) ? RPCRQUOTA_EXT_VER : RPCRQUOTA_VER;
4642 thread_t thd = vfs_context_thread(ctx);
4643 kauth_cred_t cred = vfs_context_ucred(ctx);
4644 char *path;
4645 uint64_t xid = 0;
4646 struct nfsm_chain nmreq, nmrep;
4647 mbuf_t mreq;
4648 uint32_t val = 0, bsize = 0;
4649 struct sockaddr *rqsaddr;
4650 struct timeval now;
4651
4652 if (!nmp->nm_saddr)
4653 return (ENXIO);
4654
4655 if (NMFLAG(nmp, NOQUOTA))
4656 return (ENOTSUP);
4657
4658 if (!nmp->nm_rqsaddr)
4659 MALLOC(nmp->nm_rqsaddr, struct sockaddr *, sizeof(struct sockaddr_storage), M_SONAME, M_WAITOK|M_ZERO);
4660 if (!nmp->nm_rqsaddr)
4661 return (ENOMEM);
4662 rqsaddr = nmp->nm_rqsaddr;
4663 if (rqsaddr->sa_family == AF_INET6)
4664 rqport = ntohs(((struct sockaddr_in6*)rqsaddr)->sin6_port);
4665 else if (rqsaddr->sa_family == AF_INET)
4666 rqport = ntohs(((struct sockaddr_in*)rqsaddr)->sin_port);
4667
4668 timeo = NMFLAG(nmp, SOFT) ? 10 : 60;
4669 rqproto = IPPROTO_UDP; /* XXX should prefer TCP if mount is TCP */
4670
4671 /* check if we have a recently cached rquota port */
4672 microuptime(&now);
4673 if (!rqport || ((nmp->nm_rqsaddrstamp + 60) >= (uint32_t)now.tv_sec)) {
4674 /* send portmap request to get rquota port */
4675 bcopy(nmp->nm_saddr, rqsaddr, min(sizeof(struct sockaddr_storage), nmp->nm_saddr->sa_len));
4676 error = nfs_portmap_lookup(nmp, ctx, rqsaddr, NULL, RPCPROG_RQUOTA, rqvers, rqproto, timeo);
4677 if (error)
4678 return (error);
4679 if (rqsaddr->sa_family == AF_INET6)
4680 rqport = ntohs(((struct sockaddr_in6*)rqsaddr)->sin6_port);
4681 else if (rqsaddr->sa_family == AF_INET)
4682 rqport = ntohs(((struct sockaddr_in*)rqsaddr)->sin_port);
4683 else
4684 return (EIO);
4685 if (!rqport)
4686 return (ENOTSUP);
4687 microuptime(&now);
4688 nmp->nm_rqsaddrstamp = now.tv_sec;
4689 }
4690
4691 /* rquota request */
4692 nfsm_chain_null(&nmreq);
4693 nfsm_chain_null(&nmrep);
4694 path = &vfs_statfs(nmp->nm_mountp)->f_mntfromname[0];
4695 while (*path && (*path != '/'))
4696 path++;
4697 slen = strlen(path);
4698 nfsm_chain_build_alloc_init(error, &nmreq, 3 * NFSX_UNSIGNED + nfsm_rndup(slen));
4699 nfsm_chain_add_name(error, &nmreq, path, slen, nmp);
4700 if (type == GRPQUOTA)
4701 nfsm_chain_add_32(error, &nmreq, type);
4702 nfsm_chain_add_32(error, &nmreq, id);
4703 nfsm_chain_build_done(error, &nmreq);
4704 nfsmout_if(error);
4705 error = nfsm_rpchead2(nmp, (rqproto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM,
4706 RPCPROG_RQUOTA, rqvers, RPCRQUOTA_GET,
4707 RPCAUTH_SYS, cred, NULL, nmreq.nmc_mhead, &xid, &mreq);
4708 nfsmout_if(error);
4709 nmreq.nmc_mhead = NULL;
4710 error = nfs_aux_request(nmp, thd, rqsaddr, NULL,
4711 (rqproto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM,
4712 mreq, R_XID32(xid), 0, timeo, &nmrep);
4713 nfsmout_if(error);
4714
4715 /* parse rquota response */
4716 nfsm_chain_get_32(error, &nmrep, val);
4717 if (!error && (val != RQUOTA_STAT_OK)) {
4718 if (val == RQUOTA_STAT_NOQUOTA)
4719 error = ENOENT;
4720 else if (val == RQUOTA_STAT_EPERM)
4721 error = EPERM;
4722 else
4723 error = EIO;
4724 }
4725 nfsm_chain_get_32(error, &nmrep, bsize);
4726 nfsm_chain_adv(error, &nmrep, NFSX_UNSIGNED);
4727 nfsm_chain_get_32(error, &nmrep, val);
4728 nfsmout_if(error);
4729 dqb->dqb_bhardlimit = (uint64_t)val * bsize;
4730 nfsm_chain_get_32(error, &nmrep, val);
4731 nfsmout_if(error);
4732 dqb->dqb_bsoftlimit = (uint64_t)val * bsize;
4733 nfsm_chain_get_32(error, &nmrep, val);
4734 nfsmout_if(error);
4735 dqb->dqb_curbytes = (uint64_t)val * bsize;
4736 nfsm_chain_get_32(error, &nmrep, dqb->dqb_ihardlimit);
4737 nfsm_chain_get_32(error, &nmrep, dqb->dqb_isoftlimit);
4738 nfsm_chain_get_32(error, &nmrep, dqb->dqb_curinodes);
4739 nfsm_chain_get_32(error, &nmrep, dqb->dqb_btime);
4740 nfsm_chain_get_32(error, &nmrep, dqb->dqb_itime);
4741 nfsmout_if(error);
4742 dqb->dqb_id = id;
4743 nfsmout:
4744 nfsm_chain_cleanup(&nmreq);
4745 nfsm_chain_cleanup(&nmrep);
4746 return (error);
4747 }
4748
4749 int
4750 nfs4_getquota(struct nfsmount *nmp, vfs_context_t ctx, uid_t id, int type, struct dqblk *dqb)
4751 {
4752 nfsnode_t np;
4753 int error = 0, status, nfsvers, numops;
4754 u_int64_t xid;
4755 struct nfsm_chain nmreq, nmrep;
4756 uint32_t bitmap[NFS_ATTR_BITMAP_LEN];
4757 thread_t thd = vfs_context_thread(ctx);
4758 kauth_cred_t cred = vfs_context_ucred(ctx);
4759 struct nfsreq_secinfo_args si;
4760
4761 if (type != USRQUOTA) /* NFSv4 only supports user quotas */
4762 return (ENOTSUP);
4763
4764 /* first check that the server supports any of the quota attributes */
4765 if (!NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_QUOTA_AVAIL_HARD) &&
4766 !NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_QUOTA_AVAIL_SOFT) &&
4767 !NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_QUOTA_USED))
4768 return (ENOTSUP);
4769
4770 /*
4771 * The credential passed to the server needs to have
4772 * an effective uid that matches the given uid.
4773 */
4774 if (id != kauth_cred_getuid(cred)) {
4775 struct posix_cred temp_pcred;
4776 posix_cred_t pcred = posix_cred_get(cred);
4777 bzero(&temp_pcred, sizeof(temp_pcred));
4778 temp_pcred.cr_uid = id;
4779 temp_pcred.cr_ngroups = pcred->cr_ngroups;
4780 bcopy(pcred->cr_groups, temp_pcred.cr_groups, sizeof(temp_pcred.cr_groups));
4781 cred = posix_cred_create(&temp_pcred);
4782 if (!IS_VALID_CRED(cred))
4783 return (ENOMEM);
4784 } else {
4785 kauth_cred_ref(cred);
4786 }
4787
4788 nfsvers = nmp->nm_vers;
4789 np = nmp->nm_dnp;
4790 if (!np)
4791 error = ENXIO;
4792 if (error || ((error = vnode_get(NFSTOV(np))))) {
4793 kauth_cred_unref(&cred);
4794 return(error);
4795 }
4796
4797 NFSREQ_SECINFO_SET(&si, np, NULL, 0, NULL, 0);
4798 nfsm_chain_null(&nmreq);
4799 nfsm_chain_null(&nmrep);
4800
4801 // PUTFH + GETATTR
4802 numops = 2;
4803 nfsm_chain_build_alloc_init(error, &nmreq, 15 * NFSX_UNSIGNED);
4804 nfsm_chain_add_compound_header(error, &nmreq, "quota", nmp->nm_minor_vers, numops);
4805 numops--;
4806 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTFH);
4807 nfsm_chain_add_fh(error, &nmreq, nfsvers, np->n_fhp, np->n_fhsize);
4808 numops--;
4809 nfsm_chain_add_32(error, &nmreq, NFS_OP_GETATTR);
4810 NFS_CLEAR_ATTRIBUTES(bitmap);
4811 NFS_BITMAP_SET(bitmap, NFS_FATTR_QUOTA_AVAIL_HARD);
4812 NFS_BITMAP_SET(bitmap, NFS_FATTR_QUOTA_AVAIL_SOFT);
4813 NFS_BITMAP_SET(bitmap, NFS_FATTR_QUOTA_USED);
4814 nfsm_chain_add_bitmap_supported(error, &nmreq, bitmap, nmp, NULL);
4815 nfsm_chain_build_done(error, &nmreq);
4816 nfsm_assert(error, (numops == 0), EPROTO);
4817 nfsmout_if(error);
4818 error = nfs_request2(np, NULL, &nmreq, NFSPROC4_COMPOUND, thd, cred, &si, 0, &nmrep, &xid, &status);
4819 nfsm_chain_skip_tag(error, &nmrep);
4820 nfsm_chain_get_32(error, &nmrep, numops);
4821 nfsm_chain_op_check(error, &nmrep, NFS_OP_PUTFH);
4822 nfsm_chain_op_check(error, &nmrep, NFS_OP_GETATTR);
4823 nfsm_assert(error, NFSTONMP(np), ENXIO);
4824 nfsmout_if(error);
4825 error = nfs4_parsefattr(&nmrep, NULL, NULL, NULL, dqb, NULL);
4826 nfsmout_if(error);
4827 nfsm_assert(error, NFSTONMP(np), ENXIO);
4828 nfsmout:
4829 nfsm_chain_cleanup(&nmreq);
4830 nfsm_chain_cleanup(&nmrep);
4831 vnode_put(NFSTOV(np));
4832 kauth_cred_unref(&cred);
4833 return (error);
4834 }
4835
4836 int
4837 nfs_vfs_quotactl(mount_t mp, int cmds, uid_t uid, caddr_t datap, vfs_context_t ctx)
4838 {
4839 struct nfsmount *nmp;
4840 int cmd, type, error, nfsvers;
4841 uid_t euid = kauth_cred_getuid(vfs_context_ucred(ctx));
4842 struct dqblk *dqb = (struct dqblk*)datap;
4843
4844 nmp = VFSTONFS(mp);
4845 if (nfs_mount_gone(nmp))
4846 return (ENXIO);
4847 nfsvers = nmp->nm_vers;
4848
4849 if (uid == ~0U)
4850 uid = euid;
4851
4852 /* we can only support Q_GETQUOTA */
4853 cmd = cmds >> SUBCMDSHIFT;
4854 switch (cmd) {
4855 case Q_GETQUOTA:
4856 break;
4857 case Q_QUOTAON:
4858 case Q_QUOTAOFF:
4859 case Q_SETQUOTA:
4860 case Q_SETUSE:
4861 case Q_SYNC:
4862 case Q_QUOTASTAT:
4863 return (ENOTSUP);
4864 default:
4865 return (EINVAL);
4866 }
4867
4868 type = cmds & SUBCMDMASK;
4869 if ((u_int)type >= MAXQUOTAS)
4870 return (EINVAL);
4871 if ((uid != euid) && ((error = vfs_context_suser(ctx))))
4872 return (error);
4873
4874 if (vfs_busy(mp, LK_NOWAIT))
4875 return (0);
4876 bzero(dqb, sizeof(*dqb));
4877 error = nmp->nm_funcs->nf_getquota(nmp, ctx, uid, type, dqb);
4878 vfs_unbusy(mp);
4879 return (error);
4880 }
4881 #endif
4882
4883 /*
4884 * Flush out the buffer cache
4885 */
4886 int nfs_sync_callout(vnode_t, void *);
4887
4888 struct nfs_sync_cargs {
4889 vfs_context_t ctx;
4890 int waitfor;
4891 int error;
4892 };
4893
4894 int
4895 nfs_sync_callout(vnode_t vp, void *arg)
4896 {
4897 struct nfs_sync_cargs *cargs = (struct nfs_sync_cargs*)arg;
4898 nfsnode_t np = VTONFS(vp);
4899 int error;
4900
4901 if (np->n_flag & NREVOKE) {
4902 vn_revoke(vp, REVOKEALL, cargs->ctx);
4903 return (VNODE_RETURNED);
4904 }
4905
4906 if (LIST_EMPTY(&np->n_dirtyblkhd))
4907 return (VNODE_RETURNED);
4908 if (np->n_wrbusy > 0)
4909 return (VNODE_RETURNED);
4910 if (np->n_bflag & (NBFLUSHINPROG|NBINVALINPROG))
4911 return (VNODE_RETURNED);
4912
4913 error = nfs_flush(np, cargs->waitfor, vfs_context_thread(cargs->ctx), 0);
4914 if (error)
4915 cargs->error = error;
4916
4917 return (VNODE_RETURNED);
4918 }
4919
4920 int
4921 nfs_vfs_sync(mount_t mp, int waitfor, vfs_context_t ctx)
4922 {
4923 struct nfs_sync_cargs cargs;
4924
4925 cargs.waitfor = waitfor;
4926 cargs.ctx = ctx;
4927 cargs.error = 0;
4928
4929 vnode_iterate(mp, 0, nfs_sync_callout, &cargs);
4930
4931 return (cargs.error);
4932 }
4933
4934 /*
4935 * NFS flat namespace lookup.
4936 * Currently unsupported.
4937 */
4938 /*ARGSUSED*/
4939 int
4940 nfs_vfs_vget(
4941 __unused mount_t mp,
4942 __unused ino64_t ino,
4943 __unused vnode_t *vpp,
4944 __unused vfs_context_t ctx)
4945 {
4946
4947 return (ENOTSUP);
4948 }
4949
4950 /*
4951 * At this point, this should never happen
4952 */
4953 /*ARGSUSED*/
4954 int
4955 nfs_vfs_fhtovp(
4956 __unused mount_t mp,
4957 __unused int fhlen,
4958 __unused unsigned char *fhp,
4959 __unused vnode_t *vpp,
4960 __unused vfs_context_t ctx)
4961 {
4962
4963 return (ENOTSUP);
4964 }
4965
4966 /*
4967 * Vnode pointer to File handle, should never happen either
4968 */
4969 /*ARGSUSED*/
4970 int
4971 nfs_vfs_vptofh(
4972 __unused vnode_t vp,
4973 __unused int *fhlenp,
4974 __unused unsigned char *fhp,
4975 __unused vfs_context_t ctx)
4976 {
4977
4978 return (ENOTSUP);
4979 }
4980
4981 /*
4982 * Vfs start routine, a no-op.
4983 */
4984 /*ARGSUSED*/
4985 int
4986 nfs_vfs_start(
4987 __unused mount_t mp,
4988 __unused int flags,
4989 __unused vfs_context_t ctx)
4990 {
4991
4992 return (0);
4993 }
4994
4995 /*
4996 * Build the mount info buffer for NFS_MOUNTINFO.
4997 */
4998 int
4999 nfs_mountinfo_assemble(struct nfsmount *nmp, struct xdrbuf *xb)
5000 {
5001 struct xdrbuf xbinfo, xborig;
5002 char sotype[6];
5003 uint32_t origargsvers, origargslength;
5004 uint32_t infolength_offset, curargsopaquelength_offset, curargslength_offset, attrslength_offset, curargs_end_offset, end_offset;
5005 uint32_t miattrs[NFS_MIATTR_BITMAP_LEN];
5006 uint32_t miflags_mask[NFS_MIFLAG_BITMAP_LEN];
5007 uint32_t miflags[NFS_MIFLAG_BITMAP_LEN];
5008 uint32_t mattrs[NFS_MATTR_BITMAP_LEN];
5009 uint32_t mflags_mask[NFS_MFLAG_BITMAP_LEN];
5010 uint32_t mflags[NFS_MFLAG_BITMAP_LEN];
5011 uint32_t loc, serv, addr, comp;
5012 int i, timeo, error = 0;
5013
5014 /* set up mount info attr and flag bitmaps */
5015 NFS_BITMAP_ZERO(miattrs, NFS_MIATTR_BITMAP_LEN);
5016 NFS_BITMAP_SET(miattrs, NFS_MIATTR_FLAGS);
5017 NFS_BITMAP_SET(miattrs, NFS_MIATTR_ORIG_ARGS);
5018 NFS_BITMAP_SET(miattrs, NFS_MIATTR_CUR_ARGS);
5019 NFS_BITMAP_SET(miattrs, NFS_MIATTR_CUR_LOC_INDEX);
5020 NFS_BITMAP_ZERO(miflags_mask, NFS_MIFLAG_BITMAP_LEN);
5021 NFS_BITMAP_ZERO(miflags, NFS_MIFLAG_BITMAP_LEN);
5022 NFS_BITMAP_SET(miflags_mask, NFS_MIFLAG_DEAD);
5023 NFS_BITMAP_SET(miflags_mask, NFS_MIFLAG_NOTRESP);
5024 NFS_BITMAP_SET(miflags_mask, NFS_MIFLAG_RECOVERY);
5025 if (nmp->nm_state & NFSSTA_DEAD)
5026 NFS_BITMAP_SET(miflags, NFS_MIFLAG_DEAD);
5027 if ((nmp->nm_state & (NFSSTA_TIMEO|NFSSTA_JUKEBOXTIMEO)) ||
5028 ((nmp->nm_state & NFSSTA_LOCKTIMEO) && (nmp->nm_lockmode == NFS_LOCK_MODE_ENABLED)))
5029 NFS_BITMAP_SET(miflags, NFS_MIFLAG_NOTRESP);
5030 if (nmp->nm_state & NFSSTA_RECOVER)
5031 NFS_BITMAP_SET(miflags, NFS_MIFLAG_RECOVERY);
5032
5033 /* get original mount args length */
5034 xb_init_buffer(&xborig, nmp->nm_args, 2*XDRWORD);
5035 xb_get_32(error, &xborig, origargsvers); /* version */
5036 xb_get_32(error, &xborig, origargslength); /* args length */
5037 nfsmerr_if(error);
5038
5039 /* set up current mount attributes bitmap */
5040 NFS_BITMAP_ZERO(mattrs, NFS_MATTR_BITMAP_LEN);
5041 NFS_BITMAP_SET(mattrs, NFS_MATTR_FLAGS);
5042 NFS_BITMAP_SET(mattrs, NFS_MATTR_NFS_VERSION);
5043 if (nmp->nm_vers >= NFS_VER4)
5044 NFS_BITMAP_SET(mattrs, NFS_MATTR_NFS_MINOR_VERSION);
5045 NFS_BITMAP_SET(mattrs, NFS_MATTR_READ_SIZE);
5046 NFS_BITMAP_SET(mattrs, NFS_MATTR_WRITE_SIZE);
5047 NFS_BITMAP_SET(mattrs, NFS_MATTR_READDIR_SIZE);
5048 NFS_BITMAP_SET(mattrs, NFS_MATTR_READAHEAD);
5049 NFS_BITMAP_SET(mattrs, NFS_MATTR_ATTRCACHE_REG_MIN);
5050 NFS_BITMAP_SET(mattrs, NFS_MATTR_ATTRCACHE_REG_MAX);
5051 NFS_BITMAP_SET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MIN);
5052 NFS_BITMAP_SET(mattrs, NFS_MATTR_ATTRCACHE_DIR_MAX);
5053 NFS_BITMAP_SET(mattrs, NFS_MATTR_LOCK_MODE);
5054 NFS_BITMAP_SET(mattrs, NFS_MATTR_SECURITY);
5055 if (nmp->nm_etype.selected < nmp->nm_etype.count)
5056 NFS_BITMAP_SET(mattrs, NFS_MATTR_KERB_ETYPE);
5057 NFS_BITMAP_SET(mattrs, NFS_MATTR_MAX_GROUP_LIST);
5058 NFS_BITMAP_SET(mattrs, NFS_MATTR_SOCKET_TYPE);
5059 NFS_BITMAP_SET(mattrs, NFS_MATTR_NFS_PORT);
5060 if ((nmp->nm_vers < NFS_VER4) && nmp->nm_mountport)
5061 NFS_BITMAP_SET(mattrs, NFS_MATTR_MOUNT_PORT);
5062 NFS_BITMAP_SET(mattrs, NFS_MATTR_REQUEST_TIMEOUT);
5063 if (NMFLAG(nmp, SOFT))
5064 NFS_BITMAP_SET(mattrs, NFS_MATTR_SOFT_RETRY_COUNT);
5065 if (nmp->nm_deadtimeout)
5066 NFS_BITMAP_SET(mattrs, NFS_MATTR_DEAD_TIMEOUT);
5067 if (nmp->nm_fh)
5068 NFS_BITMAP_SET(mattrs, NFS_MATTR_FH);
5069 NFS_BITMAP_SET(mattrs, NFS_MATTR_FS_LOCATIONS);
5070 NFS_BITMAP_SET(mattrs, NFS_MATTR_MNTFLAGS);
5071 if (origargsvers < NFS_ARGSVERSION_XDR)
5072 NFS_BITMAP_SET(mattrs, NFS_MATTR_MNTFROM);
5073 if (nmp->nm_realm)
5074 NFS_BITMAP_SET(mattrs, NFS_MATTR_REALM);
5075 if (nmp->nm_principal)
5076 NFS_BITMAP_SET(mattrs, NFS_MATTR_PRINCIPAL);
5077 if (nmp->nm_sprinc)
5078 NFS_BITMAP_SET(mattrs, NFS_MATTR_SVCPRINCIPAL);
5079
5080 /* set up current mount flags bitmap */
5081 /* first set the flags that we will be setting - either on OR off */
5082 NFS_BITMAP_ZERO(mflags_mask, NFS_MFLAG_BITMAP_LEN);
5083 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_SOFT);
5084 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_INTR);
5085 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_RESVPORT);
5086 if (nmp->nm_sotype == SOCK_DGRAM)
5087 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NOCONNECT);
5088 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_DUMBTIMER);
5089 if (nmp->nm_vers < NFS_VER4)
5090 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_CALLUMNT);
5091 if (nmp->nm_vers >= NFS_VER3)
5092 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_RDIRPLUS);
5093 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NONEGNAMECACHE);
5094 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_MUTEJUKEBOX);
5095 if (nmp->nm_vers >= NFS_VER4) {
5096 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_EPHEMERAL);
5097 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NOCALLBACK);
5098 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NONAMEDATTR);
5099 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NOACL);
5100 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_ACLONLY);
5101 }
5102 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NFC);
5103 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_NOQUOTA);
5104 if (nmp->nm_vers < NFS_VER4)
5105 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_MNTUDP);
5106 NFS_BITMAP_SET(mflags_mask, NFS_MFLAG_MNTQUICK);
5107 /* now set the flags that should be set */
5108 NFS_BITMAP_ZERO(mflags, NFS_MFLAG_BITMAP_LEN);
5109 if (NMFLAG(nmp, SOFT))
5110 NFS_BITMAP_SET(mflags, NFS_MFLAG_SOFT);
5111 if (NMFLAG(nmp, INTR))
5112 NFS_BITMAP_SET(mflags, NFS_MFLAG_INTR);
5113 if (NMFLAG(nmp, RESVPORT))
5114 NFS_BITMAP_SET(mflags, NFS_MFLAG_RESVPORT);
5115 if ((nmp->nm_sotype == SOCK_DGRAM) && NMFLAG(nmp, NOCONNECT))
5116 NFS_BITMAP_SET(mflags, NFS_MFLAG_NOCONNECT);
5117 if (NMFLAG(nmp, DUMBTIMER))
5118 NFS_BITMAP_SET(mflags, NFS_MFLAG_DUMBTIMER);
5119 if ((nmp->nm_vers < NFS_VER4) && NMFLAG(nmp, CALLUMNT))
5120 NFS_BITMAP_SET(mflags, NFS_MFLAG_CALLUMNT);
5121 if ((nmp->nm_vers >= NFS_VER3) && NMFLAG(nmp, RDIRPLUS))
5122 NFS_BITMAP_SET(mflags, NFS_MFLAG_RDIRPLUS);
5123 if (NMFLAG(nmp, NONEGNAMECACHE))
5124 NFS_BITMAP_SET(mflags, NFS_MFLAG_NONEGNAMECACHE);
5125 if (NMFLAG(nmp, MUTEJUKEBOX))
5126 NFS_BITMAP_SET(mflags, NFS_MFLAG_MUTEJUKEBOX);
5127 if (nmp->nm_vers >= NFS_VER4) {
5128 if (NMFLAG(nmp, EPHEMERAL))
5129 NFS_BITMAP_SET(mflags, NFS_MFLAG_EPHEMERAL);
5130 if (NMFLAG(nmp, NOCALLBACK))
5131 NFS_BITMAP_SET(mflags, NFS_MFLAG_NOCALLBACK);
5132 if (NMFLAG(nmp, NONAMEDATTR))
5133 NFS_BITMAP_SET(mflags, NFS_MFLAG_NONAMEDATTR);
5134 if (NMFLAG(nmp, NOACL))
5135 NFS_BITMAP_SET(mflags, NFS_MFLAG_NOACL);
5136 if (NMFLAG(nmp, ACLONLY))
5137 NFS_BITMAP_SET(mflags, NFS_MFLAG_ACLONLY);
5138 }
5139 if (NMFLAG(nmp, NFC))
5140 NFS_BITMAP_SET(mflags, NFS_MFLAG_NFC);
5141 if (NMFLAG(nmp, NOQUOTA) || ((nmp->nm_vers >= NFS_VER4) &&
5142 !NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_QUOTA_AVAIL_HARD) &&
5143 !NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_QUOTA_AVAIL_SOFT) &&
5144 !NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_QUOTA_USED)))
5145 NFS_BITMAP_SET(mflags, NFS_MFLAG_NOQUOTA);
5146 if ((nmp->nm_vers < NFS_VER4) && NMFLAG(nmp, MNTUDP))
5147 NFS_BITMAP_SET(mflags, NFS_MFLAG_MNTUDP);
5148 if (NMFLAG(nmp, MNTQUICK))
5149 NFS_BITMAP_SET(mflags, NFS_MFLAG_MNTQUICK);
5150
5151 /* assemble info buffer: */
5152 xb_init_buffer(&xbinfo, NULL, 0);
5153 xb_add_32(error, &xbinfo, NFS_MOUNT_INFO_VERSION);
5154 infolength_offset = xb_offset(&xbinfo);
5155 xb_add_32(error, &xbinfo, 0);
5156 xb_add_bitmap(error, &xbinfo, miattrs, NFS_MIATTR_BITMAP_LEN);
5157 xb_add_bitmap(error, &xbinfo, miflags, NFS_MIFLAG_BITMAP_LEN);
5158 xb_add_32(error, &xbinfo, origargslength);
5159 if (!error)
5160 error = xb_add_bytes(&xbinfo, nmp->nm_args, origargslength, 0);
5161
5162 /* the opaque byte count for the current mount args values: */
5163 curargsopaquelength_offset = xb_offset(&xbinfo);
5164 xb_add_32(error, &xbinfo, 0);
5165
5166 /* Encode current mount args values */
5167 xb_add_32(error, &xbinfo, NFS_ARGSVERSION_XDR);
5168 curargslength_offset = xb_offset(&xbinfo);
5169 xb_add_32(error, &xbinfo, 0);
5170 xb_add_32(error, &xbinfo, NFS_XDRARGS_VERSION_0);
5171 xb_add_bitmap(error, &xbinfo, mattrs, NFS_MATTR_BITMAP_LEN);
5172 attrslength_offset = xb_offset(&xbinfo);
5173 xb_add_32(error, &xbinfo, 0);
5174 xb_add_bitmap(error, &xbinfo, mflags_mask, NFS_MFLAG_BITMAP_LEN);
5175 xb_add_bitmap(error, &xbinfo, mflags, NFS_MFLAG_BITMAP_LEN);
5176 xb_add_32(error, &xbinfo, nmp->nm_vers); /* NFS_VERSION */
5177 if (nmp->nm_vers >= NFS_VER4)
5178 xb_add_32(error, &xbinfo, nmp->nm_minor_vers); /* NFS_MINOR_VERSION */
5179 xb_add_32(error, &xbinfo, nmp->nm_rsize); /* READ_SIZE */
5180 xb_add_32(error, &xbinfo, nmp->nm_wsize); /* WRITE_SIZE */
5181 xb_add_32(error, &xbinfo, nmp->nm_readdirsize); /* READDIR_SIZE */
5182 xb_add_32(error, &xbinfo, nmp->nm_readahead); /* READAHEAD */
5183 xb_add_32(error, &xbinfo, nmp->nm_acregmin); /* ATTRCACHE_REG_MIN */
5184 xb_add_32(error, &xbinfo, 0); /* ATTRCACHE_REG_MIN */
5185 xb_add_32(error, &xbinfo, nmp->nm_acregmax); /* ATTRCACHE_REG_MAX */
5186 xb_add_32(error, &xbinfo, 0); /* ATTRCACHE_REG_MAX */
5187 xb_add_32(error, &xbinfo, nmp->nm_acdirmin); /* ATTRCACHE_DIR_MIN */
5188 xb_add_32(error, &xbinfo, 0); /* ATTRCACHE_DIR_MIN */
5189 xb_add_32(error, &xbinfo, nmp->nm_acdirmax); /* ATTRCACHE_DIR_MAX */
5190 xb_add_32(error, &xbinfo, 0); /* ATTRCACHE_DIR_MAX */
5191 xb_add_32(error, &xbinfo, nmp->nm_lockmode); /* LOCK_MODE */
5192 if (nmp->nm_sec.count) {
5193 xb_add_32(error, &xbinfo, nmp->nm_sec.count); /* SECURITY */
5194 nfsmerr_if(error);
5195 for (i=0; i < nmp->nm_sec.count; i++)
5196 xb_add_32(error, &xbinfo, nmp->nm_sec.flavors[i]);
5197 } else if (nmp->nm_servsec.count) {
5198 xb_add_32(error, &xbinfo, nmp->nm_servsec.count); /* SECURITY */
5199 nfsmerr_if(error);
5200 for (i=0; i < nmp->nm_servsec.count; i++)
5201 xb_add_32(error, &xbinfo, nmp->nm_servsec.flavors[i]);
5202 } else {
5203 xb_add_32(error, &xbinfo, 1); /* SECURITY */
5204 xb_add_32(error, &xbinfo, nmp->nm_auth);
5205 }
5206 if (nmp->nm_etype.selected < nmp->nm_etype.count) {
5207 xb_add_32(error, &xbinfo, nmp->nm_etype.count);
5208 xb_add_32(error, &xbinfo, nmp->nm_etype.selected);
5209 for (uint32_t j=0; j < nmp->nm_etype.count; j++)
5210 xb_add_32(error, &xbinfo, nmp->nm_etype.etypes[j]);
5211 nfsmerr_if(error);
5212 }
5213 xb_add_32(error, &xbinfo, nmp->nm_numgrps); /* MAX_GROUP_LIST */
5214 nfsmerr_if(error);
5215 snprintf(sotype, sizeof(sotype), "%s%s", (nmp->nm_sotype == SOCK_DGRAM) ? "udp" : "tcp",
5216 nmp->nm_sofamily ? (nmp->nm_sofamily == AF_INET) ? "4" : "6" : "");
5217 xb_add_string(error, &xbinfo, sotype, strlen(sotype)); /* SOCKET_TYPE */
5218 xb_add_32(error, &xbinfo, ntohs(((struct sockaddr_in*)nmp->nm_saddr)->sin_port)); /* NFS_PORT */
5219 if ((nmp->nm_vers < NFS_VER4) && nmp->nm_mountport)
5220 xb_add_32(error, &xbinfo, nmp->nm_mountport); /* MOUNT_PORT */
5221 timeo = (nmp->nm_timeo * 10) / NFS_HZ;
5222 xb_add_32(error, &xbinfo, timeo/10); /* REQUEST_TIMEOUT */
5223 xb_add_32(error, &xbinfo, (timeo%10)*100000000); /* REQUEST_TIMEOUT */
5224 if (NMFLAG(nmp, SOFT))
5225 xb_add_32(error, &xbinfo, nmp->nm_retry); /* SOFT_RETRY_COUNT */
5226 if (nmp->nm_deadtimeout) {
5227 xb_add_32(error, &xbinfo, nmp->nm_deadtimeout); /* DEAD_TIMEOUT */
5228 xb_add_32(error, &xbinfo, 0); /* DEAD_TIMEOUT */
5229 }
5230 if (nmp->nm_fh)
5231 xb_add_fh(error, &xbinfo, &nmp->nm_fh->fh_data[0], nmp->nm_fh->fh_len); /* FH */
5232 xb_add_32(error, &xbinfo, nmp->nm_locations.nl_numlocs); /* FS_LOCATIONS */
5233 for (loc = 0; !error && (loc < nmp->nm_locations.nl_numlocs); loc++) {
5234 xb_add_32(error, &xbinfo, nmp->nm_locations.nl_locations[loc]->nl_servcount);
5235 for (serv = 0; !error && (serv < nmp->nm_locations.nl_locations[loc]->nl_servcount); serv++) {
5236 xb_add_string(error, &xbinfo, nmp->nm_locations.nl_locations[loc]->nl_servers[serv]->ns_name,
5237 strlen(nmp->nm_locations.nl_locations[loc]->nl_servers[serv]->ns_name));
5238 xb_add_32(error, &xbinfo, nmp->nm_locations.nl_locations[loc]->nl_servers[serv]->ns_addrcount);
5239 for (addr = 0; !error && (addr < nmp->nm_locations.nl_locations[loc]->nl_servers[serv]->ns_addrcount); addr++)
5240 xb_add_string(error, &xbinfo, nmp->nm_locations.nl_locations[loc]->nl_servers[serv]->ns_addresses[addr],
5241 strlen(nmp->nm_locations.nl_locations[loc]->nl_servers[serv]->ns_addresses[addr]));
5242 xb_add_32(error, &xbinfo, 0); /* empty server info */
5243 }
5244 xb_add_32(error, &xbinfo, nmp->nm_locations.nl_locations[loc]->nl_path.np_compcount);
5245 for (comp = 0; !error && (comp < nmp->nm_locations.nl_locations[loc]->nl_path.np_compcount); comp++)
5246 xb_add_string(error, &xbinfo, nmp->nm_locations.nl_locations[loc]->nl_path.np_components[comp],
5247 strlen(nmp->nm_locations.nl_locations[loc]->nl_path.np_components[comp]));
5248 xb_add_32(error, &xbinfo, 0); /* empty fs location info */
5249 }
5250 xb_add_32(error, &xbinfo, vfs_flags(nmp->nm_mountp)); /* MNTFLAGS */
5251 if (origargsvers < NFS_ARGSVERSION_XDR)
5252 xb_add_string(error, &xbinfo, vfs_statfs(nmp->nm_mountp)->f_mntfromname,
5253 strlen(vfs_statfs(nmp->nm_mountp)->f_mntfromname)); /* MNTFROM */
5254 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_REALM))
5255 xb_add_string(error, &xbinfo, nmp->nm_realm, strlen(nmp->nm_realm));
5256 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_PRINCIPAL))
5257 xb_add_string(error, &xbinfo, nmp->nm_principal, strlen(nmp->nm_principal));
5258 if (NFS_BITMAP_ISSET(mattrs, NFS_MATTR_SVCPRINCIPAL))
5259 xb_add_string(error, &xbinfo, nmp->nm_sprinc, strlen(nmp->nm_sprinc));
5260
5261 curargs_end_offset = xb_offset(&xbinfo);
5262
5263 /* NFS_MIATTR_CUR_LOC_INDEX */
5264 xb_add_32(error, &xbinfo, nmp->nm_locations.nl_current.nli_flags);
5265 xb_add_32(error, &xbinfo, nmp->nm_locations.nl_current.nli_loc);
5266 xb_add_32(error, &xbinfo, nmp->nm_locations.nl_current.nli_serv);
5267 xb_add_32(error, &xbinfo, nmp->nm_locations.nl_current.nli_addr);
5268
5269 xb_build_done(error, &xbinfo);
5270
5271 /* update opaque counts */
5272 end_offset = xb_offset(&xbinfo);
5273 if (!error) {
5274 error = xb_seek(&xbinfo, attrslength_offset);
5275 xb_add_32(error, &xbinfo, curargs_end_offset - attrslength_offset - XDRWORD/*don't include length field*/);
5276 }
5277 if (!error) {
5278 error = xb_seek(&xbinfo, curargslength_offset);
5279 xb_add_32(error, &xbinfo, curargs_end_offset - curargslength_offset + XDRWORD/*version*/);
5280 }
5281 if (!error) {
5282 error = xb_seek(&xbinfo, curargsopaquelength_offset);
5283 xb_add_32(error, &xbinfo, curargs_end_offset - curargslength_offset + XDRWORD/*version*/);
5284 }
5285 if (!error) {
5286 error = xb_seek(&xbinfo, infolength_offset);
5287 xb_add_32(error, &xbinfo, end_offset - infolength_offset + XDRWORD/*version*/);
5288 }
5289 nfsmerr_if(error);
5290
5291 /* copy result xdrbuf to caller */
5292 *xb = xbinfo;
5293
5294 /* and mark the local copy as not needing cleanup */
5295 xbinfo.xb_flags &= ~XB_CLEANUP;
5296 nfsmerr:
5297 xb_cleanup(&xbinfo);
5298 return (error);
5299 }
5300
5301 /*
5302 * Do that sysctl thang...
5303 */
5304 int
5305 nfs_vfs_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp,
5306 user_addr_t newp, size_t newlen, vfs_context_t ctx)
5307 {
5308 int error = 0, val;
5309 int softnobrowse;
5310 struct sysctl_req *req = NULL;
5311 union union_vfsidctl vc;
5312 mount_t mp;
5313 struct nfsmount *nmp = NULL;
5314 struct vfsquery vq;
5315 struct nfsreq *rq;
5316 boolean_t is_64_bit;
5317 fsid_t fsid;
5318 struct xdrbuf xb;
5319 struct netfs_status *nsp = NULL;
5320 int timeoutmask;
5321 uint pos, totlen, count, numThreads;
5322 #if NFSSERVER
5323 struct nfs_exportfs *nxfs;
5324 struct nfs_export *nx;
5325 struct nfs_active_user_list *ulist;
5326 struct nfs_export_stat_desc stat_desc;
5327 struct nfs_export_stat_rec statrec;
5328 struct nfs_user_stat_node *unode, *unode_next;
5329 struct nfs_user_stat_desc ustat_desc;
5330 struct nfs_user_stat_user_rec ustat_rec;
5331 struct nfs_user_stat_path_rec upath_rec;
5332 uint bytes_avail, bytes_total, recs_copied;
5333 uint numExports, numRecs;
5334 #endif /* NFSSERVER */
5335
5336 /*
5337 * All names at this level are terminal.
5338 */
5339 if (namelen > 1)
5340 return (ENOTDIR); /* overloaded */
5341
5342 is_64_bit = vfs_context_is64bit(ctx);
5343
5344 /* common code for "new style" VFS_CTL sysctl, get the mount. */
5345 switch (name[0]) {
5346 case VFS_CTL_TIMEO:
5347 case VFS_CTL_NOLOCKS:
5348 case VFS_CTL_NSTATUS:
5349 case VFS_CTL_QUERY:
5350 req = CAST_DOWN(struct sysctl_req *, oldp);
5351 if (req == NULL) {
5352 return EFAULT;
5353 }
5354 error = SYSCTL_IN(req, &vc, is_64_bit? sizeof(vc.vc64):sizeof(vc.vc32));
5355 if (error)
5356 return (error);
5357 mp = vfs_getvfs(&vc.vc32.vc_fsid); /* works for 32 and 64 */
5358 if (mp == NULL)
5359 return (ENOENT);
5360 nmp = VFSTONFS(mp);
5361 if (!nmp)
5362 return (ENOENT);
5363 bzero(&vq, sizeof(vq));
5364 req->newidx = 0;
5365 if (is_64_bit) {
5366 req->newptr = vc.vc64.vc_ptr;
5367 req->newlen = (size_t)vc.vc64.vc_len;
5368 } else {
5369 req->newptr = CAST_USER_ADDR_T(vc.vc32.vc_ptr);
5370 req->newlen = vc.vc32.vc_len;
5371 }
5372 break;
5373 }
5374
5375 switch(name[0]) {
5376 case NFS_NFSSTATS:
5377 if (!oldp) {
5378 *oldlenp = sizeof nfsstats;
5379 return (0);
5380 }
5381
5382 if (*oldlenp < sizeof nfsstats) {
5383 *oldlenp = sizeof nfsstats;
5384 return (ENOMEM);
5385 }
5386
5387 error = copyout(&nfsstats, oldp, sizeof nfsstats);
5388 if (error)
5389 return (error);
5390
5391 if (newp && newlen != sizeof nfsstats)
5392 return (EINVAL);
5393
5394 if (newp)
5395 return copyin(newp, &nfsstats, sizeof nfsstats);
5396 return (0);
5397 case NFS_MOUNTINFO:
5398 /* read in the fsid */
5399 if (*oldlenp < sizeof(fsid))
5400 return (EINVAL);
5401 if ((error = copyin(oldp, &fsid, sizeof(fsid))))
5402 return (error);
5403 /* swizzle it back to host order */
5404 fsid.val[0] = ntohl(fsid.val[0]);
5405 fsid.val[1] = ntohl(fsid.val[1]);
5406 /* find mount and make sure it's NFS */
5407 if (((mp = vfs_getvfs(&fsid))) == NULL)
5408 return (ENOENT);
5409 if (strcmp(mp->mnt_vfsstat.f_fstypename, "nfs"))
5410 return (EINVAL);
5411 if (((nmp = VFSTONFS(mp))) == NULL)
5412 return (ENOENT);
5413 xb_init(&xb, 0);
5414 if ((error = nfs_mountinfo_assemble(nmp, &xb)))
5415 return (error);
5416 if (*oldlenp < xb.xb_u.xb_buffer.xbb_len)
5417 error = ENOMEM;
5418 else
5419 error = copyout(xb_buffer_base(&xb), oldp, xb.xb_u.xb_buffer.xbb_len);
5420 *oldlenp = xb.xb_u.xb_buffer.xbb_len;
5421 xb_cleanup(&xb);
5422 break;
5423 #if NFSSERVER
5424 case NFS_EXPORTSTATS:
5425 /* setup export stat descriptor */
5426 stat_desc.rec_vers = NFS_EXPORT_STAT_REC_VERSION;
5427
5428 if (!nfsrv_is_initialized()) {
5429 stat_desc.rec_count = 0;
5430 if (oldp && (*oldlenp >= sizeof(struct nfs_export_stat_desc)))
5431 error = copyout(&stat_desc, oldp, sizeof(struct nfs_export_stat_desc));
5432 *oldlenp = sizeof(struct nfs_export_stat_desc);
5433 return (error);
5434 }
5435
5436 /* Count the number of exported directories */
5437 lck_rw_lock_shared(&nfsrv_export_rwlock);
5438 numExports = 0;
5439 LIST_FOREACH(nxfs, &nfsrv_exports, nxfs_next)
5440 LIST_FOREACH(nx, &nxfs->nxfs_exports, nx_next)
5441 numExports += 1;
5442
5443 /* update stat descriptor's export record count */
5444 stat_desc.rec_count = numExports;
5445
5446 /* calculate total size of required buffer */
5447 totlen = sizeof(struct nfs_export_stat_desc) + (numExports * sizeof(struct nfs_export_stat_rec));
5448
5449 /* Check caller's buffer */
5450 if (oldp == 0) {
5451 lck_rw_done(&nfsrv_export_rwlock);
5452 /* indicate required buffer len */
5453 *oldlenp = totlen;
5454 return (0);
5455 }
5456
5457 /* We require the caller's buffer to be at least large enough to hold the descriptor */
5458 if (*oldlenp < sizeof(struct nfs_export_stat_desc)) {
5459 lck_rw_done(&nfsrv_export_rwlock);
5460 /* indicate required buffer len */
5461 *oldlenp = totlen;
5462 return (ENOMEM);
5463 }
5464
5465 /* indicate required buffer len */
5466 *oldlenp = totlen;
5467
5468 /* check if export table is empty */
5469 if (!numExports) {
5470 lck_rw_done(&nfsrv_export_rwlock);
5471 error = copyout(&stat_desc, oldp, sizeof(struct nfs_export_stat_desc));
5472 return (error);
5473 }
5474
5475 /* calculate how many actual export stat records fit into caller's buffer */
5476 numRecs = (*oldlenp - sizeof(struct nfs_export_stat_desc)) / sizeof(struct nfs_export_stat_rec);
5477
5478 if (!numRecs) {
5479 /* caller's buffer can only accomodate descriptor */
5480 lck_rw_done(&nfsrv_export_rwlock);
5481 stat_desc.rec_count = 0;
5482 error = copyout(&stat_desc, oldp, sizeof(struct nfs_export_stat_desc));
5483 return (error);
5484 }
5485
5486 /* adjust to actual number of records to copyout to caller's buffer */
5487 if (numRecs > numExports)
5488 numRecs = numExports;
5489
5490 /* set actual number of records we are returning */
5491 stat_desc.rec_count = numRecs;
5492
5493 /* first copy out the stat descriptor */
5494 pos = 0;
5495 error = copyout(&stat_desc, oldp + pos, sizeof(struct nfs_export_stat_desc));
5496 if (error) {
5497 lck_rw_done(&nfsrv_export_rwlock);
5498 return (error);
5499 }
5500 pos += sizeof(struct nfs_export_stat_desc);
5501
5502 /* Loop through exported directories */
5503 count = 0;
5504 LIST_FOREACH(nxfs, &nfsrv_exports, nxfs_next) {
5505 LIST_FOREACH(nx, &nxfs->nxfs_exports, nx_next) {
5506
5507 if (count >= numRecs)
5508 break;
5509
5510 /* build exported filesystem path */
5511 snprintf(statrec.path, sizeof(statrec.path), "%s%s%s",
5512 nxfs->nxfs_path, ((nxfs->nxfs_path[1] && nx->nx_path[0]) ? "/" : ""),
5513 nx->nx_path);
5514
5515 /* build the 64-bit export stat counters */
5516 statrec.ops = ((uint64_t)nx->nx_stats.ops.hi << 32) |
5517 nx->nx_stats.ops.lo;
5518 statrec.bytes_read = ((uint64_t)nx->nx_stats.bytes_read.hi << 32) |
5519 nx->nx_stats.bytes_read.lo;
5520 statrec.bytes_written = ((uint64_t)nx->nx_stats.bytes_written.hi << 32) |
5521 nx->nx_stats.bytes_written.lo;
5522 error = copyout(&statrec, oldp + pos, sizeof(statrec));
5523 if (error) {
5524 lck_rw_done(&nfsrv_export_rwlock);
5525 return (error);
5526 }
5527 /* advance buffer position */
5528 pos += sizeof(statrec);
5529 }
5530 }
5531 lck_rw_done(&nfsrv_export_rwlock);
5532 break;
5533 case NFS_USERSTATS:
5534 /* init structures used for copying out of kernel */
5535 ustat_desc.rec_vers = NFS_USER_STAT_REC_VERSION;
5536 ustat_rec.rec_type = NFS_USER_STAT_USER_REC;
5537 upath_rec.rec_type = NFS_USER_STAT_PATH_REC;
5538
5539 /* initialize counters */
5540 bytes_total = sizeof(struct nfs_user_stat_desc);
5541 bytes_avail = *oldlenp;
5542 recs_copied = 0;
5543
5544 if (!nfsrv_is_initialized()) /* NFS server not initialized, so no stats */
5545 goto ustat_skip;
5546
5547 /* reclaim old expired user nodes */
5548 nfsrv_active_user_list_reclaim();
5549
5550 /* reserve space for the buffer descriptor */
5551 if (bytes_avail >= sizeof(struct nfs_user_stat_desc))
5552 bytes_avail -= sizeof(struct nfs_user_stat_desc);
5553 else
5554 bytes_avail = 0;
5555
5556 /* put buffer position past the buffer descriptor */
5557 pos = sizeof(struct nfs_user_stat_desc);
5558
5559 /* Loop through exported directories */
5560 lck_rw_lock_shared(&nfsrv_export_rwlock);
5561 LIST_FOREACH(nxfs, &nfsrv_exports, nxfs_next) {
5562 LIST_FOREACH(nx, &nxfs->nxfs_exports, nx_next) {
5563 /* copy out path */
5564 if (bytes_avail >= sizeof(struct nfs_user_stat_path_rec)) {
5565 snprintf(upath_rec.path, sizeof(upath_rec.path), "%s%s%s",
5566 nxfs->nxfs_path, ((nxfs->nxfs_path[1] && nx->nx_path[0]) ? "/" : ""),
5567 nx->nx_path);
5568
5569 error = copyout(&upath_rec, oldp + pos, sizeof(struct nfs_user_stat_path_rec));
5570 if (error) {
5571 /* punt */
5572 goto ustat_done;
5573 }
5574
5575 pos += sizeof(struct nfs_user_stat_path_rec);
5576 bytes_avail -= sizeof(struct nfs_user_stat_path_rec);
5577 recs_copied++;
5578 }
5579 else {
5580 /* Caller's buffer is exhausted */
5581 bytes_avail = 0;
5582 }
5583
5584 bytes_total += sizeof(struct nfs_user_stat_path_rec);
5585
5586 /* Scan through all user nodes of this export */
5587 ulist = &nx->nx_user_list;
5588 lck_mtx_lock(&ulist->user_mutex);
5589 for (unode = TAILQ_FIRST(&ulist->user_lru); unode; unode = unode_next) {
5590 unode_next = TAILQ_NEXT(unode, lru_link);
5591
5592 /* copy out node if there is space */
5593 if (bytes_avail >= sizeof(struct nfs_user_stat_user_rec)) {
5594 /* prepare a user stat rec for copying out */
5595 ustat_rec.uid = unode->uid;
5596 bcopy(&unode->sock, &ustat_rec.sock, unode->sock.ss_len);
5597 ustat_rec.ops = unode->ops;
5598 ustat_rec.bytes_read = unode->bytes_read;
5599 ustat_rec.bytes_written = unode->bytes_written;
5600 ustat_rec.tm_start = unode->tm_start;
5601 ustat_rec.tm_last = unode->tm_last;
5602
5603 error = copyout(&ustat_rec, oldp + pos, sizeof(struct nfs_user_stat_user_rec));
5604
5605 if (error) {
5606 /* punt */
5607 lck_mtx_unlock(&ulist->user_mutex);
5608 goto ustat_done;
5609 }
5610
5611 pos += sizeof(struct nfs_user_stat_user_rec);
5612 bytes_avail -= sizeof(struct nfs_user_stat_user_rec);
5613 recs_copied++;
5614 }
5615 else {
5616 /* Caller's buffer is exhausted */
5617 bytes_avail = 0;
5618 }
5619 bytes_total += sizeof(struct nfs_user_stat_user_rec);
5620 }
5621 /* can unlock this export's list now */
5622 lck_mtx_unlock(&ulist->user_mutex);
5623 }
5624 }
5625
5626 ustat_done:
5627 /* unlock the export table */
5628 lck_rw_done(&nfsrv_export_rwlock);
5629
5630 ustat_skip:
5631 /* indicate number of actual records copied */
5632 ustat_desc.rec_count = recs_copied;
5633
5634 if (!error) {
5635 /* check if there was enough room for the buffer descriptor */
5636 if (*oldlenp >= sizeof(struct nfs_user_stat_desc))
5637 error = copyout(&ustat_desc, oldp, sizeof(struct nfs_user_stat_desc));
5638 else
5639 error = ENOMEM;
5640
5641 /* always indicate required buffer size */
5642 *oldlenp = bytes_total;
5643 }
5644 break;
5645 case NFS_USERCOUNT:
5646 if (!oldp) {
5647 *oldlenp = sizeof(nfsrv_user_stat_node_count);
5648 return (0);
5649 }
5650
5651 if (*oldlenp < sizeof(nfsrv_user_stat_node_count)) {
5652 *oldlenp = sizeof(nfsrv_user_stat_node_count);
5653 return (ENOMEM);
5654 }
5655
5656 if (nfsrv_is_initialized()) {
5657 /* reclaim old expired user nodes */
5658 nfsrv_active_user_list_reclaim();
5659 }
5660
5661 error = copyout(&nfsrv_user_stat_node_count, oldp, sizeof(nfsrv_user_stat_node_count));
5662 break;
5663 #endif /* NFSSERVER */
5664 case VFS_CTL_NOLOCKS:
5665 if (req->oldptr != USER_ADDR_NULL) {
5666 lck_mtx_lock(&nmp->nm_lock);
5667 val = (nmp->nm_lockmode == NFS_LOCK_MODE_DISABLED) ? 1 : 0;
5668 lck_mtx_unlock(&nmp->nm_lock);
5669 error = SYSCTL_OUT(req, &val, sizeof(val));
5670 if (error)
5671 return (error);
5672 }
5673 if (req->newptr != USER_ADDR_NULL) {
5674 error = SYSCTL_IN(req, &val, sizeof(val));
5675 if (error)
5676 return (error);
5677 lck_mtx_lock(&nmp->nm_lock);
5678 if (nmp->nm_lockmode == NFS_LOCK_MODE_LOCAL) {
5679 /* can't toggle locks when using local locks */
5680 error = EINVAL;
5681 } else if ((nmp->nm_vers >= NFS_VER4) && val) {
5682 /* can't disable locks for NFSv4 */
5683 error = EINVAL;
5684 } else if (val) {
5685 if ((nmp->nm_vers <= NFS_VER3) && (nmp->nm_lockmode == NFS_LOCK_MODE_ENABLED))
5686 nfs_lockd_mount_unregister(nmp);
5687 nmp->nm_lockmode = NFS_LOCK_MODE_DISABLED;
5688 nmp->nm_state &= ~NFSSTA_LOCKTIMEO;
5689 } else {
5690 if ((nmp->nm_vers <= NFS_VER3) && (nmp->nm_lockmode == NFS_LOCK_MODE_DISABLED))
5691 nfs_lockd_mount_register(nmp);
5692 nmp->nm_lockmode = NFS_LOCK_MODE_ENABLED;
5693 }
5694 lck_mtx_unlock(&nmp->nm_lock);
5695 }
5696 break;
5697 case VFS_CTL_QUERY:
5698 lck_mtx_lock(&nmp->nm_lock);
5699 /* XXX don't allow users to know about/disconnect unresponsive, soft, nobrowse mounts */
5700 softnobrowse = (NMFLAG(nmp, SOFT) && (vfs_flags(nmp->nm_mountp) & MNT_DONTBROWSE));
5701 if (!softnobrowse && (nmp->nm_state & NFSSTA_TIMEO))
5702 vq.vq_flags |= VQ_NOTRESP;
5703 if (!softnobrowse && (nmp->nm_state & NFSSTA_JUKEBOXTIMEO) && !NMFLAG(nmp, MUTEJUKEBOX))
5704 vq.vq_flags |= VQ_NOTRESP;
5705 if (!softnobrowse && (nmp->nm_state & NFSSTA_LOCKTIMEO) &&
5706 (nmp->nm_lockmode == NFS_LOCK_MODE_ENABLED))
5707 vq.vq_flags |= VQ_NOTRESP;
5708 if (nmp->nm_state & NFSSTA_DEAD)
5709 vq.vq_flags |= VQ_DEAD;
5710 lck_mtx_unlock(&nmp->nm_lock);
5711 error = SYSCTL_OUT(req, &vq, sizeof(vq));
5712 break;
5713 case VFS_CTL_TIMEO:
5714 if (req->oldptr != USER_ADDR_NULL) {
5715 lck_mtx_lock(&nmp->nm_lock);
5716 val = nmp->nm_tprintf_initial_delay;
5717 lck_mtx_unlock(&nmp->nm_lock);
5718 error = SYSCTL_OUT(req, &val, sizeof(val));
5719 if (error)
5720 return (error);
5721 }
5722 if (req->newptr != USER_ADDR_NULL) {
5723 error = SYSCTL_IN(req, &val, sizeof(val));
5724 if (error)
5725 return (error);
5726 lck_mtx_lock(&nmp->nm_lock);
5727 if (val < 0)
5728 nmp->nm_tprintf_initial_delay = 0;
5729 else
5730 nmp->nm_tprintf_initial_delay = val;
5731 lck_mtx_unlock(&nmp->nm_lock);
5732 }
5733 break;
5734 case VFS_CTL_NSTATUS:
5735 /*
5736 * Return the status of this mount. This is much more
5737 * information than VFS_CTL_QUERY. In addition to the
5738 * vq_flags return the significant mount options along
5739 * with the list of threads blocked on the mount and
5740 * how long the threads have been waiting.
5741 */
5742
5743 lck_mtx_lock(nfs_request_mutex);
5744 lck_mtx_lock(&nmp->nm_lock);
5745
5746 /*
5747 * Count the number of requests waiting for a reply.
5748 * Note: there could be multiple requests from the same thread.
5749 */
5750 numThreads = 0;
5751 TAILQ_FOREACH(rq, &nfs_reqq, r_chain) {
5752 if (rq->r_nmp == nmp)
5753 numThreads++;
5754 }
5755
5756 /* Calculate total size of result buffer */
5757 totlen = sizeof(struct netfs_status) + (numThreads * sizeof(uint64_t));
5758
5759 if (req->oldptr == USER_ADDR_NULL) { // Caller is querying buffer size
5760 lck_mtx_unlock(&nmp->nm_lock);
5761 lck_mtx_unlock(nfs_request_mutex);
5762 return SYSCTL_OUT(req, NULL, totlen);
5763 }
5764 if (req->oldlen < totlen) { // Check if caller's buffer is big enough
5765 lck_mtx_unlock(&nmp->nm_lock);
5766 lck_mtx_unlock(nfs_request_mutex);
5767 return (ERANGE);
5768 }
5769
5770 MALLOC(nsp, struct netfs_status *, totlen, M_TEMP, M_WAITOK|M_ZERO);
5771 if (nsp == NULL) {
5772 lck_mtx_unlock(&nmp->nm_lock);
5773 lck_mtx_unlock(nfs_request_mutex);
5774 return (ENOMEM);
5775 }
5776 timeoutmask = NFSSTA_TIMEO | NFSSTA_LOCKTIMEO | NFSSTA_JUKEBOXTIMEO;
5777 if (nmp->nm_state & timeoutmask)
5778 nsp->ns_status |= VQ_NOTRESP;
5779 if (nmp->nm_state & NFSSTA_DEAD)
5780 nsp->ns_status |= VQ_DEAD;
5781
5782 (void) nfs_mountopts(nmp, nsp->ns_mountopts, sizeof(nsp->ns_mountopts));
5783 nsp->ns_threadcount = numThreads;
5784
5785 /*
5786 * Get the thread ids of threads waiting for a reply
5787 * and find the longest wait time.
5788 */
5789 if (numThreads > 0) {
5790 struct timeval now;
5791 time_t sendtime;
5792
5793 microuptime(&now);
5794 count = 0;
5795 sendtime = now.tv_sec;
5796 TAILQ_FOREACH(rq, &nfs_reqq, r_chain) {
5797 if (rq->r_nmp == nmp) {
5798 if (rq->r_start < sendtime)
5799 sendtime = rq->r_start;
5800 // A thread_id of zero is used to represent an async I/O request.
5801 nsp->ns_threadids[count] =
5802 rq->r_thread ? thread_tid(rq->r_thread) : 0;
5803 if (++count >= numThreads)
5804 break;
5805 }
5806 }
5807 nsp->ns_waittime = now.tv_sec - sendtime;
5808 }
5809
5810 lck_mtx_unlock(&nmp->nm_lock);
5811 lck_mtx_unlock(nfs_request_mutex);
5812
5813 error = SYSCTL_OUT(req, nsp, totlen);
5814 FREE(nsp, M_TEMP);
5815 break;
5816 default:
5817 return (ENOTSUP);
5818 }
5819 return (error);
5820 }