4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 1986, 2010, Oracle and/or its affiliates. All rights reserved.
26 * Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T.
27 * All rights reserved.
30 #include <sys/param.h>
31 #include <sys/types.h>
32 #include <sys/systm.h>
35 #include <sys/vnode.h>
36 #include <sys/pathname.h>
37 #include <sys/sysmacros.h>
39 #include <sys/mkdev.h>
40 #include <sys/mount.h>
41 #include <sys/mntent.h>
42 #include <sys/statvfs.h>
43 #include <sys/errno.h>
44 #include <sys/debug.h>
45 #include <sys/cmn_err.h>
46 #include <sys/utsname.h>
47 #include <sys/bootconf.h>
48 #include <sys/modctl.h>
50 #include <sys/flock.h>
51 #include <sys/policy.h>
53 #include <sys/class.h>
54 #include <sys/socket.h>
55 #include <sys/netconfig.h>
57 #include <rpc/types.h>
62 #include <nfs/nfs_clnt.h>
63 #include <nfs/rnode.h>
64 #include <nfs/mount.h>
65 #include <nfs/nfs_acl.h>
67 #include <sys/fs_subr.h>
70 * From rpcsec module (common/rpcsec).
72 extern int sec_clnt_loadinfo(struct sec_data
*, struct sec_data
**, model_t
);
73 extern void sec_clnt_freeinfo(struct sec_data
*);
76 * The order and contents of this structure must be kept in sync with that of
77 * rfsreqcnt_v3_tmpl in nfs_stats.c
79 static char *rfsnames_v3
[] = {
80 "null", "getattr", "setattr", "lookup", "access", "readlink", "read",
81 "write", "create", "mkdir", "symlink", "mknod", "remove", "rmdir",
82 "rename", "link", "readdir", "readdirplus", "fsstat", "fsinfo",
87 * This table maps from NFS protocol number into call type.
88 * Zero means a "Lookup" type call
89 * One means a "Read" type call
90 * Two means a "Write" type call
91 * This is used to select a default time-out.
93 static uchar_t call_type_v3
[] = {
100 * Similar table, but to determine which timer to use
101 * (only real reads and writes!)
103 static uchar_t timer_type_v3
[] = {
110 * This table maps from NFS protocol number into a call type
111 * for the semisoft mount option.
112 * Zero means do not repeat operation.
115 static uchar_t ss_call_type_v3
[] = {
122 * nfs3 vfs operations.
124 static int nfs3_mount(vfs_t
*, vnode_t
*, struct mounta
*, cred_t
*);
125 static int nfs3_unmount(vfs_t
*, int, cred_t
*);
126 static int nfs3_root(vfs_t
*, vnode_t
**);
127 static int nfs3_statvfs(vfs_t
*, struct statvfs64
*);
128 static int nfs3_sync(vfs_t
*, short, cred_t
*);
129 static int nfs3_vget(vfs_t
*, vnode_t
**, fid_t
*);
130 static int nfs3_mountroot(vfs_t
*, whymountroot_t
);
131 static void nfs3_freevfs(vfs_t
*);
133 static int nfs3rootvp(vnode_t
**, vfs_t
*, struct servinfo
*,
134 int, cred_t
*, zone_t
*);
137 * Initialize the vfs structure
140 static int nfs3fstyp
;
143 * Debug variable to check for rdma based
144 * transport startup and cleanup. Controlled
145 * through /etc/system. Off by default.
147 extern int rdma_debug
;
149 const struct vfsops nfs3_vfsops
= {
150 .vfs_mount
= nfs3_mount
,
151 .vfs_unmount
= nfs3_unmount
,
152 .vfs_root
= nfs3_root
,
153 .vfs_statvfs
= nfs3_statvfs
,
154 .vfs_sync
= nfs3_sync
,
155 .vfs_vget
= nfs3_vget
,
156 .vfs_mountroot
= nfs3_mountroot
,
157 .vfs_freevfs
= nfs3_freevfs
,
161 nfs3init(int fstyp
, char *name
)
165 error
= vfs_setfsops(fstyp
, &nfs3_vfsops
);
167 zcmn_err(GLOBAL_ZONEID
, CE_WARN
,
168 "nfs3init: bad fstyp");
183 nfs3_free_args(struct nfs_args
*nargs
, nfs_fhandle
*fh
)
187 kmem_free(fh
, sizeof (*fh
));
190 if (nargs
->knconf
->knc_protofmly
)
191 kmem_free(nargs
->knconf
->knc_protofmly
, KNC_STRSIZE
);
192 if (nargs
->knconf
->knc_proto
)
193 kmem_free(nargs
->knconf
->knc_proto
, KNC_STRSIZE
);
194 kmem_free(nargs
->knconf
, sizeof (*nargs
->knconf
));
195 nargs
->knconf
= NULL
;
199 kmem_free(nargs
->fh
, strlen(nargs
->fh
) + 1);
203 if (nargs
->hostname
) {
204 kmem_free(nargs
->hostname
, strlen(nargs
->hostname
) + 1);
205 nargs
->hostname
= NULL
;
209 if (nargs
->addr
->buf
) {
210 ASSERT(nargs
->addr
->len
);
211 kmem_free(nargs
->addr
->buf
, nargs
->addr
->len
);
213 kmem_free(nargs
->addr
, sizeof (struct netbuf
));
217 if (nargs
->syncaddr
) {
218 ASSERT(nargs
->syncaddr
->len
);
219 if (nargs
->syncaddr
->buf
) {
220 ASSERT(nargs
->syncaddr
->len
);
221 kmem_free(nargs
->syncaddr
->buf
, nargs
->syncaddr
->len
);
223 kmem_free(nargs
->syncaddr
, sizeof (struct netbuf
));
224 nargs
->syncaddr
= NULL
;
227 if (nargs
->netname
) {
228 kmem_free(nargs
->netname
, strlen(nargs
->netname
) + 1);
229 nargs
->netname
= NULL
;
232 if (nargs
->nfs_ext_u
.nfs_extA
.secdata
) {
233 sec_clnt_freeinfo(nargs
->nfs_ext_u
.nfs_extA
.secdata
);
234 nargs
->nfs_ext_u
.nfs_extA
.secdata
= NULL
;
239 nfs3_copyin(char *data
, int datalen
, struct nfs_args
*nargs
, nfs_fhandle
*fh
)
243 size_t nlen
; /* length of netname */
244 size_t hlen
; /* length of hostname */
245 char netname
[MAXNETNAMELEN
+1]; /* server's netname */
246 struct netbuf addr
; /* server's address */
247 struct netbuf syncaddr
; /* AUTH_DES time sync addr */
248 struct knetconfig
*knconf
; /* transport knetconfig structure */
249 struct sec_data
*secdata
= NULL
; /* security data */
250 STRUCT_DECL(nfs_args
, args
); /* nfs mount arguments */
251 STRUCT_DECL(knetconfig
, knconf_tmp
);
252 STRUCT_DECL(netbuf
, addr_tmp
);
258 bzero(nargs
, sizeof (*nargs
));
260 STRUCT_INIT(args
, get_udatamodel());
261 bzero(STRUCT_BUF(args
), SIZEOF_STRUCT(nfs_args
, DATAMODEL_NATIVE
));
262 if (copyin(data
, STRUCT_BUF(args
), MIN(datalen
, STRUCT_SIZE(args
))))
265 nargs
->wsize
= STRUCT_FGET(args
, wsize
);
266 nargs
->rsize
= STRUCT_FGET(args
, rsize
);
267 nargs
->timeo
= STRUCT_FGET(args
, timeo
);
268 nargs
->retrans
= STRUCT_FGET(args
, retrans
);
269 nargs
->acregmin
= STRUCT_FGET(args
, acregmin
);
270 nargs
->acregmax
= STRUCT_FGET(args
, acregmax
);
271 nargs
->acdirmin
= STRUCT_FGET(args
, acdirmin
);
272 nargs
->acdirmax
= STRUCT_FGET(args
, acdirmax
);
274 flags
= STRUCT_FGET(args
, flags
);
275 nargs
->flags
= flags
;
281 * Allocate space for a knetconfig structure and
282 * its strings and copy in from user-land.
284 knconf
= kmem_zalloc(sizeof (*knconf
), KM_SLEEP
);
285 STRUCT_INIT(knconf_tmp
, get_udatamodel());
286 if (copyin(STRUCT_FGETP(args
, knconf
), STRUCT_BUF(knconf_tmp
),
287 STRUCT_SIZE(knconf_tmp
))) {
288 kmem_free(knconf
, sizeof (*knconf
));
292 knconf
->knc_semantics
= STRUCT_FGET(knconf_tmp
, knc_semantics
);
293 knconf
->knc_protofmly
= STRUCT_FGETP(knconf_tmp
, knc_protofmly
);
294 knconf
->knc_proto
= STRUCT_FGETP(knconf_tmp
, knc_proto
);
295 if (get_udatamodel() != DATAMODEL_LP64
) {
296 knconf
->knc_rdev
= expldev(STRUCT_FGET(knconf_tmp
, knc_rdev
));
298 knconf
->knc_rdev
= STRUCT_FGET(knconf_tmp
, knc_rdev
);
301 pf
= kmem_alloc(KNC_STRSIZE
, KM_SLEEP
);
302 p
= kmem_alloc(KNC_STRSIZE
, KM_SLEEP
);
303 error
= copyinstr(knconf
->knc_protofmly
, pf
, KNC_STRSIZE
, NULL
);
305 kmem_free(pf
, KNC_STRSIZE
);
306 kmem_free(p
, KNC_STRSIZE
);
307 kmem_free(knconf
, sizeof (*knconf
));
311 error
= copyinstr(knconf
->knc_proto
, p
, KNC_STRSIZE
, NULL
);
313 kmem_free(pf
, KNC_STRSIZE
);
314 kmem_free(p
, KNC_STRSIZE
);
315 kmem_free(knconf
, sizeof (*knconf
));
320 knconf
->knc_protofmly
= pf
;
321 knconf
->knc_proto
= p
;
323 nargs
->knconf
= knconf
;
327 STRUCT_INIT(addr_tmp
, get_udatamodel());
328 if (copyin(STRUCT_FGETP(args
, addr
), STRUCT_BUF(addr_tmp
),
329 STRUCT_SIZE(addr_tmp
))) {
334 nargs
->addr
= kmem_alloc(sizeof (struct netbuf
), KM_SLEEP
);
335 userbufptr
= STRUCT_FGETP(addr_tmp
, buf
);
336 addr
.len
= STRUCT_FGET(addr_tmp
, len
);
337 addr
.buf
= kmem_alloc(addr
.len
, KM_SLEEP
);
338 addr
.maxlen
= addr
.len
;
339 if (copyin(userbufptr
, addr
.buf
, addr
.len
)) {
340 kmem_free(addr
.buf
, addr
.len
);
344 bcopy(&addr
, nargs
->addr
, sizeof (struct netbuf
));
347 * Get the root fhandle
350 if (copyin(STRUCT_FGETP(args
, fh
), fh
, sizeof (nfs_fhandle
))) {
357 * Get server's hostname
359 if (flags
& NFSMNT_HOSTNAME
) {
360 error
= copyinstr(STRUCT_FGETP(args
, hostname
), netname
,
361 sizeof (netname
), &hlen
);
364 nargs
->hostname
= kmem_zalloc(hlen
, KM_SLEEP
);
365 (void) strcpy(nargs
->hostname
, netname
);
367 nargs
->hostname
= NULL
;
372 * If there are syncaddr and netname data, load them in. This is
373 * to support data needed for NFSV4 when AUTH_DH is the negotiated
374 * flavor via SECINFO. (instead of using MOUNT protocol in V3).
377 if (flags
& NFSMNT_SECURE
) {
378 if (STRUCT_FGETP(args
, syncaddr
) == NULL
) {
383 STRUCT_INIT(addr_tmp
, get_udatamodel());
384 if (copyin(STRUCT_FGETP(args
, syncaddr
), STRUCT_BUF(addr_tmp
),
385 STRUCT_SIZE(addr_tmp
))) {
389 userbufptr
= STRUCT_FGETP(addr_tmp
, buf
);
390 syncaddr
.len
= STRUCT_FGET(addr_tmp
, len
);
391 syncaddr
.buf
= kmem_alloc(syncaddr
.len
, KM_SLEEP
);
392 syncaddr
.maxlen
= syncaddr
.len
;
393 if (copyin(userbufptr
, syncaddr
.buf
, syncaddr
.len
)) {
394 kmem_free(syncaddr
.buf
, syncaddr
.len
);
399 nargs
->syncaddr
= kmem_alloc(sizeof (struct netbuf
), KM_SLEEP
);
400 bcopy(&syncaddr
, nargs
->syncaddr
, sizeof (struct netbuf
));
402 ASSERT(STRUCT_FGETP(args
, netname
));
404 if (copyinstr(STRUCT_FGETP(args
, netname
), netname
,
405 sizeof (netname
), &nlen
)) {
410 netname
[nlen
] = '\0';
411 nargs
->netname
= kmem_zalloc(nlen
, KM_SLEEP
);
412 (void) strcpy(nargs
->netname
, netname
);
416 * Get the extention data which has the security data structure.
417 * This includes data for AUTH_SYS as well.
419 if (flags
& NFSMNT_NEWARGS
) {
420 nargs
->nfs_args_ext
= STRUCT_FGET(args
, nfs_args_ext
);
421 if (nargs
->nfs_args_ext
== NFS_ARGS_EXTA
||
422 nargs
->nfs_args_ext
== NFS_ARGS_EXTB
) {
424 * Indicating the application is using the new
425 * sec_data structure to pass in the security
428 if (STRUCT_FGETP(args
,
429 nfs_ext_u
.nfs_extA
.secdata
) != NULL
) {
430 error
= sec_clnt_loadinfo(
431 (struct sec_data
*)STRUCT_FGETP(args
,
432 nfs_ext_u
.nfs_extA
.secdata
), &secdata
,
435 nargs
->nfs_ext_u
.nfs_extA
.secdata
= secdata
;
445 * We may have a linked list of nfs_args structures,
446 * which means the user is looking for failover. If
447 * the mount is either not "read-only" or "soft",
448 * we want to bail out with EINVAL.
450 if (nargs
->nfs_args_ext
== NFS_ARGS_EXTB
)
451 nargs
->nfs_ext_u
.nfs_extB
.next
=
452 STRUCT_FGETP(args
, nfs_ext_u
.nfs_extB
.next
);
456 nfs3_free_args(nargs
, fh
);
464 * Set up mount info record and attach it to vfs struct.
467 nfs3_mount(vfs_t
*vfsp
, vnode_t
*mvp
, struct mounta
*uap
, cred_t
*cr
)
469 struct nfs_args
*args
= NULL
;
470 nfs_fhandle
*fhandle
= NULL
;
471 char *data
= uap
->dataptr
;
473 vnode_t
*rtvp
; /* the server's root */
474 mntinfo_t
*mi
; /* mount info, pointed at by vfs */
475 size_t nlen
; /* length of netname */
476 struct knetconfig
*knconf
; /* transport knetconfig structure */
477 struct knetconfig
*rdma_knconf
; /* rdma transport structure */
479 struct servinfo
*svp
; /* nfs server info */
480 struct servinfo
*svp_tail
= NULL
; /* previous nfs server info */
481 struct servinfo
*svp_head
; /* first nfs server info */
482 struct servinfo
*svp_2ndlast
; /* 2nd last in server info list */
483 struct sec_data
*secdata
; /* security data */
484 int flags
, addr_type
;
485 zone_t
*zone
= nfs_zone();
486 zone_t
*mntzone
= NULL
;
489 if ((error
= secpolicy_fs_mount(cr
, mvp
, vfsp
)) != 0)
492 if (mvp
->v_type
!= VDIR
)
498 * nfs_args is now versioned and is extensible, so
499 * uap->datalen might be different from sizeof (args)
500 * in a compatible situation.
505 if (!(uap
->flags
& MS_SYSSPACE
)) {
507 args
= kmem_alloc(sizeof (struct nfs_args
), KM_SLEEP
);
509 nfs3_free_args(args
, fhandle
);
513 fhandle
= kmem_alloc(sizeof (nfs_fhandle
), KM_SLEEP
);
514 error
= nfs3_copyin(data
, uap
->datalen
, args
, fhandle
);
517 kmem_free(args
, sizeof (*args
));
521 args
= (struct nfs_args
*)data
;
522 fhandle
= (nfs_fhandle
*)args
->fh
;
528 if (uap
->flags
& MS_REMOUNT
) {
532 if (uap
->flags
& MS_SYSSPACE
) {
533 error
= copystr(uap
->fstype
, name
, FSTYPSZ
, &n
);
535 nfs3_free_args(args
, fhandle
);
536 kmem_free(args
, sizeof (*args
));
537 error
= copyinstr(uap
->fstype
, name
, FSTYPSZ
, &n
);
540 if (error
== ENAMETOOLONG
)
546 * This check is to ensure that the request is a
547 * genuine nfs remount request.
550 if (strncmp(name
, "nfs", 3) != 0)
554 * If the request changes the locking type, disallow the
556 * because it's questionable whether we can transfer the
557 * locking state correctly.
560 if ((mi
= VFTOMI(vfsp
)) != NULL
) {
564 new_mi_llock
= (flags
& NFSMNT_LLOCK
) ? 1 : 0;
565 old_mi_llock
= (mi
->mi_flags
& MI_LLOCK
) ? 1 : 0;
566 if (old_mi_llock
!= new_mi_llock
)
572 mutex_enter(&mvp
->v_lock
);
573 if (!(uap
->flags
& MS_OVERLAY
) &&
574 (mvp
->v_count
!= 1 || (mvp
->v_flag
& VROOT
))) {
575 mutex_exit(&mvp
->v_lock
);
576 if (!(uap
->flags
& MS_SYSSPACE
)) {
577 nfs3_free_args(args
, fhandle
);
578 kmem_free(args
, sizeof (*args
));
582 mutex_exit(&mvp
->v_lock
);
584 /* make sure things are zeroed for errout: */
590 * A valid knetconfig structure is required.
592 if (!(flags
& NFSMNT_KNCONF
)) {
593 if (!(uap
->flags
& MS_SYSSPACE
)) {
594 nfs3_free_args(args
, fhandle
);
595 kmem_free(args
, sizeof (*args
));
600 if ((strlen(args
->knconf
->knc_protofmly
) >= KNC_STRSIZE
) ||
601 (strlen(args
->knconf
->knc_proto
) >= KNC_STRSIZE
)) {
602 if (!(uap
->flags
& MS_SYSSPACE
)) {
603 nfs3_free_args(args
, fhandle
);
604 kmem_free(args
, sizeof (*args
));
610 * Allocate a servinfo struct.
612 svp
= kmem_zalloc(sizeof (*svp
), KM_SLEEP
);
613 mutex_init(&svp
->sv_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
615 svp_2ndlast
= svp_tail
;
616 svp_tail
->sv_next
= svp
;
624 svp
->sv_knconf
= args
->knconf
;
627 if (args
->addr
== NULL
|| args
->addr
->buf
== NULL
) {
632 svp
->sv_addr
.maxlen
= args
->addr
->maxlen
;
633 svp
->sv_addr
.len
= args
->addr
->len
;
634 svp
->sv_addr
.buf
= args
->addr
->buf
;
635 args
->addr
->buf
= NULL
;
638 * Check the root fhandle length
641 if (fhandle
->fh_len
> NFS3_FHSIZE
|| fhandle
->fh_len
== 0) {
644 zcmn_err(getzoneid(), CE_WARN
,
645 "nfs3_mount: got an invalid fhandle. fh_len = %d",
647 fhandle
->fh_len
= NFS_FHANDLE_LEN
;
648 nfs_printfhandle(fhandle
);
653 bcopy(&fhandle
->fh_buf
, &svp
->sv_fhandle
.fh_buf
, fhandle
->fh_len
);
654 svp
->sv_fhandle
.fh_len
= fhandle
->fh_len
;
657 * Get server's hostname
659 if (flags
& NFSMNT_HOSTNAME
) {
660 if (args
->hostname
== NULL
) {
664 svp
->sv_hostnamelen
= strlen(args
->hostname
) + 1;
665 svp
->sv_hostname
= args
->hostname
;
666 args
->hostname
= NULL
;
668 char *p
= "unknown-host";
669 svp
->sv_hostnamelen
= strlen(p
) + 1;
670 svp
->sv_hostname
= kmem_zalloc(svp
->sv_hostnamelen
, KM_SLEEP
);
671 (void) strcpy(svp
->sv_hostname
, p
);
676 * RDMA MOUNT SUPPORT FOR NFS v3:
677 * Establish, is it possible to use RDMA, if so overload the
678 * knconf with rdma specific knconf and free the orignal.
680 if ((flags
& NFSMNT_TRYRDMA
) || (flags
& NFSMNT_DORDMA
)) {
682 * Determine the addr type for RDMA, IPv4 or v6.
684 if (strcmp(svp
->sv_knconf
->knc_protofmly
, NC_INET
) == 0)
686 else if (strcmp(svp
->sv_knconf
->knc_protofmly
, NC_INET6
) == 0)
687 addr_type
= AF_INET6
;
689 if (rdma_reachable(addr_type
, &svp
->sv_addr
,
690 &rdma_knconf
) == 0) {
692 * If successful, hijack the orignal knconf and
693 * replace with a new one, depending on the flags.
695 svp
->sv_origknconf
= svp
->sv_knconf
;
696 svp
->sv_knconf
= rdma_knconf
;
697 knconf
= rdma_knconf
;
699 if (flags
& NFSMNT_TRYRDMA
) {
702 zcmn_err(getzoneid(), CE_WARN
,
703 "no RDMA onboard, revert\n");
707 if (flags
& NFSMNT_DORDMA
) {
709 * If proto=rdma is specified and no RDMA
710 * path to this server is avialable then
712 * This is not included in the mountable
713 * server list or the replica list.
714 * Check if more servers are specified;
715 * Failover case, otherwise bail out of mount.
717 if (args
->nfs_args_ext
== NFS_ARGS_EXTB
&&
718 args
->nfs_ext_u
.nfs_extB
.next
!= NULL
) {
720 args
->nfs_ext_u
.nfs_extB
.next
;
721 if (uap
->flags
& MS_RDONLY
&&
722 !(flags
& NFSMNT_SOFT
)) {
723 if (svp_head
->sv_next
== NULL
) {
729 svp_tail
= svp_2ndlast
;
730 svp_2ndlast
->sv_next
=
738 * This is the last server specified
739 * in the nfs_args list passed down
740 * and its not rdma capable.
742 if (svp_head
->sv_next
== NULL
) {
744 * Is this the only one
749 zcmn_err(getzoneid(),
756 * There is list, since some
757 * servers specified before
758 * this passed all requirements
760 svp_tail
= svp_2ndlast
;
761 svp_2ndlast
->sv_next
= NULL
;
771 * Get the extention data which has the new security data structure.
773 if (flags
& NFSMNT_NEWARGS
) {
774 switch (args
->nfs_args_ext
) {
778 * Indicating the application is using the new
779 * sec_data structure to pass in the security
782 secdata
= args
->nfs_ext_u
.nfs_extA
.secdata
;
783 if (args
->nfs_ext_u
.nfs_extA
.secdata
== NULL
) {
787 * Need to validate the flavor here if
788 * sysspace, userspace was already
789 * validate from the nfs_copyin function.
791 switch (secdata
->rpcflavor
) {
797 args
->nfs_ext_u
.nfs_extA
.secdata
= NULL
;
810 } else if (flags
& NFSMNT_SECURE
) {
812 * Keep this for backward compatibility to support
813 * NFSMNT_SECURE/NFSMNT_RPCTIMESYNC flags.
815 if (args
->syncaddr
== NULL
|| args
->syncaddr
->buf
== NULL
) {
820 * Move security related data to the sec_data structure.
823 dh_k4_clntdata_t
*data
;
825 secdata
= kmem_alloc(sizeof (*secdata
), KM_SLEEP
);
826 if (flags
& NFSMNT_RPCTIMESYNC
)
827 secdata
->flags
|= AUTH_F_RPCTIMESYNC
;
828 data
= kmem_alloc(sizeof (*data
), KM_SLEEP
);
829 bcopy(args
->syncaddr
, &data
->syncaddr
,
830 sizeof (*args
->syncaddr
));
833 * duplicate the knconf information for the
836 data
->knconf
= kmem_alloc(sizeof (*knconf
), KM_SLEEP
);
837 *data
->knconf
= *knconf
;
838 pf
= kmem_alloc(KNC_STRSIZE
, KM_SLEEP
);
839 p
= kmem_alloc(KNC_STRSIZE
, KM_SLEEP
);
840 bcopy(knconf
->knc_protofmly
, pf
, KNC_STRSIZE
);
841 bcopy(knconf
->knc_proto
, pf
, KNC_STRSIZE
);
842 data
->knconf
->knc_protofmly
= pf
;
843 data
->knconf
->knc_proto
= p
;
845 nlen
= strlen(args
->hostname
) + 1;
846 /* move server netname to the sec_data structure */
848 data
->netname
= kmem_alloc(nlen
, KM_SLEEP
);
849 bcopy(args
->hostname
, data
->netname
, nlen
);
850 data
->netnamelen
= nlen
;
852 secdata
->secmod
= secdata
->rpcflavor
= AUTH_DES
;
853 secdata
->data
= (caddr_t
)data
;
856 secdata
= kmem_alloc(sizeof (*secdata
), KM_SLEEP
);
857 secdata
->secmod
= secdata
->rpcflavor
= AUTH_UNIX
;
858 secdata
->data
= NULL
;
861 svp
->sv_secdata
= secdata
;
867 * If mount secure failed, we will fall back to AUTH_NONE
868 * and try again. nfs3rootvp() will turn this back off.
870 * The NFS Version 3 mount uses the FSINFO and GETATTR
871 * procedures. The server should not care if these procedures
872 * have the proper security flavor, so if mount retries using
873 * AUTH_NONE that does not require a credential setup for root
874 * then the automounter would work without requiring root to be
875 * keylogged into AUTH_DES.
877 if (secdata
->rpcflavor
!= AUTH_UNIX
&&
878 secdata
->rpcflavor
!= AUTH_LOOPBACK
)
879 secdata
->flags
|= AUTH_F_TRYNONE
;
884 * We may have a linked list of nfs_args structures,
885 * which means the user is looking for failover. If
886 * the mount is either not "read-only" or "soft",
887 * we want to bail out with EINVAL.
889 if (args
->nfs_args_ext
== NFS_ARGS_EXTB
&&
890 args
->nfs_ext_u
.nfs_extB
.next
!= NULL
) {
891 if (uap
->flags
& MS_RDONLY
&& !(flags
& NFSMNT_SOFT
)) {
892 data
= (char *)args
->nfs_ext_u
.nfs_extB
.next
;
900 * Determine the zone we're being mounted into.
902 zone_hold(mntzone
= zone
); /* start with this assumption */
903 if (getzoneid() == GLOBAL_ZONEID
) {
905 mntzone
= zone_find_by_path(refstr_value(vfsp
->vfs_mntpt
));
906 ASSERT(mntzone
!= NULL
);
907 if (mntzone
!= zone
) {
914 * Stop the mount from going any further if the zone is going away.
916 if (zone_status_get(mntzone
) >= ZONE_IS_SHUTTING_DOWN
) {
925 error
= nfs3rootvp(&rtvp
, vfsp
, svp_head
, flags
, cr
, mntzone
);
931 * Set option fields in the mount info record
935 if (svp_head
->sv_next
)
936 mi
->mi_flags
|= MI_LLOCK
;
938 error
= nfs_setopts(rtvp
, DATAMODEL_NATIVE
, args
);
944 if (rp
->r_flags
& RHASHED
)
953 nfs_async_stop(vfsp
);
954 nfs_async_manager_stop(vfsp
);
955 if (mi
->mi_io_kstats
) {
956 kstat_delete(mi
->mi_io_kstats
);
957 mi
->mi_io_kstats
= NULL
;
959 if (mi
->mi_ro_kstats
) {
960 kstat_delete(mi
->mi_ro_kstats
);
961 mi
->mi_ro_kstats
= NULL
;
968 if (!(uap
->flags
& MS_SYSSPACE
)) {
969 nfs3_free_args(args
, fhandle
);
970 kmem_free(args
, sizeof (*args
));
979 static int nfs3_dynamic
= 0; /* global variable to enable dynamic retrans. */
980 static ushort_t nfs3_max_threads
= 8; /* max number of active async threads */
981 uint_t nfs3_bsize
= 32 * 1024; /* client `block' size */
982 static uint_t nfs3_async_clusters
= 1; /* # of reqs from each async queue */
983 static uint_t nfs3_cots_timeo
= NFS_COTS_TIMEO
;
986 nfs3rootvp(vnode_t
**rtvpp
, vfs_t
*vfsp
, struct servinfo
*svp
,
987 int flags
, cred_t
*cr
, zone_t
*zone
)
993 struct FSINFO3args args
;
994 struct FSINFO3res res
;
999 uint_t max_transfer_size
;
1000 struct nfs_stats
*nfsstatsp
;
1001 cred_t
*lcr
= NULL
, *tcr
= cr
;
1003 nfsstatsp
= zone_getspecific(nfsstat_zone_key
, nfs_zone());
1004 ASSERT(nfsstatsp
!= NULL
);
1006 ASSERT(nfs_zone() == zone
);
1008 * Create a mount record and link it to the vfs struct.
1010 mi
= kmem_zalloc(sizeof (*mi
), KM_SLEEP
);
1011 mutex_init(&mi
->mi_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
1012 mutex_init(&mi
->mi_remap_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
1013 mi
->mi_flags
= MI_ACL
| MI_EXTATTR
;
1014 if (!(flags
& NFSMNT_SOFT
))
1015 mi
->mi_flags
|= MI_HARD
;
1016 if ((flags
& NFSMNT_SEMISOFT
))
1017 mi
->mi_flags
|= MI_SEMISOFT
;
1018 if ((flags
& NFSMNT_NOPRINT
))
1019 mi
->mi_flags
|= MI_NOPRINT
;
1020 if (flags
& NFSMNT_INT
)
1021 mi
->mi_flags
|= MI_INT
;
1022 mi
->mi_retrans
= NFS_RETRIES
;
1023 if (svp
->sv_knconf
->knc_semantics
== NC_TPI_COTS_ORD
||
1024 svp
->sv_knconf
->knc_semantics
== NC_TPI_COTS
)
1025 mi
->mi_timeo
= nfs3_cots_timeo
;
1027 mi
->mi_timeo
= NFS_TIMEO
;
1028 mi
->mi_prog
= NFS_PROGRAM
;
1029 mi
->mi_vers
= NFS_V3
;
1030 mi
->mi_rfsnames
= rfsnames_v3
;
1031 mi
->mi_reqs
= nfsstatsp
->nfs_stats_v3
.rfsreqcnt_ptr
;
1032 mi
->mi_call_type
= call_type_v3
;
1033 mi
->mi_ss_call_type
= ss_call_type_v3
;
1034 mi
->mi_timer_type
= timer_type_v3
;
1035 mi
->mi_aclnames
= aclnames_v3
;
1036 mi
->mi_aclreqs
= nfsstatsp
->nfs_stats_v3
.aclreqcnt_ptr
;
1037 mi
->mi_acl_call_type
= acl_call_type_v3
;
1038 mi
->mi_acl_ss_call_type
= acl_ss_call_type_v3
;
1039 mi
->mi_acl_timer_type
= acl_timer_type_v3
;
1040 cv_init(&mi
->mi_failover_cv
, NULL
, CV_DEFAULT
, NULL
);
1041 mi
->mi_servers
= svp
;
1042 mi
->mi_curr_serv
= svp
;
1043 mi
->mi_acregmin
= SEC2HR(ACREGMIN
);
1044 mi
->mi_acregmax
= SEC2HR(ACREGMAX
);
1045 mi
->mi_acdirmin
= SEC2HR(ACDIRMIN
);
1046 mi
->mi_acdirmax
= SEC2HR(ACDIRMAX
);
1049 mi
->mi_flags
|= MI_DYNAMIC
;
1051 if (flags
& NFSMNT_DIRECTIO
)
1052 mi
->mi_flags
|= MI_DIRECTIO
;
1055 * Make a vfs struct for nfs. We do this here instead of below
1056 * because rtvp needs a vfs before we can do a getattr on it.
1058 * Assign a unique device id to the mount
1060 mutex_enter(&nfs_minor_lock
);
1062 nfs_minor
= (nfs_minor
+ 1) & MAXMIN32
;
1063 nfs_dev
= makedevice(nfs_major
, nfs_minor
);
1064 } while (vfs_devismounted(nfs_dev
));
1065 mutex_exit(&nfs_minor_lock
);
1067 vfsp
->vfs_dev
= nfs_dev
;
1068 vfs_make_fsid(&vfsp
->vfs_fsid
, nfs_dev
, nfs3fstyp
);
1069 vfsp
->vfs_data
= (caddr_t
)mi
;
1070 vfsp
->vfs_fstype
= nfsfstyp
;
1073 * Verify that nfs3_bsize tuneable is set to an
1074 * acceptable value. It be a multiple of PAGESIZE or
1075 * file corruption can occur.
1077 if (nfs3_bsize
& PAGEOFFSET
)
1078 nfs3_bsize
&= PAGEMASK
;
1079 if (nfs3_bsize
< PAGESIZE
)
1080 nfs3_bsize
= PAGESIZE
;
1081 vfsp
->vfs_bsize
= nfs3_bsize
;
1084 * Initialize fields used to support async putpage operations.
1086 for (i
= 0; i
< NFS_ASYNC_TYPES
; i
++)
1087 mi
->mi_async_clusters
[i
] = nfs3_async_clusters
;
1088 mi
->mi_async_init_clusters
= nfs3_async_clusters
;
1089 mi
->mi_async_curr
[NFS_ASYNC_QUEUE
] =
1090 mi
->mi_async_curr
[NFS_ASYNC_PGOPS_QUEUE
] = &mi
->mi_async_reqs
[0];
1091 mi
->mi_max_threads
= nfs3_max_threads
;
1092 mutex_init(&mi
->mi_async_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
1093 cv_init(&mi
->mi_async_reqs_cv
, NULL
, CV_DEFAULT
, NULL
);
1094 cv_init(&mi
->mi_async_work_cv
[NFS_ASYNC_QUEUE
], NULL
, CV_DEFAULT
, NULL
);
1095 cv_init(&mi
->mi_async_work_cv
[NFS_ASYNC_PGOPS_QUEUE
], NULL
,
1097 cv_init(&mi
->mi_async_cv
, NULL
, CV_DEFAULT
, NULL
);
1101 zone_init_ref(&mi
->mi_zone_ref
);
1102 zone_hold_ref(zone
, &mi
->mi_zone_ref
, ZONE_REF_NFS
);
1103 nfs_mi_zonelist_add(mi
);
1106 * Make the root vnode, use it to get attributes,
1107 * then remake it with the attributes.
1109 rtvp
= makenfs3node((nfs_fh3
*)&svp
->sv_fhandle
,
1110 NULL
, vfsp
, gethrtime(), cr
, NULL
, NULL
);
1113 * Make the FSINFO calls, primarily at this point to
1114 * determine the transfer size. For client failover,
1115 * we'll want this to be the minimum bid from any
1116 * server, so that we don't overrun stated limits.
1118 * While we're looping, we'll turn off AUTH_F_TRYNONE,
1119 * which is only for the mount operation.
1122 mi
->mi_tsize
= nfs3_tsize(svp
->sv_knconf
);
1123 mi
->mi_stsize
= mi
->mi_tsize
;
1125 mi
->mi_curread
= nfs3_bsize
;
1126 mi
->mi_curwrite
= mi
->mi_curread
;
1129 * If the uid is set then set the creds for secure mounts
1130 * by proxy processes such as automountd.
1132 if (svp
->sv_secdata
->uid
!= 0 &&
1133 svp
->sv_secdata
->rpcflavor
== RPCSEC_GSS
) {
1135 (void) crsetugid(lcr
, svp
->sv_secdata
->uid
, crgetgid(cr
));
1139 for (svp
= mi
->mi_servers
; svp
!= NULL
; svp
= svp
->sv_next
) {
1141 mi
->mi_curr_serv
= svp
;
1142 max_transfer_size
= nfs3_tsize(svp
->sv_knconf
);
1143 mi
->mi_tsize
= MIN(max_transfer_size
, mi
->mi_tsize
);
1144 mi
->mi_stsize
= MIN(max_transfer_size
, mi
->mi_stsize
);
1145 mi
->mi_curread
= MIN(max_transfer_size
, mi
->mi_curread
);
1146 mi
->mi_curwrite
= MIN(max_transfer_size
, mi
->mi_curwrite
);
1147 args
.fsroot
= *(nfs_fh3
*)&svp
->sv_fhandle
;
1149 error
= rfs3call(mi
, NFSPROC3_FSINFO
,
1150 xdr_nfs_fh3
, (caddr_t
)&args
,
1151 xdr_FSINFO3res
, (caddr_t
)&res
, tcr
,
1152 &douprintf
, &res
.status
, 0, NULL
);
1155 error
= geterrno3(res
.status
);
1159 /* get type of root node */
1160 if (res
.resok
.obj_attributes
.attributes
) {
1161 if (res
.resok
.obj_attributes
.attr
.type
< NF3REG
||
1162 res
.resok
.obj_attributes
.attr
.type
> NF3FIFO
) {
1164 zcmn_err(getzoneid(), CE_WARN
,
1165 "NFS3 server %s returned a bad file type for root",
1168 zcmn_err(getzoneid(), CE_WARN
,
1169 "NFS server %s returned a bad file type for root",
1175 if (rtvp
->v_type
!= VNON
&& rtvp
->v_type
!=
1176 nf3_to_vt
[res
.resok
.obj_attributes
.attr
.
1179 zcmn_err(getzoneid(), CE_WARN
,
1180 "NFS3 server %s returned a different file type for root",
1183 zcmn_err(getzoneid(), CE_WARN
,
1184 "NFS server %s returned a different file type for root",
1191 nf3_to_vt
[res
.resok
.obj_attributes
.attr
.
1196 if (res
.resok
.rtmax
!= 0) {
1197 mi
->mi_tsize
= MIN(res
.resok
.rtmax
, mi
->mi_tsize
);
1198 if (res
.resok
.rtpref
!= 0) {
1199 mi
->mi_curread
= MIN(res
.resok
.rtpref
,
1202 mi
->mi_curread
= MIN(res
.resok
.rtmax
,
1205 } else if (res
.resok
.rtpref
!= 0) {
1206 mi
->mi_tsize
= MIN(res
.resok
.rtpref
, mi
->mi_tsize
);
1207 mi
->mi_curread
= MIN(res
.resok
.rtpref
, mi
->mi_curread
);
1210 zcmn_err(getzoneid(), CE_WARN
,
1211 "NFS3 server %s returned 0 for read transfer sizes",
1214 zcmn_err(getzoneid(), CE_WARN
,
1215 "NFS server %s returned 0 for read transfer sizes",
1221 if (res
.resok
.wtmax
!= 0) {
1222 mi
->mi_stsize
= MIN(res
.resok
.wtmax
, mi
->mi_stsize
);
1223 if (res
.resok
.wtpref
!= 0) {
1224 mi
->mi_curwrite
= MIN(res
.resok
.wtpref
,
1227 mi
->mi_curwrite
= MIN(res
.resok
.wtmax
,
1230 } else if (res
.resok
.wtpref
!= 0) {
1231 mi
->mi_stsize
= MIN(res
.resok
.wtpref
, mi
->mi_stsize
);
1232 mi
->mi_curwrite
= MIN(res
.resok
.wtpref
,
1236 zcmn_err(getzoneid(), CE_WARN
,
1237 "NFS3 server %s returned 0 for write transfer sizes",
1240 zcmn_err(getzoneid(), CE_WARN
,
1241 "NFS server %s returned 0 for write transfer sizes",
1249 * These signal the ability of the server to create
1250 * hard links and symbolic links, so they really
1251 * aren't relevant if there is more than one server.
1252 * We'll set them here, though it probably looks odd.
1254 if (res
.resok
.properties
& FSF3_LINK
)
1255 mi
->mi_flags
|= MI_LINK
;
1256 if (res
.resok
.properties
& FSF3_SYMLINK
)
1257 mi
->mi_flags
|= MI_SYMLINK
;
1259 /* Pick up smallest non-zero maxfilesize value */
1260 if (res
.resok
.maxfilesize
) {
1261 if (mi
->mi_maxfilesize
) {
1262 mi
->mi_maxfilesize
= MIN(mi
->mi_maxfilesize
,
1263 res
.resok
.maxfilesize
);
1265 mi
->mi_maxfilesize
= res
.resok
.maxfilesize
;
1269 * AUTH_F_TRYNONE is only for the mount operation,
1270 * so turn it back off.
1272 svp
->sv_secdata
->flags
&= ~AUTH_F_TRYNONE
;
1274 mi
->mi_curr_serv
= mi
->mi_servers
;
1277 * Start the thread responsible for handling async worker threads.
1279 VFS_HOLD(vfsp
); /* add reference for thread */
1280 mi
->mi_manager_thread
= zthread_create(NULL
, 0, nfs_async_manager
,
1281 vfsp
, 0, minclsyspri
);
1282 ASSERT(mi
->mi_manager_thread
!= NULL
);
1287 nfs_mnt_kstat_init(vfsp
);
1289 /* If we didn't get a type, get one now */
1290 if (rtvp
->v_type
== VNON
) {
1291 va
.va_mask
= AT_ALL
;
1293 error
= nfs3getattr(rtvp
, &va
, tcr
);
1296 rtvp
->v_type
= va
.va_type
;
1299 mi
->mi_type
= rtvp
->v_type
;
1308 * An error occurred somewhere, need to clean up...
1309 * We need to release our reference to the root vnode and
1310 * destroy the mntinfo struct that we just created.
1315 if (rp
->r_flags
& RHASHED
)
1318 nfs_async_stop(vfsp
);
1319 nfs_async_manager_stop(vfsp
);
1320 if (mi
->mi_io_kstats
) {
1321 kstat_delete(mi
->mi_io_kstats
);
1322 mi
->mi_io_kstats
= NULL
;
1324 if (mi
->mi_ro_kstats
) {
1325 kstat_delete(mi
->mi_ro_kstats
);
1326 mi
->mi_ro_kstats
= NULL
;
1337 nfs3_unmount(vfs_t
*vfsp
, int flag
, cred_t
*cr
)
1342 if (secpolicy_fs_unmount(cr
, vfsp
) != 0)
1346 if (flag
& MS_FORCE
) {
1348 vfsp
->vfs_flag
|= VFS_UNMOUNTED
;
1351 * We are about to stop the async manager.
1352 * Let every one know not to schedule any
1353 * more async requests
1355 mutex_enter(&mi
->mi_async_lock
);
1356 mi
->mi_max_threads
= 0;
1357 NFS_WAKEALL_ASYNC_WORKERS(mi
->mi_async_work_cv
);
1358 mutex_exit(&mi
->mi_async_lock
);
1361 * We need to stop the manager thread explicitly; the worker
1362 * threads can time out and exit on their own.
1364 nfs_async_manager_stop(vfsp
);
1365 destroy_rtable(vfsp
, cr
);
1366 if (mi
->mi_io_kstats
) {
1367 kstat_delete(mi
->mi_io_kstats
);
1368 mi
->mi_io_kstats
= NULL
;
1370 if (mi
->mi_ro_kstats
) {
1371 kstat_delete(mi
->mi_ro_kstats
);
1372 mi
->mi_ro_kstats
= NULL
;
1377 * Wait until all asynchronous putpage operations on
1378 * this file system are complete before flushing rnodes
1381 omax
= mi
->mi_max_threads
;
1382 if (nfs_async_stop_sig(vfsp
)) {
1387 * If there are any active vnodes on this file system,
1388 * then the file system is busy and can't be umounted.
1390 if (check_rtable(vfsp
)) {
1391 mutex_enter(&mi
->mi_async_lock
);
1392 mi
->mi_max_threads
= omax
;
1393 mutex_exit(&mi
->mi_async_lock
);
1397 * The unmount can't fail from now on; stop the worker thread manager.
1399 nfs_async_manager_stop(vfsp
);
1401 * Destroy all rnodes belonging to this file system from the
1402 * rnode hash queues and purge any resources allocated to
1405 destroy_rtable(vfsp
, cr
);
1406 if (mi
->mi_io_kstats
) {
1407 kstat_delete(mi
->mi_io_kstats
);
1408 mi
->mi_io_kstats
= NULL
;
1410 if (mi
->mi_ro_kstats
) {
1411 kstat_delete(mi
->mi_ro_kstats
);
1412 mi
->mi_ro_kstats
= NULL
;
1421 nfs3_root(vfs_t
*vfsp
, vnode_t
**vpp
)
1431 if (nfs_zone() != mi
->mi_zone
)
1434 svp
= mi
->mi_curr_serv
;
1435 if (svp
&& (svp
->sv_flags
& SV_ROOT_STALE
)) {
1436 mutex_enter(&svp
->sv_lock
);
1437 svp
->sv_flags
&= ~SV_ROOT_STALE
;
1438 mutex_exit(&svp
->sv_lock
);
1442 vp
= makenfs3node((nfs_fh3
*)&mi
->mi_curr_serv
->sv_fhandle
,
1443 NULL
, vfsp
, gethrtime(), CRED(), NULL
, NULL
);
1446 * if the SV_ROOT_STALE flag was reset above, reset the
1447 * RSTALE flag if needed and return an error
1449 if (error
== ENOENT
) {
1451 if (svp
&& rp
->r_flags
& RSTALE
) {
1452 mutex_enter(&rp
->r_statelock
);
1453 rp
->r_flags
&= ~RSTALE
;
1454 mutex_exit(&rp
->r_statelock
);
1460 ASSERT(vp
->v_type
== VNON
|| vp
->v_type
== mi
->mi_type
);
1462 vp
->v_type
= mi
->mi_type
;
1470 * Get file system statistics.
1473 nfs3_statvfs(vfs_t
*vfsp
, struct statvfs64
*sbp
)
1477 struct FSSTAT3args args
;
1478 struct FSSTAT3res res
;
1486 if (nfs_zone() != mi
->mi_zone
)
1488 error
= nfs3_root(vfsp
, &vp
);
1494 args
.fsroot
= *VTOFH3(vp
);
1496 fi
.fhp
= (caddr_t
)&args
.fsroot
;
1497 fi
.copyproc
= nfs3copyfh
;
1498 fi
.lookupproc
= nfs3lookup
;
1499 fi
.xattrdirproc
= acl_getxattrdir3
;
1505 error
= rfs3call(mi
, NFSPROC3_FSSTAT
,
1506 xdr_nfs_fh3
, (caddr_t
)&args
,
1507 xdr_FSSTAT3res
, (caddr_t
)&res
, cr
,
1508 &douprintf
, &res
.status
, 0, &fi
);
1515 error
= geterrno3(res
.status
);
1517 nfs3_cache_post_op_attr(vp
, &res
.resok
.obj_attributes
, t
, cr
);
1518 sbp
->f_bsize
= MAXBSIZE
;
1519 sbp
->f_frsize
= DEV_BSIZE
;
1521 * Allow -1 fields to pass through unconverted. These
1522 * indicate "don't know" fields.
1524 if (res
.resok
.tbytes
== (size3
)-1)
1525 sbp
->f_blocks
= (fsblkcnt64_t
)res
.resok
.tbytes
;
1527 sbp
->f_blocks
= (fsblkcnt64_t
)
1528 (res
.resok
.tbytes
/ DEV_BSIZE
);
1530 if (res
.resok
.fbytes
== (size3
)-1)
1531 sbp
->f_bfree
= (fsblkcnt64_t
)res
.resok
.fbytes
;
1533 sbp
->f_bfree
= (fsblkcnt64_t
)
1534 (res
.resok
.fbytes
/ DEV_BSIZE
);
1536 if (res
.resok
.abytes
== (size3
)-1)
1537 sbp
->f_bavail
= (fsblkcnt64_t
)res
.resok
.abytes
;
1539 sbp
->f_bavail
= (fsblkcnt64_t
)
1540 (res
.resok
.abytes
/ DEV_BSIZE
);
1542 sbp
->f_files
= (fsfilcnt64_t
)res
.resok
.tfiles
;
1543 sbp
->f_ffree
= (fsfilcnt64_t
)res
.resok
.ffiles
;
1544 sbp
->f_favail
= (fsfilcnt64_t
)res
.resok
.afiles
;
1545 sbp
->f_fsid
= (unsigned long)vfsp
->vfs_fsid
.val
[0];
1546 (void) strncpy(sbp
->f_basetype
,
1547 vfssw
[vfsp
->vfs_fstype
].vsw_name
, FSTYPSZ
);
1548 sbp
->f_flag
= vf_to_stf(vfsp
->vfs_flag
);
1549 sbp
->f_namemax
= (ulong_t
)-1;
1551 nfs3_cache_post_op_attr(vp
, &res
.resfail
.obj_attributes
, t
, cr
);
1552 PURGE_STALE_FH(error
, vp
, cr
);
1560 static kmutex_t nfs3_syncbusy
;
1563 * Flush dirty nfs files for file system vfsp.
1564 * If vfsp == NULL, all nfs files are flushed.
1568 nfs3_sync(vfs_t
*vfsp
, short flag
, cred_t
*cr
)
1571 * Cross-zone calls are OK here, since this translates to a
1572 * fop_putpage(B_ASYNC), which gets picked up by the right zone.
1574 if (!(flag
& SYNC_ATTR
) && mutex_tryenter(&nfs3_syncbusy
) != 0) {
1576 mutex_exit(&nfs3_syncbusy
);
1583 nfs3_vget(vfs_t
*vfsp
, vnode_t
**vpp
, fid_t
*fidp
)
1590 if (fidp
->fid_len
> NFS3_FHSIZE
) {
1595 if (nfs_zone() != VFTOMI(vfsp
)->mi_zone
)
1597 fh
.fh3_length
= fidp
->fid_len
;
1598 bcopy(fidp
->fid_data
, fh
.fh3_u
.data
, fh
.fh3_length
);
1600 vp
= makenfs3node(&fh
, NULL
, vfsp
, gethrtime(), CRED(), NULL
, NULL
);
1602 if (VTOR(vp
)->r_flags
& RSTALE
) {
1608 if (vp
->v_type
== VNON
) {
1609 va
.va_mask
= AT_ALL
;
1610 error
= nfs3getattr(vp
, &va
, CRED());
1616 vp
->v_type
= va
.va_type
;
1626 nfs3_mountroot(vfs_t
*vfsp
, whymountroot_t why
)
1629 char root_hostname
[SYS_NMLN
+1];
1630 struct servinfo
*svp
;
1638 struct nfs_args args
; /* nfs mount arguments */
1639 static char token
[10];
1641 bzero(&args
, sizeof (args
));
1643 /* do this BEFORE getfile which causes xid stamps to be initialized */
1644 clkset(-1L); /* hack for now - until we get time svc? */
1646 if (why
== ROOT_REMOUNT
) {
1650 panic("nfs3_mountroot: why == ROOT_REMOUNT");
1653 if (why
== ROOT_UNMOUNT
) {
1655 * Nothing to do for NFS.
1666 getfsname("root", name
, sizeof (token
));
1669 root_path
= pn
.pn_path
;
1671 svp
= kmem_zalloc(sizeof (*svp
), KM_SLEEP
);
1672 svp
->sv_knconf
= kmem_zalloc(sizeof (*svp
->sv_knconf
), KM_SLEEP
);
1673 svp
->sv_knconf
->knc_protofmly
= kmem_alloc(KNC_STRSIZE
, KM_SLEEP
);
1674 svp
->sv_knconf
->knc_proto
= kmem_alloc(KNC_STRSIZE
, KM_SLEEP
);
1677 * Get server address
1678 * Get the root fhandle
1679 * Get server's transport
1680 * Get server's hostname
1683 args
.addr
= &svp
->sv_addr
;
1684 args
.fh
= (char *)&svp
->sv_fhandle
;
1685 args
.knconf
= svp
->sv_knconf
;
1686 args
.hostname
= root_hostname
;
1688 if (error
= mount_root(*name
? name
: "root", root_path
, NFS_V3
,
1689 &args
, &vfsflags
)) {
1690 if (error
== EPROTONOSUPPORT
)
1691 nfs_cmn_err(error
, CE_WARN
, "nfs3_mountroot: "
1692 "mount_root failed: server doesn't support NFS V3");
1694 nfs_cmn_err(error
, CE_WARN
,
1695 "nfs3_mountroot: mount_root failed: %m");
1700 svp
->sv_hostnamelen
= (int)(strlen(root_hostname
) + 1);
1701 svp
->sv_hostname
= kmem_alloc(svp
->sv_hostnamelen
, KM_SLEEP
);
1702 (void) strcpy(svp
->sv_hostname
, root_hostname
);
1705 * Force root partition to always be mounted with AUTH_UNIX for now
1707 svp
->sv_secdata
= kmem_alloc(sizeof (*svp
->sv_secdata
), KM_SLEEP
);
1708 svp
->sv_secdata
->secmod
= AUTH_UNIX
;
1709 svp
->sv_secdata
->rpcflavor
= AUTH_UNIX
;
1710 svp
->sv_secdata
->data
= NULL
;
1715 error
= nfs3rootvp(&rtvp
, vfsp
, svp
, args
.flags
, cr
, global_zone
);
1725 error
= nfs_setopts(rtvp
, DATAMODEL_NATIVE
, &args
);
1727 nfs_cmn_err(error
, CE_WARN
,
1728 "nfs3_mountroot: invalid root mount options");
1733 (void) vfs_lock_wait(vfsp
);
1734 vfs_add(NULL
, vfsp
, vfsflags
);
1737 size
= strlen(svp
->sv_hostname
);
1738 (void) strcpy(rootfs
.bo_name
, svp
->sv_hostname
);
1739 rootfs
.bo_name
[size
] = ':';
1740 (void) strcpy(&rootfs
.bo_name
[size
+ 1], root_path
);
1747 nfs_async_stop(vfsp
);
1748 nfs_async_manager_stop(vfsp
);
1758 * Initialization routine for VFS routines. Should only be called once
1763 mutex_init(&nfs3_syncbusy
, NULL
, MUTEX_DEFAULT
, NULL
);
1770 mutex_destroy(&nfs3_syncbusy
);
1774 nfs3_freevfs(vfs_t
*vfsp
)
1779 /* free up the resources */
1781 svp
= mi
->mi_servers
;
1782 mi
->mi_servers
= mi
->mi_curr_serv
= NULL
;
1786 * By this time we should have already deleted the
1787 * mi kstats in the unmount code. If they are still around
1790 ASSERT(mi
->mi_io_kstats
== NULL
);