1/* 2 * Copyright (c) 2000-2008 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ 29/* 30 * Copyright (c) 1989, 1993, 1995 31 * The Regents of the University of California. All rights reserved. 32 * 33 * This code is derived from software contributed to Berkeley by 34 * Rick Macklem at The University of Guelph. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed by the University of 47 * California, Berkeley and its contributors. 48 * 4. Neither the name of the University nor the names of its contributors 49 * may be used to endorse or promote products derived from this software 50 * without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 * 64 * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95 65 * FreeBSD-Id: nfs_vfsops.c,v 1.52 1997/11/12 05:42:21 julian Exp $ 66 */ 67/* 68 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce 69 * support for mandatory and extensible security protections. This notice 70 * is included in support of clause 2.2 (b) of the Apple Public License, 71 * Version 2.0. 72 */ 73 74#include <sys/param.h> 75#include <sys/systm.h> 76#include <sys/conf.h> 77#include <sys/ioctl.h> 78#include <sys/signal.h> 79#include <sys/proc_internal.h> /* for fs rooting to update rootdir in fdp */ 80#include <sys/kauth.h> 81#include <sys/vnode_internal.h> 82#include <sys/malloc.h> 83#include <sys/kernel.h> 84#include <sys/sysctl.h> 85#include <sys/mount_internal.h> 86#include <sys/kpi_mbuf.h> 87#include <sys/socket.h> 88#include <sys/socketvar.h> 89#include <sys/fcntl.h> 90#include <sys/quota.h> 91#include <libkern/OSAtomic.h> 92 93#include <sys/vm.h> 94#include <sys/vmparam.h> 95 96#if !defined(NO_MOUNT_PRIVATE) 97#include <sys/filedesc.h> 98#endif /* NO_MOUNT_PRIVATE */ 99 100#include <net/if.h> 101#include <net/route.h> 102#include <netinet/in.h> 103 104#include <nfs/rpcv2.h> 105#include <nfs/krpc.h> 106#include <nfs/nfsproto.h> 107#include <nfs/nfs.h> 108#include <nfs/nfsnode.h> 109#include <nfs/nfs_gss.h> 110#include <nfs/nfsmount.h> 111#include <nfs/xdr_subs.h> 112#include <nfs/nfsm_subs.h> 113#include <nfs/nfsdiskless.h> 114#include <nfs/nfs_lock.h> 115#if CONFIG_MACF 116#include <security/mac_framework.h> 117#endif 118 119#include <pexpert/pexpert.h> 120 121/* 122 * NFS client globals 123 */ 124 125int nfs_ticks; 126static lck_grp_t *nfs_mount_grp; 127uint32_t nfs_fs_attr_bitmap[NFS_ATTR_BITMAP_LEN]; 128uint32_t nfs_object_attr_bitmap[NFS_ATTR_BITMAP_LEN]; 129uint32_t nfs_getattr_bitmap[NFS_ATTR_BITMAP_LEN]; 130 131/* NFS requests */ 132struct nfs_reqqhead nfs_reqq; 133lck_grp_t *nfs_request_grp; 134lck_mtx_t *nfs_request_mutex; 135thread_call_t nfs_request_timer_call; 136int nfs_request_timer_on; 137u_long nfs_xid = 0; 138u_long nfs_xidwrap = 0; /* to build a (non-wrapping) 64 bit xid */ 139 140thread_call_t nfs_buf_timer_call; 141 142/* nfsiod */ 143lck_grp_t *nfsiod_lck_grp; 144lck_mtx_t *nfsiod_mutex; 145struct nfsiodlist nfsiodfree, nfsiodwork; 146struct nfsiodmountlist nfsiodmounts; 147int nfsiod_thread_count = 0; 148int nfsiod_thread_max = NFS_DEFASYNCTHREAD; 149int nfs_max_async_writes = NFS_DEFMAXASYNCWRITES; 150 151int nfs_iosize = NFS_IOSIZE; 152int nfs_access_cache_timeout = NFS_MAXATTRTIMO; 153int nfs_allow_async = 0; 154int nfs_statfs_rate_limit = NFS_DEFSTATFSRATELIMIT; 155int nfs_lockd_mounts = 0; 156int nfs_lockd_request_sent = 0; 157 158int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY; 159int nfs_tprintf_delay = NFS_TPRINTF_DELAY; 160 161 162static int mountnfs(struct user_nfs_args *,mount_t,mbuf_t,vfs_context_t,vnode_t *); 163static int nfs_mount_diskless(struct nfs_dlmount *, const char *, int, vnode_t *, mount_t *, vfs_context_t); 164#if !defined(NO_MOUNT_PRIVATE) 165static int nfs_mount_diskless_private(struct nfs_dlmount *, const char *, int, vnode_t *, mount_t *, vfs_context_t); 166#endif /* NO_MOUNT_PRIVATE */ 167 168/* 169 * NFS VFS operations. 170 */ 171static int nfs_vfs_mount(mount_t, vnode_t, user_addr_t, vfs_context_t); 172static int nfs_vfs_start(mount_t, int, vfs_context_t); 173static int nfs_vfs_unmount(mount_t, int, vfs_context_t); 174static int nfs_vfs_root(mount_t, vnode_t *, vfs_context_t); 175static int nfs_vfs_quotactl(mount_t, int, uid_t, caddr_t, vfs_context_t); 176static int nfs_vfs_getattr(mount_t, struct vfs_attr *, vfs_context_t); 177static int nfs_vfs_sync(mount_t, int, vfs_context_t); 178static int nfs_vfs_vget(mount_t, ino64_t, vnode_t *, vfs_context_t); 179static int nfs_vfs_vptofh(vnode_t, int *, unsigned char *, vfs_context_t); 180static int nfs_vfs_fhtovp(mount_t, int, unsigned char *, vnode_t *, vfs_context_t); 181static int nfs_vfs_init(struct vfsconf *); 182static int nfs_vfs_sysctl(int *, u_int, user_addr_t, size_t *, user_addr_t, size_t, vfs_context_t); 183 184struct vfsops nfs_vfsops = { 185 nfs_vfs_mount, 186 nfs_vfs_start, 187 nfs_vfs_unmount, 188 nfs_vfs_root, 189 nfs_vfs_quotactl, 190 nfs_vfs_getattr, 191 nfs_vfs_sync, 192 nfs_vfs_vget, 193 nfs_vfs_fhtovp, 194 nfs_vfs_vptofh, 195 nfs_vfs_init, 196 nfs_vfs_sysctl, 197 NULL, /* setattr */ 198 { NULL, /* reserved */ 199 NULL, /* reserved */ 200 NULL, /* reserved */ 201 NULL, /* reserved */ 202 NULL, /* reserved */ 203 NULL, /* reserved */ 204 NULL } /* reserved */ 205}; 206 207 208/* 209 * version-specific NFS functions 210 */ 211static int nfs3_mount(struct nfsmount *, vfs_context_t, struct user_nfs_args *, nfsnode_t *); 212static int nfs4_mount(struct nfsmount *, vfs_context_t, struct user_nfs_args *, nfsnode_t *); 213static int nfs3_update_statfs(struct nfsmount *, vfs_context_t); 214static int nfs4_update_statfs(struct nfsmount *, vfs_context_t); 215#if !QUOTA 216#define nfs3_getquota NULL 217#define nfs4_getquota NULL 218#else 219static int nfs3_getquota(struct nfsmount *, vfs_context_t, u_long, int, struct dqblk *); 220static int nfs4_getquota(struct nfsmount *, vfs_context_t, u_long, int, struct dqblk *); 221#endif 222 223struct nfs_funcs nfs3_funcs = { 224 nfs3_mount, 225 nfs3_update_statfs, 226 nfs3_getquota, 227 nfs3_access_rpc, 228 nfs3_getattr_rpc, 229 nfs3_setattr_rpc, 230 nfs3_read_rpc_async, 231 nfs3_read_rpc_async_finish, 232 nfs3_readlink_rpc, 233 nfs3_write_rpc_async, 234 nfs3_write_rpc_async_finish, 235 nfs3_commit_rpc, 236 nfs3_lookup_rpc_async, 237 nfs3_lookup_rpc_async_finish, 238 nfs3_remove_rpc, 239 nfs3_rename_rpc 240 }; 241struct nfs_funcs nfs4_funcs = { 242 nfs4_mount, 243 nfs4_update_statfs, 244 nfs4_getquota, 245 nfs4_access_rpc, 246 nfs4_getattr_rpc, 247 nfs4_setattr_rpc, 248 nfs4_read_rpc_async, 249 nfs4_read_rpc_async_finish, 250 nfs4_readlink_rpc, 251 nfs4_write_rpc_async, 252 nfs4_write_rpc_async_finish, 253 nfs4_commit_rpc, 254 nfs4_lookup_rpc_async, 255 nfs4_lookup_rpc_async_finish, 256 nfs4_remove_rpc, 257 nfs4_rename_rpc 258 }; 259 260/* 261 * Called once to initialize data structures... 262 */ 263static int 264nfs_vfs_init(struct vfsconf *vfsp) 265{ 266 int i; 267 268 /* 269 * Check to see if major data structures haven't bloated. 270 */ 271 if (sizeof (struct nfsnode) > NFS_NODEALLOC) { 272 printf("struct nfsnode bloated (> %dbytes)\n", NFS_NODEALLOC); 273 printf("Try reducing NFS_SMALLFH\n"); 274 } 275 if (sizeof (struct nfsmount) > NFS_MNTALLOC) { 276 printf("struct nfsmount bloated (> %dbytes)\n", NFS_MNTALLOC); 277 printf("Try reducing NFS_MUIDHASHSIZ\n"); 278 } 279 280 nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000; 281 if (nfs_ticks < 1) 282 nfs_ticks = 1; 283 284 /* init async I/O thread pool state */ 285 TAILQ_INIT(&nfsiodfree); 286 TAILQ_INIT(&nfsiodwork); 287 TAILQ_INIT(&nfsiodmounts); 288 nfsiod_lck_grp = lck_grp_alloc_init("nfsiod", LCK_GRP_ATTR_NULL); 289 nfsiod_mutex = lck_mtx_alloc_init(nfsiod_lck_grp, LCK_ATTR_NULL); 290 291 /* init mount lock group */ 292 nfs_mount_grp = lck_grp_alloc_init("nfs_mount", LCK_GRP_ATTR_NULL); 293 294 /* init request list mutex */ 295 nfs_request_grp = lck_grp_alloc_init("nfs_request", LCK_GRP_ATTR_NULL); 296 nfs_request_mutex = lck_mtx_alloc_init(nfs_request_grp, LCK_ATTR_NULL); 297 298 /* initialize NFS request list */ 299 TAILQ_INIT(&nfs_reqq); 300 301 nfs_nbinit(); /* Init the nfsbuf table */ 302 nfs_nhinit(); /* Init the nfsnode table */ 303 nfs_lockinit(); /* Init the nfs lock state */ 304 nfs_gss_init(); /* Init RPCSEC_GSS security */ 305 306 /* NFSv4 stuff */ 307 NFS4_PER_FS_ATTRIBUTES(nfs_fs_attr_bitmap); 308 NFS4_PER_OBJECT_ATTRIBUTES(nfs_object_attr_bitmap); 309 NFS4_DEFAULT_ATTRIBUTES(nfs_getattr_bitmap); 310 for (i=0; i < NFS_ATTR_BITMAP_LEN; i++) 311 nfs_getattr_bitmap[i] &= nfs_object_attr_bitmap[i]; 312 313 /* initialize NFS timer callouts */ 314 nfs_request_timer_call = thread_call_allocate(nfs_request_timer, NULL); 315 nfs_buf_timer_call = thread_call_allocate(nfs_buf_timer, NULL); 316 317 vfsp->vfc_refcount++; /* make us non-unloadable */ 318 return (0); 319} 320 321/* 322 * nfs statfs call 323 */ 324static int 325nfs3_update_statfs(struct nfsmount *nmp, vfs_context_t ctx) 326{ 327 nfsnode_t np; 328 int error = 0, lockerror, status, nfsvers; 329 u_int64_t xid; 330 struct nfsm_chain nmreq, nmrep; 331 uint32_t val; 332 333 nfsvers = nmp->nm_vers; 334 np = nmp->nm_dnp; 335 if ((error = vnode_get(NFSTOV(np)))) 336 return(error); 337 338 nfsm_chain_null(&nmreq); 339 nfsm_chain_null(&nmrep); 340 341 nfsm_chain_build_alloc_init(error, &nmreq, NFSX_FH(nfsvers)); 342 nfsm_chain_add_fh(error, &nmreq, nfsvers, np->n_fhp, np->n_fhsize); 343 nfsm_chain_build_done(error, &nmreq); 344 nfsmout_if(error); 345 error = nfs_request(np, NULL, &nmreq, NFSPROC_FSSTAT, ctx, 346 &nmrep, &xid, &status); 347 if ((lockerror = nfs_lock(np, NFS_NODE_LOCK_EXCLUSIVE))) 348 error = lockerror; 349 if (nfsvers == NFS_VER3) 350 nfsm_chain_postop_attr_update(error, &nmrep, np, &xid); 351 if (!lockerror) 352 nfs_unlock(np); 353 if (!error) 354 error = status; 355 nfsm_assert(error, NFSTONMP(np), ENXIO); 356 nfsmout_if(error); 357 lck_mtx_lock(&nmp->nm_lock); 358 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_TOTAL); 359 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_FREE); 360 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_AVAIL); 361 if (nfsvers == NFS_VER3) { 362 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_FILES_AVAIL); 363 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_FILES_TOTAL); 364 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_FILES_FREE); 365 nmp->nm_fsattr.nfsa_bsize = NFS_FABLKSIZE; 366 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_space_total); 367 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_space_free); 368 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_space_avail); 369 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_files_total); 370 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_files_free); 371 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_files_avail); 372 // skip invarsec 373 } else { 374 nfsm_chain_adv(error, &nmrep, NFSX_UNSIGNED); // skip tsize? 375 nfsm_chain_get_32(error, &nmrep, nmp->nm_fsattr.nfsa_bsize); 376 nfsm_chain_get_32(error, &nmrep, val); 377 nfsmout_if(error); 378 if (nmp->nm_fsattr.nfsa_bsize <= 0) 379 nmp->nm_fsattr.nfsa_bsize = NFS_FABLKSIZE; 380 nmp->nm_fsattr.nfsa_space_total = (uint64_t)val * nmp->nm_fsattr.nfsa_bsize; 381 nfsm_chain_get_32(error, &nmrep, val); 382 nfsmout_if(error); 383 nmp->nm_fsattr.nfsa_space_free = (uint64_t)val * nmp->nm_fsattr.nfsa_bsize; 384 nfsm_chain_get_32(error, &nmrep, val); 385 nfsmout_if(error); 386 nmp->nm_fsattr.nfsa_space_avail = (uint64_t)val * nmp->nm_fsattr.nfsa_bsize; 387 } 388 lck_mtx_unlock(&nmp->nm_lock); 389nfsmout: 390 nfsm_chain_cleanup(&nmreq); 391 nfsm_chain_cleanup(&nmrep); 392 vnode_put(NFSTOV(np)); 393 return (error); 394} 395 396static int 397nfs4_update_statfs(struct nfsmount *nmp, vfs_context_t ctx) 398{ 399 nfsnode_t np; 400 int error = 0, lockerror, status, nfsvers, numops; 401 u_int64_t xid; 402 struct nfsm_chain nmreq, nmrep; 403 uint32_t bitmap[NFS_ATTR_BITMAP_LEN]; 404 struct nfs_vattr nvattr; 405 406 nfsvers = nmp->nm_vers; 407 np = nmp->nm_dnp; 408 if ((error = vnode_get(NFSTOV(np)))) 409 return(error); 410 411 nfsm_chain_null(&nmreq); 412 nfsm_chain_null(&nmrep); 413 414 // PUTFH + GETATTR 415 numops = 2; 416 nfsm_chain_build_alloc_init(error, &nmreq, 15 * NFSX_UNSIGNED); 417 nfsm_chain_add_compound_header(error, &nmreq, "statfs", numops); 418 numops--; 419 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTFH); 420 nfsm_chain_add_fh(error, &nmreq, nfsvers, np->n_fhp, np->n_fhsize); 421 numops--; 422 nfsm_chain_add_32(error, &nmreq, NFS_OP_GETATTR); 423 NFS_COPY_ATTRIBUTES(nfs_getattr_bitmap, bitmap); 424 NFS4_STATFS_ATTRIBUTES(bitmap); 425 nfsm_chain_add_bitmap_masked(error, &nmreq, bitmap, 426 NFS_ATTR_BITMAP_LEN, nmp->nm_fsattr.nfsa_supp_attr); 427 nfsm_chain_build_done(error, &nmreq); 428 nfsm_assert(error, (numops == 0), EPROTO); 429 nfsmout_if(error); 430 error = nfs_request(np, NULL, &nmreq, NFSPROC4_COMPOUND, ctx, &nmrep, &xid, &status); 431 nfsm_chain_skip_tag(error, &nmrep); 432 nfsm_chain_get_32(error, &nmrep, numops); 433 nfsm_chain_op_check(error, &nmrep, NFS_OP_PUTFH); 434 nfsm_chain_op_check(error, &nmrep, NFS_OP_GETATTR); 435 nfsm_assert(error, NFSTONMP(np), ENXIO); 436 nfsmout_if(error); 437 lck_mtx_lock(&nmp->nm_lock); 438 NFS_CLEAR_ATTRIBUTES(nvattr.nva_bitmap); 439 error = nfs4_parsefattr(&nmrep, &nmp->nm_fsattr, &nvattr, NULL, NULL); 440 lck_mtx_unlock(&nmp->nm_lock); 441 nfsmout_if(error); 442 if ((lockerror = nfs_lock(np, NFS_NODE_LOCK_EXCLUSIVE))) 443 error = lockerror; 444 if (!error) 445 nfs_loadattrcache(np, &nvattr, &xid, 0); 446 if (!lockerror) 447 nfs_unlock(np); 448 nfsm_assert(error, NFSTONMP(np), ENXIO); 449 nfsmout_if(error); 450 nmp->nm_fsattr.nfsa_bsize = NFS_FABLKSIZE; 451nfsmout: 452 nfsm_chain_cleanup(&nmreq); 453 nfsm_chain_cleanup(&nmrep); 454 vnode_put(NFSTOV(np)); 455 return (error); 456} 457 458 459/* 460 * The NFS VFS_GETATTR function: "statfs"-type information is retrieved 461 * using the nf_update_statfs() function, and other attributes are cobbled 462 * together from whatever sources we can (getattr, fsinfo, pathconf). 463 */ 464static int 465nfs_vfs_getattr(mount_t mp, struct vfs_attr *fsap, vfs_context_t ctx) 466{ 467 struct nfsmount *nmp; 468 uint32_t bsize; 469 int error = 0, nfsvers; 470 471 if (!(nmp = VFSTONFS(mp))) 472 return (ENXIO); 473 nfsvers = nmp->nm_vers; 474 475 if (VFSATTR_IS_ACTIVE(fsap, f_bsize) || 476 VFSATTR_IS_ACTIVE(fsap, f_iosize) || 477 VFSATTR_IS_ACTIVE(fsap, f_blocks) || 478 VFSATTR_IS_ACTIVE(fsap, f_bfree) || 479 VFSATTR_IS_ACTIVE(fsap, f_bavail) || 480 VFSATTR_IS_ACTIVE(fsap, f_bused) || 481 VFSATTR_IS_ACTIVE(fsap, f_files) || 482 VFSATTR_IS_ACTIVE(fsap, f_ffree)) { 483 int statfsrate = nfs_statfs_rate_limit; 484 int refresh = 1; 485 486 /* 487 * Are we rate-limiting statfs RPCs? 488 * (Treat values less than 1 or greater than 1,000,000 as no limit.) 489 */ 490 if ((statfsrate > 0) && (statfsrate < 1000000)) { 491 struct timeval now; 492 uint32_t stamp; 493 494 microuptime(&now); 495 lck_mtx_lock(&nmp->nm_lock); 496 stamp = (now.tv_sec * statfsrate) + (now.tv_usec / (1000000/statfsrate)); 497 if (stamp != nmp->nm_fsattrstamp) { 498 refresh = 1; 499 nmp->nm_fsattrstamp = stamp; 500 } else { 501 refresh = 0; 502 } 503 lck_mtx_unlock(&nmp->nm_lock); 504 } 505 506 if (refresh) 507 error = nmp->nm_funcs->nf_update_statfs(nmp, ctx); 508 if ((error == ESTALE) || (error == ETIMEDOUT)) 509 error = 0; 510 if (error) 511 return (error); 512 513 lck_mtx_lock(&nmp->nm_lock); 514 VFSATTR_RETURN(fsap, f_iosize, nfs_iosize); 515 VFSATTR_RETURN(fsap, f_bsize, nmp->nm_fsattr.nfsa_bsize); 516 bsize = nmp->nm_fsattr.nfsa_bsize; 517 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_TOTAL)) 518 VFSATTR_RETURN(fsap, f_blocks, nmp->nm_fsattr.nfsa_space_total / bsize); 519 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_FREE)) 520 VFSATTR_RETURN(fsap, f_bfree, nmp->nm_fsattr.nfsa_space_free / bsize); 521 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_AVAIL)) 522 VFSATTR_RETURN(fsap, f_bavail, nmp->nm_fsattr.nfsa_space_avail / bsize); 523 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_TOTAL) && 524 NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SPACE_FREE)) 525 VFSATTR_RETURN(fsap, f_bused, 526 (nmp->nm_fsattr.nfsa_space_total / bsize) - 527 (nmp->nm_fsattr.nfsa_space_free / bsize)); 528 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_FILES_TOTAL)) 529 VFSATTR_RETURN(fsap, f_files, nmp->nm_fsattr.nfsa_files_total); 530 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_FILES_FREE)) 531 VFSATTR_RETURN(fsap, f_ffree, nmp->nm_fsattr.nfsa_files_free); 532 lck_mtx_unlock(&nmp->nm_lock); 533 } 534 535 if (VFSATTR_IS_ACTIVE(fsap, f_capabilities)) { 536 u_int32_t caps, valid; 537 nfsnode_t np; 538 539 nfsm_assert(error, VFSTONFS(mp), ENXIO); 540 if (error) 541 return (error); 542 np = nmp->nm_dnp; 543 lck_mtx_lock(&nmp->nm_lock); 544 545 /* 546 * The capabilities[] array defines what this volume supports. 547 * 548 * The valid[] array defines which bits this code understands 549 * the meaning of (whether the volume has that capability or not). 550 * Any zero bits here means "I don't know what you're asking about" 551 * and the caller cannot tell whether that capability is 552 * present or not. 553 */ 554 caps = valid = 0; 555 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SYMLINK_SUPPORT)) { 556 valid |= VOL_CAP_FMT_SYMBOLICLINKS; 557 if (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_SYMLINK) 558 caps |= VOL_CAP_FMT_SYMBOLICLINKS; 559 } 560 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_LINK_SUPPORT)) { 561 valid |= VOL_CAP_FMT_HARDLINKS; 562 if (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_LINK) 563 caps |= VOL_CAP_FMT_HARDLINKS; 564 } 565 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_CASE_INSENSITIVE)) { 566 valid |= VOL_CAP_FMT_CASE_SENSITIVE; 567 if (!(nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_CASE_INSENSITIVE)) 568 caps |= VOL_CAP_FMT_CASE_SENSITIVE; 569 } 570 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_CASE_PRESERVING)) { 571 valid |= VOL_CAP_FMT_CASE_PRESERVING; 572 if (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_CASE_PRESERVING) 573 caps |= VOL_CAP_FMT_CASE_PRESERVING; 574 } 575 /* Note: VOL_CAP_FMT_2TB_FILESIZE is actually used to test for "large file support" */ 576 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXFILESIZE)) { 577 /* Is server's max file size at least 4GB? */ 578 if (nmp->nm_fsattr.nfsa_maxfilesize >= 0x100000000ULL) 579 caps |= VOL_CAP_FMT_2TB_FILESIZE; 580 } else if (nfsvers >= NFS_VER3) { 581 /* 582 * NFSv3 and up supports 64 bits of file size. 583 * So, we'll just assume maxfilesize >= 4GB 584 */ 585 caps |= VOL_CAP_FMT_2TB_FILESIZE; 586 } 587 if (nfsvers >= NFS_VER4) { 588 caps |= VOL_CAP_FMT_HIDDEN_FILES; 589 valid |= VOL_CAP_FMT_HIDDEN_FILES; 590 // VOL_CAP_FMT_OPENDENYMODES 591 } 592 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_FORMAT] = 593 // VOL_CAP_FMT_PERSISTENTOBJECTIDS | 594 // VOL_CAP_FMT_SYMBOLICLINKS | 595 // VOL_CAP_FMT_HARDLINKS | 596 // VOL_CAP_FMT_JOURNAL | 597 // VOL_CAP_FMT_JOURNAL_ACTIVE | 598 // VOL_CAP_FMT_NO_ROOT_TIMES | 599 // VOL_CAP_FMT_SPARSE_FILES | 600 // VOL_CAP_FMT_ZERO_RUNS | 601 // VOL_CAP_FMT_CASE_SENSITIVE | 602 // VOL_CAP_FMT_CASE_PRESERVING | 603 // VOL_CAP_FMT_FAST_STATFS | 604 // VOL_CAP_FMT_2TB_FILESIZE | 605 // VOL_CAP_FMT_OPENDENYMODES | 606 // VOL_CAP_FMT_HIDDEN_FILES | 607 caps; 608 fsap->f_capabilities.valid[VOL_CAPABILITIES_FORMAT] = 609 VOL_CAP_FMT_PERSISTENTOBJECTIDS | 610 // VOL_CAP_FMT_SYMBOLICLINKS | 611 // VOL_CAP_FMT_HARDLINKS | 612 // VOL_CAP_FMT_JOURNAL | 613 // VOL_CAP_FMT_JOURNAL_ACTIVE | 614 // VOL_CAP_FMT_NO_ROOT_TIMES | 615 // VOL_CAP_FMT_SPARSE_FILES | 616 // VOL_CAP_FMT_ZERO_RUNS | 617 // VOL_CAP_FMT_CASE_SENSITIVE | 618 // VOL_CAP_FMT_CASE_PRESERVING | 619 VOL_CAP_FMT_FAST_STATFS | 620 VOL_CAP_FMT_2TB_FILESIZE | 621 // VOL_CAP_FMT_OPENDENYMODES | 622 // VOL_CAP_FMT_HIDDEN_FILES | 623 valid; 624 625 /* 626 * We don't support most of the interfaces. 627 * 628 * We MAY support locking, but we don't have any easy way of probing. 629 * We can tell if there's no lockd running or if locks have been 630 * disabled for a mount, so we can definitely answer NO in that case. 631 * Any attempt to send a request to lockd to test for locking support 632 * may cause the lazily-launched locking daemons to be started 633 * unnecessarily. So we avoid that. However, we do record if we ever 634 * successfully perform a lock operation on a mount point, so if it 635 * looks like lock ops have worked, we do report that we support them. 636 */ 637 caps = valid = 0; 638 if (nfsvers >= NFS_VER4) { 639 caps = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK; 640 valid = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK; 641 // VOL_CAP_INT_EXTENDED_SECURITY 642 // VOL_CAP_INT_NAMEDSTREAMS 643 // VOL_CAP_INT_EXTENDED_ATTR 644 } else if ((nmp->nm_flag & NFSMNT_NOLOCKS)) { 645 /* locks disabled on this mount, so they definitely won't work */ 646 valid = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK; 647 } else if (nmp->nm_state & NFSSTA_LOCKSWORK) { 648 caps = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK; 649 valid = VOL_CAP_INT_ADVLOCK | VOL_CAP_INT_FLOCK; 650 } 651 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_INTERFACES] = 652 // VOL_CAP_INT_SEARCHFS | 653 // VOL_CAP_INT_ATTRLIST | 654 // VOL_CAP_INT_NFSEXPORT | 655 // VOL_CAP_INT_READDIRATTR | 656 // VOL_CAP_INT_EXCHANGEDATA | 657 // VOL_CAP_INT_COPYFILE | 658 // VOL_CAP_INT_ALLOCATE | 659 // VOL_CAP_INT_VOL_RENAME | 660 // VOL_CAP_INT_ADVLOCK | 661 // VOL_CAP_INT_FLOCK | 662 // VOL_CAP_INT_EXTENDED_SECURITY | 663 // VOL_CAP_INT_USERACCESS | 664 // VOL_CAP_INT_MANLOCK | 665 // VOL_CAP_INT_NAMEDSTREAMS | 666 // VOL_CAP_INT_EXTENDED_ATTR | 667 caps; 668 fsap->f_capabilities.valid[VOL_CAPABILITIES_INTERFACES] = 669 VOL_CAP_INT_SEARCHFS | 670 VOL_CAP_INT_ATTRLIST | 671 VOL_CAP_INT_NFSEXPORT | 672 VOL_CAP_INT_READDIRATTR | 673 VOL_CAP_INT_EXCHANGEDATA | 674 VOL_CAP_INT_COPYFILE | 675 VOL_CAP_INT_ALLOCATE | 676 VOL_CAP_INT_VOL_RENAME | 677 // VOL_CAP_INT_ADVLOCK | 678 // VOL_CAP_INT_FLOCK | 679 // VOL_CAP_INT_EXTENDED_SECURITY | 680 // VOL_CAP_INT_USERACCESS | 681 // VOL_CAP_INT_MANLOCK | 682 // VOL_CAP_INT_NAMEDSTREAMS | 683 // VOL_CAP_INT_EXTENDED_ATTR | 684 valid; 685 686 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED1] = 0; 687 fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED1] = 0; 688 689 fsap->f_capabilities.capabilities[VOL_CAPABILITIES_RESERVED2] = 0; 690 fsap->f_capabilities.valid[VOL_CAPABILITIES_RESERVED2] = 0; 691 692 VFSATTR_SET_SUPPORTED(fsap, f_capabilities); 693 lck_mtx_unlock(&nmp->nm_lock); 694 } 695 696 if (VFSATTR_IS_ACTIVE(fsap, f_attributes)) { 697 fsap->f_attributes.validattr.commonattr = 0; 698 fsap->f_attributes.validattr.volattr = 699 ATTR_VOL_CAPABILITIES | ATTR_VOL_ATTRIBUTES; 700 fsap->f_attributes.validattr.dirattr = 0; 701 fsap->f_attributes.validattr.fileattr = 0; 702 fsap->f_attributes.validattr.forkattr = 0; 703 704 fsap->f_attributes.nativeattr.commonattr = 0; 705 fsap->f_attributes.nativeattr.volattr = 706 ATTR_VOL_CAPABILITIES | ATTR_VOL_ATTRIBUTES; 707 fsap->f_attributes.nativeattr.dirattr = 0; 708 fsap->f_attributes.nativeattr.fileattr = 0; 709 fsap->f_attributes.nativeattr.forkattr = 0; 710 711 VFSATTR_SET_SUPPORTED(fsap, f_attributes); 712 } 713 714 return (error); 715} 716 717/* 718 * nfs version 3 fsinfo rpc call 719 */ 720static int 721nfs3_fsinfo(struct nfsmount *nmp, nfsnode_t np, vfs_context_t ctx) 722{ 723 int error = 0, lockerror, status, prefsize, maxsize, nmlocked = 0; 724 u_int64_t xid; 725 uint32_t val; 726 struct nfsm_chain nmreq, nmrep; 727 728 nfsm_chain_null(&nmreq); 729 nfsm_chain_null(&nmrep); 730 731 nfsm_chain_build_alloc_init(error, &nmreq, NFSX_FH(nmp->nm_vers)); 732 nfsm_chain_add_fh(error, &nmreq, nmp->nm_vers, np->n_fhp, np->n_fhsize); 733 nfsm_chain_build_done(error, &nmreq); 734 nfsmout_if(error); 735 error = nfs_request(np, NULL, &nmreq, NFSPROC_FSINFO, ctx, 736 &nmrep, &xid, &status); 737 if ((lockerror = nfs_lock(np, NFS_NODE_LOCK_EXCLUSIVE))) 738 error = lockerror; 739 nfsm_chain_postop_attr_update(error, &nmrep, np, &xid); 740 if (!lockerror) 741 nfs_unlock(np); 742 if (!error) 743 error = status; 744 nfsmout_if(error); 745 746 lck_mtx_lock(&nmp->nm_lock); 747 nmlocked = 1; 748 749 nfsm_chain_get_32(error, &nmrep, maxsize); 750 nfsm_chain_get_32(error, &nmrep, prefsize); 751 nfsmout_if(error); 752 nmp->nm_fsattr.nfsa_maxread = maxsize; 753 if (prefsize < nmp->nm_rsize) 754 nmp->nm_rsize = (prefsize + NFS_FABLKSIZE - 1) & 755 ~(NFS_FABLKSIZE - 1); 756 if (maxsize < nmp->nm_rsize) { 757 nmp->nm_rsize = maxsize & ~(NFS_FABLKSIZE - 1); 758 if (nmp->nm_rsize == 0) 759 nmp->nm_rsize = maxsize; 760 } 761 nfsm_chain_adv(error, &nmrep, NFSX_UNSIGNED); // skip rtmult 762 763 nfsm_chain_get_32(error, &nmrep, maxsize); 764 nfsm_chain_get_32(error, &nmrep, prefsize); 765 nfsmout_if(error); 766 nmp->nm_fsattr.nfsa_maxwrite = maxsize; 767 if (prefsize < nmp->nm_wsize) 768 nmp->nm_wsize = (prefsize + NFS_FABLKSIZE - 1) & 769 ~(NFS_FABLKSIZE - 1); 770 if (maxsize < nmp->nm_wsize) { 771 nmp->nm_wsize = maxsize & ~(NFS_FABLKSIZE - 1); 772 if (nmp->nm_wsize == 0) 773 nmp->nm_wsize = maxsize; 774 } 775 nfsm_chain_adv(error, &nmrep, NFSX_UNSIGNED); // skip wtmult 776 777 nfsm_chain_get_32(error, &nmrep, prefsize); 778 nfsmout_if(error); 779 if (prefsize < nmp->nm_readdirsize) 780 nmp->nm_readdirsize = prefsize; 781 if (maxsize < nmp->nm_readdirsize) 782 nmp->nm_readdirsize = maxsize; 783 784 nfsm_chain_get_64(error, &nmrep, nmp->nm_fsattr.nfsa_maxfilesize); 785 786 nfsm_chain_adv(error, &nmrep, 2 * NFSX_UNSIGNED); // skip time_delta 787 788 /* convert FS properties to our own flags */ 789 nfsm_chain_get_32(error, &nmrep, val); 790 nfsmout_if(error); 791 if (val & NFSV3FSINFO_LINK) 792 nmp->nm_fsattr.nfsa_flags |= NFS_FSFLAG_LINK; 793 if (val & NFSV3FSINFO_SYMLINK) 794 nmp->nm_fsattr.nfsa_flags |= NFS_FSFLAG_SYMLINK; 795 if (val & NFSV3FSINFO_HOMOGENEOUS) 796 nmp->nm_fsattr.nfsa_flags |= NFS_FSFLAG_HOMOGENEOUS; 797 if (val & NFSV3FSINFO_CANSETTIME) 798 nmp->nm_fsattr.nfsa_flags |= NFS_FSFLAG_SET_TIME; 799 nmp->nm_state |= NFSSTA_GOTFSINFO; 800 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXREAD); 801 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXWRITE); 802 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXFILESIZE); 803 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_LINK_SUPPORT); 804 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_SYMLINK_SUPPORT); 805 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_HOMOGENEOUS); 806 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_CANSETTIME); 807nfsmout: 808 if (nmlocked) 809 lck_mtx_unlock(&nmp->nm_lock); 810 nfsm_chain_cleanup(&nmreq); 811 nfsm_chain_cleanup(&nmrep); 812 return (error); 813} 814 815/* 816 * Mount a remote root fs via. nfs. This depends on the info in the 817 * nfs_diskless structure that has been filled in properly by some primary 818 * bootstrap. 819 * It goes something like this: 820 * - do enough of "ifconfig" by calling ifioctl() so that the system 821 * can talk to the server 822 * - If nfs_diskless.mygateway is filled in, use that address as 823 * a default gateway. 824 * - hand craft the swap nfs vnode hanging off a fake mount point 825 * if swdevt[0].sw_dev == NODEV 826 * - build the rootfs mount point and call mountnfs() to do the rest. 827 */ 828int 829nfs_mountroot(void) 830{ 831 struct nfs_diskless nd; 832 struct nfs_vattr nvattr; 833 mount_t mp = NULL; 834 vnode_t vp = NULL; 835 vfs_context_t ctx; 836 int error; 837#if !defined(NO_MOUNT_PRIVATE) 838 mount_t mppriv = NULL; 839 vnode_t vppriv = NULL; 840#endif /* NO_MOUNT_PRIVATE */ 841 int v3, sotype; 842 843 /* 844 * Call nfs_boot_init() to fill in the nfs_diskless struct. 845 * Note: networking must already have been configured before 846 * we're called. 847 */ 848 bzero((caddr_t) &nd, sizeof(nd)); 849 error = nfs_boot_init(&nd); 850 if (error) { 851 panic("nfs_boot_init failed with %d\n", error); 852 } 853 854 /* 855 * Try NFSv3 first, then fallback to NFSv2. 856 * Likewise, try TCP first, then fall back to UDP. 857 */ 858 v3 = 1; 859 sotype = SOCK_STREAM; 860 861tryagain: 862 error = nfs_boot_getfh(&nd, v3, sotype); 863 if (error) { 864 if (error == EHOSTDOWN || error == EHOSTUNREACH) { 865 if (nd.nd_root.ndm_path) 866 FREE_ZONE(nd.nd_root.ndm_path, 867 MAXPATHLEN, M_NAMEI); 868 if (nd.nd_private.ndm_path) 869 FREE_ZONE(nd.nd_private.ndm_path, 870 MAXPATHLEN, M_NAMEI); 871 return (error); 872 } 873 if (v3) { 874 if (sotype == SOCK_STREAM) { 875 printf("nfs_boot_getfh(v3,TCP) failed with %d, trying UDP...\n", error); 876 sotype = SOCK_DGRAM; 877 goto tryagain; 878 } 879 printf("nfs_boot_getfh(v3,UDP) failed with %d, trying v2...\n", error); 880 v3 = 0; 881 sotype = SOCK_STREAM; 882 goto tryagain; 883 } else if (sotype == SOCK_STREAM) { 884 printf("nfs_boot_getfh(v2,TCP) failed with %d, trying UDP...\n", error); 885 sotype = SOCK_DGRAM; 886 goto tryagain; 887 } 888 switch(error) { 889 case EPROGUNAVAIL: 890 panic("nfs_boot_getfh(v2,UDP) failed: NFS server mountd not responding - check server configuration: %s", PE_boot_args()); 891 case EACCES: 892 case EPERM: 893 panic("nfs_boot_getfh(v2,UDP) failed: NFS server refused mount - check server configuration: %s", PE_boot_args()); 894 default: 895 panic("nfs_boot_getfh(v2,UDP) failed with %d: %s", error, PE_boot_args()); 896 } 897 } 898 899 ctx = vfs_context_kernel(); 900 901 /* 902 * Create the root mount point. 903 */ 904#if !defined(NO_MOUNT_PRIVATE) 905 { 906 //PWC hack until we have a real "mount" tool to remount root rw 907 int rw_root=0; 908 int flags = MNT_ROOTFS|MNT_RDONLY; 909 PE_parse_boot_argn("-rwroot_hack", &rw_root, sizeof (rw_root)); 910 if(rw_root) 911 { 912 flags = MNT_ROOTFS; 913 kprintf("-rwroot_hack in effect: mounting root fs read/write\n"); 914 } 915 916 if ((error = nfs_mount_diskless(&nd.nd_root, "/", flags, &vp, &mp, ctx))) 917#else 918 if ((error = nfs_mount_diskless(&nd.nd_root, "/", MNT_ROOTFS, &vp, &mp, ctx))) 919#endif /* NO_MOUNT_PRIVATE */ 920 { 921 if (v3) { 922 if (sotype == SOCK_STREAM) { 923 printf("nfs_mount_diskless(v3,TCP) failed with %d, trying UDP...\n", error); 924 sotype = SOCK_DGRAM; 925 goto tryagain; 926 } 927 printf("nfs_mount_diskless(v3,UDP) failed with %d, trying v2...\n", error); 928 v3 = 0; 929 sotype = SOCK_STREAM; 930 goto tryagain; 931 } else if (sotype == SOCK_STREAM) { 932 printf("nfs_mount_diskless(v2,TCP) failed with %d, trying UDP...\n", error); 933 sotype = SOCK_DGRAM; 934 goto tryagain; 935 } 936 panic("nfs_mount_diskless(v2,UDP) root failed with %d: %s\n", error, PE_boot_args()); 937 } 938 } 939 printf("root on %s\n", (char *)&nd.nd_root.ndm_host); 940 941 vfs_unbusy(mp); 942 mount_list_add(mp); 943 rootvp = vp; 944 945#if !defined(NO_MOUNT_PRIVATE) 946 if (nd.nd_private.ndm_saddr.sin_addr.s_addr) { 947 error = nfs_mount_diskless_private(&nd.nd_private, "/private", 948 0, &vppriv, &mppriv, ctx); 949 if (error) { 950 panic("nfs_mount_diskless private failed with %d\n", error); 951 } 952 printf("private on %s\n", (char *)&nd.nd_private.ndm_host); 953 954 vfs_unbusy(mppriv); 955 mount_list_add(mppriv); 956 } 957 958#endif /* NO_MOUNT_PRIVATE */ 959 960 if (nd.nd_root.ndm_path) 961 FREE_ZONE(nd.nd_root.ndm_path, MAXPATHLEN, M_NAMEI); 962 if (nd.nd_private.ndm_path) 963 FREE_ZONE(nd.nd_private.ndm_path, MAXPATHLEN, M_NAMEI); 964 965 /* Get root attributes (for the time). */ 966 error = nfs_getattr(VTONFS(vp), &nvattr, ctx, 0); 967 if (error) panic("nfs_mountroot: getattr for root"); 968 return (0); 969} 970 971/* 972 * Internal version of mount system call for diskless setup. 973 */ 974static int 975nfs_mount_diskless( 976 struct nfs_dlmount *ndmntp, 977 const char *mntname, 978 int mntflag, 979 vnode_t *vpp, 980 mount_t *mpp, 981 vfs_context_t ctx) 982{ 983 struct user_nfs_args args; 984 mount_t mp; 985 mbuf_t m; 986 int error; 987 988 if ((error = vfs_rootmountalloc("nfs", ndmntp->ndm_host, &mp))) { 989 printf("nfs_mount_diskless: NFS not configured"); 990 return (error); 991 } 992 993 mp->mnt_flag |= mntflag; 994 if (!(mntflag & MNT_RDONLY)) 995 mp->mnt_flag &= ~MNT_RDONLY; 996 997 /* Initialize mount args. */ 998 bzero((caddr_t) &args, sizeof(args)); 999 args.addr = CAST_USER_ADDR_T(&ndmntp->ndm_saddr); 1000 args.addrlen = ndmntp->ndm_saddr.sin_len; 1001 args.sotype = ndmntp->ndm_sotype; 1002 args.fh = CAST_USER_ADDR_T(&ndmntp->ndm_fh[0]); 1003 args.fhsize = ndmntp->ndm_fhlen; 1004 args.hostname = CAST_USER_ADDR_T(ndmntp->ndm_host); 1005 args.flags = NFSMNT_RESVPORT; 1006 if (ndmntp->ndm_nfsv3) 1007 args.flags |= NFSMNT_NFSV3; 1008 1009 error = mbuf_get(MBUF_WAITOK, MBUF_TYPE_SONAME, &m); 1010 if (error) { 1011 printf("nfs_mount_diskless: mbuf_get(soname) failed"); 1012 return (error); 1013 } 1014 mbuf_setlen(m, ndmntp->ndm_saddr.sin_len); 1015 bcopy(&ndmntp->ndm_saddr, mbuf_data(m), ndmntp->ndm_saddr.sin_len); 1016 if ((error = mountnfs(&args, mp, m, ctx, vpp))) { 1017 printf("nfs_mountroot: mount %s failed: %d\n", mntname, error); 1018 // XXX vfs_rootmountfailed(mp); 1019 mount_list_lock(); 1020 mp->mnt_vtable->vfc_refcount--; 1021 mount_list_unlock(); 1022 vfs_unbusy(mp); 1023 mount_lock_destroy(mp); 1024#if CONFIG_MACF 1025 mac_mount_label_destroy(mp); 1026#endif 1027 FREE_ZONE(mp, sizeof(struct mount), M_MOUNT); 1028 return (error); 1029 } 1030 *mpp = mp; 1031 return (0); 1032} 1033 1034#if !defined(NO_MOUNT_PRIVATE) 1035/* 1036 * Internal version of mount system call to mount "/private" 1037 * separately in diskless setup 1038 */ 1039static int 1040nfs_mount_diskless_private( 1041 struct nfs_dlmount *ndmntp, 1042 const char *mntname, 1043 int mntflag, 1044 vnode_t *vpp, 1045 mount_t *mpp, 1046 vfs_context_t ctx) 1047{ 1048 struct user_nfs_args args; 1049 mount_t mp; 1050 mbuf_t m; 1051 int error; 1052 proc_t procp; 1053 struct vfstable *vfsp; 1054 struct nameidata nd; 1055 vnode_t vp; 1056 1057 procp = current_proc(); /* XXX */ 1058 1059 { 1060 /* 1061 * mimic main()!. Temporarily set up rootvnode and other stuff so 1062 * that namei works. Need to undo this because main() does it, too 1063 */ 1064 struct filedesc *fdp; /* pointer to file descriptor state */ 1065 fdp = procp->p_fd; 1066 mountlist.tqh_first->mnt_flag |= MNT_ROOTFS; 1067 1068 /* Get the vnode for '/'. Set fdp->fd_cdir to reference it. */ 1069 if (VFS_ROOT(mountlist.tqh_first, &rootvnode, NULL)) 1070 panic("cannot find root vnode"); 1071 error = vnode_ref(rootvnode); 1072 if (error) { 1073 printf("nfs_mountroot: vnode_ref() failed on root vnode!\n"); 1074 goto out; 1075 } 1076 fdp->fd_cdir = rootvnode; 1077 fdp->fd_rdir = NULL; 1078 } 1079 1080 /* 1081 * Get vnode to be covered 1082 */ 1083 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE32, 1084 CAST_USER_ADDR_T(mntname), ctx); 1085 if ((error = namei(&nd))) { 1086 printf("nfs_mountroot: private namei failed!\n"); 1087 goto out; 1088 } 1089 { 1090 /* undo vnode_ref() in mimic main()! */ 1091 vnode_rele(rootvnode); 1092 } 1093 nameidone(&nd); 1094 vp = nd.ni_vp; 1095 1096 if ((error = VNOP_FSYNC(vp, MNT_WAIT, ctx)) || 1097 (error = buf_invalidateblks(vp, BUF_WRITE_DATA, 0, 0))) { 1098 vnode_put(vp); 1099 goto out; 1100 } 1101 if (vnode_vtype(vp) != VDIR) { 1102 vnode_put(vp); 1103 error = ENOTDIR; 1104 goto out; 1105 } 1106 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) 1107 if (!strncmp(vfsp->vfc_name, "nfs", sizeof(vfsp->vfc_name))) 1108 break; 1109 if (vfsp == NULL) { 1110 printf("nfs_mountroot: private NFS not configured\n"); 1111 vnode_put(vp); 1112 error = ENODEV; 1113 goto out; 1114 } 1115 if (vnode_mountedhere(vp) != NULL) { 1116 vnode_put(vp); 1117 error = EBUSY; 1118 goto out; 1119 } 1120 1121 /* 1122 * Allocate and initialize the filesystem. 1123 */ 1124 mp = _MALLOC_ZONE((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); 1125 if (!mp) { 1126 printf("nfs_mountroot: unable to allocate mount structure\n"); 1127 vnode_put(vp); 1128 error = ENOMEM; 1129 goto out; 1130 } 1131 bzero((char *)mp, (u_long)sizeof(struct mount)); 1132 1133 /* Initialize the default IO constraints */ 1134 mp->mnt_maxreadcnt = mp->mnt_maxwritecnt = MAXPHYS; 1135 mp->mnt_segreadcnt = mp->mnt_segwritecnt = 32; 1136 mp->mnt_ioflags = 0; 1137 mp->mnt_realrootvp = NULLVP; 1138 mp->mnt_authcache_ttl = CACHED_LOOKUP_RIGHT_TTL; 1139 1140 mount_lock_init(mp); 1141 TAILQ_INIT(&mp->mnt_vnodelist); 1142 TAILQ_INIT(&mp->mnt_workerqueue); 1143 TAILQ_INIT(&mp->mnt_newvnodes); 1144 (void)vfs_busy(mp, LK_NOWAIT); 1145 TAILQ_INIT(&mp->mnt_vnodelist); 1146 mount_list_lock(); 1147 vfsp->vfc_refcount++; 1148 mount_list_unlock(); 1149 mp->mnt_vtable = vfsp; 1150 mp->mnt_op = vfsp->vfc_vfsops; 1151 // mp->mnt_stat.f_type = vfsp->vfc_typenum; 1152 mp->mnt_flag = mntflag; 1153 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; 1154 strncpy(mp->mnt_vfsstat.f_fstypename, vfsp->vfc_name, MFSNAMELEN-1); 1155 vp->v_mountedhere = mp; 1156 mp->mnt_vnodecovered = vp; 1157 mp->mnt_vfsstat.f_owner = kauth_cred_getuid(kauth_cred_get()); 1158 (void) copystr(mntname, mp->mnt_vfsstat.f_mntonname, MNAMELEN - 1, 0); 1159 (void) copystr(ndmntp->ndm_host, mp->mnt_vfsstat.f_mntfromname, MNAMELEN - 1, 0); 1160#if CONFIG_MACF 1161 mac_mount_label_init(mp); 1162 mac_mount_label_associate(ctx, mp); 1163#endif 1164 1165 /* Initialize mount args. */ 1166 bzero((caddr_t) &args, sizeof(args)); 1167 args.addr = CAST_USER_ADDR_T(&ndmntp->ndm_saddr); 1168 args.addrlen = ndmntp->ndm_saddr.sin_len; 1169 args.sotype = ndmntp->ndm_sotype; 1170 args.fh = CAST_USER_ADDR_T(ndmntp->ndm_fh); 1171 args.fhsize = ndmntp->ndm_fhlen; 1172 args.hostname = CAST_USER_ADDR_T(ndmntp->ndm_host); 1173 args.flags = NFSMNT_RESVPORT; 1174 if (ndmntp->ndm_nfsv3) 1175 args.flags |= NFSMNT_NFSV3; 1176 1177 error = mbuf_get(MBUF_WAITOK, MBUF_TYPE_SONAME, &m); 1178 if (error) { 1179 printf("nfs_mount_diskless_private: mbuf_get(soname) failed"); 1180 goto out; 1181 } 1182 mbuf_setlen(m, ndmntp->ndm_saddr.sin_len); 1183 bcopy(&ndmntp->ndm_saddr, mbuf_data(m), ndmntp->ndm_saddr.sin_len); 1184 if ((error = mountnfs(&args, mp, m, ctx, &vp))) { 1185 printf("nfs_mountroot: mount %s failed: %d\n", mntname, error); 1186 mount_list_lock(); 1187 vfsp->vfc_refcount--; 1188 mount_list_unlock(); 1189 vfs_unbusy(mp); 1190 mount_lock_destroy(mp); 1191#if CONFIG_MACF 1192 mac_mount_label_destroy(mp); 1193#endif 1194 FREE_ZONE(mp, sizeof (struct mount), M_MOUNT); 1195 goto out; 1196 } 1197 1198 *mpp = mp; 1199 *vpp = vp; 1200out: 1201 return (error); 1202} 1203#endif /* NO_MOUNT_PRIVATE */ 1204 1205/* 1206 * VFS Operations. 1207 * 1208 * mount system call 1209 */ 1210static int 1211nfs_vfs_mount(mount_t mp, vnode_t vp, user_addr_t data, vfs_context_t ctx) 1212{ 1213 int error, argsvers; 1214 struct user_nfs_args args; 1215 struct nfs_args tempargs; 1216 mbuf_t nam; 1217 size_t len; 1218 u_char nfh[NFSX_V3FHMAX]; 1219 char *mntfrom; 1220 1221 error = copyin(data, (caddr_t)&argsvers, sizeof (argsvers)); 1222 if (error) 1223 return (error); 1224 1225 switch (argsvers) { 1226 case 3: 1227 if (vfs_context_is64bit(ctx)) 1228 error = copyin(data, (caddr_t)&args, sizeof (struct user_nfs_args3)); 1229 else 1230 error = copyin(data, (caddr_t)&tempargs, sizeof (struct nfs_args3)); 1231 break; 1232 case 4: 1233 if (vfs_context_is64bit(ctx)) 1234 error = copyin(data, (caddr_t)&args, sizeof (struct user_nfs_args4)); 1235 else 1236 error = copyin(data, (caddr_t)&tempargs, sizeof (struct nfs_args4)); 1237 break; 1238 case 5: 1239 if (vfs_context_is64bit(ctx)) 1240 error = copyin(data, (caddr_t)&args, sizeof (args)); 1241 else 1242 error = copyin(data, (caddr_t)&tempargs, sizeof (tempargs)); 1243 break; 1244 default: 1245 return (EPROGMISMATCH); 1246 } 1247 if (error) 1248 return (error); 1249 1250 if (!vfs_context_is64bit(ctx)) { 1251 args.version = tempargs.version; 1252 args.addrlen = tempargs.addrlen; 1253 args.sotype = tempargs.sotype; 1254 args.proto = tempargs.proto; 1255 args.fhsize = tempargs.fhsize; 1256 args.flags = tempargs.flags; 1257 args.wsize = tempargs.wsize; 1258 args.rsize = tempargs.rsize; 1259 args.readdirsize = tempargs.readdirsize; 1260 args.timeo = tempargs.timeo; 1261 args.retrans = tempargs.retrans; 1262 args.maxgrouplist = tempargs.maxgrouplist; 1263 args.readahead = tempargs.readahead; 1264 args.leaseterm = tempargs.leaseterm; 1265 args.deadthresh = tempargs.deadthresh; 1266 args.addr = CAST_USER_ADDR_T(tempargs.addr); 1267 args.fh = CAST_USER_ADDR_T(tempargs.fh); 1268 args.hostname = CAST_USER_ADDR_T(tempargs.hostname); 1269 if (argsvers >= 4) { 1270 args.acregmin = tempargs.acregmin; 1271 args.acregmax = tempargs.acregmax; 1272 args.acdirmin = tempargs.acdirmin; 1273 args.acdirmax = tempargs.acdirmax; 1274 } 1275 if (argsvers >= 5) 1276 args.auth = tempargs.auth; 1277 } 1278 1279 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) 1280 return (EINVAL); 1281 if (args.fhsize > 0) { 1282 error = copyin(args.fh, (caddr_t)nfh, args.fhsize); 1283 if (error) 1284 return (error); 1285 } 1286 1287 mntfrom = &vfs_statfs(mp)->f_mntfromname[0]; 1288 error = copyinstr(args.hostname, mntfrom, MAXPATHLEN-1, &len); 1289 if (error) 1290 return (error); 1291 bzero(&mntfrom[len], MAXPATHLEN - len); 1292 1293 /* sockargs() call must be after above copyin() calls */ 1294 error = sockargs(&nam, args.addr, args.addrlen, MBUF_TYPE_SONAME); 1295 if (error) 1296 return (error); 1297 1298 args.fh = CAST_USER_ADDR_T(&nfh[0]); 1299 error = mountnfs(&args, mp, nam, ctx, &vp); 1300 return (error); 1301} 1302 1303/* 1304 * Common code for mount and mountroot 1305 */ 1306 1307static int 1308nfs3_mount( 1309 struct nfsmount *nmp, 1310 vfs_context_t ctx, 1311 struct user_nfs_args *argp, 1312 nfsnode_t *npp) 1313{ 1314 int error = 0; 1315 struct nfs_vattr nvattr; 1316 u_int64_t xid; 1317 u_char *fhp; 1318 1319 *npp = NULL; 1320 1321 /* 1322 * Get file attributes for the mountpoint. These are needed 1323 * in order to properly create the root vnode. 1324 */ 1325 // LP64todo - fix CAST_DOWN of argp->fh 1326 fhp = CAST_DOWN(u_char *, argp->fh); 1327 error = nfs3_getattr_rpc(NULL, nmp->nm_mountp, fhp, argp->fhsize, 1328 ctx, &nvattr, &xid); 1329 if (error) 1330 goto out; 1331 1332 error = nfs_nget(nmp->nm_mountp, NULL, NULL, fhp, argp->fhsize, 1333 &nvattr, &xid, NG_MARKROOT, npp); 1334 if (*npp) 1335 nfs_unlock(*npp); 1336 if (error) 1337 goto out; 1338 1339 /* 1340 * Try to make sure we have all the general info from the server. 1341 */ 1342 if (nmp->nm_vers == NFS_VER2) { 1343 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXNAME); 1344 nmp->nm_fsattr.nfsa_maxname = NFS_MAXNAMLEN; 1345 } else if (nmp->nm_vers == NFS_VER3) { 1346 /* get the NFSv3 FSINFO */ 1347 error = nfs3_fsinfo(nmp, *npp, ctx); 1348 if (error) 1349 goto out; 1350 /* If the server indicates all pathconf info is */ 1351 /* the same, grab a copy of that info now */ 1352 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_HOMOGENEOUS) && 1353 (nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_HOMOGENEOUS)) { 1354 struct nfs_fsattr nfsa; 1355 if (!nfs3_pathconf_rpc(*npp, &nfsa, ctx)) { 1356 /* cache a copy of the results */ 1357 lck_mtx_lock(&nmp->nm_lock); 1358 nfs3_pathconf_cache(nmp, &nfsa); 1359 lck_mtx_unlock(&nmp->nm_lock); 1360 } 1361 } 1362 } 1363out: 1364 if (*npp && error) { 1365 vnode_put(NFSTOV(*npp)); 1366 *npp = NULL; 1367 } 1368 return (error); 1369} 1370 1371static int 1372nfs4_mount( 1373 struct nfsmount *nmp, 1374 vfs_context_t ctx, 1375 __unused struct user_nfs_args *argp, 1376 nfsnode_t *npp) 1377{ 1378 struct nfsm_chain nmreq, nmrep; 1379 int error = 0, numops, status, interval; 1380 char *path = &vfs_statfs(nmp->nm_mountp)->f_mntfromname[0]; 1381 char *name, *nextname; 1382 fhandle_t fh; 1383 struct nfs_vattr nvattr; 1384 u_int64_t xid; 1385 struct timeval now; 1386 1387 *npp = NULL; 1388 fh.fh_len = 0; 1389 microtime(&now); 1390 nmp->nm_mounttime = ((uint64_t)now.tv_sec << 32) | now.tv_usec; 1391 1392 /* look up path to get fh and attrs for mount point root */ 1393 numops = 2; // PUTROOTFH + LOOKUP* + GETATTR 1394 while (*path && (*path != '/')) 1395 path++; 1396 name = path; 1397 while (*name) { 1398 while (*name && (*name == '/')) 1399 name++; 1400 if (!*name) 1401 break; 1402 nextname = name; 1403 while (*nextname && (*nextname != '/')) 1404 nextname++; 1405 numops++; 1406 name = nextname; 1407 } 1408 nfsm_chain_build_alloc_init(error, &nmreq, 25 * NFSX_UNSIGNED); 1409 nfsm_chain_add_compound_header(error, &nmreq, "mount", numops); 1410 numops--; 1411 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTROOTFH); 1412 // (LOOKUP)* 1413 name = path; 1414 while (*name) { 1415 while (*name && (*name == '/')) 1416 name++; 1417 if (!*name) 1418 break; 1419 nextname = name; 1420 while (*nextname && (*nextname != '/')) 1421 nextname++; 1422 numops--; 1423 nfsm_chain_add_32(error, &nmreq, NFS_OP_LOOKUP); 1424 nfsm_chain_add_string(error, &nmreq, name, nextname - name); 1425 name = nextname; 1426 } 1427 numops--; 1428 nfsm_chain_add_32(error, &nmreq, NFS_OP_GETATTR); 1429 NFS4_DEFAULT_ATTRIBUTES(nmp->nm_fsattr.nfsa_supp_attr); 1430 NFS_BITMAP_SET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_FILEHANDLE); 1431 nfsm_chain_add_bitmap(error, &nmreq, nmp->nm_fsattr.nfsa_supp_attr, NFS_ATTR_BITMAP_LEN); 1432 nfsm_chain_build_done(error, &nmreq); 1433 nfsm_assert(error, (numops == 0), EPROTO); 1434 nfsmout_if(error); 1435 error = nfs_request(NULL, nmp->nm_mountp, &nmreq, NFSPROC4_COMPOUND, ctx, &nmrep, &xid, &status); 1436 nfsm_chain_skip_tag(error, &nmrep); 1437 nfsm_chain_get_32(error, &nmrep, numops); 1438 nfsm_chain_op_check(error, &nmrep, NFS_OP_PUTROOTFH); 1439 name = path; 1440 while (*name) { 1441 while (*name && (*name == '/')) 1442 name++; 1443 if (!*name) 1444 break; 1445 nextname = name; 1446 while (*nextname && (*nextname != '/')) 1447 nextname++; 1448 nfsm_chain_op_check(error, &nmrep, NFS_OP_LOOKUP); 1449 name = nextname; 1450 } 1451 nfsm_chain_op_check(error, &nmrep, NFS_OP_GETATTR); 1452 nfsmout_if(error); 1453 NFS_CLEAR_ATTRIBUTES(nmp->nm_fsattr.nfsa_bitmap); 1454 NFS_CLEAR_ATTRIBUTES(&nvattr.nva_bitmap); 1455 error = nfs4_parsefattr(&nmrep, &nmp->nm_fsattr, &nvattr, &fh, NULL); 1456 if (!error && !NFS_BITMAP_ISSET(&nvattr.nva_bitmap, NFS_FATTR_FILEHANDLE)) { 1457 printf("nfs: mount didn't return filehandle?\n"); 1458 error = EBADRPC; 1459 } 1460 nfsmout_if(error); 1461 1462 error = nfs_nget(nmp->nm_mountp, NULL, NULL, fh.fh_data, fh.fh_len, &nvattr, &xid, NG_MARKROOT, npp); 1463 nfsmout_if(error); 1464 1465 /* XXX local locking for now */ 1466 vfs_setlocklocal(nmp->nm_mountp); 1467 1468 /* adjust I/O sizes to server limits */ 1469 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXREAD)) { 1470 if (nmp->nm_fsattr.nfsa_maxread < (uint64_t)nmp->nm_rsize) { 1471 nmp->nm_rsize = nmp->nm_fsattr.nfsa_maxread & ~(NFS_FABLKSIZE - 1); 1472 if (nmp->nm_rsize == 0) 1473 nmp->nm_rsize = nmp->nm_fsattr.nfsa_maxread; 1474 } 1475 } 1476 if (NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_MAXWRITE)) { 1477 if (nmp->nm_fsattr.nfsa_maxwrite < (uint64_t)nmp->nm_wsize) { 1478 nmp->nm_wsize = nmp->nm_fsattr.nfsa_maxwrite & ~(NFS_FABLKSIZE - 1); 1479 if (nmp->nm_wsize == 0) 1480 nmp->nm_wsize = nmp->nm_fsattr.nfsa_maxwrite; 1481 } 1482 } 1483 1484 /* set up lease renew timer */ 1485 nmp->nm_renew_timer = thread_call_allocate(nfs4_renew_timer, nmp); 1486 interval = nmp->nm_fsattr.nfsa_lease / 2; 1487 if (interval < 1) 1488 interval = 1; 1489 nfs_interval_timer_start(nmp->nm_renew_timer, interval * 1000); 1490 1491nfsmout: 1492 if (*npp) 1493 nfs_unlock(*npp); 1494 return (error); 1495} 1496 1497static int 1498mountnfs( 1499 struct user_nfs_args *argp, 1500 mount_t mp, 1501 mbuf_t nam, 1502 vfs_context_t ctx, 1503 vnode_t *vpp) 1504{ 1505 struct nfsmount *nmp; 1506 nfsnode_t np; 1507 int error, maxio, iosize; 1508 struct vfsstatfs *sbp; 1509 struct timespec ts = { 1, 0 }; 1510 1511 /* 1512 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes 1513 * no sense in that context. 1514 */ 1515 if (argp->sotype == SOCK_STREAM) 1516 argp->flags &= ~NFSMNT_NOCONN; 1517 1518 if (vfs_flags(mp) & MNT_UPDATE) { 1519 nmp = VFSTONFS(mp); 1520 /* update paths, file handles, etc, here XXX */ 1521 mbuf_freem(nam); 1522 return (0); 1523 } else { 1524 MALLOC_ZONE(nmp, struct nfsmount *, 1525 sizeof (struct nfsmount), M_NFSMNT, M_WAITOK); 1526 if (!nmp) { 1527 mbuf_freem(nam); 1528 return (ENOMEM); 1529 } 1530 bzero((caddr_t)nmp, sizeof (struct nfsmount)); 1531 lck_mtx_init(&nmp->nm_lock, nfs_mount_grp, LCK_ATTR_NULL); 1532 TAILQ_INIT(&nmp->nm_resendq); 1533 TAILQ_INIT(&nmp->nm_iodq); 1534 TAILQ_INIT(&nmp->nm_gsscl); 1535 vfs_setfsprivate(mp, nmp); 1536 1537 nfs_nhinit_finish(); 1538 } 1539 lck_mtx_lock(&nmp->nm_lock); 1540 1541 /* setup defaults */ 1542 nmp->nm_vers = NFS_VER2; 1543 nmp->nm_timeo = NFS_TIMEO; 1544 nmp->nm_retry = NFS_RETRANS; 1545 if (argp->sotype == SOCK_DGRAM) { 1546 nmp->nm_wsize = NFS_DGRAM_WSIZE; 1547 nmp->nm_rsize = NFS_DGRAM_RSIZE; 1548 } else { 1549 nmp->nm_wsize = NFS_WSIZE; 1550 nmp->nm_rsize = NFS_RSIZE; 1551 } 1552 nmp->nm_readdirsize = NFS_READDIRSIZE; 1553 nmp->nm_numgrps = NFS_MAXGRPS; 1554 nmp->nm_readahead = NFS_DEFRAHEAD; 1555 nmp->nm_tprintf_delay = nfs_tprintf_delay; 1556 if (nmp->nm_tprintf_delay < 0) 1557 nmp->nm_tprintf_delay = 0; 1558 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay; 1559 if (nmp->nm_tprintf_initial_delay < 0) 1560 nmp->nm_tprintf_initial_delay = 0; 1561 nmp->nm_acregmin = NFS_MINATTRTIMO; 1562 nmp->nm_acregmax = NFS_MAXATTRTIMO; 1563 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO; 1564 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO; 1565 nmp->nm_auth = RPCAUTH_SYS; 1566 1567 vfs_getnewfsid(mp); 1568 nmp->nm_mountp = mp; 1569 vfs_setauthopaque(mp); 1570 nmp->nm_flag = argp->flags; 1571 nmp->nm_nam = nam; 1572 1573 if (argp->flags & NFSMNT_NFSV4) { 1574 nmp->nm_vers = NFS_VER4; 1575 /* NFSv4 is only allowed over TCP. */ 1576 if (argp->sotype != SOCK_STREAM) { 1577 error = EINVAL; 1578 goto bad; 1579 } 1580 } else if (argp->flags & NFSMNT_NFSV3) 1581 nmp->nm_vers = NFS_VER3; 1582 1583 if (nmp->nm_vers == NFS_VER2) 1584 nmp->nm_flag &= ~NFSMNT_RDIRPLUS; 1585 1586 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) { 1587 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10; 1588 if (nmp->nm_timeo < NFS_MINTIMEO) 1589 nmp->nm_timeo = NFS_MINTIMEO; 1590 else if (nmp->nm_timeo > NFS_MAXTIMEO) 1591 nmp->nm_timeo = NFS_MAXTIMEO; 1592 } 1593 1594 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) { 1595 nmp->nm_retry = argp->retrans; 1596 if (nmp->nm_retry > NFS_MAXREXMIT) 1597 nmp->nm_retry = NFS_MAXREXMIT; 1598 } 1599 1600 if (nmp->nm_vers != NFS_VER2) { 1601 if (argp->sotype == SOCK_DGRAM) 1602 maxio = NFS_MAXDGRAMDATA; 1603 else 1604 maxio = NFS_MAXDATA; 1605 } else 1606 maxio = NFS_V2MAXDATA; 1607 1608 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) { 1609 nmp->nm_wsize = argp->wsize; 1610 /* Round down to multiple of blocksize */ 1611 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1); 1612 if (nmp->nm_wsize <= 0) 1613 nmp->nm_wsize = NFS_FABLKSIZE; 1614 } 1615 if (nmp->nm_wsize > maxio) 1616 nmp->nm_wsize = maxio; 1617 if (nmp->nm_wsize > NFS_MAXBSIZE) 1618 nmp->nm_wsize = NFS_MAXBSIZE; 1619 1620 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) { 1621 nmp->nm_rsize = argp->rsize; 1622 /* Round down to multiple of blocksize */ 1623 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1); 1624 if (nmp->nm_rsize <= 0) 1625 nmp->nm_rsize = NFS_FABLKSIZE; 1626 } 1627 if (nmp->nm_rsize > maxio) 1628 nmp->nm_rsize = maxio; 1629 if (nmp->nm_rsize > NFS_MAXBSIZE) 1630 nmp->nm_rsize = NFS_MAXBSIZE; 1631 1632 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) { 1633 nmp->nm_readdirsize = argp->readdirsize; 1634 } 1635 if (nmp->nm_readdirsize > maxio) 1636 nmp->nm_readdirsize = maxio; 1637 if (nmp->nm_readdirsize > nmp->nm_rsize) 1638 nmp->nm_readdirsize = nmp->nm_rsize; 1639 1640 if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 && 1641 argp->maxgrouplist <= NFS_MAXGRPS) 1642 nmp->nm_numgrps = argp->maxgrouplist; 1643 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0 && 1644 argp->readahead <= NFS_MAXRAHEAD) 1645 nmp->nm_readahead = argp->readahead; 1646 if (argp->flags & NFSMNT_READAHEAD) 1647 nmp->nm_readahead = argp->readahead; 1648 if (nmp->nm_readahead < 0) 1649 nmp->nm_readahead = 0; 1650 else if (nmp->nm_readahead > NFS_MAXRAHEAD) 1651 nmp->nm_readahead = NFS_MAXRAHEAD; 1652 1653 if (argp->version >= 4) { 1654 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0) 1655 nmp->nm_acregmin = argp->acregmin; 1656 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0) 1657 nmp->nm_acregmax = argp->acregmax; 1658 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0) 1659 nmp->nm_acdirmin = argp->acdirmin; 1660 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0) 1661 nmp->nm_acdirmax = argp->acdirmax; 1662 if (nmp->nm_acregmin > nmp->nm_acregmax) 1663 nmp->nm_acregmin = nmp->nm_acregmax; 1664 if (nmp->nm_acdirmin > nmp->nm_acdirmax) 1665 nmp->nm_acdirmin = nmp->nm_acdirmax; 1666 } 1667 if (argp->version >= 5) { 1668 if (argp->flags & NFSMNT_SECFLAVOR) { 1669 /* 1670 * Check for valid security flavor 1671 */ 1672 switch (argp->auth) { 1673 case RPCAUTH_SYS: 1674 case RPCAUTH_KRB5: 1675 case RPCAUTH_KRB5I: 1676 case RPCAUTH_KRB5P: 1677 nmp->nm_auth = argp->auth; 1678 break; 1679 default: 1680 error = EINVAL; 1681 goto bad; 1682 } 1683 } 1684 } 1685 1686 /* set up the version-specific function tables */ 1687 if (nmp->nm_vers < NFS_VER4) 1688 nmp->nm_funcs = &nfs3_funcs; 1689 else 1690 nmp->nm_funcs = &nfs4_funcs; 1691 1692 /* Set up the sockets and related info */ 1693 nmp->nm_sotype = argp->sotype; 1694 nmp->nm_soproto = argp->proto; 1695 if (nmp->nm_sotype == SOCK_DGRAM) 1696 TAILQ_INIT(&nmp->nm_cwndq); 1697 1698 lck_mtx_unlock(&nmp->nm_lock); 1699 1700 /* make sure mbuf constants are set up */ 1701 if (!nfs_mbuf_mhlen) 1702 nfs_mbuf_init(); 1703 1704 /* NFS does its own node locking */ 1705 mp->mnt_vtable->vfc_threadsafe = TRUE; 1706 1707 /* set up the socket */ 1708 if ((error = nfs_connect(nmp))) 1709 goto bad; 1710 1711 /* 1712 * Get the root node/attributes from the NFS server and 1713 * do any basic, version-specific setup. 1714 */ 1715 error = nmp->nm_funcs->nf_mount(nmp, ctx, argp, &np); 1716 if (error) 1717 goto bad; 1718 1719 /* 1720 * A reference count is needed on the node representing the 1721 * remote root. If this object is not persistent, then backward 1722 * traversals of the mount point (i.e. "..") will not work if 1723 * the node gets flushed out of the cache. 1724 */ 1725 nmp->nm_dnp = np; 1726 *vpp = NFSTOV(np); 1727 /* get usecount and drop iocount */ 1728 error = vnode_ref(*vpp); 1729 vnode_put(*vpp); 1730 if (error) 1731 goto bad; 1732 1733 /* 1734 * Do statfs to ensure static info gets set to reasonable values. 1735 */ 1736 if ((error = nmp->nm_funcs->nf_update_statfs(nmp, ctx))) 1737 goto bad; 1738 sbp = vfs_statfs(mp); 1739 sbp->f_bsize = nmp->nm_fsattr.nfsa_bsize; 1740 sbp->f_blocks = nmp->nm_fsattr.nfsa_space_total / sbp->f_bsize; 1741 sbp->f_bfree = nmp->nm_fsattr.nfsa_space_free / sbp->f_bsize; 1742 sbp->f_bavail = nmp->nm_fsattr.nfsa_space_avail / sbp->f_bsize; 1743 sbp->f_bused = (nmp->nm_fsattr.nfsa_space_total / sbp->f_bsize) - 1744 (nmp->nm_fsattr.nfsa_space_free / sbp->f_bsize); 1745 sbp->f_files = nmp->nm_fsattr.nfsa_files_total; 1746 sbp->f_ffree = nmp->nm_fsattr.nfsa_files_free; 1747 sbp->f_iosize = nfs_iosize; 1748 1749 /* 1750 * Calculate the size used for I/O buffers. Use the larger 1751 * of the two sizes to minimise NFS requests but make sure 1752 * that it is at least one VM page to avoid wasting buffer 1753 * space and to allow easy mmapping of I/O buffers. 1754 * The read/write RPC calls handle the splitting up of 1755 * buffers into multiple requests if the buffer size is 1756 * larger than the I/O size. 1757 */ 1758 iosize = max(nmp->nm_rsize, nmp->nm_wsize); 1759 if (iosize < PAGE_SIZE) 1760 iosize = PAGE_SIZE; 1761 nmp->nm_biosize = trunc_page_32(iosize); 1762 1763 /* 1764 * V3 mounts give us a (relatively) reliable remote access(2) 1765 * call, so advertise the fact. 1766 * 1767 * XXX this may not be the best way to go, as the granularity 1768 * offered isn't a good match to our needs. 1769 */ 1770 if (nmp->nm_vers != NFS_VER2) 1771 vfs_setauthopaqueaccess(mp); 1772 1773 if (nmp->nm_flag & NFSMNT_LOCALLOCKS) 1774 vfs_setlocklocal(nmp->nm_mountp); 1775 if (!(nmp->nm_flag & (NFSMNT_NOLOCKS|NFSMNT_LOCALLOCKS))) 1776 nfs_lockd_mount_change(1); 1777 1778 lck_mtx_lock(&nmp->nm_lock); 1779 nmp->nm_state |= NFSSTA_MOUNTED; 1780 lck_mtx_unlock(&nmp->nm_lock); 1781 return (0); 1782bad: 1783 /* mark the socket for termination */ 1784 lck_mtx_lock(&nmp->nm_lock); 1785 nmp->nm_sockflags |= NMSOCK_UNMOUNT; 1786 /* wait for any socket poking to complete */ 1787 while (nmp->nm_sockflags & NMSOCK_POKE) 1788 msleep(&nmp->nm_sockflags, &nmp->nm_lock, PZERO-1, "nfswaitpoke", &ts); 1789 /* wait for the socket thread to terminate */ 1790 while (nmp->nm_sockthd) { 1791 wakeup(&nmp->nm_sockthd); 1792 msleep(&nmp->nm_sockthd, &nmp->nm_lock, PZERO-1, "nfswaitsockthd", &ts); 1793 } 1794 /* tear down the socket */ 1795 lck_mtx_unlock(&nmp->nm_lock); 1796 nfs_disconnect(nmp); 1797 if (nmp->nm_renew_timer) { 1798 thread_call_cancel(nmp->nm_renew_timer); 1799 thread_call_free(nmp->nm_renew_timer); 1800 } 1801 lck_mtx_destroy(&nmp->nm_lock, nfs_mount_grp); 1802 FREE_ZONE((caddr_t)nmp, sizeof (struct nfsmount), M_NFSMNT); 1803 mbuf_freem(nam); 1804 return (error); 1805} 1806 1807 1808/* 1809 * unmount system call 1810 */ 1811static int 1812nfs_vfs_unmount( 1813 mount_t mp, 1814 int mntflags, 1815 __unused vfs_context_t ctx) 1816{ 1817 struct nfsmount *nmp; 1818 vnode_t vp; 1819 int error, flags = 0, docallback; 1820 struct nfsreq *req, *treq; 1821 struct nfs_reqqhead iodq; 1822 struct timespec ts = { 1, 0 }; 1823 1824 nmp = VFSTONFS(mp); 1825 lck_mtx_lock(&nmp->nm_lock); 1826 /* 1827 * During a force unmount we want to... 1828 * Mark that we are doing a force unmount. 1829 * Make the mountpoint soft. 1830 */ 1831 if (mntflags & MNT_FORCE) { 1832 flags |= FORCECLOSE; 1833 nmp->nm_state |= NFSSTA_FORCE; 1834 nmp->nm_flag |= NFSMNT_SOFT; 1835 } 1836 /* 1837 * Goes something like this.. 1838 * - Call vflush() to clear out vnodes for this file system, 1839 * except for the swap files. Deal with them in 2nd pass. 1840 * - Decrement reference on the vnode representing remote root. 1841 * - Close the socket 1842 * - Free up the data structures 1843 */ 1844 vp = NFSTOV(nmp->nm_dnp); 1845 lck_mtx_unlock(&nmp->nm_lock); 1846 1847 /* 1848 * vflush will check for busy vnodes on mountpoint. 1849 * Will do the right thing for MNT_FORCE. That is, we should 1850 * not get EBUSY back. 1851 */ 1852 error = vflush(mp, vp, SKIPSWAP | flags); 1853 if (mntflags & MNT_FORCE) { 1854 error = vflush(mp, NULLVP, flags); /* locks vp in the process */ 1855 } else { 1856 if (vnode_isinuse(vp, 1)) 1857 return (EBUSY); 1858 error = vflush(mp, vp, flags); 1859 } 1860 if (error) 1861 return (error); 1862 1863 lck_mtx_lock(&nmp->nm_lock); 1864 nmp->nm_state &= ~NFSSTA_MOUNTED; 1865 lck_mtx_unlock(&nmp->nm_lock); 1866 1867 /* 1868 * Release the root vnode reference held by mountnfs() 1869 */ 1870 vnode_rele(vp); 1871 1872 vflush(mp, NULLVP, FORCECLOSE); 1873 1874 /* 1875 * Destroy any RPCSEC_GSS contexts 1876 */ 1877 if (!TAILQ_EMPTY(&nmp->nm_gsscl)) 1878 nfs_gss_clnt_ctx_unmount(nmp, mntflags); 1879 1880 vfs_setfsprivate(mp, 0); /* don't want to end up using stale vp */ 1881 1882 /* mark the socket for termination */ 1883 lck_mtx_lock(&nmp->nm_lock); 1884 nmp->nm_sockflags |= NMSOCK_UNMOUNT; 1885 1886 /* wait for any socket poking to complete */ 1887 while (nmp->nm_sockflags & NMSOCK_POKE) 1888 msleep(&nmp->nm_sockflags, &nmp->nm_lock, PZERO-1, "nfswaitpoke", &ts); 1889 1890 /* wait for the socket thread to terminate */ 1891 while (nmp->nm_sockthd) { 1892 wakeup(&nmp->nm_sockthd); 1893 msleep(&nmp->nm_sockthd, &nmp->nm_lock, PZERO-1, "nfswaitsockthd", &ts); 1894 } 1895 1896 /* tear down the socket */ 1897 lck_mtx_unlock(&nmp->nm_lock); 1898 nfs_disconnect(nmp); 1899 lck_mtx_lock(&nmp->nm_lock); 1900 1901 /* cancel any renew timer */ 1902 if (nmp->nm_renew_timer) { 1903 thread_call_cancel(nmp->nm_renew_timer); 1904 thread_call_free(nmp->nm_renew_timer); 1905 } 1906 1907 mbuf_freem(nmp->nm_nam); 1908 lck_mtx_unlock(&nmp->nm_lock); 1909 1910 if (!(nmp->nm_flag & (NFSMNT_NOLOCKS|NFSMNT_LOCALLOCKS))) 1911 nfs_lockd_mount_change(-1); 1912 1913 /* 1914 * Loop through outstanding request list and remove dangling 1915 * references to defunct nfsmount struct 1916 */ 1917 TAILQ_INIT(&iodq); 1918 lck_mtx_lock(nfs_request_mutex); 1919 TAILQ_FOREACH(req, &nfs_reqq, r_chain) { 1920 if (req->r_nmp == nmp) { 1921 lck_mtx_lock(&req->r_mtx); 1922 req->r_nmp = NULL; 1923 lck_mtx_unlock(&req->r_mtx); 1924 if (req->r_callback.rcb_func) { 1925 /* async I/O RPC needs to be finished */ 1926 lck_mtx_lock(nfsiod_mutex); 1927 if (req->r_achain.tqe_next == NFSREQNOLIST) 1928 TAILQ_INSERT_TAIL(&iodq, req, r_achain); 1929 lck_mtx_unlock(nfsiod_mutex); 1930 } 1931 lck_mtx_lock(&nmp->nm_lock); 1932 if (req->r_rchain.tqe_next != NFSREQNOLIST) { 1933 TAILQ_REMOVE(&nmp->nm_resendq, req, r_rchain); 1934 req->r_rchain.tqe_next = NFSREQNOLIST; 1935 req->r_flags &= ~R_RESENDQ; 1936 } 1937 lck_mtx_unlock(&nmp->nm_lock); 1938 wakeup(req); 1939 } 1940 } 1941 lck_mtx_unlock(nfs_request_mutex); 1942 1943 /* finish any async I/O RPCs queued up */ 1944 lck_mtx_lock(nfsiod_mutex); 1945 TAILQ_CONCAT(&iodq, &nmp->nm_iodq, r_achain); 1946 lck_mtx_unlock(nfsiod_mutex); 1947 TAILQ_FOREACH_SAFE(req, &iodq, r_achain, treq) { 1948 TAILQ_REMOVE(&iodq, req, r_achain); 1949 req->r_achain.tqe_next = NFSREQNOLIST; 1950 lck_mtx_lock(&req->r_mtx); 1951 req->r_error = ENXIO; 1952 docallback = !(req->r_flags & R_WAITSENT); 1953 lck_mtx_unlock(&req->r_mtx); 1954 if (docallback) 1955 req->r_callback.rcb_func(req); 1956 } 1957 1958 lck_mtx_destroy(&nmp->nm_lock, nfs_mount_grp); 1959 FREE_ZONE((caddr_t)nmp, sizeof (struct nfsmount), M_NFSMNT); 1960 return (0); 1961} 1962 1963/* 1964 * Return root of a filesystem 1965 */ 1966static int 1967nfs_vfs_root(mount_t mp, vnode_t *vpp, __unused vfs_context_t ctx) 1968{ 1969 vnode_t vp; 1970 struct nfsmount *nmp; 1971 int error; 1972 u_long vpid; 1973 1974 nmp = VFSTONFS(mp); 1975 vp = NFSTOV(nmp->nm_dnp); 1976 vpid = vnode_vid(vp); 1977 while ((error = vnode_getwithvid(vp, vpid))) { 1978 /* vnode_get() may return ENOENT if the dir changes. */ 1979 /* If that happens, just try it again, else return the error. */ 1980 if ((error != ENOENT) || (vnode_vid(vp) == vpid)) 1981 return (error); 1982 vpid = vnode_vid(vp); 1983 } 1984 *vpp = vp; 1985 return (0); 1986} 1987 1988/* 1989 * Do operations associated with quotas 1990 */ 1991#if !QUOTA 1992static int 1993nfs_vfs_quotactl( 1994 __unused mount_t mp, 1995 __unused int cmds, 1996 __unused uid_t uid, 1997 __unused caddr_t datap, 1998 __unused vfs_context_t context) 1999{ 2000 return (ENOTSUP); 2001} 2002#else 2003static int 2004nfs_aux_request( 2005 struct nfsmount *nmp, 2006 thread_t thd, 2007 struct sockaddr_in *saddr, 2008 mbuf_t mreq, 2009 uint32_t xid, 2010 int timeo, 2011 struct nfsm_chain *nmrep) 2012{ 2013 int error = 0, on = 1, try, sendat = 2; 2014 socket_t so = NULL; 2015 struct timeval tv = { 1, 0 }; 2016 mbuf_t m, mrep = NULL; 2017 struct msghdr msg; 2018 uint32_t rxid, reply, reply_status, rejected_status; 2019 uint32_t verf_type, verf_len, accepted_status; 2020 size_t readlen; 2021 2022 /* create socket and set options */ 2023 if (((error = sock_socket(saddr->sin_family, SOCK_DGRAM, IPPROTO_UDP, NULL, NULL, &so))) || 2024 ((error = sock_setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)))) || 2025 ((error = sock_setsockopt(so, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)))) || 2026 ((error = sock_setsockopt(so, SOL_SOCKET, SO_NOADDRERR, &on, sizeof(on))))) 2027 goto nfsmout; 2028 2029 for (try=0; try < timeo; try++) { 2030 if ((error = nfs_sigintr(nmp, NULL, thd, 0))) 2031 break; 2032 if (!try || (try == sendat)) { 2033 /* send the request (resending periodically) */ 2034 if ((error = mbuf_copym(mreq, 0, MBUF_COPYALL, MBUF_WAITOK, &m))) 2035 goto nfsmout; 2036 bzero(&msg, sizeof(msg)); 2037 msg.msg_name = saddr; 2038 msg.msg_namelen = saddr->sin_len; 2039 if ((error = sock_sendmbuf(so, &msg, m, 0, NULL))) 2040 goto nfsmout; 2041 sendat *= 2; 2042 if (sendat > 30) 2043 sendat = 30; 2044 } 2045 /* wait for the response */ 2046 readlen = 1<<18; 2047 bzero(&msg, sizeof(msg)); 2048 error = sock_receivembuf(so, &msg, &mrep, 0, &readlen); 2049 if (error == EWOULDBLOCK) 2050 continue; 2051 nfsmout_if(error); 2052 /* parse the response */ 2053 nfsm_chain_dissect_init(error, nmrep, mrep); 2054 nfsm_chain_get_32(error, nmrep, rxid); 2055 nfsm_chain_get_32(error, nmrep, reply); 2056 nfsmout_if(error); 2057 if ((rxid != xid) || (reply != RPC_REPLY)) 2058 error = EBADRPC; 2059 nfsm_chain_get_32(error, nmrep, reply_status); 2060 nfsmout_if(error); 2061 if (reply_status == RPC_MSGDENIED) { 2062 nfsm_chain_get_32(error, nmrep, rejected_status); 2063 nfsmout_if(error); 2064 error = (rejected_status == RPC_MISMATCH) ? ENOTSUP : EACCES; 2065 goto nfsmout; 2066 } 2067 nfsm_chain_get_32(error, nmrep, verf_type); /* verifier flavor */ 2068 nfsm_chain_get_32(error, nmrep, verf_len); /* verifier length */ 2069 nfsmout_if(error); 2070 if (verf_len) 2071 nfsm_chain_adv(error, nmrep, nfsm_rndup(verf_len)); 2072 nfsm_chain_get_32(error, nmrep, accepted_status); 2073 nfsm_assert(error, (accepted_status == RPC_SUCCESS), EIO); 2074 break; 2075 } 2076nfsmout: 2077 if (so) { 2078 sock_shutdown(so, SHUT_RDWR); 2079 sock_close(so); 2080 } 2081 mbuf_freem(mreq); 2082 return (error); 2083} 2084 2085static int 2086nfs3_getquota(struct nfsmount *nmp, vfs_context_t ctx, u_long id, int type, struct dqblk *dqb) 2087{ 2088 int error = 0, auth_len, slen, timeo; 2089 int rqvers = (type == GRPQUOTA) ? RPCRQUOTA_EXT_VER : RPCRQUOTA_VER; 2090 thread_t thd = vfs_context_thread(ctx); 2091 kauth_cred_t cred = vfs_context_ucred(ctx); 2092 char *path; 2093 uint64_t xid = 0; 2094 struct nfsm_chain nmreq, nmrep; 2095 mbuf_t mreq; 2096 uint32_t val = 0, bsize; 2097 struct sockaddr *nam = mbuf_data(nmp->nm_nam); 2098 struct sockaddr_in saddr; 2099 struct timeval now; 2100 2101 bcopy(nam, &saddr, min(sizeof(saddr), nam->sa_len)); 2102 auth_len = ((((cred->cr_ngroups - 1) > nmp->nm_numgrps) ? 2103 nmp->nm_numgrps : (cred->cr_ngroups - 1)) << 2) + 2104 5 * NFSX_UNSIGNED; 2105 timeo = (nmp->nm_flag & NFSMNT_SOFT) ? 10 : 60; 2106 nfsm_chain_null(&nmreq); 2107 nfsm_chain_null(&nmrep); 2108 2109 /* check if we have a recently cached rquota port */ 2110 if (nmp->nm_rqport) { 2111 microuptime(&now); 2112 if ((nmp->nm_rqportstamp + 60) >= (uint32_t)now.tv_sec) 2113 goto got_rqport; 2114 } 2115 2116 /* send portmap request to get rquota port */ 2117 saddr.sin_port = htons(PMAPPORT); 2118 nfsm_chain_build_alloc_init(error, &nmreq, 4*NFSX_UNSIGNED); 2119 nfsm_chain_add_32(error, &nmreq, RPCPROG_RQUOTA); 2120 nfsm_chain_add_32(error, &nmreq, rqvers); 2121 nfsm_chain_add_32(error, &nmreq, IPPROTO_UDP); 2122 nfsm_chain_add_32(error, &nmreq, 0); 2123 nfsm_chain_build_done(error, &nmreq); 2124 nfsmout_if(error); 2125 error = nfsm_rpchead2(SOCK_DGRAM, PMAPPROG, PMAPVERS, PMAPPROC_GETPORT, 2126 RPCAUTH_SYS, auth_len, cred, NULL, nmreq.nmc_mhead, &xid, &mreq); 2127 nfsmout_if(error); 2128 nmreq.nmc_mhead = NULL; 2129 error = nfs_aux_request(nmp, thd, &saddr, mreq, R_XID32(xid), timeo, &nmrep); 2130 nfsmout_if(error); 2131 2132 /* grab rquota port from portmap response */ 2133 nfsm_chain_get_32(error, &nmrep, val); 2134 nfsmout_if(error); 2135 nmp->nm_rqport = val; 2136 microuptime(&now); 2137 nmp->nm_rqportstamp = now.tv_sec; 2138 nfsm_chain_cleanup(&nmreq); 2139 nfsm_chain_cleanup(&nmrep); 2140 xid = 0; 2141 2142got_rqport: 2143 /* rquota request */ 2144 saddr.sin_port = htons(nmp->nm_rqport); 2145 path = &vfs_statfs(nmp->nm_mountp)->f_mntfromname[0]; 2146 while (*path && (*path != '/')) 2147 path++; 2148 slen = strlen(path); 2149 nfsm_chain_build_alloc_init(error, &nmreq, 3 * NFSX_UNSIGNED + nfsm_rndup(slen)); 2150 nfsm_chain_add_string(error, &nmreq, path, slen); 2151 if (type == GRPQUOTA) 2152 nfsm_chain_add_32(error, &nmreq, type); 2153 nfsm_chain_add_32(error, &nmreq, id); 2154 nfsm_chain_build_done(error, &nmreq); 2155 nfsmout_if(error); 2156 error = nfsm_rpchead2(SOCK_DGRAM, RPCPROG_RQUOTA, rqvers, RPCRQUOTA_GET, 2157 RPCAUTH_SYS, auth_len, cred, NULL, nmreq.nmc_mhead, &xid, &mreq); 2158 nfsmout_if(error); 2159 nmreq.nmc_mhead = NULL; 2160 error = nfs_aux_request(nmp, thd, &saddr, mreq, R_XID32(xid), timeo, &nmrep); 2161 nfsmout_if(error); 2162 2163 /* parse rquota response */ 2164 nfsm_chain_get_32(error, &nmrep, val); 2165 if (!error && (val != RQUOTA_STAT_OK)) { 2166 if (val == RQUOTA_STAT_NOQUOTA) 2167 error = ENOENT; 2168 else if (val == RQUOTA_STAT_EPERM) 2169 error = EPERM; 2170 else 2171 error = EIO; 2172 } 2173 nfsm_chain_get_32(error, &nmrep, bsize); 2174 nfsm_chain_adv(error, &nmrep, NFSX_UNSIGNED); 2175 nfsm_chain_get_32(error, &nmrep, val); 2176 nfsmout_if(error); 2177 dqb->dqb_bhardlimit = (uint64_t)val * bsize; 2178 nfsm_chain_get_32(error, &nmrep, val); 2179 nfsmout_if(error); 2180 dqb->dqb_bsoftlimit = (uint64_t)val * bsize; 2181 nfsm_chain_get_32(error, &nmrep, val); 2182 nfsmout_if(error); 2183 dqb->dqb_curbytes = (uint64_t)val * bsize; 2184 nfsm_chain_get_32(error, &nmrep, dqb->dqb_ihardlimit); 2185 nfsm_chain_get_32(error, &nmrep, dqb->dqb_isoftlimit); 2186 nfsm_chain_get_32(error, &nmrep, dqb->dqb_curinodes); 2187 nfsm_chain_get_32(error, &nmrep, dqb->dqb_btime); 2188 nfsm_chain_get_32(error, &nmrep, dqb->dqb_itime); 2189 nfsmout_if(error); 2190 dqb->dqb_id = id; 2191nfsmout: 2192 nfsm_chain_cleanup(&nmreq); 2193 nfsm_chain_cleanup(&nmrep); 2194 return (error); 2195} 2196 2197static int 2198nfs4_getquota(struct nfsmount *nmp, vfs_context_t ctx, u_long id, int type, struct dqblk *dqb) 2199{ 2200 nfsnode_t np; 2201 int error = 0, status, nfsvers, numops; 2202 u_int64_t xid; 2203 struct nfsm_chain nmreq, nmrep; 2204 uint32_t bitmap[NFS_ATTR_BITMAP_LEN]; 2205 thread_t thd = vfs_context_thread(ctx); 2206 kauth_cred_t cred = vfs_context_ucred(ctx); 2207 2208 if (type != USRQUOTA) /* NFSv4 only supports user quotas */ 2209 return (ENOTSUP); 2210 2211 /* first check that the server supports any of the quota attributes */ 2212 if (!NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_QUOTA_AVAIL_HARD) && 2213 !NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_QUOTA_AVAIL_SOFT) && 2214 !NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_supp_attr, NFS_FATTR_QUOTA_USED)) 2215 return (ENOTSUP); 2216 2217 /* 2218 * The credential passed to the server needs to have 2219 * an effective uid that matches the given uid. 2220 */ 2221 if (id != kauth_cred_getuid(cred)) { 2222 struct ucred temp_cred; 2223 bzero(&temp_cred, sizeof(temp_cred)); 2224 temp_cred.cr_uid = id; 2225 temp_cred.cr_ngroups = cred->cr_ngroups; 2226 bcopy(cred->cr_groups, temp_cred.cr_groups, sizeof(temp_cred.cr_groups)); 2227 cred = kauth_cred_create(&temp_cred); 2228 if (!IS_VALID_CRED(cred)) 2229 return (ENOMEM); 2230 } else { 2231 kauth_cred_ref(cred); 2232 } 2233 2234 nfsvers = nmp->nm_vers; 2235 np = nmp->nm_dnp; 2236 if ((error = vnode_get(NFSTOV(np)))) { 2237 kauth_cred_unref(&cred); 2238 return(error); 2239 } 2240 2241 nfsm_chain_null(&nmreq); 2242 nfsm_chain_null(&nmrep); 2243 2244 // PUTFH + GETATTR 2245 numops = 2; 2246 nfsm_chain_build_alloc_init(error, &nmreq, 15 * NFSX_UNSIGNED); 2247 nfsm_chain_add_compound_header(error, &nmreq, "quota", numops); 2248 numops--; 2249 nfsm_chain_add_32(error, &nmreq, NFS_OP_PUTFH); 2250 nfsm_chain_add_fh(error, &nmreq, nfsvers, np->n_fhp, np->n_fhsize); 2251 numops--; 2252 nfsm_chain_add_32(error, &nmreq, NFS_OP_GETATTR); 2253 NFS_CLEAR_ATTRIBUTES(bitmap); 2254 NFS_BITMAP_SET(bitmap, NFS_FATTR_QUOTA_AVAIL_HARD); 2255 NFS_BITMAP_SET(bitmap, NFS_FATTR_QUOTA_AVAIL_SOFT); 2256 NFS_BITMAP_SET(bitmap, NFS_FATTR_QUOTA_USED); 2257 nfsm_chain_add_bitmap_masked(error, &nmreq, bitmap, 2258 NFS_ATTR_BITMAP_LEN, nmp->nm_fsattr.nfsa_supp_attr); 2259 nfsm_chain_build_done(error, &nmreq); 2260 nfsm_assert(error, (numops == 0), EPROTO); 2261 nfsmout_if(error); 2262 error = nfs_request2(np, NULL, &nmreq, NFSPROC4_COMPOUND, thd, cred, 0, &nmrep, &xid, &status); 2263 nfsm_chain_skip_tag(error, &nmrep); 2264 nfsm_chain_get_32(error, &nmrep, numops); 2265 nfsm_chain_op_check(error, &nmrep, NFS_OP_PUTFH); 2266 nfsm_chain_op_check(error, &nmrep, NFS_OP_GETATTR); 2267 nfsm_assert(error, NFSTONMP(np), ENXIO); 2268 nfsmout_if(error); 2269 error = nfs4_parsefattr(&nmrep, NULL, NULL, NULL, dqb); 2270 nfsmout_if(error); 2271 nfsm_assert(error, NFSTONMP(np), ENXIO); 2272nfsmout: 2273 nfsm_chain_cleanup(&nmreq); 2274 nfsm_chain_cleanup(&nmrep); 2275 vnode_put(NFSTOV(np)); 2276 kauth_cred_unref(&cred); 2277 return (error); 2278} 2279 2280static int 2281nfs_vfs_quotactl(mount_t mp, int cmds, uid_t uid, caddr_t datap, vfs_context_t ctx) 2282{ 2283 struct nfsmount *nmp; 2284 int cmd, type, error, nfsvers; 2285 uid_t ruid = vfs_context_ucred(ctx)->cr_ruid; 2286 struct dqblk *dqb = (struct dqblk*)datap; 2287 2288 if (!(nmp = VFSTONFS(mp))) 2289 return (ENXIO); 2290 nfsvers = nmp->nm_vers; 2291 2292 if (uid == ~0U) 2293 uid = ruid; 2294 2295 /* we can only support Q_GETQUOTA */ 2296 cmd = cmds >> SUBCMDSHIFT; 2297 switch (cmd) { 2298 case Q_GETQUOTA: 2299 break; 2300 case Q_QUOTAON: 2301 case Q_QUOTAOFF: 2302 case Q_SETQUOTA: 2303 case Q_SETUSE: 2304 case Q_SYNC: 2305 case Q_QUOTASTAT: 2306 return (ENOTSUP); 2307 default: 2308 return (EINVAL); 2309 } 2310 2311 type = cmds & SUBCMDMASK; 2312 if ((u_int)type >= MAXQUOTAS) 2313 return (EINVAL); 2314 if ((uid != ruid) && ((error = vfs_context_suser(ctx)))) 2315 return (error); 2316 2317 if (vfs_busy(mp, LK_NOWAIT)) 2318 return (0); 2319 bzero(dqb, sizeof(*dqb)); 2320 error = nmp->nm_funcs->nf_getquota(nmp, ctx, uid, type, dqb); 2321 vfs_unbusy(mp); 2322 return (error); 2323} 2324#endif 2325 2326/* 2327 * Flush out the buffer cache 2328 */ 2329 2330struct nfs_sync_cargs { 2331 thread_t thd; 2332 int waitfor; 2333 int error; 2334}; 2335 2336static int 2337nfs_sync_callout(vnode_t vp, void *arg) 2338{ 2339 struct nfs_sync_cargs *cargs = (struct nfs_sync_cargs*)arg; 2340 int error; 2341 2342 if (LIST_EMPTY(&VTONFS(vp)->n_dirtyblkhd)) 2343 return (VNODE_RETURNED); 2344 if (VTONFS(vp)->n_wrbusy > 0) 2345 return (VNODE_RETURNED); 2346 if (VTONFS(vp)->n_bflag & (NBFLUSHINPROG|NBINVALINPROG)) 2347 return (VNODE_RETURNED); 2348 2349 error = nfs_flush(VTONFS(vp), cargs->waitfor, cargs->thd, 0); 2350 if (error) 2351 cargs->error = error; 2352 2353 return (VNODE_RETURNED); 2354} 2355 2356static int 2357nfs_vfs_sync(mount_t mp, int waitfor, vfs_context_t ctx) 2358{ 2359 struct nfs_sync_cargs cargs; 2360 2361 cargs.waitfor = waitfor; 2362 cargs.thd = vfs_context_thread(ctx); 2363 cargs.error = 0; 2364 2365 vnode_iterate(mp, 0, nfs_sync_callout, &cargs); 2366 2367 return (cargs.error); 2368} 2369 2370/* 2371 * NFS flat namespace lookup. 2372 * Currently unsupported. 2373 */ 2374/*ARGSUSED*/ 2375static int 2376nfs_vfs_vget( 2377 __unused mount_t mp, 2378 __unused ino64_t ino, 2379 __unused vnode_t *vpp, 2380 __unused vfs_context_t ctx) 2381{ 2382 2383 return (ENOTSUP); 2384} 2385 2386/* 2387 * At this point, this should never happen 2388 */ 2389/*ARGSUSED*/ 2390static int 2391nfs_vfs_fhtovp( 2392 __unused mount_t mp, 2393 __unused int fhlen, 2394 __unused unsigned char *fhp, 2395 __unused vnode_t *vpp, 2396 __unused vfs_context_t ctx) 2397{ 2398 2399 return (ENOTSUP); 2400} 2401 2402/* 2403 * Vnode pointer to File handle, should never happen either 2404 */ 2405/*ARGSUSED*/ 2406static int 2407nfs_vfs_vptofh( 2408 __unused vnode_t vp, 2409 __unused int *fhlenp, 2410 __unused unsigned char *fhp, 2411 __unused vfs_context_t ctx) 2412{ 2413 2414 return (ENOTSUP); 2415} 2416 2417/* 2418 * Vfs start routine, a no-op. 2419 */ 2420/*ARGSUSED*/ 2421static int 2422nfs_vfs_start( 2423 __unused mount_t mp, 2424 __unused int flags, 2425 __unused vfs_context_t ctx) 2426{ 2427 2428 return (0); 2429} 2430 2431/* 2432 * Do that sysctl thang... 2433 */ 2434static int 2435nfs_vfs_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp, 2436 user_addr_t newp, size_t newlen, vfs_context_t ctx) 2437{ 2438 int error = 0, val, softnobrowse; 2439 struct sysctl_req *req = NULL; 2440 struct vfsidctl vc; 2441 struct user_vfsidctl user_vc; 2442 mount_t mp; 2443 struct nfsmount *nmp = NULL; 2444 struct vfsquery vq; 2445 boolean_t is_64_bit; 2446#if NFSSERVER 2447 struct nfs_exportfs *nxfs; 2448 struct nfs_export *nx; 2449 struct nfs_active_user_list *ulist; 2450 struct nfs_export_stat_desc stat_desc; 2451 struct nfs_export_stat_rec statrec; 2452 struct nfs_user_stat_node *unode, *unode_next; 2453 struct nfs_user_stat_desc ustat_desc; 2454 struct nfs_user_stat_user_rec ustat_rec; 2455 struct nfs_user_stat_path_rec upath_rec; 2456 uint bytes_avail, bytes_total, recs_copied; 2457 uint numExports, totlen, pos, numRecs, count; 2458#endif /* NFSSERVER */ 2459 2460 /* 2461 * All names at this level are terminal. 2462 */ 2463 if (namelen > 1) 2464 return (ENOTDIR); /* overloaded */ 2465 2466 is_64_bit = vfs_context_is64bit(ctx); 2467 2468 /* common code for "new style" VFS_CTL sysctl, get the mount. */ 2469 switch (name[0]) { 2470 case VFS_CTL_TIMEO: 2471 case VFS_CTL_QUERY: 2472 case VFS_CTL_NOLOCKS: 2473 req = CAST_DOWN(struct sysctl_req *, oldp); 2474 if (is_64_bit) { 2475 error = SYSCTL_IN(req, &user_vc, sizeof(user_vc)); 2476 if (error) 2477 return (error); 2478 mp = vfs_getvfs(&user_vc.vc_fsid); 2479 } else { 2480 error = SYSCTL_IN(req, &vc, sizeof(vc)); 2481 if (error) 2482 return (error); 2483 mp = vfs_getvfs(&vc.vc_fsid); 2484 } 2485 if (mp == NULL) 2486 return (ENOENT); 2487 nmp = VFSTONFS(mp); 2488 if (nmp == NULL) 2489 return (ENOENT); 2490 bzero(&vq, sizeof(vq)); 2491 req->newidx = 0; 2492 if (is_64_bit) { 2493 req->newptr = user_vc.vc_ptr; 2494 req->newlen = (size_t)user_vc.vc_len; 2495 } else { 2496 req->newptr = CAST_USER_ADDR_T(vc.vc_ptr); 2497 req->newlen = vc.vc_len; 2498 } 2499 } 2500 2501 switch(name[0]) { 2502 case NFS_NFSSTATS: 2503 if (!oldp) { 2504 *oldlenp = sizeof nfsstats; 2505 return (0); 2506 } 2507 2508 if (*oldlenp < sizeof nfsstats) { 2509 *oldlenp = sizeof nfsstats; 2510 return (ENOMEM); 2511 } 2512 2513 error = copyout(&nfsstats, oldp, sizeof nfsstats); 2514 if (error) 2515 return (error); 2516 2517 if (newp && newlen != sizeof nfsstats) 2518 return (EINVAL); 2519 2520 if (newp) 2521 return copyin(newp, &nfsstats, sizeof nfsstats); 2522 return (0); 2523#if NFSSERVER 2524 case NFS_EXPORTSTATS: 2525 /* setup export stat descriptor */ 2526 stat_desc.rec_vers = NFS_EXPORT_STAT_REC_VERSION; 2527 2528 if (!nfsrv_is_initialized()) { 2529 stat_desc.rec_count = 0; 2530 if (oldp && (*oldlenp >= sizeof(struct nfs_export_stat_desc))) 2531 error = copyout(&stat_desc, oldp, sizeof(struct nfs_export_stat_desc)); 2532 *oldlenp = sizeof(struct nfs_export_stat_desc); 2533 return (error); 2534 } 2535 2536 /* Count the number of exported directories */ 2537 lck_rw_lock_shared(&nfsrv_export_rwlock); 2538 numExports = 0; 2539 LIST_FOREACH(nxfs, &nfsrv_exports, nxfs_next) 2540 LIST_FOREACH(nx, &nxfs->nxfs_exports, nx_next) 2541 numExports += 1; 2542 2543 /* update stat descriptor's export record count */ 2544 stat_desc.rec_count = numExports; 2545 2546 /* calculate total size of required buffer */ 2547 totlen = sizeof(struct nfs_export_stat_desc) + (numExports * sizeof(struct nfs_export_stat_rec)); 2548 2549 /* Check caller's buffer */ 2550 if (oldp == 0) { 2551 lck_rw_done(&nfsrv_export_rwlock); 2552 /* indicate required buffer len */ 2553 *oldlenp = totlen; 2554 return (0); 2555 } 2556 2557 /* We require the caller's buffer to be at least large enough to hold the descriptor */ 2558 if (*oldlenp < sizeof(struct nfs_export_stat_desc)) { 2559 lck_rw_done(&nfsrv_export_rwlock); 2560 /* indicate required buffer len */ 2561 *oldlenp = totlen; 2562 return (ENOMEM); 2563 } 2564 2565 /* indicate required buffer len */ 2566 *oldlenp = totlen; 2567 2568 /* check if export table is empty */ 2569 if (!numExports) { 2570 lck_rw_done(&nfsrv_export_rwlock); 2571 error = copyout(&stat_desc, oldp, sizeof(struct nfs_export_stat_desc)); 2572 return (error); 2573 } 2574 2575 /* calculate how many actual export stat records fit into caller's buffer */ 2576 numRecs = (*oldlenp - sizeof(struct nfs_export_stat_desc)) / sizeof(struct nfs_export_stat_rec); 2577 2578 if (!numRecs) { 2579 /* caller's buffer can only accomodate descriptor */ 2580 lck_rw_done(&nfsrv_export_rwlock); 2581 stat_desc.rec_count = 0; 2582 error = copyout(&stat_desc, oldp, sizeof(struct nfs_export_stat_desc)); 2583 return (error); 2584 } 2585 2586 /* adjust to actual number of records to copyout to caller's buffer */ 2587 if (numRecs > numExports) 2588 numRecs = numExports; 2589 2590 /* set actual number of records we are returning */ 2591 stat_desc.rec_count = numRecs; 2592 2593 /* first copy out the stat descriptor */ 2594 pos = 0; 2595 error = copyout(&stat_desc, oldp + pos, sizeof(struct nfs_export_stat_desc)); 2596 if (error) { 2597 lck_rw_done(&nfsrv_export_rwlock); 2598 return (error); 2599 } 2600 pos += sizeof(struct nfs_export_stat_desc); 2601 2602 /* Loop through exported directories */ 2603 count = 0; 2604 LIST_FOREACH(nxfs, &nfsrv_exports, nxfs_next) { 2605 LIST_FOREACH(nx, &nxfs->nxfs_exports, nx_next) { 2606 2607 if (count >= numRecs) 2608 break; 2609 2610 /* build exported filesystem path */ 2611 snprintf(statrec.path, sizeof(statrec.path), "%s%s%s", 2612 nxfs->nxfs_path, ((nxfs->nxfs_path[1] && nx->nx_path[0]) ? "/" : ""), 2613 nx->nx_path); 2614 2615 /* build the 64-bit export stat counters */ 2616 statrec.ops = ((uint64_t)nx->nx_stats.ops.hi << 32) | 2617 nx->nx_stats.ops.lo; 2618 statrec.bytes_read = ((uint64_t)nx->nx_stats.bytes_read.hi << 32) | 2619 nx->nx_stats.bytes_read.lo; 2620 statrec.bytes_written = ((uint64_t)nx->nx_stats.bytes_written.hi << 32) | 2621 nx->nx_stats.bytes_written.lo; 2622 error = copyout(&statrec, oldp + pos, sizeof(statrec)); 2623 if (error) { 2624 lck_rw_done(&nfsrv_export_rwlock); 2625 return (error); 2626 } 2627 /* advance buffer position */ 2628 pos += sizeof(statrec); 2629 } 2630 } 2631 lck_rw_done(&nfsrv_export_rwlock); 2632 break; 2633 case NFS_USERSTATS: 2634 /* init structures used for copying out of kernel */ 2635 ustat_desc.rec_vers = NFS_USER_STAT_REC_VERSION; 2636 ustat_rec.rec_type = NFS_USER_STAT_USER_REC; 2637 upath_rec.rec_type = NFS_USER_STAT_PATH_REC; 2638 2639 /* initialize counters */ 2640 bytes_total = sizeof(struct nfs_user_stat_desc); 2641 bytes_avail = *oldlenp; 2642 recs_copied = 0; 2643 2644 if (!nfsrv_is_initialized()) /* NFS server not initialized, so no stats */ 2645 goto ustat_skip; 2646 2647 /* reclaim old expired user nodes */ 2648 nfsrv_active_user_list_reclaim(); 2649 2650 /* reserve space for the buffer descriptor */ 2651 if (bytes_avail >= sizeof(struct nfs_user_stat_desc)) 2652 bytes_avail -= sizeof(struct nfs_user_stat_desc); 2653 else 2654 bytes_avail = 0; 2655 2656 /* put buffer position past the buffer descriptor */ 2657 pos = sizeof(struct nfs_user_stat_desc); 2658 2659 /* Loop through exported directories */ 2660 lck_rw_lock_shared(&nfsrv_export_rwlock); 2661 LIST_FOREACH(nxfs, &nfsrv_exports, nxfs_next) { 2662 LIST_FOREACH(nx, &nxfs->nxfs_exports, nx_next) { 2663 /* copy out path */ 2664 if (bytes_avail >= sizeof(struct nfs_user_stat_path_rec)) { 2665 snprintf(upath_rec.path, sizeof(upath_rec.path), "%s%s%s", 2666 nxfs->nxfs_path, ((nxfs->nxfs_path[1] && nx->nx_path[0]) ? "/" : ""), 2667 nx->nx_path); 2668 2669 error = copyout(&upath_rec, oldp + pos, sizeof(struct nfs_user_stat_path_rec)); 2670 if (error) { 2671 /* punt */ 2672 goto ustat_done; 2673 } 2674 2675 pos += sizeof(struct nfs_user_stat_path_rec); 2676 bytes_avail -= sizeof(struct nfs_user_stat_path_rec); 2677 recs_copied++; 2678 } 2679 else { 2680 /* Caller's buffer is exhausted */ 2681 bytes_avail = 0; 2682 } 2683 2684 bytes_total += sizeof(struct nfs_user_stat_path_rec); 2685 2686 /* Scan through all user nodes of this export */ 2687 ulist = &nx->nx_user_list; 2688 lck_mtx_lock(&ulist->user_mutex); 2689 for (unode = TAILQ_FIRST(&ulist->user_lru); unode; unode = unode_next) { 2690 unode_next = TAILQ_NEXT(unode, lru_link); 2691 2692 /* copy out node if there is space */ 2693 if (bytes_avail >= sizeof(struct nfs_user_stat_user_rec)) { 2694 /* prepare a user stat rec for copying out */ 2695 ustat_rec.uid = unode->uid; 2696 bcopy(&unode->sock, &ustat_rec.sock, unode->sock.ss_len); 2697 ustat_rec.ops = unode->ops; 2698 ustat_rec.bytes_read = unode->bytes_read; 2699 ustat_rec.bytes_written = unode->bytes_written; 2700 ustat_rec.tm_start = unode->tm_start; 2701 ustat_rec.tm_last = unode->tm_last; 2702 2703 error = copyout(&ustat_rec, oldp + pos, sizeof(struct nfs_user_stat_user_rec)); 2704 2705 if (error) { 2706 /* punt */ 2707 lck_mtx_unlock(&ulist->user_mutex); 2708 goto ustat_done; 2709 } 2710 2711 pos += sizeof(struct nfs_user_stat_user_rec); 2712 bytes_avail -= sizeof(struct nfs_user_stat_user_rec); 2713 recs_copied++; 2714 } 2715 else { 2716 /* Caller's buffer is exhausted */ 2717 bytes_avail = 0; 2718 } 2719 bytes_total += sizeof(struct nfs_user_stat_user_rec); 2720 } 2721 /* can unlock this export's list now */ 2722 lck_mtx_unlock(&ulist->user_mutex); 2723 } 2724 } 2725 2726ustat_done: 2727 /* unlock the export table */ 2728 lck_rw_done(&nfsrv_export_rwlock); 2729 2730ustat_skip: 2731 /* indicate number of actual records copied */ 2732 ustat_desc.rec_count = recs_copied; 2733 2734 if (!error) { 2735 /* check if there was enough room for the buffer descriptor */ 2736 if (*oldlenp >= sizeof(struct nfs_user_stat_desc)) 2737 error = copyout(&ustat_desc, oldp, sizeof(struct nfs_user_stat_desc)); 2738 else 2739 error = ENOMEM; 2740 2741 /* always indicate required buffer size */ 2742 *oldlenp = bytes_total; 2743 } 2744 break; 2745 case NFS_USERCOUNT: 2746 if (!oldp) { 2747 *oldlenp = sizeof(nfsrv_user_stat_node_count); 2748 return (0); 2749 } 2750 2751 if (*oldlenp < sizeof(nfsrv_user_stat_node_count)) { 2752 *oldlenp = sizeof(nfsrv_user_stat_node_count); 2753 return (ENOMEM); 2754 } 2755 2756 if (nfsrv_is_initialized()) { 2757 /* reclaim old expired user nodes */ 2758 nfsrv_active_user_list_reclaim(); 2759 } 2760 2761 error = copyout(&nfsrv_user_stat_node_count, oldp, sizeof(nfsrv_user_stat_node_count)); 2762 break; 2763#endif /* NFSSERVER */ 2764 case VFS_CTL_NOLOCKS: 2765 if (req->oldptr != USER_ADDR_NULL) { 2766 lck_mtx_lock(&nmp->nm_lock); 2767 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0; 2768 lck_mtx_unlock(&nmp->nm_lock); 2769 error = SYSCTL_OUT(req, &val, sizeof(val)); 2770 if (error) 2771 return (error); 2772 } 2773 if (req->newptr != USER_ADDR_NULL) { 2774 error = SYSCTL_IN(req, &val, sizeof(val)); 2775 if (error) 2776 return (error); 2777 lck_mtx_lock(&nmp->nm_lock); 2778 if (nmp->nm_flag & NFSMNT_LOCALLOCKS) { 2779 /* can't toggle locks when using local locks */ 2780 error = EINVAL; 2781 } else if (val) { 2782 if (!(nmp->nm_flag & NFSMNT_NOLOCKS)) 2783 nfs_lockd_mount_change(-1); 2784 nmp->nm_flag |= NFSMNT_NOLOCKS; 2785 nmp->nm_state &= ~NFSSTA_LOCKTIMEO; 2786 } else { 2787 if (nmp->nm_flag & NFSMNT_NOLOCKS) 2788 nfs_lockd_mount_change(1); 2789 nmp->nm_flag &= ~NFSMNT_NOLOCKS; 2790 } 2791 lck_mtx_unlock(&nmp->nm_lock); 2792 } 2793 break; 2794 case VFS_CTL_QUERY: 2795 lck_mtx_lock(&nmp->nm_lock); 2796 /* XXX don't allow users to know about/disconnect unresponsive, soft, nobrowse mounts */ 2797 softnobrowse = ((nmp->nm_flag & NFSMNT_SOFT) && (vfs_flags(nmp->nm_mountp) & MNT_DONTBROWSE)); 2798 if (!softnobrowse && (nmp->nm_state & (NFSSTA_TIMEO|NFSSTA_JUKEBOXTIMEO))) 2799 vq.vq_flags |= VQ_NOTRESP; 2800 if (!softnobrowse && !(nmp->nm_flag & (NFSMNT_NOLOCKS|NFSMNT_LOCALLOCKS)) && 2801 (nmp->nm_state & NFSSTA_LOCKTIMEO)) 2802 vq.vq_flags |= VQ_NOTRESP; 2803 lck_mtx_unlock(&nmp->nm_lock); 2804 error = SYSCTL_OUT(req, &vq, sizeof(vq)); 2805 break; 2806 case VFS_CTL_TIMEO: 2807 if (req->oldptr != USER_ADDR_NULL) { 2808 lck_mtx_lock(&nmp->nm_lock); 2809 val = nmp->nm_tprintf_initial_delay; 2810 lck_mtx_unlock(&nmp->nm_lock); 2811 error = SYSCTL_OUT(req, &val, sizeof(val)); 2812 if (error) 2813 return (error); 2814 } 2815 if (req->newptr != USER_ADDR_NULL) { 2816 error = SYSCTL_IN(req, &val, sizeof(val)); 2817 if (error) 2818 return (error); 2819 lck_mtx_lock(&nmp->nm_lock); 2820 if (val < 0) 2821 nmp->nm_tprintf_initial_delay = 0; 2822 else 2823 nmp->nm_tprintf_initial_delay = val; 2824 lck_mtx_unlock(&nmp->nm_lock); 2825 } 2826 break; 2827 default: 2828 return (ENOTSUP); 2829 } 2830 return (error); 2831} 2832