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