nfs_clvfsops.c revision 1.1.1.1.6.2 1 1.1.1.1.6.2 yamt /* $NetBSD: nfs_clvfsops.c,v 1.1.1.1.6.2 2014/05/22 11:41:00 yamt Exp $ */
2 1.1.1.1.6.2 yamt /*-
3 1.1.1.1.6.2 yamt * Copyright (c) 1989, 1993, 1995
4 1.1.1.1.6.2 yamt * The Regents of the University of California. All rights reserved.
5 1.1.1.1.6.2 yamt *
6 1.1.1.1.6.2 yamt * This code is derived from software contributed to Berkeley by
7 1.1.1.1.6.2 yamt * Rick Macklem at The University of Guelph.
8 1.1.1.1.6.2 yamt *
9 1.1.1.1.6.2 yamt * Redistribution and use in source and binary forms, with or without
10 1.1.1.1.6.2 yamt * modification, are permitted provided that the following conditions
11 1.1.1.1.6.2 yamt * are met:
12 1.1.1.1.6.2 yamt * 1. Redistributions of source code must retain the above copyright
13 1.1.1.1.6.2 yamt * notice, this list of conditions and the following disclaimer.
14 1.1.1.1.6.2 yamt * 2. Redistributions in binary form must reproduce the above copyright
15 1.1.1.1.6.2 yamt * notice, this list of conditions and the following disclaimer in the
16 1.1.1.1.6.2 yamt * documentation and/or other materials provided with the distribution.
17 1.1.1.1.6.2 yamt * 4. Neither the name of the University nor the names of its contributors
18 1.1.1.1.6.2 yamt * may be used to endorse or promote products derived from this software
19 1.1.1.1.6.2 yamt * without specific prior written permission.
20 1.1.1.1.6.2 yamt *
21 1.1.1.1.6.2 yamt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 1.1.1.1.6.2 yamt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 1.1.1.1.6.2 yamt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 1.1.1.1.6.2 yamt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 1.1.1.1.6.2 yamt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 1.1.1.1.6.2 yamt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 1.1.1.1.6.2 yamt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 1.1.1.1.6.2 yamt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 1.1.1.1.6.2 yamt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 1.1.1.1.6.2 yamt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 1.1.1.1.6.2 yamt * SUCH DAMAGE.
32 1.1.1.1.6.2 yamt *
33 1.1.1.1.6.2 yamt * from nfs_vfsops.c 8.12 (Berkeley) 5/20/95
34 1.1.1.1.6.2 yamt */
35 1.1.1.1.6.2 yamt
36 1.1.1.1.6.2 yamt #include <sys/cdefs.h>
37 1.1.1.1.6.2 yamt /* __FBSDID("FreeBSD: head/sys/fs/nfsclient/nfs_clvfsops.c 255136 2013-09-01 23:02:59Z rmacklem "); */
38 1.1.1.1.6.2 yamt __RCSID("$NetBSD: nfs_clvfsops.c,v 1.1.1.1.6.2 2014/05/22 11:41:00 yamt Exp $");
39 1.1.1.1.6.2 yamt
40 1.1.1.1.6.2 yamt
41 1.1.1.1.6.2 yamt #include "opt_bootp.h"
42 1.1.1.1.6.2 yamt #include "opt_nfsroot.h"
43 1.1.1.1.6.2 yamt
44 1.1.1.1.6.2 yamt #include <sys/param.h>
45 1.1.1.1.6.2 yamt #include <sys/systm.h>
46 1.1.1.1.6.2 yamt #include <sys/kernel.h>
47 1.1.1.1.6.2 yamt #include <sys/bio.h>
48 1.1.1.1.6.2 yamt #include <sys/buf.h>
49 1.1.1.1.6.2 yamt #include <sys/clock.h>
50 1.1.1.1.6.2 yamt #include <sys/jail.h>
51 1.1.1.1.6.2 yamt #include <sys/limits.h>
52 1.1.1.1.6.2 yamt #include <sys/lock.h>
53 1.1.1.1.6.2 yamt #include <sys/malloc.h>
54 1.1.1.1.6.2 yamt #include <sys/mbuf.h>
55 1.1.1.1.6.2 yamt #include <sys/module.h>
56 1.1.1.1.6.2 yamt #include <sys/mount.h>
57 1.1.1.1.6.2 yamt #include <sys/proc.h>
58 1.1.1.1.6.2 yamt #include <sys/socket.h>
59 1.1.1.1.6.2 yamt #include <sys/socketvar.h>
60 1.1.1.1.6.2 yamt #include <sys/sockio.h>
61 1.1.1.1.6.2 yamt #include <sys/sysctl.h>
62 1.1.1.1.6.2 yamt #include <sys/vnode.h>
63 1.1.1.1.6.2 yamt #include <sys/signalvar.h>
64 1.1.1.1.6.2 yamt
65 1.1.1.1.6.2 yamt #include <vm/vm.h>
66 1.1.1.1.6.2 yamt #include <vm/vm_extern.h>
67 1.1.1.1.6.2 yamt #include <vm/uma.h>
68 1.1.1.1.6.2 yamt
69 1.1.1.1.6.2 yamt #include <net/if.h>
70 1.1.1.1.6.2 yamt #include <net/route.h>
71 1.1.1.1.6.2 yamt #include <netinet/in.h>
72 1.1.1.1.6.2 yamt
73 1.1.1.1.6.2 yamt #include <fs/nfs/nfsport.h>
74 1.1.1.1.6.2 yamt #include <fs/nfsclient/nfsnode.h>
75 1.1.1.1.6.2 yamt #include <fs/nfsclient/nfsmount.h>
76 1.1.1.1.6.2 yamt #include <fs/nfsclient/nfs.h>
77 1.1.1.1.6.2 yamt #include <nfs/nfsdiskless.h>
78 1.1.1.1.6.2 yamt
79 1.1.1.1.6.2 yamt FEATURE(nfscl, "NFSv4 client");
80 1.1.1.1.6.2 yamt
81 1.1.1.1.6.2 yamt extern int nfscl_ticks;
82 1.1.1.1.6.2 yamt extern struct timeval nfsboottime;
83 1.1.1.1.6.2 yamt extern struct nfsstats newnfsstats;
84 1.1.1.1.6.2 yamt extern int nfsrv_useacl;
85 1.1.1.1.6.2 yamt extern int nfscl_debuglevel;
86 1.1.1.1.6.2 yamt extern enum nfsiod_state ncl_iodwant[NFS_MAXASYNCDAEMON];
87 1.1.1.1.6.2 yamt extern struct nfsmount *ncl_iodmount[NFS_MAXASYNCDAEMON];
88 1.1.1.1.6.2 yamt extern struct mtx ncl_iod_mutex;
89 1.1.1.1.6.2 yamt NFSCLSTATEMUTEX;
90 1.1.1.1.6.2 yamt
91 1.1.1.1.6.2 yamt MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "New NFS request header");
92 1.1.1.1.6.2 yamt MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "New NFS mount struct");
93 1.1.1.1.6.2 yamt
94 1.1.1.1.6.2 yamt SYSCTL_DECL(_vfs_nfs);
95 1.1.1.1.6.2 yamt static int nfs_ip_paranoia = 1;
96 1.1.1.1.6.2 yamt SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
97 1.1.1.1.6.2 yamt &nfs_ip_paranoia, 0, "");
98 1.1.1.1.6.2 yamt static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
99 1.1.1.1.6.2 yamt SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_INITIAL_DELAY,
100 1.1.1.1.6.2 yamt downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, "");
101 1.1.1.1.6.2 yamt /* how long between console messages "nfs server foo not responding" */
102 1.1.1.1.6.2 yamt static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
103 1.1.1.1.6.2 yamt SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY,
104 1.1.1.1.6.2 yamt downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
105 1.1.1.1.6.2 yamt
106 1.1.1.1.6.2 yamt static int nfs_mountroot(struct mount *);
107 1.1.1.1.6.2 yamt static void nfs_sec_name(char *, int *);
108 1.1.1.1.6.2 yamt static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
109 1.1.1.1.6.2 yamt struct nfs_args *argp, const char *, struct ucred *,
110 1.1.1.1.6.2 yamt struct thread *);
111 1.1.1.1.6.2 yamt static int mountnfs(struct nfs_args *, struct mount *,
112 1.1.1.1.6.2 yamt struct sockaddr *, char *, u_char *, int, u_char *, int,
113 1.1.1.1.6.2 yamt u_char *, int, struct vnode **, struct ucred *,
114 1.1.1.1.6.2 yamt struct thread *, int, int, int);
115 1.1.1.1.6.2 yamt static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
116 1.1.1.1.6.2 yamt struct sockaddr_storage *, int *, off_t *,
117 1.1.1.1.6.2 yamt struct timeval *);
118 1.1.1.1.6.2 yamt static vfs_mount_t nfs_mount;
119 1.1.1.1.6.2 yamt static vfs_cmount_t nfs_cmount;
120 1.1.1.1.6.2 yamt static vfs_unmount_t nfs_unmount;
121 1.1.1.1.6.2 yamt static vfs_root_t nfs_root;
122 1.1.1.1.6.2 yamt static vfs_statfs_t nfs_statfs;
123 1.1.1.1.6.2 yamt static vfs_sync_t nfs_sync;
124 1.1.1.1.6.2 yamt static vfs_sysctl_t nfs_sysctl;
125 1.1.1.1.6.2 yamt static vfs_purge_t nfs_purge;
126 1.1.1.1.6.2 yamt
127 1.1.1.1.6.2 yamt /*
128 1.1.1.1.6.2 yamt * nfs vfs operations.
129 1.1.1.1.6.2 yamt */
130 1.1.1.1.6.2 yamt static struct vfsops nfs_vfsops = {
131 1.1.1.1.6.2 yamt .vfs_init = ncl_init,
132 1.1.1.1.6.2 yamt .vfs_mount = nfs_mount,
133 1.1.1.1.6.2 yamt .vfs_cmount = nfs_cmount,
134 1.1.1.1.6.2 yamt .vfs_root = nfs_root,
135 1.1.1.1.6.2 yamt .vfs_statfs = nfs_statfs,
136 1.1.1.1.6.2 yamt .vfs_sync = nfs_sync,
137 1.1.1.1.6.2 yamt .vfs_uninit = ncl_uninit,
138 1.1.1.1.6.2 yamt .vfs_unmount = nfs_unmount,
139 1.1.1.1.6.2 yamt .vfs_sysctl = nfs_sysctl,
140 1.1.1.1.6.2 yamt .vfs_purge = nfs_purge,
141 1.1.1.1.6.2 yamt };
142 1.1.1.1.6.2 yamt VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK | VFCF_SBDRY);
143 1.1.1.1.6.2 yamt
144 1.1.1.1.6.2 yamt /* So that loader and kldload(2) can find us, wherever we are.. */
145 1.1.1.1.6.2 yamt MODULE_VERSION(nfs, 1);
146 1.1.1.1.6.2 yamt MODULE_DEPEND(nfs, nfscommon, 1, 1, 1);
147 1.1.1.1.6.2 yamt MODULE_DEPEND(nfs, krpc, 1, 1, 1);
148 1.1.1.1.6.2 yamt MODULE_DEPEND(nfs, nfssvc, 1, 1, 1);
149 1.1.1.1.6.2 yamt MODULE_DEPEND(nfs, nfslock, 1, 1, 1);
150 1.1.1.1.6.2 yamt
151 1.1.1.1.6.2 yamt /*
152 1.1.1.1.6.2 yamt * This structure is now defined in sys/nfs/nfs_diskless.c so that it
153 1.1.1.1.6.2 yamt * can be shared by both NFS clients. It is declared here so that it
154 1.1.1.1.6.2 yamt * will be defined for kernels built without NFS_ROOT, although it
155 1.1.1.1.6.2 yamt * isn't used in that case.
156 1.1.1.1.6.2 yamt */
157 1.1.1.1.6.2 yamt #if !defined(NFS_ROOT) && !defined(NFSCLIENT)
158 1.1.1.1.6.2 yamt struct nfs_diskless nfs_diskless = { { { 0 } } };
159 1.1.1.1.6.2 yamt struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
160 1.1.1.1.6.2 yamt int nfs_diskless_valid = 0;
161 1.1.1.1.6.2 yamt #endif
162 1.1.1.1.6.2 yamt
163 1.1.1.1.6.2 yamt SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
164 1.1.1.1.6.2 yamt &nfs_diskless_valid, 0,
165 1.1.1.1.6.2 yamt "Has the diskless struct been filled correctly");
166 1.1.1.1.6.2 yamt
167 1.1.1.1.6.2 yamt SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
168 1.1.1.1.6.2 yamt nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
169 1.1.1.1.6.2 yamt
170 1.1.1.1.6.2 yamt SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
171 1.1.1.1.6.2 yamt &nfsv3_diskless.root_saddr, sizeof(nfsv3_diskless.root_saddr),
172 1.1.1.1.6.2 yamt "%Ssockaddr_in", "Diskless root nfs address");
173 1.1.1.1.6.2 yamt
174 1.1.1.1.6.2 yamt
175 1.1.1.1.6.2 yamt void newnfsargs_ntoh(struct nfs_args *);
176 1.1.1.1.6.2 yamt static int nfs_mountdiskless(char *,
177 1.1.1.1.6.2 yamt struct sockaddr_in *, struct nfs_args *,
178 1.1.1.1.6.2 yamt struct thread *, struct vnode **, struct mount *);
179 1.1.1.1.6.2 yamt static void nfs_convert_diskless(void);
180 1.1.1.1.6.2 yamt static void nfs_convert_oargs(struct nfs_args *args,
181 1.1.1.1.6.2 yamt struct onfs_args *oargs);
182 1.1.1.1.6.2 yamt
183 1.1.1.1.6.2 yamt int
184 1.1.1.1.6.2 yamt newnfs_iosize(struct nfsmount *nmp)
185 1.1.1.1.6.2 yamt {
186 1.1.1.1.6.2 yamt int iosize, maxio;
187 1.1.1.1.6.2 yamt
188 1.1.1.1.6.2 yamt /* First, set the upper limit for iosize */
189 1.1.1.1.6.2 yamt if (nmp->nm_flag & NFSMNT_NFSV4) {
190 1.1.1.1.6.2 yamt maxio = NFS_MAXBSIZE;
191 1.1.1.1.6.2 yamt } else if (nmp->nm_flag & NFSMNT_NFSV3) {
192 1.1.1.1.6.2 yamt if (nmp->nm_sotype == SOCK_DGRAM)
193 1.1.1.1.6.2 yamt maxio = NFS_MAXDGRAMDATA;
194 1.1.1.1.6.2 yamt else
195 1.1.1.1.6.2 yamt maxio = NFS_MAXBSIZE;
196 1.1.1.1.6.2 yamt } else {
197 1.1.1.1.6.2 yamt maxio = NFS_V2MAXDATA;
198 1.1.1.1.6.2 yamt }
199 1.1.1.1.6.2 yamt if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0)
200 1.1.1.1.6.2 yamt nmp->nm_rsize = maxio;
201 1.1.1.1.6.2 yamt if (nmp->nm_rsize > MAXBSIZE)
202 1.1.1.1.6.2 yamt nmp->nm_rsize = MAXBSIZE;
203 1.1.1.1.6.2 yamt if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0)
204 1.1.1.1.6.2 yamt nmp->nm_readdirsize = maxio;
205 1.1.1.1.6.2 yamt if (nmp->nm_readdirsize > nmp->nm_rsize)
206 1.1.1.1.6.2 yamt nmp->nm_readdirsize = nmp->nm_rsize;
207 1.1.1.1.6.2 yamt if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0)
208 1.1.1.1.6.2 yamt nmp->nm_wsize = maxio;
209 1.1.1.1.6.2 yamt if (nmp->nm_wsize > MAXBSIZE)
210 1.1.1.1.6.2 yamt nmp->nm_wsize = MAXBSIZE;
211 1.1.1.1.6.2 yamt
212 1.1.1.1.6.2 yamt /*
213 1.1.1.1.6.2 yamt * Calculate the size used for io buffers. Use the larger
214 1.1.1.1.6.2 yamt * of the two sizes to minimise nfs requests but make sure
215 1.1.1.1.6.2 yamt * that it is at least one VM page to avoid wasting buffer
216 1.1.1.1.6.2 yamt * space.
217 1.1.1.1.6.2 yamt */
218 1.1.1.1.6.2 yamt iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
219 1.1.1.1.6.2 yamt iosize = imax(iosize, PAGE_SIZE);
220 1.1.1.1.6.2 yamt nmp->nm_mountp->mnt_stat.f_iosize = iosize;
221 1.1.1.1.6.2 yamt return (iosize);
222 1.1.1.1.6.2 yamt }
223 1.1.1.1.6.2 yamt
224 1.1.1.1.6.2 yamt static void
225 1.1.1.1.6.2 yamt nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
226 1.1.1.1.6.2 yamt {
227 1.1.1.1.6.2 yamt
228 1.1.1.1.6.2 yamt args->version = NFS_ARGSVERSION;
229 1.1.1.1.6.2 yamt args->addr = oargs->addr;
230 1.1.1.1.6.2 yamt args->addrlen = oargs->addrlen;
231 1.1.1.1.6.2 yamt args->sotype = oargs->sotype;
232 1.1.1.1.6.2 yamt args->proto = oargs->proto;
233 1.1.1.1.6.2 yamt args->fh = oargs->fh;
234 1.1.1.1.6.2 yamt args->fhsize = oargs->fhsize;
235 1.1.1.1.6.2 yamt args->flags = oargs->flags;
236 1.1.1.1.6.2 yamt args->wsize = oargs->wsize;
237 1.1.1.1.6.2 yamt args->rsize = oargs->rsize;
238 1.1.1.1.6.2 yamt args->readdirsize = oargs->readdirsize;
239 1.1.1.1.6.2 yamt args->timeo = oargs->timeo;
240 1.1.1.1.6.2 yamt args->retrans = oargs->retrans;
241 1.1.1.1.6.2 yamt args->readahead = oargs->readahead;
242 1.1.1.1.6.2 yamt args->hostname = oargs->hostname;
243 1.1.1.1.6.2 yamt }
244 1.1.1.1.6.2 yamt
245 1.1.1.1.6.2 yamt static void
246 1.1.1.1.6.2 yamt nfs_convert_diskless(void)
247 1.1.1.1.6.2 yamt {
248 1.1.1.1.6.2 yamt
249 1.1.1.1.6.2 yamt bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
250 1.1.1.1.6.2 yamt sizeof(struct ifaliasreq));
251 1.1.1.1.6.2 yamt bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
252 1.1.1.1.6.2 yamt sizeof(struct sockaddr_in));
253 1.1.1.1.6.2 yamt nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
254 1.1.1.1.6.2 yamt if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
255 1.1.1.1.6.2 yamt nfsv3_diskless.root_fhsize = NFSX_MYFH;
256 1.1.1.1.6.2 yamt bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_MYFH);
257 1.1.1.1.6.2 yamt } else {
258 1.1.1.1.6.2 yamt nfsv3_diskless.root_fhsize = NFSX_V2FH;
259 1.1.1.1.6.2 yamt bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
260 1.1.1.1.6.2 yamt }
261 1.1.1.1.6.2 yamt bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
262 1.1.1.1.6.2 yamt sizeof(struct sockaddr_in));
263 1.1.1.1.6.2 yamt bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
264 1.1.1.1.6.2 yamt nfsv3_diskless.root_time = nfs_diskless.root_time;
265 1.1.1.1.6.2 yamt bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
266 1.1.1.1.6.2 yamt MAXHOSTNAMELEN);
267 1.1.1.1.6.2 yamt nfs_diskless_valid = 3;
268 1.1.1.1.6.2 yamt }
269 1.1.1.1.6.2 yamt
270 1.1.1.1.6.2 yamt /*
271 1.1.1.1.6.2 yamt * nfs statfs call
272 1.1.1.1.6.2 yamt */
273 1.1.1.1.6.2 yamt static int
274 1.1.1.1.6.2 yamt nfs_statfs(struct mount *mp, struct statfs *sbp)
275 1.1.1.1.6.2 yamt {
276 1.1.1.1.6.2 yamt struct vnode *vp;
277 1.1.1.1.6.2 yamt struct thread *td;
278 1.1.1.1.6.2 yamt struct nfsmount *nmp = VFSTONFS(mp);
279 1.1.1.1.6.2 yamt struct nfsvattr nfsva;
280 1.1.1.1.6.2 yamt struct nfsfsinfo fs;
281 1.1.1.1.6.2 yamt struct nfsstatfs sb;
282 1.1.1.1.6.2 yamt int error = 0, attrflag, gotfsinfo = 0, ret;
283 1.1.1.1.6.2 yamt struct nfsnode *np;
284 1.1.1.1.6.2 yamt
285 1.1.1.1.6.2 yamt td = curthread;
286 1.1.1.1.6.2 yamt
287 1.1.1.1.6.2 yamt error = vfs_busy(mp, MBF_NOWAIT);
288 1.1.1.1.6.2 yamt if (error)
289 1.1.1.1.6.2 yamt return (error);
290 1.1.1.1.6.2 yamt error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
291 1.1.1.1.6.2 yamt if (error) {
292 1.1.1.1.6.2 yamt vfs_unbusy(mp);
293 1.1.1.1.6.2 yamt return (error);
294 1.1.1.1.6.2 yamt }
295 1.1.1.1.6.2 yamt vp = NFSTOV(np);
296 1.1.1.1.6.2 yamt mtx_lock(&nmp->nm_mtx);
297 1.1.1.1.6.2 yamt if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
298 1.1.1.1.6.2 yamt mtx_unlock(&nmp->nm_mtx);
299 1.1.1.1.6.2 yamt error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva,
300 1.1.1.1.6.2 yamt &attrflag, NULL);
301 1.1.1.1.6.2 yamt if (!error)
302 1.1.1.1.6.2 yamt gotfsinfo = 1;
303 1.1.1.1.6.2 yamt } else
304 1.1.1.1.6.2 yamt mtx_unlock(&nmp->nm_mtx);
305 1.1.1.1.6.2 yamt if (!error)
306 1.1.1.1.6.2 yamt error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva,
307 1.1.1.1.6.2 yamt &attrflag, NULL);
308 1.1.1.1.6.2 yamt if (error != 0)
309 1.1.1.1.6.2 yamt NFSCL_DEBUG(2, "statfs=%d\n", error);
310 1.1.1.1.6.2 yamt if (attrflag == 0) {
311 1.1.1.1.6.2 yamt ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
312 1.1.1.1.6.2 yamt td->td_ucred, td, &nfsva, NULL, NULL);
313 1.1.1.1.6.2 yamt if (ret) {
314 1.1.1.1.6.2 yamt /*
315 1.1.1.1.6.2 yamt * Just set default values to get things going.
316 1.1.1.1.6.2 yamt */
317 1.1.1.1.6.2 yamt NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
318 1.1.1.1.6.2 yamt nfsva.na_vattr.va_type = VDIR;
319 1.1.1.1.6.2 yamt nfsva.na_vattr.va_mode = 0777;
320 1.1.1.1.6.2 yamt nfsva.na_vattr.va_nlink = 100;
321 1.1.1.1.6.2 yamt nfsva.na_vattr.va_uid = (uid_t)0;
322 1.1.1.1.6.2 yamt nfsva.na_vattr.va_gid = (gid_t)0;
323 1.1.1.1.6.2 yamt nfsva.na_vattr.va_fileid = 2;
324 1.1.1.1.6.2 yamt nfsva.na_vattr.va_gen = 1;
325 1.1.1.1.6.2 yamt nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
326 1.1.1.1.6.2 yamt nfsva.na_vattr.va_size = 512 * 1024;
327 1.1.1.1.6.2 yamt }
328 1.1.1.1.6.2 yamt }
329 1.1.1.1.6.2 yamt (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
330 1.1.1.1.6.2 yamt if (!error) {
331 1.1.1.1.6.2 yamt mtx_lock(&nmp->nm_mtx);
332 1.1.1.1.6.2 yamt if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4))
333 1.1.1.1.6.2 yamt nfscl_loadfsinfo(nmp, &fs);
334 1.1.1.1.6.2 yamt nfscl_loadsbinfo(nmp, &sb, sbp);
335 1.1.1.1.6.2 yamt sbp->f_iosize = newnfs_iosize(nmp);
336 1.1.1.1.6.2 yamt mtx_unlock(&nmp->nm_mtx);
337 1.1.1.1.6.2 yamt if (sbp != &mp->mnt_stat) {
338 1.1.1.1.6.2 yamt bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
339 1.1.1.1.6.2 yamt bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
340 1.1.1.1.6.2 yamt }
341 1.1.1.1.6.2 yamt strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
342 1.1.1.1.6.2 yamt } else if (NFS_ISV4(vp)) {
343 1.1.1.1.6.2 yamt error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
344 1.1.1.1.6.2 yamt }
345 1.1.1.1.6.2 yamt vput(vp);
346 1.1.1.1.6.2 yamt vfs_unbusy(mp);
347 1.1.1.1.6.2 yamt return (error);
348 1.1.1.1.6.2 yamt }
349 1.1.1.1.6.2 yamt
350 1.1.1.1.6.2 yamt /*
351 1.1.1.1.6.2 yamt * nfs version 3 fsinfo rpc call
352 1.1.1.1.6.2 yamt */
353 1.1.1.1.6.2 yamt int
354 1.1.1.1.6.2 yamt ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
355 1.1.1.1.6.2 yamt struct thread *td)
356 1.1.1.1.6.2 yamt {
357 1.1.1.1.6.2 yamt struct nfsfsinfo fs;
358 1.1.1.1.6.2 yamt struct nfsvattr nfsva;
359 1.1.1.1.6.2 yamt int error, attrflag;
360 1.1.1.1.6.2 yamt
361 1.1.1.1.6.2 yamt error = nfsrpc_fsinfo(vp, &fs, cred, td, &nfsva, &attrflag, NULL);
362 1.1.1.1.6.2 yamt if (!error) {
363 1.1.1.1.6.2 yamt if (attrflag)
364 1.1.1.1.6.2 yamt (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0,
365 1.1.1.1.6.2 yamt 1);
366 1.1.1.1.6.2 yamt mtx_lock(&nmp->nm_mtx);
367 1.1.1.1.6.2 yamt nfscl_loadfsinfo(nmp, &fs);
368 1.1.1.1.6.2 yamt mtx_unlock(&nmp->nm_mtx);
369 1.1.1.1.6.2 yamt }
370 1.1.1.1.6.2 yamt return (error);
371 1.1.1.1.6.2 yamt }
372 1.1.1.1.6.2 yamt
373 1.1.1.1.6.2 yamt /*
374 1.1.1.1.6.2 yamt * Mount a remote root fs via. nfs. This depends on the info in the
375 1.1.1.1.6.2 yamt * nfs_diskless structure that has been filled in properly by some primary
376 1.1.1.1.6.2 yamt * bootstrap.
377 1.1.1.1.6.2 yamt * It goes something like this:
378 1.1.1.1.6.2 yamt * - do enough of "ifconfig" by calling ifioctl() so that the system
379 1.1.1.1.6.2 yamt * can talk to the server
380 1.1.1.1.6.2 yamt * - If nfs_diskless.mygateway is filled in, use that address as
381 1.1.1.1.6.2 yamt * a default gateway.
382 1.1.1.1.6.2 yamt * - build the rootfs mount point and call mountnfs() to do the rest.
383 1.1.1.1.6.2 yamt *
384 1.1.1.1.6.2 yamt * It is assumed to be safe to read, modify, and write the nfsv3_diskless
385 1.1.1.1.6.2 yamt * structure, as well as other global NFS client variables here, as
386 1.1.1.1.6.2 yamt * nfs_mountroot() will be called once in the boot before any other NFS
387 1.1.1.1.6.2 yamt * client activity occurs.
388 1.1.1.1.6.2 yamt */
389 1.1.1.1.6.2 yamt static int
390 1.1.1.1.6.2 yamt nfs_mountroot(struct mount *mp)
391 1.1.1.1.6.2 yamt {
392 1.1.1.1.6.2 yamt struct thread *td = curthread;
393 1.1.1.1.6.2 yamt struct nfsv3_diskless *nd = &nfsv3_diskless;
394 1.1.1.1.6.2 yamt struct socket *so;
395 1.1.1.1.6.2 yamt struct vnode *vp;
396 1.1.1.1.6.2 yamt struct ifreq ir;
397 1.1.1.1.6.2 yamt int error;
398 1.1.1.1.6.2 yamt u_long l;
399 1.1.1.1.6.2 yamt char buf[128];
400 1.1.1.1.6.2 yamt char *cp;
401 1.1.1.1.6.2 yamt
402 1.1.1.1.6.2 yamt #if defined(BOOTP_NFSROOT) && defined(BOOTP)
403 1.1.1.1.6.2 yamt bootpc_init(); /* use bootp to get nfs_diskless filled in */
404 1.1.1.1.6.2 yamt #elif defined(NFS_ROOT)
405 1.1.1.1.6.2 yamt nfs_setup_diskless();
406 1.1.1.1.6.2 yamt #endif
407 1.1.1.1.6.2 yamt
408 1.1.1.1.6.2 yamt if (nfs_diskless_valid == 0)
409 1.1.1.1.6.2 yamt return (-1);
410 1.1.1.1.6.2 yamt if (nfs_diskless_valid == 1)
411 1.1.1.1.6.2 yamt nfs_convert_diskless();
412 1.1.1.1.6.2 yamt
413 1.1.1.1.6.2 yamt /*
414 1.1.1.1.6.2 yamt * XXX splnet, so networks will receive...
415 1.1.1.1.6.2 yamt */
416 1.1.1.1.6.2 yamt splnet();
417 1.1.1.1.6.2 yamt
418 1.1.1.1.6.2 yamt /*
419 1.1.1.1.6.2 yamt * Do enough of ifconfig(8) so that the critical net interface can
420 1.1.1.1.6.2 yamt * talk to the server.
421 1.1.1.1.6.2 yamt */
422 1.1.1.1.6.2 yamt error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
423 1.1.1.1.6.2 yamt td->td_ucred, td);
424 1.1.1.1.6.2 yamt if (error)
425 1.1.1.1.6.2 yamt panic("nfs_mountroot: socreate(%04x): %d",
426 1.1.1.1.6.2 yamt nd->myif.ifra_addr.sa_family, error);
427 1.1.1.1.6.2 yamt
428 1.1.1.1.6.2 yamt #if 0 /* XXX Bad idea */
429 1.1.1.1.6.2 yamt /*
430 1.1.1.1.6.2 yamt * We might not have been told the right interface, so we pass
431 1.1.1.1.6.2 yamt * over the first ten interfaces of the same kind, until we get
432 1.1.1.1.6.2 yamt * one of them configured.
433 1.1.1.1.6.2 yamt */
434 1.1.1.1.6.2 yamt
435 1.1.1.1.6.2 yamt for (i = strlen(nd->myif.ifra_name) - 1;
436 1.1.1.1.6.2 yamt nd->myif.ifra_name[i] >= '0' &&
437 1.1.1.1.6.2 yamt nd->myif.ifra_name[i] <= '9';
438 1.1.1.1.6.2 yamt nd->myif.ifra_name[i] ++) {
439 1.1.1.1.6.2 yamt error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
440 1.1.1.1.6.2 yamt if(!error)
441 1.1.1.1.6.2 yamt break;
442 1.1.1.1.6.2 yamt }
443 1.1.1.1.6.2 yamt #endif
444 1.1.1.1.6.2 yamt error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
445 1.1.1.1.6.2 yamt if (error)
446 1.1.1.1.6.2 yamt panic("nfs_mountroot: SIOCAIFADDR: %d", error);
447 1.1.1.1.6.2 yamt if ((cp = getenv("boot.netif.mtu")) != NULL) {
448 1.1.1.1.6.2 yamt ir.ifr_mtu = strtol(cp, NULL, 10);
449 1.1.1.1.6.2 yamt bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
450 1.1.1.1.6.2 yamt freeenv(cp);
451 1.1.1.1.6.2 yamt error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
452 1.1.1.1.6.2 yamt if (error)
453 1.1.1.1.6.2 yamt printf("nfs_mountroot: SIOCSIFMTU: %d", error);
454 1.1.1.1.6.2 yamt }
455 1.1.1.1.6.2 yamt soclose(so);
456 1.1.1.1.6.2 yamt
457 1.1.1.1.6.2 yamt /*
458 1.1.1.1.6.2 yamt * If the gateway field is filled in, set it as the default route.
459 1.1.1.1.6.2 yamt * Note that pxeboot will set a default route of 0 if the route
460 1.1.1.1.6.2 yamt * is not set by the DHCP server. Check also for a value of 0
461 1.1.1.1.6.2 yamt * to avoid panicking inappropriately in that situation.
462 1.1.1.1.6.2 yamt */
463 1.1.1.1.6.2 yamt if (nd->mygateway.sin_len != 0 &&
464 1.1.1.1.6.2 yamt nd->mygateway.sin_addr.s_addr != 0) {
465 1.1.1.1.6.2 yamt struct sockaddr_in mask, sin;
466 1.1.1.1.6.2 yamt
467 1.1.1.1.6.2 yamt bzero((caddr_t)&mask, sizeof(mask));
468 1.1.1.1.6.2 yamt sin = mask;
469 1.1.1.1.6.2 yamt sin.sin_family = AF_INET;
470 1.1.1.1.6.2 yamt sin.sin_len = sizeof(sin);
471 1.1.1.1.6.2 yamt /* XXX MRT use table 0 for this sort of thing */
472 1.1.1.1.6.2 yamt CURVNET_SET(TD_TO_VNET(td));
473 1.1.1.1.6.2 yamt error = rtrequest_fib(RTM_ADD, (struct sockaddr *)&sin,
474 1.1.1.1.6.2 yamt (struct sockaddr *)&nd->mygateway,
475 1.1.1.1.6.2 yamt (struct sockaddr *)&mask,
476 1.1.1.1.6.2 yamt RTF_UP | RTF_GATEWAY, NULL, RT_DEFAULT_FIB);
477 1.1.1.1.6.2 yamt CURVNET_RESTORE();
478 1.1.1.1.6.2 yamt if (error)
479 1.1.1.1.6.2 yamt panic("nfs_mountroot: RTM_ADD: %d", error);
480 1.1.1.1.6.2 yamt }
481 1.1.1.1.6.2 yamt
482 1.1.1.1.6.2 yamt /*
483 1.1.1.1.6.2 yamt * Create the rootfs mount point.
484 1.1.1.1.6.2 yamt */
485 1.1.1.1.6.2 yamt nd->root_args.fh = nd->root_fh;
486 1.1.1.1.6.2 yamt nd->root_args.fhsize = nd->root_fhsize;
487 1.1.1.1.6.2 yamt l = ntohl(nd->root_saddr.sin_addr.s_addr);
488 1.1.1.1.6.2 yamt snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
489 1.1.1.1.6.2 yamt (l >> 24) & 0xff, (l >> 16) & 0xff,
490 1.1.1.1.6.2 yamt (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
491 1.1.1.1.6.2 yamt printf("NFS ROOT: %s\n", buf);
492 1.1.1.1.6.2 yamt nd->root_args.hostname = buf;
493 1.1.1.1.6.2 yamt if ((error = nfs_mountdiskless(buf,
494 1.1.1.1.6.2 yamt &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
495 1.1.1.1.6.2 yamt return (error);
496 1.1.1.1.6.2 yamt }
497 1.1.1.1.6.2 yamt
498 1.1.1.1.6.2 yamt /*
499 1.1.1.1.6.2 yamt * This is not really an nfs issue, but it is much easier to
500 1.1.1.1.6.2 yamt * set hostname here and then let the "/etc/rc.xxx" files
501 1.1.1.1.6.2 yamt * mount the right /var based upon its preset value.
502 1.1.1.1.6.2 yamt */
503 1.1.1.1.6.2 yamt mtx_lock(&prison0.pr_mtx);
504 1.1.1.1.6.2 yamt strlcpy(prison0.pr_hostname, nd->my_hostnam,
505 1.1.1.1.6.2 yamt sizeof(prison0.pr_hostname));
506 1.1.1.1.6.2 yamt mtx_unlock(&prison0.pr_mtx);
507 1.1.1.1.6.2 yamt inittodr(ntohl(nd->root_time));
508 1.1.1.1.6.2 yamt return (0);
509 1.1.1.1.6.2 yamt }
510 1.1.1.1.6.2 yamt
511 1.1.1.1.6.2 yamt /*
512 1.1.1.1.6.2 yamt * Internal version of mount system call for diskless setup.
513 1.1.1.1.6.2 yamt */
514 1.1.1.1.6.2 yamt static int
515 1.1.1.1.6.2 yamt nfs_mountdiskless(char *path,
516 1.1.1.1.6.2 yamt struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
517 1.1.1.1.6.2 yamt struct vnode **vpp, struct mount *mp)
518 1.1.1.1.6.2 yamt {
519 1.1.1.1.6.2 yamt struct sockaddr *nam;
520 1.1.1.1.6.2 yamt int dirlen, error;
521 1.1.1.1.6.2 yamt char *dirpath;
522 1.1.1.1.6.2 yamt
523 1.1.1.1.6.2 yamt /*
524 1.1.1.1.6.2 yamt * Find the directory path in "path", which also has the server's
525 1.1.1.1.6.2 yamt * name/ip address in it.
526 1.1.1.1.6.2 yamt */
527 1.1.1.1.6.2 yamt dirpath = strchr(path, ':');
528 1.1.1.1.6.2 yamt if (dirpath != NULL)
529 1.1.1.1.6.2 yamt dirlen = strlen(++dirpath);
530 1.1.1.1.6.2 yamt else
531 1.1.1.1.6.2 yamt dirlen = 0;
532 1.1.1.1.6.2 yamt nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
533 1.1.1.1.6.2 yamt if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
534 1.1.1.1.6.2 yamt NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NAMETIMEO,
535 1.1.1.1.6.2 yamt NFS_DEFAULT_NEGNAMETIMEO, 0)) != 0) {
536 1.1.1.1.6.2 yamt printf("nfs_mountroot: mount %s on /: %d\n", path, error);
537 1.1.1.1.6.2 yamt return (error);
538 1.1.1.1.6.2 yamt }
539 1.1.1.1.6.2 yamt return (0);
540 1.1.1.1.6.2 yamt }
541 1.1.1.1.6.2 yamt
542 1.1.1.1.6.2 yamt static void
543 1.1.1.1.6.2 yamt nfs_sec_name(char *sec, int *flagsp)
544 1.1.1.1.6.2 yamt {
545 1.1.1.1.6.2 yamt if (!strcmp(sec, "krb5"))
546 1.1.1.1.6.2 yamt *flagsp |= NFSMNT_KERB;
547 1.1.1.1.6.2 yamt else if (!strcmp(sec, "krb5i"))
548 1.1.1.1.6.2 yamt *flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY);
549 1.1.1.1.6.2 yamt else if (!strcmp(sec, "krb5p"))
550 1.1.1.1.6.2 yamt *flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY);
551 1.1.1.1.6.2 yamt }
552 1.1.1.1.6.2 yamt
553 1.1.1.1.6.2 yamt static void
554 1.1.1.1.6.2 yamt nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
555 1.1.1.1.6.2 yamt const char *hostname, struct ucred *cred, struct thread *td)
556 1.1.1.1.6.2 yamt {
557 1.1.1.1.6.2 yamt int s;
558 1.1.1.1.6.2 yamt int adjsock;
559 1.1.1.1.6.2 yamt char *p;
560 1.1.1.1.6.2 yamt
561 1.1.1.1.6.2 yamt s = splnet();
562 1.1.1.1.6.2 yamt
563 1.1.1.1.6.2 yamt /*
564 1.1.1.1.6.2 yamt * Set read-only flag if requested; otherwise, clear it if this is
565 1.1.1.1.6.2 yamt * an update. If this is not an update, then either the read-only
566 1.1.1.1.6.2 yamt * flag is already clear, or this is a root mount and it was set
567 1.1.1.1.6.2 yamt * intentionally at some previous point.
568 1.1.1.1.6.2 yamt */
569 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
570 1.1.1.1.6.2 yamt MNT_ILOCK(mp);
571 1.1.1.1.6.2 yamt mp->mnt_flag |= MNT_RDONLY;
572 1.1.1.1.6.2 yamt MNT_IUNLOCK(mp);
573 1.1.1.1.6.2 yamt } else if (mp->mnt_flag & MNT_UPDATE) {
574 1.1.1.1.6.2 yamt MNT_ILOCK(mp);
575 1.1.1.1.6.2 yamt mp->mnt_flag &= ~MNT_RDONLY;
576 1.1.1.1.6.2 yamt MNT_IUNLOCK(mp);
577 1.1.1.1.6.2 yamt }
578 1.1.1.1.6.2 yamt
579 1.1.1.1.6.2 yamt /*
580 1.1.1.1.6.2 yamt * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
581 1.1.1.1.6.2 yamt * no sense in that context. Also, set up appropriate retransmit
582 1.1.1.1.6.2 yamt * and soft timeout behavior.
583 1.1.1.1.6.2 yamt */
584 1.1.1.1.6.2 yamt if (argp->sotype == SOCK_STREAM) {
585 1.1.1.1.6.2 yamt nmp->nm_flag &= ~NFSMNT_NOCONN;
586 1.1.1.1.6.2 yamt nmp->nm_timeo = NFS_MAXTIMEO;
587 1.1.1.1.6.2 yamt if ((argp->flags & NFSMNT_NFSV4) != 0)
588 1.1.1.1.6.2 yamt nmp->nm_retry = INT_MAX;
589 1.1.1.1.6.2 yamt else
590 1.1.1.1.6.2 yamt nmp->nm_retry = NFS_RETRANS_TCP;
591 1.1.1.1.6.2 yamt }
592 1.1.1.1.6.2 yamt
593 1.1.1.1.6.2 yamt /* Also clear RDIRPLUS if NFSv2, it crashes some servers */
594 1.1.1.1.6.2 yamt if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
595 1.1.1.1.6.2 yamt argp->flags &= ~NFSMNT_RDIRPLUS;
596 1.1.1.1.6.2 yamt nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
597 1.1.1.1.6.2 yamt }
598 1.1.1.1.6.2 yamt
599 1.1.1.1.6.2 yamt /* Re-bind if rsrvd port requested and wasn't on one */
600 1.1.1.1.6.2 yamt adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
601 1.1.1.1.6.2 yamt && (argp->flags & NFSMNT_RESVPORT);
602 1.1.1.1.6.2 yamt /* Also re-bind if we're switching to/from a connected UDP socket */
603 1.1.1.1.6.2 yamt adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
604 1.1.1.1.6.2 yamt (argp->flags & NFSMNT_NOCONN));
605 1.1.1.1.6.2 yamt
606 1.1.1.1.6.2 yamt /* Update flags atomically. Don't change the lock bits. */
607 1.1.1.1.6.2 yamt nmp->nm_flag = argp->flags | nmp->nm_flag;
608 1.1.1.1.6.2 yamt splx(s);
609 1.1.1.1.6.2 yamt
610 1.1.1.1.6.2 yamt if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
611 1.1.1.1.6.2 yamt nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
612 1.1.1.1.6.2 yamt if (nmp->nm_timeo < NFS_MINTIMEO)
613 1.1.1.1.6.2 yamt nmp->nm_timeo = NFS_MINTIMEO;
614 1.1.1.1.6.2 yamt else if (nmp->nm_timeo > NFS_MAXTIMEO)
615 1.1.1.1.6.2 yamt nmp->nm_timeo = NFS_MAXTIMEO;
616 1.1.1.1.6.2 yamt }
617 1.1.1.1.6.2 yamt
618 1.1.1.1.6.2 yamt if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
619 1.1.1.1.6.2 yamt nmp->nm_retry = argp->retrans;
620 1.1.1.1.6.2 yamt if (nmp->nm_retry > NFS_MAXREXMIT)
621 1.1.1.1.6.2 yamt nmp->nm_retry = NFS_MAXREXMIT;
622 1.1.1.1.6.2 yamt }
623 1.1.1.1.6.2 yamt
624 1.1.1.1.6.2 yamt if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
625 1.1.1.1.6.2 yamt nmp->nm_wsize = argp->wsize;
626 1.1.1.1.6.2 yamt /* Round down to multiple of blocksize */
627 1.1.1.1.6.2 yamt nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
628 1.1.1.1.6.2 yamt if (nmp->nm_wsize <= 0)
629 1.1.1.1.6.2 yamt nmp->nm_wsize = NFS_FABLKSIZE;
630 1.1.1.1.6.2 yamt }
631 1.1.1.1.6.2 yamt
632 1.1.1.1.6.2 yamt if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
633 1.1.1.1.6.2 yamt nmp->nm_rsize = argp->rsize;
634 1.1.1.1.6.2 yamt /* Round down to multiple of blocksize */
635 1.1.1.1.6.2 yamt nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
636 1.1.1.1.6.2 yamt if (nmp->nm_rsize <= 0)
637 1.1.1.1.6.2 yamt nmp->nm_rsize = NFS_FABLKSIZE;
638 1.1.1.1.6.2 yamt }
639 1.1.1.1.6.2 yamt
640 1.1.1.1.6.2 yamt if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
641 1.1.1.1.6.2 yamt nmp->nm_readdirsize = argp->readdirsize;
642 1.1.1.1.6.2 yamt }
643 1.1.1.1.6.2 yamt
644 1.1.1.1.6.2 yamt if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
645 1.1.1.1.6.2 yamt nmp->nm_acregmin = argp->acregmin;
646 1.1.1.1.6.2 yamt else
647 1.1.1.1.6.2 yamt nmp->nm_acregmin = NFS_MINATTRTIMO;
648 1.1.1.1.6.2 yamt if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
649 1.1.1.1.6.2 yamt nmp->nm_acregmax = argp->acregmax;
650 1.1.1.1.6.2 yamt else
651 1.1.1.1.6.2 yamt nmp->nm_acregmax = NFS_MAXATTRTIMO;
652 1.1.1.1.6.2 yamt if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
653 1.1.1.1.6.2 yamt nmp->nm_acdirmin = argp->acdirmin;
654 1.1.1.1.6.2 yamt else
655 1.1.1.1.6.2 yamt nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
656 1.1.1.1.6.2 yamt if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
657 1.1.1.1.6.2 yamt nmp->nm_acdirmax = argp->acdirmax;
658 1.1.1.1.6.2 yamt else
659 1.1.1.1.6.2 yamt nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
660 1.1.1.1.6.2 yamt if (nmp->nm_acdirmin > nmp->nm_acdirmax)
661 1.1.1.1.6.2 yamt nmp->nm_acdirmin = nmp->nm_acdirmax;
662 1.1.1.1.6.2 yamt if (nmp->nm_acregmin > nmp->nm_acregmax)
663 1.1.1.1.6.2 yamt nmp->nm_acregmin = nmp->nm_acregmax;
664 1.1.1.1.6.2 yamt
665 1.1.1.1.6.2 yamt if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
666 1.1.1.1.6.2 yamt if (argp->readahead <= NFS_MAXRAHEAD)
667 1.1.1.1.6.2 yamt nmp->nm_readahead = argp->readahead;
668 1.1.1.1.6.2 yamt else
669 1.1.1.1.6.2 yamt nmp->nm_readahead = NFS_MAXRAHEAD;
670 1.1.1.1.6.2 yamt }
671 1.1.1.1.6.2 yamt if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
672 1.1.1.1.6.2 yamt if (argp->wcommitsize < nmp->nm_wsize)
673 1.1.1.1.6.2 yamt nmp->nm_wcommitsize = nmp->nm_wsize;
674 1.1.1.1.6.2 yamt else
675 1.1.1.1.6.2 yamt nmp->nm_wcommitsize = argp->wcommitsize;
676 1.1.1.1.6.2 yamt }
677 1.1.1.1.6.2 yamt
678 1.1.1.1.6.2 yamt adjsock |= ((nmp->nm_sotype != argp->sotype) ||
679 1.1.1.1.6.2 yamt (nmp->nm_soproto != argp->proto));
680 1.1.1.1.6.2 yamt
681 1.1.1.1.6.2 yamt if (nmp->nm_client != NULL && adjsock) {
682 1.1.1.1.6.2 yamt int haslock = 0, error = 0;
683 1.1.1.1.6.2 yamt
684 1.1.1.1.6.2 yamt if (nmp->nm_sotype == SOCK_STREAM) {
685 1.1.1.1.6.2 yamt error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock);
686 1.1.1.1.6.2 yamt if (!error)
687 1.1.1.1.6.2 yamt haslock = 1;
688 1.1.1.1.6.2 yamt }
689 1.1.1.1.6.2 yamt if (!error) {
690 1.1.1.1.6.2 yamt newnfs_disconnect(&nmp->nm_sockreq);
691 1.1.1.1.6.2 yamt if (haslock)
692 1.1.1.1.6.2 yamt newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
693 1.1.1.1.6.2 yamt nmp->nm_sotype = argp->sotype;
694 1.1.1.1.6.2 yamt nmp->nm_soproto = argp->proto;
695 1.1.1.1.6.2 yamt if (nmp->nm_sotype == SOCK_DGRAM)
696 1.1.1.1.6.2 yamt while (newnfs_connect(nmp, &nmp->nm_sockreq,
697 1.1.1.1.6.2 yamt cred, td, 0)) {
698 1.1.1.1.6.2 yamt printf("newnfs_args: retrying connect\n");
699 1.1.1.1.6.2 yamt (void) nfs_catnap(PSOCK, 0, "newnfscon");
700 1.1.1.1.6.2 yamt }
701 1.1.1.1.6.2 yamt }
702 1.1.1.1.6.2 yamt } else {
703 1.1.1.1.6.2 yamt nmp->nm_sotype = argp->sotype;
704 1.1.1.1.6.2 yamt nmp->nm_soproto = argp->proto;
705 1.1.1.1.6.2 yamt }
706 1.1.1.1.6.2 yamt
707 1.1.1.1.6.2 yamt if (hostname != NULL) {
708 1.1.1.1.6.2 yamt strlcpy(nmp->nm_hostname, hostname,
709 1.1.1.1.6.2 yamt sizeof(nmp->nm_hostname));
710 1.1.1.1.6.2 yamt p = strchr(nmp->nm_hostname, ':');
711 1.1.1.1.6.2 yamt if (p != NULL)
712 1.1.1.1.6.2 yamt *p = '\0';
713 1.1.1.1.6.2 yamt }
714 1.1.1.1.6.2 yamt }
715 1.1.1.1.6.2 yamt
716 1.1.1.1.6.2 yamt static const char *nfs_opts[] = { "from", "nfs_args",
717 1.1.1.1.6.2 yamt "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
718 1.1.1.1.6.2 yamt "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
719 1.1.1.1.6.2 yamt "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus",
720 1.1.1.1.6.2 yamt "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
721 1.1.1.1.6.2 yamt "retrans", "acregmin", "acregmax", "acdirmin", "acdirmax", "resvport",
722 1.1.1.1.6.2 yamt "readahead", "hostname", "timeout", "addr", "fh", "nfsv3", "sec",
723 1.1.1.1.6.2 yamt "principal", "nfsv4", "gssname", "allgssname", "dirpath", "minorversion",
724 1.1.1.1.6.2 yamt "nametimeo", "negnametimeo", "nocto", "pnfs", "wcommitsize",
725 1.1.1.1.6.2 yamt NULL };
726 1.1.1.1.6.2 yamt
727 1.1.1.1.6.2 yamt /*
728 1.1.1.1.6.2 yamt * VFS Operations.
729 1.1.1.1.6.2 yamt *
730 1.1.1.1.6.2 yamt * mount system call
731 1.1.1.1.6.2 yamt * It seems a bit dumb to copyinstr() the host and path here and then
732 1.1.1.1.6.2 yamt * bcopy() them in mountnfs(), but I wanted to detect errors before
733 1.1.1.1.6.2 yamt * doing the sockargs() call because sockargs() allocates an mbuf and
734 1.1.1.1.6.2 yamt * an error after that means that I have to release the mbuf.
735 1.1.1.1.6.2 yamt */
736 1.1.1.1.6.2 yamt /* ARGSUSED */
737 1.1.1.1.6.2 yamt static int
738 1.1.1.1.6.2 yamt nfs_mount(struct mount *mp)
739 1.1.1.1.6.2 yamt {
740 1.1.1.1.6.2 yamt struct nfs_args args = {
741 1.1.1.1.6.2 yamt .version = NFS_ARGSVERSION,
742 1.1.1.1.6.2 yamt .addr = NULL,
743 1.1.1.1.6.2 yamt .addrlen = sizeof (struct sockaddr_in),
744 1.1.1.1.6.2 yamt .sotype = SOCK_STREAM,
745 1.1.1.1.6.2 yamt .proto = 0,
746 1.1.1.1.6.2 yamt .fh = NULL,
747 1.1.1.1.6.2 yamt .fhsize = 0,
748 1.1.1.1.6.2 yamt .flags = NFSMNT_RESVPORT,
749 1.1.1.1.6.2 yamt .wsize = NFS_WSIZE,
750 1.1.1.1.6.2 yamt .rsize = NFS_RSIZE,
751 1.1.1.1.6.2 yamt .readdirsize = NFS_READDIRSIZE,
752 1.1.1.1.6.2 yamt .timeo = 10,
753 1.1.1.1.6.2 yamt .retrans = NFS_RETRANS,
754 1.1.1.1.6.2 yamt .readahead = NFS_DEFRAHEAD,
755 1.1.1.1.6.2 yamt .wcommitsize = 0, /* was: NQ_DEFLEASE */
756 1.1.1.1.6.2 yamt .hostname = NULL,
757 1.1.1.1.6.2 yamt .acregmin = NFS_MINATTRTIMO,
758 1.1.1.1.6.2 yamt .acregmax = NFS_MAXATTRTIMO,
759 1.1.1.1.6.2 yamt .acdirmin = NFS_MINDIRATTRTIMO,
760 1.1.1.1.6.2 yamt .acdirmax = NFS_MAXDIRATTRTIMO,
761 1.1.1.1.6.2 yamt };
762 1.1.1.1.6.2 yamt int error = 0, ret, len;
763 1.1.1.1.6.2 yamt struct sockaddr *nam = NULL;
764 1.1.1.1.6.2 yamt struct vnode *vp;
765 1.1.1.1.6.2 yamt struct thread *td;
766 1.1.1.1.6.2 yamt char hst[MNAMELEN];
767 1.1.1.1.6.2 yamt u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
768 1.1.1.1.6.2 yamt char *opt, *name, *secname;
769 1.1.1.1.6.2 yamt int nametimeo = NFS_DEFAULT_NAMETIMEO;
770 1.1.1.1.6.2 yamt int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
771 1.1.1.1.6.2 yamt int minvers = 0;
772 1.1.1.1.6.2 yamt int dirlen, has_nfs_args_opt, krbnamelen, srvkrbnamelen;
773 1.1.1.1.6.2 yamt size_t hstlen;
774 1.1.1.1.6.2 yamt
775 1.1.1.1.6.2 yamt has_nfs_args_opt = 0;
776 1.1.1.1.6.2 yamt if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
777 1.1.1.1.6.2 yamt error = EINVAL;
778 1.1.1.1.6.2 yamt goto out;
779 1.1.1.1.6.2 yamt }
780 1.1.1.1.6.2 yamt
781 1.1.1.1.6.2 yamt td = curthread;
782 1.1.1.1.6.2 yamt if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS) {
783 1.1.1.1.6.2 yamt error = nfs_mountroot(mp);
784 1.1.1.1.6.2 yamt goto out;
785 1.1.1.1.6.2 yamt }
786 1.1.1.1.6.2 yamt
787 1.1.1.1.6.2 yamt nfscl_init();
788 1.1.1.1.6.2 yamt
789 1.1.1.1.6.2 yamt /*
790 1.1.1.1.6.2 yamt * The old mount_nfs program passed the struct nfs_args
791 1.1.1.1.6.2 yamt * from userspace to kernel. The new mount_nfs program
792 1.1.1.1.6.2 yamt * passes string options via nmount() from userspace to kernel
793 1.1.1.1.6.2 yamt * and we populate the struct nfs_args in the kernel.
794 1.1.1.1.6.2 yamt */
795 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
796 1.1.1.1.6.2 yamt error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
797 1.1.1.1.6.2 yamt sizeof(args));
798 1.1.1.1.6.2 yamt if (error != 0)
799 1.1.1.1.6.2 yamt goto out;
800 1.1.1.1.6.2 yamt
801 1.1.1.1.6.2 yamt if (args.version != NFS_ARGSVERSION) {
802 1.1.1.1.6.2 yamt error = EPROGMISMATCH;
803 1.1.1.1.6.2 yamt goto out;
804 1.1.1.1.6.2 yamt }
805 1.1.1.1.6.2 yamt has_nfs_args_opt = 1;
806 1.1.1.1.6.2 yamt }
807 1.1.1.1.6.2 yamt
808 1.1.1.1.6.2 yamt /* Handle the new style options. */
809 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
810 1.1.1.1.6.2 yamt args.flags |= NFSMNT_NOCONN;
811 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
812 1.1.1.1.6.2 yamt args.flags |= NFSMNT_NOCONN;
813 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
814 1.1.1.1.6.2 yamt args.flags |= NFSMNT_NOLOCKD;
815 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
816 1.1.1.1.6.2 yamt args.flags &= ~NFSMNT_NOLOCKD;
817 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
818 1.1.1.1.6.2 yamt args.flags |= NFSMNT_INT;
819 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
820 1.1.1.1.6.2 yamt args.flags |= NFSMNT_RDIRPLUS;
821 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
822 1.1.1.1.6.2 yamt args.flags |= NFSMNT_RESVPORT;
823 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
824 1.1.1.1.6.2 yamt args.flags &= ~NFSMNT_RESVPORT;
825 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
826 1.1.1.1.6.2 yamt args.flags |= NFSMNT_SOFT;
827 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
828 1.1.1.1.6.2 yamt args.flags &= ~NFSMNT_SOFT;
829 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
830 1.1.1.1.6.2 yamt args.sotype = SOCK_DGRAM;
831 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
832 1.1.1.1.6.2 yamt args.sotype = SOCK_DGRAM;
833 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
834 1.1.1.1.6.2 yamt args.sotype = SOCK_STREAM;
835 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
836 1.1.1.1.6.2 yamt args.flags |= NFSMNT_NFSV3;
837 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
838 1.1.1.1.6.2 yamt args.flags |= NFSMNT_NFSV4;
839 1.1.1.1.6.2 yamt args.sotype = SOCK_STREAM;
840 1.1.1.1.6.2 yamt }
841 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
842 1.1.1.1.6.2 yamt args.flags |= NFSMNT_ALLGSSNAME;
843 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
844 1.1.1.1.6.2 yamt args.flags |= NFSMNT_NOCTO;
845 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "pnfs", NULL, NULL) == 0)
846 1.1.1.1.6.2 yamt args.flags |= NFSMNT_PNFS;
847 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
848 1.1.1.1.6.2 yamt if (opt == NULL) {
849 1.1.1.1.6.2 yamt vfs_mount_error(mp, "illegal readdirsize");
850 1.1.1.1.6.2 yamt error = EINVAL;
851 1.1.1.1.6.2 yamt goto out;
852 1.1.1.1.6.2 yamt }
853 1.1.1.1.6.2 yamt ret = sscanf(opt, "%d", &args.readdirsize);
854 1.1.1.1.6.2 yamt if (ret != 1 || args.readdirsize <= 0) {
855 1.1.1.1.6.2 yamt vfs_mount_error(mp, "illegal readdirsize: %s",
856 1.1.1.1.6.2 yamt opt);
857 1.1.1.1.6.2 yamt error = EINVAL;
858 1.1.1.1.6.2 yamt goto out;
859 1.1.1.1.6.2 yamt }
860 1.1.1.1.6.2 yamt args.flags |= NFSMNT_READDIRSIZE;
861 1.1.1.1.6.2 yamt }
862 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
863 1.1.1.1.6.2 yamt if (opt == NULL) {
864 1.1.1.1.6.2 yamt vfs_mount_error(mp, "illegal readahead");
865 1.1.1.1.6.2 yamt error = EINVAL;
866 1.1.1.1.6.2 yamt goto out;
867 1.1.1.1.6.2 yamt }
868 1.1.1.1.6.2 yamt ret = sscanf(opt, "%d", &args.readahead);
869 1.1.1.1.6.2 yamt if (ret != 1 || args.readahead <= 0) {
870 1.1.1.1.6.2 yamt vfs_mount_error(mp, "illegal readahead: %s",
871 1.1.1.1.6.2 yamt opt);
872 1.1.1.1.6.2 yamt error = EINVAL;
873 1.1.1.1.6.2 yamt goto out;
874 1.1.1.1.6.2 yamt }
875 1.1.1.1.6.2 yamt args.flags |= NFSMNT_READAHEAD;
876 1.1.1.1.6.2 yamt }
877 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
878 1.1.1.1.6.2 yamt if (opt == NULL) {
879 1.1.1.1.6.2 yamt vfs_mount_error(mp, "illegal wsize");
880 1.1.1.1.6.2 yamt error = EINVAL;
881 1.1.1.1.6.2 yamt goto out;
882 1.1.1.1.6.2 yamt }
883 1.1.1.1.6.2 yamt ret = sscanf(opt, "%d", &args.wsize);
884 1.1.1.1.6.2 yamt if (ret != 1 || args.wsize <= 0) {
885 1.1.1.1.6.2 yamt vfs_mount_error(mp, "illegal wsize: %s",
886 1.1.1.1.6.2 yamt opt);
887 1.1.1.1.6.2 yamt error = EINVAL;
888 1.1.1.1.6.2 yamt goto out;
889 1.1.1.1.6.2 yamt }
890 1.1.1.1.6.2 yamt args.flags |= NFSMNT_WSIZE;
891 1.1.1.1.6.2 yamt }
892 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
893 1.1.1.1.6.2 yamt if (opt == NULL) {
894 1.1.1.1.6.2 yamt vfs_mount_error(mp, "illegal rsize");
895 1.1.1.1.6.2 yamt error = EINVAL;
896 1.1.1.1.6.2 yamt goto out;
897 1.1.1.1.6.2 yamt }
898 1.1.1.1.6.2 yamt ret = sscanf(opt, "%d", &args.rsize);
899 1.1.1.1.6.2 yamt if (ret != 1 || args.rsize <= 0) {
900 1.1.1.1.6.2 yamt vfs_mount_error(mp, "illegal wsize: %s",
901 1.1.1.1.6.2 yamt opt);
902 1.1.1.1.6.2 yamt error = EINVAL;
903 1.1.1.1.6.2 yamt goto out;
904 1.1.1.1.6.2 yamt }
905 1.1.1.1.6.2 yamt args.flags |= NFSMNT_RSIZE;
906 1.1.1.1.6.2 yamt }
907 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
908 1.1.1.1.6.2 yamt if (opt == NULL) {
909 1.1.1.1.6.2 yamt vfs_mount_error(mp, "illegal retrans");
910 1.1.1.1.6.2 yamt error = EINVAL;
911 1.1.1.1.6.2 yamt goto out;
912 1.1.1.1.6.2 yamt }
913 1.1.1.1.6.2 yamt ret = sscanf(opt, "%d", &args.retrans);
914 1.1.1.1.6.2 yamt if (ret != 1 || args.retrans <= 0) {
915 1.1.1.1.6.2 yamt vfs_mount_error(mp, "illegal retrans: %s",
916 1.1.1.1.6.2 yamt opt);
917 1.1.1.1.6.2 yamt error = EINVAL;
918 1.1.1.1.6.2 yamt goto out;
919 1.1.1.1.6.2 yamt }
920 1.1.1.1.6.2 yamt args.flags |= NFSMNT_RETRANS;
921 1.1.1.1.6.2 yamt }
922 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
923 1.1.1.1.6.2 yamt ret = sscanf(opt, "%d", &args.acregmin);
924 1.1.1.1.6.2 yamt if (ret != 1 || args.acregmin < 0) {
925 1.1.1.1.6.2 yamt vfs_mount_error(mp, "illegal acregmin: %s",
926 1.1.1.1.6.2 yamt opt);
927 1.1.1.1.6.2 yamt error = EINVAL;
928 1.1.1.1.6.2 yamt goto out;
929 1.1.1.1.6.2 yamt }
930 1.1.1.1.6.2 yamt args.flags |= NFSMNT_ACREGMIN;
931 1.1.1.1.6.2 yamt }
932 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
933 1.1.1.1.6.2 yamt ret = sscanf(opt, "%d", &args.acregmax);
934 1.1.1.1.6.2 yamt if (ret != 1 || args.acregmax < 0) {
935 1.1.1.1.6.2 yamt vfs_mount_error(mp, "illegal acregmax: %s",
936 1.1.1.1.6.2 yamt opt);
937 1.1.1.1.6.2 yamt error = EINVAL;
938 1.1.1.1.6.2 yamt goto out;
939 1.1.1.1.6.2 yamt }
940 1.1.1.1.6.2 yamt args.flags |= NFSMNT_ACREGMAX;
941 1.1.1.1.6.2 yamt }
942 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
943 1.1.1.1.6.2 yamt ret = sscanf(opt, "%d", &args.acdirmin);
944 1.1.1.1.6.2 yamt if (ret != 1 || args.acdirmin < 0) {
945 1.1.1.1.6.2 yamt vfs_mount_error(mp, "illegal acdirmin: %s",
946 1.1.1.1.6.2 yamt opt);
947 1.1.1.1.6.2 yamt error = EINVAL;
948 1.1.1.1.6.2 yamt goto out;
949 1.1.1.1.6.2 yamt }
950 1.1.1.1.6.2 yamt args.flags |= NFSMNT_ACDIRMIN;
951 1.1.1.1.6.2 yamt }
952 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
953 1.1.1.1.6.2 yamt ret = sscanf(opt, "%d", &args.acdirmax);
954 1.1.1.1.6.2 yamt if (ret != 1 || args.acdirmax < 0) {
955 1.1.1.1.6.2 yamt vfs_mount_error(mp, "illegal acdirmax: %s",
956 1.1.1.1.6.2 yamt opt);
957 1.1.1.1.6.2 yamt error = EINVAL;
958 1.1.1.1.6.2 yamt goto out;
959 1.1.1.1.6.2 yamt }
960 1.1.1.1.6.2 yamt args.flags |= NFSMNT_ACDIRMAX;
961 1.1.1.1.6.2 yamt }
962 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) {
963 1.1.1.1.6.2 yamt ret = sscanf(opt, "%d", &args.wcommitsize);
964 1.1.1.1.6.2 yamt if (ret != 1 || args.wcommitsize < 0) {
965 1.1.1.1.6.2 yamt vfs_mount_error(mp, "illegal wcommitsize: %s", opt);
966 1.1.1.1.6.2 yamt error = EINVAL;
967 1.1.1.1.6.2 yamt goto out;
968 1.1.1.1.6.2 yamt }
969 1.1.1.1.6.2 yamt args.flags |= NFSMNT_WCOMMITSIZE;
970 1.1.1.1.6.2 yamt }
971 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
972 1.1.1.1.6.2 yamt ret = sscanf(opt, "%d", &args.timeo);
973 1.1.1.1.6.2 yamt if (ret != 1 || args.timeo <= 0) {
974 1.1.1.1.6.2 yamt vfs_mount_error(mp, "illegal timeout: %s",
975 1.1.1.1.6.2 yamt opt);
976 1.1.1.1.6.2 yamt error = EINVAL;
977 1.1.1.1.6.2 yamt goto out;
978 1.1.1.1.6.2 yamt }
979 1.1.1.1.6.2 yamt args.flags |= NFSMNT_TIMEO;
980 1.1.1.1.6.2 yamt }
981 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) {
982 1.1.1.1.6.2 yamt ret = sscanf(opt, "%d", &nametimeo);
983 1.1.1.1.6.2 yamt if (ret != 1 || nametimeo < 0) {
984 1.1.1.1.6.2 yamt vfs_mount_error(mp, "illegal nametimeo: %s", opt);
985 1.1.1.1.6.2 yamt error = EINVAL;
986 1.1.1.1.6.2 yamt goto out;
987 1.1.1.1.6.2 yamt }
988 1.1.1.1.6.2 yamt }
989 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
990 1.1.1.1.6.2 yamt == 0) {
991 1.1.1.1.6.2 yamt ret = sscanf(opt, "%d", &negnametimeo);
992 1.1.1.1.6.2 yamt if (ret != 1 || negnametimeo < 0) {
993 1.1.1.1.6.2 yamt vfs_mount_error(mp, "illegal negnametimeo: %s",
994 1.1.1.1.6.2 yamt opt);
995 1.1.1.1.6.2 yamt error = EINVAL;
996 1.1.1.1.6.2 yamt goto out;
997 1.1.1.1.6.2 yamt }
998 1.1.1.1.6.2 yamt }
999 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "minorversion", (void **)&opt, NULL) ==
1000 1.1.1.1.6.2 yamt 0) {
1001 1.1.1.1.6.2 yamt ret = sscanf(opt, "%d", &minvers);
1002 1.1.1.1.6.2 yamt if (ret != 1 || minvers < 0 || minvers > 1 ||
1003 1.1.1.1.6.2 yamt (args.flags & NFSMNT_NFSV4) == 0) {
1004 1.1.1.1.6.2 yamt vfs_mount_error(mp, "illegal minorversion: %s", opt);
1005 1.1.1.1.6.2 yamt error = EINVAL;
1006 1.1.1.1.6.2 yamt goto out;
1007 1.1.1.1.6.2 yamt }
1008 1.1.1.1.6.2 yamt }
1009 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "sec",
1010 1.1.1.1.6.2 yamt (void **) &secname, NULL) == 0)
1011 1.1.1.1.6.2 yamt nfs_sec_name(secname, &args.flags);
1012 1.1.1.1.6.2 yamt
1013 1.1.1.1.6.2 yamt if (mp->mnt_flag & MNT_UPDATE) {
1014 1.1.1.1.6.2 yamt struct nfsmount *nmp = VFSTONFS(mp);
1015 1.1.1.1.6.2 yamt
1016 1.1.1.1.6.2 yamt if (nmp == NULL) {
1017 1.1.1.1.6.2 yamt error = EIO;
1018 1.1.1.1.6.2 yamt goto out;
1019 1.1.1.1.6.2 yamt }
1020 1.1.1.1.6.2 yamt
1021 1.1.1.1.6.2 yamt /*
1022 1.1.1.1.6.2 yamt * If a change from TCP->UDP is done and there are thread(s)
1023 1.1.1.1.6.2 yamt * that have I/O RPC(s) in progress with a tranfer size
1024 1.1.1.1.6.2 yamt * greater than NFS_MAXDGRAMDATA, those thread(s) will be
1025 1.1.1.1.6.2 yamt * hung, retrying the RPC(s) forever. Usually these threads
1026 1.1.1.1.6.2 yamt * will be seen doing an uninterruptible sleep on wait channel
1027 1.1.1.1.6.2 yamt * "newnfsreq" (truncated to "newnfsre" by procstat).
1028 1.1.1.1.6.2 yamt */
1029 1.1.1.1.6.2 yamt if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
1030 1.1.1.1.6.2 yamt tprintf(td->td_proc, LOG_WARNING,
1031 1.1.1.1.6.2 yamt "Warning: mount -u that changes TCP->UDP can result in hung threads\n");
1032 1.1.1.1.6.2 yamt
1033 1.1.1.1.6.2 yamt /*
1034 1.1.1.1.6.2 yamt * When doing an update, we can't change version,
1035 1.1.1.1.6.2 yamt * security, switch lockd strategies or change cookie
1036 1.1.1.1.6.2 yamt * translation
1037 1.1.1.1.6.2 yamt */
1038 1.1.1.1.6.2 yamt args.flags = (args.flags &
1039 1.1.1.1.6.2 yamt ~(NFSMNT_NFSV3 |
1040 1.1.1.1.6.2 yamt NFSMNT_NFSV4 |
1041 1.1.1.1.6.2 yamt NFSMNT_KERB |
1042 1.1.1.1.6.2 yamt NFSMNT_INTEGRITY |
1043 1.1.1.1.6.2 yamt NFSMNT_PRIVACY |
1044 1.1.1.1.6.2 yamt NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1045 1.1.1.1.6.2 yamt (nmp->nm_flag &
1046 1.1.1.1.6.2 yamt (NFSMNT_NFSV3 |
1047 1.1.1.1.6.2 yamt NFSMNT_NFSV4 |
1048 1.1.1.1.6.2 yamt NFSMNT_KERB |
1049 1.1.1.1.6.2 yamt NFSMNT_INTEGRITY |
1050 1.1.1.1.6.2 yamt NFSMNT_PRIVACY |
1051 1.1.1.1.6.2 yamt NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1052 1.1.1.1.6.2 yamt nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
1053 1.1.1.1.6.2 yamt goto out;
1054 1.1.1.1.6.2 yamt }
1055 1.1.1.1.6.2 yamt
1056 1.1.1.1.6.2 yamt /*
1057 1.1.1.1.6.2 yamt * Make the nfs_ip_paranoia sysctl serve as the default connection
1058 1.1.1.1.6.2 yamt * or no-connection mode for those protocols that support
1059 1.1.1.1.6.2 yamt * no-connection mode (the flag will be cleared later for protocols
1060 1.1.1.1.6.2 yamt * that do not support no-connection mode). This will allow a client
1061 1.1.1.1.6.2 yamt * to receive replies from a different IP then the request was
1062 1.1.1.1.6.2 yamt * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
1063 1.1.1.1.6.2 yamt * not 0.
1064 1.1.1.1.6.2 yamt */
1065 1.1.1.1.6.2 yamt if (nfs_ip_paranoia == 0)
1066 1.1.1.1.6.2 yamt args.flags |= NFSMNT_NOCONN;
1067 1.1.1.1.6.2 yamt
1068 1.1.1.1.6.2 yamt if (has_nfs_args_opt != 0) {
1069 1.1.1.1.6.2 yamt /*
1070 1.1.1.1.6.2 yamt * In the 'nfs_args' case, the pointers in the args
1071 1.1.1.1.6.2 yamt * structure are in userland - we copy them in here.
1072 1.1.1.1.6.2 yamt */
1073 1.1.1.1.6.2 yamt if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1074 1.1.1.1.6.2 yamt vfs_mount_error(mp, "Bad file handle");
1075 1.1.1.1.6.2 yamt error = EINVAL;
1076 1.1.1.1.6.2 yamt goto out;
1077 1.1.1.1.6.2 yamt }
1078 1.1.1.1.6.2 yamt error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1079 1.1.1.1.6.2 yamt args.fhsize);
1080 1.1.1.1.6.2 yamt if (error != 0)
1081 1.1.1.1.6.2 yamt goto out;
1082 1.1.1.1.6.2 yamt error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
1083 1.1.1.1.6.2 yamt if (error != 0)
1084 1.1.1.1.6.2 yamt goto out;
1085 1.1.1.1.6.2 yamt bzero(&hst[hstlen], MNAMELEN - hstlen);
1086 1.1.1.1.6.2 yamt args.hostname = hst;
1087 1.1.1.1.6.2 yamt /* sockargs() call must be after above copyin() calls */
1088 1.1.1.1.6.2 yamt error = getsockaddr(&nam, (caddr_t)args.addr,
1089 1.1.1.1.6.2 yamt args.addrlen);
1090 1.1.1.1.6.2 yamt if (error != 0)
1091 1.1.1.1.6.2 yamt goto out;
1092 1.1.1.1.6.2 yamt } else {
1093 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1094 1.1.1.1.6.2 yamt &args.fhsize) == 0) {
1095 1.1.1.1.6.2 yamt if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
1096 1.1.1.1.6.2 yamt vfs_mount_error(mp, "Bad file handle");
1097 1.1.1.1.6.2 yamt error = EINVAL;
1098 1.1.1.1.6.2 yamt goto out;
1099 1.1.1.1.6.2 yamt }
1100 1.1.1.1.6.2 yamt bcopy(args.fh, nfh, args.fhsize);
1101 1.1.1.1.6.2 yamt } else {
1102 1.1.1.1.6.2 yamt args.fhsize = 0;
1103 1.1.1.1.6.2 yamt }
1104 1.1.1.1.6.2 yamt (void) vfs_getopt(mp->mnt_optnew, "hostname",
1105 1.1.1.1.6.2 yamt (void **)&args.hostname, &len);
1106 1.1.1.1.6.2 yamt if (args.hostname == NULL) {
1107 1.1.1.1.6.2 yamt vfs_mount_error(mp, "Invalid hostname");
1108 1.1.1.1.6.2 yamt error = EINVAL;
1109 1.1.1.1.6.2 yamt goto out;
1110 1.1.1.1.6.2 yamt }
1111 1.1.1.1.6.2 yamt bcopy(args.hostname, hst, MNAMELEN);
1112 1.1.1.1.6.2 yamt hst[MNAMELEN - 1] = '\0';
1113 1.1.1.1.6.2 yamt }
1114 1.1.1.1.6.2 yamt
1115 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1116 1.1.1.1.6.2 yamt strlcpy(srvkrbname, name, sizeof (srvkrbname));
1117 1.1.1.1.6.2 yamt else
1118 1.1.1.1.6.2 yamt snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1119 1.1.1.1.6.2 yamt srvkrbnamelen = strlen(srvkrbname);
1120 1.1.1.1.6.2 yamt
1121 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1122 1.1.1.1.6.2 yamt strlcpy(krbname, name, sizeof (krbname));
1123 1.1.1.1.6.2 yamt else
1124 1.1.1.1.6.2 yamt krbname[0] = '\0';
1125 1.1.1.1.6.2 yamt krbnamelen = strlen(krbname);
1126 1.1.1.1.6.2 yamt
1127 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "dirpath", (void **)&name, NULL) == 0)
1128 1.1.1.1.6.2 yamt strlcpy(dirpath, name, sizeof (dirpath));
1129 1.1.1.1.6.2 yamt else
1130 1.1.1.1.6.2 yamt dirpath[0] = '\0';
1131 1.1.1.1.6.2 yamt dirlen = strlen(dirpath);
1132 1.1.1.1.6.2 yamt
1133 1.1.1.1.6.2 yamt if (has_nfs_args_opt == 0) {
1134 1.1.1.1.6.2 yamt if (vfs_getopt(mp->mnt_optnew, "addr",
1135 1.1.1.1.6.2 yamt (void **)&args.addr, &args.addrlen) == 0) {
1136 1.1.1.1.6.2 yamt if (args.addrlen > SOCK_MAXADDRLEN) {
1137 1.1.1.1.6.2 yamt error = ENAMETOOLONG;
1138 1.1.1.1.6.2 yamt goto out;
1139 1.1.1.1.6.2 yamt }
1140 1.1.1.1.6.2 yamt nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1141 1.1.1.1.6.2 yamt bcopy(args.addr, nam, args.addrlen);
1142 1.1.1.1.6.2 yamt nam->sa_len = args.addrlen;
1143 1.1.1.1.6.2 yamt } else {
1144 1.1.1.1.6.2 yamt vfs_mount_error(mp, "No server address");
1145 1.1.1.1.6.2 yamt error = EINVAL;
1146 1.1.1.1.6.2 yamt goto out;
1147 1.1.1.1.6.2 yamt }
1148 1.1.1.1.6.2 yamt }
1149 1.1.1.1.6.2 yamt
1150 1.1.1.1.6.2 yamt args.fh = nfh;
1151 1.1.1.1.6.2 yamt error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
1152 1.1.1.1.6.2 yamt dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
1153 1.1.1.1.6.2 yamt nametimeo, negnametimeo, minvers);
1154 1.1.1.1.6.2 yamt out:
1155 1.1.1.1.6.2 yamt if (!error) {
1156 1.1.1.1.6.2 yamt MNT_ILOCK(mp);
1157 1.1.1.1.6.2 yamt mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_NO_IOPF;
1158 1.1.1.1.6.2 yamt MNT_IUNLOCK(mp);
1159 1.1.1.1.6.2 yamt }
1160 1.1.1.1.6.2 yamt return (error);
1161 1.1.1.1.6.2 yamt }
1162 1.1.1.1.6.2 yamt
1163 1.1.1.1.6.2 yamt
1164 1.1.1.1.6.2 yamt /*
1165 1.1.1.1.6.2 yamt * VFS Operations.
1166 1.1.1.1.6.2 yamt *
1167 1.1.1.1.6.2 yamt * mount system call
1168 1.1.1.1.6.2 yamt * It seems a bit dumb to copyinstr() the host and path here and then
1169 1.1.1.1.6.2 yamt * bcopy() them in mountnfs(), but I wanted to detect errors before
1170 1.1.1.1.6.2 yamt * doing the sockargs() call because sockargs() allocates an mbuf and
1171 1.1.1.1.6.2 yamt * an error after that means that I have to release the mbuf.
1172 1.1.1.1.6.2 yamt */
1173 1.1.1.1.6.2 yamt /* ARGSUSED */
1174 1.1.1.1.6.2 yamt static int
1175 1.1.1.1.6.2 yamt nfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
1176 1.1.1.1.6.2 yamt {
1177 1.1.1.1.6.2 yamt int error;
1178 1.1.1.1.6.2 yamt struct nfs_args args;
1179 1.1.1.1.6.2 yamt
1180 1.1.1.1.6.2 yamt error = copyin(data, &args, sizeof (struct nfs_args));
1181 1.1.1.1.6.2 yamt if (error)
1182 1.1.1.1.6.2 yamt return error;
1183 1.1.1.1.6.2 yamt
1184 1.1.1.1.6.2 yamt ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1185 1.1.1.1.6.2 yamt
1186 1.1.1.1.6.2 yamt error = kernel_mount(ma, flags);
1187 1.1.1.1.6.2 yamt return (error);
1188 1.1.1.1.6.2 yamt }
1189 1.1.1.1.6.2 yamt
1190 1.1.1.1.6.2 yamt /*
1191 1.1.1.1.6.2 yamt * Common code for mount and mountroot
1192 1.1.1.1.6.2 yamt */
1193 1.1.1.1.6.2 yamt static int
1194 1.1.1.1.6.2 yamt mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1195 1.1.1.1.6.2 yamt char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
1196 1.1.1.1.6.2 yamt u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
1197 1.1.1.1.6.2 yamt struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo,
1198 1.1.1.1.6.2 yamt int minvers)
1199 1.1.1.1.6.2 yamt {
1200 1.1.1.1.6.2 yamt struct nfsmount *nmp;
1201 1.1.1.1.6.2 yamt struct nfsnode *np;
1202 1.1.1.1.6.2 yamt int error, trycnt, ret;
1203 1.1.1.1.6.2 yamt struct nfsvattr nfsva;
1204 1.1.1.1.6.2 yamt struct nfsclclient *clp;
1205 1.1.1.1.6.2 yamt struct nfsclds *dsp, *tdsp;
1206 1.1.1.1.6.2 yamt uint32_t lease;
1207 1.1.1.1.6.2 yamt static u_int64_t clval = 0;
1208 1.1.1.1.6.2 yamt
1209 1.1.1.1.6.2 yamt NFSCL_DEBUG(3, "in mnt\n");
1210 1.1.1.1.6.2 yamt clp = NULL;
1211 1.1.1.1.6.2 yamt if (mp->mnt_flag & MNT_UPDATE) {
1212 1.1.1.1.6.2 yamt nmp = VFSTONFS(mp);
1213 1.1.1.1.6.2 yamt printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1214 1.1.1.1.6.2 yamt FREE(nam, M_SONAME);
1215 1.1.1.1.6.2 yamt return (0);
1216 1.1.1.1.6.2 yamt } else {
1217 1.1.1.1.6.2 yamt MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount) +
1218 1.1.1.1.6.2 yamt krbnamelen + dirlen + srvkrbnamelen + 2,
1219 1.1.1.1.6.2 yamt M_NEWNFSMNT, M_WAITOK | M_ZERO);
1220 1.1.1.1.6.2 yamt TAILQ_INIT(&nmp->nm_bufq);
1221 1.1.1.1.6.2 yamt if (clval == 0)
1222 1.1.1.1.6.2 yamt clval = (u_int64_t)nfsboottime.tv_sec;
1223 1.1.1.1.6.2 yamt nmp->nm_clval = clval++;
1224 1.1.1.1.6.2 yamt nmp->nm_krbnamelen = krbnamelen;
1225 1.1.1.1.6.2 yamt nmp->nm_dirpathlen = dirlen;
1226 1.1.1.1.6.2 yamt nmp->nm_srvkrbnamelen = srvkrbnamelen;
1227 1.1.1.1.6.2 yamt if (td->td_ucred->cr_uid != (uid_t)0) {
1228 1.1.1.1.6.2 yamt /*
1229 1.1.1.1.6.2 yamt * nm_uid is used to get KerberosV credentials for
1230 1.1.1.1.6.2 yamt * the nfsv4 state handling operations if there is
1231 1.1.1.1.6.2 yamt * no host based principal set. Use the uid of
1232 1.1.1.1.6.2 yamt * this user if not root, since they are doing the
1233 1.1.1.1.6.2 yamt * mount. I don't think setting this for root will
1234 1.1.1.1.6.2 yamt * work, since root normally does not have user
1235 1.1.1.1.6.2 yamt * credentials in a credentials cache.
1236 1.1.1.1.6.2 yamt */
1237 1.1.1.1.6.2 yamt nmp->nm_uid = td->td_ucred->cr_uid;
1238 1.1.1.1.6.2 yamt } else {
1239 1.1.1.1.6.2 yamt /*
1240 1.1.1.1.6.2 yamt * Just set to -1, so it won't be used.
1241 1.1.1.1.6.2 yamt */
1242 1.1.1.1.6.2 yamt nmp->nm_uid = (uid_t)-1;
1243 1.1.1.1.6.2 yamt }
1244 1.1.1.1.6.2 yamt
1245 1.1.1.1.6.2 yamt /* Copy and null terminate all the names */
1246 1.1.1.1.6.2 yamt if (nmp->nm_krbnamelen > 0) {
1247 1.1.1.1.6.2 yamt bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1248 1.1.1.1.6.2 yamt nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1249 1.1.1.1.6.2 yamt }
1250 1.1.1.1.6.2 yamt if (nmp->nm_dirpathlen > 0) {
1251 1.1.1.1.6.2 yamt bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1252 1.1.1.1.6.2 yamt nmp->nm_dirpathlen);
1253 1.1.1.1.6.2 yamt nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1254 1.1.1.1.6.2 yamt + 1] = '\0';
1255 1.1.1.1.6.2 yamt }
1256 1.1.1.1.6.2 yamt if (nmp->nm_srvkrbnamelen > 0) {
1257 1.1.1.1.6.2 yamt bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1258 1.1.1.1.6.2 yamt nmp->nm_srvkrbnamelen);
1259 1.1.1.1.6.2 yamt nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1260 1.1.1.1.6.2 yamt + nmp->nm_srvkrbnamelen + 2] = '\0';
1261 1.1.1.1.6.2 yamt }
1262 1.1.1.1.6.2 yamt nmp->nm_sockreq.nr_cred = crhold(cred);
1263 1.1.1.1.6.2 yamt mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1264 1.1.1.1.6.2 yamt mp->mnt_data = nmp;
1265 1.1.1.1.6.2 yamt nmp->nm_getinfo = nfs_getnlminfo;
1266 1.1.1.1.6.2 yamt nmp->nm_vinvalbuf = ncl_vinvalbuf;
1267 1.1.1.1.6.2 yamt }
1268 1.1.1.1.6.2 yamt vfs_getnewfsid(mp);
1269 1.1.1.1.6.2 yamt nmp->nm_mountp = mp;
1270 1.1.1.1.6.2 yamt mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
1271 1.1.1.1.6.2 yamt
1272 1.1.1.1.6.2 yamt /*
1273 1.1.1.1.6.2 yamt * Since nfs_decode_args() might optionally set them, these
1274 1.1.1.1.6.2 yamt * need to be set to defaults before the call, so that the
1275 1.1.1.1.6.2 yamt * optional settings aren't overwritten.
1276 1.1.1.1.6.2 yamt */
1277 1.1.1.1.6.2 yamt nmp->nm_nametimeo = nametimeo;
1278 1.1.1.1.6.2 yamt nmp->nm_negnametimeo = negnametimeo;
1279 1.1.1.1.6.2 yamt nmp->nm_timeo = NFS_TIMEO;
1280 1.1.1.1.6.2 yamt nmp->nm_retry = NFS_RETRANS;
1281 1.1.1.1.6.2 yamt nmp->nm_readahead = NFS_DEFRAHEAD;
1282 1.1.1.1.6.2 yamt if (desiredvnodes >= 11000)
1283 1.1.1.1.6.2 yamt nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000);
1284 1.1.1.1.6.2 yamt else
1285 1.1.1.1.6.2 yamt nmp->nm_wcommitsize = hibufspace / 10;
1286 1.1.1.1.6.2 yamt if ((argp->flags & NFSMNT_NFSV4) != 0)
1287 1.1.1.1.6.2 yamt nmp->nm_minorvers = minvers;
1288 1.1.1.1.6.2 yamt else
1289 1.1.1.1.6.2 yamt nmp->nm_minorvers = 0;
1290 1.1.1.1.6.2 yamt
1291 1.1.1.1.6.2 yamt nfs_decode_args(mp, nmp, argp, hst, cred, td);
1292 1.1.1.1.6.2 yamt
1293 1.1.1.1.6.2 yamt /*
1294 1.1.1.1.6.2 yamt * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1295 1.1.1.1.6.2 yamt * high, depending on whether we end up with negative offsets in
1296 1.1.1.1.6.2 yamt * the client or server somewhere. 2GB-1 may be safer.
1297 1.1.1.1.6.2 yamt *
1298 1.1.1.1.6.2 yamt * For V3, ncl_fsinfo will adjust this as necessary. Assume maximum
1299 1.1.1.1.6.2 yamt * that we can handle until we find out otherwise.
1300 1.1.1.1.6.2 yamt */
1301 1.1.1.1.6.2 yamt if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1302 1.1.1.1.6.2 yamt nmp->nm_maxfilesize = 0xffffffffLL;
1303 1.1.1.1.6.2 yamt else
1304 1.1.1.1.6.2 yamt nmp->nm_maxfilesize = OFF_MAX;
1305 1.1.1.1.6.2 yamt
1306 1.1.1.1.6.2 yamt if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1307 1.1.1.1.6.2 yamt nmp->nm_wsize = NFS_WSIZE;
1308 1.1.1.1.6.2 yamt nmp->nm_rsize = NFS_RSIZE;
1309 1.1.1.1.6.2 yamt nmp->nm_readdirsize = NFS_READDIRSIZE;
1310 1.1.1.1.6.2 yamt }
1311 1.1.1.1.6.2 yamt nmp->nm_numgrps = NFS_MAXGRPS;
1312 1.1.1.1.6.2 yamt nmp->nm_tprintf_delay = nfs_tprintf_delay;
1313 1.1.1.1.6.2 yamt if (nmp->nm_tprintf_delay < 0)
1314 1.1.1.1.6.2 yamt nmp->nm_tprintf_delay = 0;
1315 1.1.1.1.6.2 yamt nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1316 1.1.1.1.6.2 yamt if (nmp->nm_tprintf_initial_delay < 0)
1317 1.1.1.1.6.2 yamt nmp->nm_tprintf_initial_delay = 0;
1318 1.1.1.1.6.2 yamt nmp->nm_fhsize = argp->fhsize;
1319 1.1.1.1.6.2 yamt if (nmp->nm_fhsize > 0)
1320 1.1.1.1.6.2 yamt bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1321 1.1.1.1.6.2 yamt bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1322 1.1.1.1.6.2 yamt nmp->nm_nam = nam;
1323 1.1.1.1.6.2 yamt /* Set up the sockets and per-host congestion */
1324 1.1.1.1.6.2 yamt nmp->nm_sotype = argp->sotype;
1325 1.1.1.1.6.2 yamt nmp->nm_soproto = argp->proto;
1326 1.1.1.1.6.2 yamt nmp->nm_sockreq.nr_prog = NFS_PROG;
1327 1.1.1.1.6.2 yamt if ((argp->flags & NFSMNT_NFSV4))
1328 1.1.1.1.6.2 yamt nmp->nm_sockreq.nr_vers = NFS_VER4;
1329 1.1.1.1.6.2 yamt else if ((argp->flags & NFSMNT_NFSV3))
1330 1.1.1.1.6.2 yamt nmp->nm_sockreq.nr_vers = NFS_VER3;
1331 1.1.1.1.6.2 yamt else
1332 1.1.1.1.6.2 yamt nmp->nm_sockreq.nr_vers = NFS_VER2;
1333 1.1.1.1.6.2 yamt
1334 1.1.1.1.6.2 yamt
1335 1.1.1.1.6.2 yamt if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
1336 1.1.1.1.6.2 yamt goto bad;
1337 1.1.1.1.6.2 yamt /* For NFSv4.1, get the clientid now. */
1338 1.1.1.1.6.2 yamt if (nmp->nm_minorvers > 0) {
1339 1.1.1.1.6.2 yamt NFSCL_DEBUG(3, "at getcl\n");
1340 1.1.1.1.6.2 yamt error = nfscl_getcl(mp, cred, td, 0, &clp);
1341 1.1.1.1.6.2 yamt NFSCL_DEBUG(3, "aft getcl=%d\n", error);
1342 1.1.1.1.6.2 yamt if (error != 0)
1343 1.1.1.1.6.2 yamt goto bad;
1344 1.1.1.1.6.2 yamt }
1345 1.1.1.1.6.2 yamt
1346 1.1.1.1.6.2 yamt if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1347 1.1.1.1.6.2 yamt nmp->nm_dirpathlen > 0) {
1348 1.1.1.1.6.2 yamt NFSCL_DEBUG(3, "in dirp\n");
1349 1.1.1.1.6.2 yamt /*
1350 1.1.1.1.6.2 yamt * If the fhsize on the mount point == 0 for V4, the mount
1351 1.1.1.1.6.2 yamt * path needs to be looked up.
1352 1.1.1.1.6.2 yamt */
1353 1.1.1.1.6.2 yamt trycnt = 3;
1354 1.1.1.1.6.2 yamt do {
1355 1.1.1.1.6.2 yamt error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1356 1.1.1.1.6.2 yamt cred, td);
1357 1.1.1.1.6.2 yamt NFSCL_DEBUG(3, "aft dirp=%d\n", error);
1358 1.1.1.1.6.2 yamt if (error)
1359 1.1.1.1.6.2 yamt (void) nfs_catnap(PZERO, error, "nfsgetdirp");
1360 1.1.1.1.6.2 yamt } while (error && --trycnt > 0);
1361 1.1.1.1.6.2 yamt if (error) {
1362 1.1.1.1.6.2 yamt error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
1363 1.1.1.1.6.2 yamt goto bad;
1364 1.1.1.1.6.2 yamt }
1365 1.1.1.1.6.2 yamt }
1366 1.1.1.1.6.2 yamt
1367 1.1.1.1.6.2 yamt /*
1368 1.1.1.1.6.2 yamt * A reference count is needed on the nfsnode representing the
1369 1.1.1.1.6.2 yamt * remote root. If this object is not persistent, then backward
1370 1.1.1.1.6.2 yamt * traversals of the mount point (i.e. "..") will not work if
1371 1.1.1.1.6.2 yamt * the nfsnode gets flushed out of the cache. Ufs does not have
1372 1.1.1.1.6.2 yamt * this problem, because one can identify root inodes by their
1373 1.1.1.1.6.2 yamt * number == ROOTINO (2).
1374 1.1.1.1.6.2 yamt */
1375 1.1.1.1.6.2 yamt if (nmp->nm_fhsize > 0) {
1376 1.1.1.1.6.2 yamt /*
1377 1.1.1.1.6.2 yamt * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1378 1.1.1.1.6.2 yamt * non-zero for the root vnode. f_iosize will be set correctly
1379 1.1.1.1.6.2 yamt * by nfs_statfs() before any I/O occurs.
1380 1.1.1.1.6.2 yamt */
1381 1.1.1.1.6.2 yamt mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1382 1.1.1.1.6.2 yamt error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1383 1.1.1.1.6.2 yamt LK_EXCLUSIVE);
1384 1.1.1.1.6.2 yamt if (error)
1385 1.1.1.1.6.2 yamt goto bad;
1386 1.1.1.1.6.2 yamt *vpp = NFSTOV(np);
1387 1.1.1.1.6.2 yamt
1388 1.1.1.1.6.2 yamt /*
1389 1.1.1.1.6.2 yamt * Get file attributes and transfer parameters for the
1390 1.1.1.1.6.2 yamt * mountpoint. This has the side effect of filling in
1391 1.1.1.1.6.2 yamt * (*vpp)->v_type with the correct value.
1392 1.1.1.1.6.2 yamt */
1393 1.1.1.1.6.2 yamt ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1394 1.1.1.1.6.2 yamt cred, td, &nfsva, NULL, &lease);
1395 1.1.1.1.6.2 yamt if (ret) {
1396 1.1.1.1.6.2 yamt /*
1397 1.1.1.1.6.2 yamt * Just set default values to get things going.
1398 1.1.1.1.6.2 yamt */
1399 1.1.1.1.6.2 yamt NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1400 1.1.1.1.6.2 yamt nfsva.na_vattr.va_type = VDIR;
1401 1.1.1.1.6.2 yamt nfsva.na_vattr.va_mode = 0777;
1402 1.1.1.1.6.2 yamt nfsva.na_vattr.va_nlink = 100;
1403 1.1.1.1.6.2 yamt nfsva.na_vattr.va_uid = (uid_t)0;
1404 1.1.1.1.6.2 yamt nfsva.na_vattr.va_gid = (gid_t)0;
1405 1.1.1.1.6.2 yamt nfsva.na_vattr.va_fileid = 2;
1406 1.1.1.1.6.2 yamt nfsva.na_vattr.va_gen = 1;
1407 1.1.1.1.6.2 yamt nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1408 1.1.1.1.6.2 yamt nfsva.na_vattr.va_size = 512 * 1024;
1409 1.1.1.1.6.2 yamt lease = 60;
1410 1.1.1.1.6.2 yamt }
1411 1.1.1.1.6.2 yamt (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1412 1.1.1.1.6.2 yamt if (nmp->nm_minorvers > 0) {
1413 1.1.1.1.6.2 yamt NFSCL_DEBUG(3, "lease=%d\n", (int)lease);
1414 1.1.1.1.6.2 yamt NFSLOCKCLSTATE();
1415 1.1.1.1.6.2 yamt clp->nfsc_renew = NFSCL_RENEW(lease);
1416 1.1.1.1.6.2 yamt clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;
1417 1.1.1.1.6.2 yamt clp->nfsc_clientidrev++;
1418 1.1.1.1.6.2 yamt if (clp->nfsc_clientidrev == 0)
1419 1.1.1.1.6.2 yamt clp->nfsc_clientidrev++;
1420 1.1.1.1.6.2 yamt NFSUNLOCKCLSTATE();
1421 1.1.1.1.6.2 yamt /*
1422 1.1.1.1.6.2 yamt * Mount will succeed, so the renew thread can be
1423 1.1.1.1.6.2 yamt * started now.
1424 1.1.1.1.6.2 yamt */
1425 1.1.1.1.6.2 yamt nfscl_start_renewthread(clp);
1426 1.1.1.1.6.2 yamt nfscl_clientrelease(clp);
1427 1.1.1.1.6.2 yamt }
1428 1.1.1.1.6.2 yamt if (argp->flags & NFSMNT_NFSV3)
1429 1.1.1.1.6.2 yamt ncl_fsinfo(nmp, *vpp, cred, td);
1430 1.1.1.1.6.2 yamt
1431 1.1.1.1.6.2 yamt /* Mark if the mount point supports NFSv4 ACLs. */
1432 1.1.1.1.6.2 yamt if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 &&
1433 1.1.1.1.6.2 yamt ret == 0 &&
1434 1.1.1.1.6.2 yamt NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) {
1435 1.1.1.1.6.2 yamt MNT_ILOCK(mp);
1436 1.1.1.1.6.2 yamt mp->mnt_flag |= MNT_NFS4ACLS;
1437 1.1.1.1.6.2 yamt MNT_IUNLOCK(mp);
1438 1.1.1.1.6.2 yamt }
1439 1.1.1.1.6.2 yamt
1440 1.1.1.1.6.2 yamt /*
1441 1.1.1.1.6.2 yamt * Lose the lock but keep the ref.
1442 1.1.1.1.6.2 yamt */
1443 1.1.1.1.6.2 yamt NFSVOPUNLOCK(*vpp, 0);
1444 1.1.1.1.6.2 yamt return (0);
1445 1.1.1.1.6.2 yamt }
1446 1.1.1.1.6.2 yamt error = EIO;
1447 1.1.1.1.6.2 yamt
1448 1.1.1.1.6.2 yamt bad:
1449 1.1.1.1.6.2 yamt if (clp != NULL)
1450 1.1.1.1.6.2 yamt nfscl_clientrelease(clp);
1451 1.1.1.1.6.2 yamt newnfs_disconnect(&nmp->nm_sockreq);
1452 1.1.1.1.6.2 yamt crfree(nmp->nm_sockreq.nr_cred);
1453 1.1.1.1.6.2 yamt if (nmp->nm_sockreq.nr_auth != NULL)
1454 1.1.1.1.6.2 yamt AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1455 1.1.1.1.6.2 yamt mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1456 1.1.1.1.6.2 yamt mtx_destroy(&nmp->nm_mtx);
1457 1.1.1.1.6.2 yamt if (nmp->nm_clp != NULL) {
1458 1.1.1.1.6.2 yamt NFSLOCKCLSTATE();
1459 1.1.1.1.6.2 yamt LIST_REMOVE(nmp->nm_clp, nfsc_list);
1460 1.1.1.1.6.2 yamt NFSUNLOCKCLSTATE();
1461 1.1.1.1.6.2 yamt free(nmp->nm_clp, M_NFSCLCLIENT);
1462 1.1.1.1.6.2 yamt }
1463 1.1.1.1.6.2 yamt TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
1464 1.1.1.1.6.2 yamt nfscl_freenfsclds(dsp);
1465 1.1.1.1.6.2 yamt FREE(nmp, M_NEWNFSMNT);
1466 1.1.1.1.6.2 yamt FREE(nam, M_SONAME);
1467 1.1.1.1.6.2 yamt return (error);
1468 1.1.1.1.6.2 yamt }
1469 1.1.1.1.6.2 yamt
1470 1.1.1.1.6.2 yamt /*
1471 1.1.1.1.6.2 yamt * unmount system call
1472 1.1.1.1.6.2 yamt */
1473 1.1.1.1.6.2 yamt static int
1474 1.1.1.1.6.2 yamt nfs_unmount(struct mount *mp, int mntflags)
1475 1.1.1.1.6.2 yamt {
1476 1.1.1.1.6.2 yamt struct thread *td;
1477 1.1.1.1.6.2 yamt struct nfsmount *nmp;
1478 1.1.1.1.6.2 yamt int error, flags = 0, i, trycnt = 0;
1479 1.1.1.1.6.2 yamt struct nfsclds *dsp, *tdsp;
1480 1.1.1.1.6.2 yamt
1481 1.1.1.1.6.2 yamt td = curthread;
1482 1.1.1.1.6.2 yamt
1483 1.1.1.1.6.2 yamt if (mntflags & MNT_FORCE)
1484 1.1.1.1.6.2 yamt flags |= FORCECLOSE;
1485 1.1.1.1.6.2 yamt nmp = VFSTONFS(mp);
1486 1.1.1.1.6.2 yamt /*
1487 1.1.1.1.6.2 yamt * Goes something like this..
1488 1.1.1.1.6.2 yamt * - Call vflush() to clear out vnodes for this filesystem
1489 1.1.1.1.6.2 yamt * - Close the socket
1490 1.1.1.1.6.2 yamt * - Free up the data structures
1491 1.1.1.1.6.2 yamt */
1492 1.1.1.1.6.2 yamt /* In the forced case, cancel any outstanding requests. */
1493 1.1.1.1.6.2 yamt if (mntflags & MNT_FORCE) {
1494 1.1.1.1.6.2 yamt error = newnfs_nmcancelreqs(nmp);
1495 1.1.1.1.6.2 yamt if (error)
1496 1.1.1.1.6.2 yamt goto out;
1497 1.1.1.1.6.2 yamt /* For a forced close, get rid of the renew thread now */
1498 1.1.1.1.6.2 yamt nfscl_umount(nmp, td);
1499 1.1.1.1.6.2 yamt }
1500 1.1.1.1.6.2 yamt /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1501 1.1.1.1.6.2 yamt do {
1502 1.1.1.1.6.2 yamt error = vflush(mp, 1, flags, td);
1503 1.1.1.1.6.2 yamt if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1504 1.1.1.1.6.2 yamt (void) nfs_catnap(PSOCK, error, "newndm");
1505 1.1.1.1.6.2 yamt } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1506 1.1.1.1.6.2 yamt if (error)
1507 1.1.1.1.6.2 yamt goto out;
1508 1.1.1.1.6.2 yamt
1509 1.1.1.1.6.2 yamt /*
1510 1.1.1.1.6.2 yamt * We are now committed to the unmount.
1511 1.1.1.1.6.2 yamt */
1512 1.1.1.1.6.2 yamt if ((mntflags & MNT_FORCE) == 0)
1513 1.1.1.1.6.2 yamt nfscl_umount(nmp, td);
1514 1.1.1.1.6.2 yamt /* Make sure no nfsiods are assigned to this mount. */
1515 1.1.1.1.6.2 yamt mtx_lock(&ncl_iod_mutex);
1516 1.1.1.1.6.2 yamt for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
1517 1.1.1.1.6.2 yamt if (ncl_iodmount[i] == nmp) {
1518 1.1.1.1.6.2 yamt ncl_iodwant[i] = NFSIOD_AVAILABLE;
1519 1.1.1.1.6.2 yamt ncl_iodmount[i] = NULL;
1520 1.1.1.1.6.2 yamt }
1521 1.1.1.1.6.2 yamt mtx_unlock(&ncl_iod_mutex);
1522 1.1.1.1.6.2 yamt newnfs_disconnect(&nmp->nm_sockreq);
1523 1.1.1.1.6.2 yamt crfree(nmp->nm_sockreq.nr_cred);
1524 1.1.1.1.6.2 yamt FREE(nmp->nm_nam, M_SONAME);
1525 1.1.1.1.6.2 yamt if (nmp->nm_sockreq.nr_auth != NULL)
1526 1.1.1.1.6.2 yamt AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1527 1.1.1.1.6.2 yamt mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1528 1.1.1.1.6.2 yamt mtx_destroy(&nmp->nm_mtx);
1529 1.1.1.1.6.2 yamt TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
1530 1.1.1.1.6.2 yamt nfscl_freenfsclds(dsp);
1531 1.1.1.1.6.2 yamt FREE(nmp, M_NEWNFSMNT);
1532 1.1.1.1.6.2 yamt out:
1533 1.1.1.1.6.2 yamt return (error);
1534 1.1.1.1.6.2 yamt }
1535 1.1.1.1.6.2 yamt
1536 1.1.1.1.6.2 yamt /*
1537 1.1.1.1.6.2 yamt * Return root of a filesystem
1538 1.1.1.1.6.2 yamt */
1539 1.1.1.1.6.2 yamt static int
1540 1.1.1.1.6.2 yamt nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1541 1.1.1.1.6.2 yamt {
1542 1.1.1.1.6.2 yamt struct vnode *vp;
1543 1.1.1.1.6.2 yamt struct nfsmount *nmp;
1544 1.1.1.1.6.2 yamt struct nfsnode *np;
1545 1.1.1.1.6.2 yamt int error;
1546 1.1.1.1.6.2 yamt
1547 1.1.1.1.6.2 yamt nmp = VFSTONFS(mp);
1548 1.1.1.1.6.2 yamt error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1549 1.1.1.1.6.2 yamt if (error)
1550 1.1.1.1.6.2 yamt return error;
1551 1.1.1.1.6.2 yamt vp = NFSTOV(np);
1552 1.1.1.1.6.2 yamt /*
1553 1.1.1.1.6.2 yamt * Get transfer parameters and attributes for root vnode once.
1554 1.1.1.1.6.2 yamt */
1555 1.1.1.1.6.2 yamt mtx_lock(&nmp->nm_mtx);
1556 1.1.1.1.6.2 yamt if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1557 1.1.1.1.6.2 yamt mtx_unlock(&nmp->nm_mtx);
1558 1.1.1.1.6.2 yamt ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1559 1.1.1.1.6.2 yamt } else
1560 1.1.1.1.6.2 yamt mtx_unlock(&nmp->nm_mtx);
1561 1.1.1.1.6.2 yamt if (vp->v_type == VNON)
1562 1.1.1.1.6.2 yamt vp->v_type = VDIR;
1563 1.1.1.1.6.2 yamt vp->v_vflag |= VV_ROOT;
1564 1.1.1.1.6.2 yamt *vpp = vp;
1565 1.1.1.1.6.2 yamt return (0);
1566 1.1.1.1.6.2 yamt }
1567 1.1.1.1.6.2 yamt
1568 1.1.1.1.6.2 yamt /*
1569 1.1.1.1.6.2 yamt * Flush out the buffer cache
1570 1.1.1.1.6.2 yamt */
1571 1.1.1.1.6.2 yamt /* ARGSUSED */
1572 1.1.1.1.6.2 yamt static int
1573 1.1.1.1.6.2 yamt nfs_sync(struct mount *mp, int waitfor)
1574 1.1.1.1.6.2 yamt {
1575 1.1.1.1.6.2 yamt struct vnode *vp, *mvp;
1576 1.1.1.1.6.2 yamt struct thread *td;
1577 1.1.1.1.6.2 yamt int error, allerror = 0;
1578 1.1.1.1.6.2 yamt
1579 1.1.1.1.6.2 yamt td = curthread;
1580 1.1.1.1.6.2 yamt
1581 1.1.1.1.6.2 yamt MNT_ILOCK(mp);
1582 1.1.1.1.6.2 yamt /*
1583 1.1.1.1.6.2 yamt * If a forced dismount is in progress, return from here so that
1584 1.1.1.1.6.2 yamt * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1585 1.1.1.1.6.2 yamt * calling VFS_UNMOUNT().
1586 1.1.1.1.6.2 yamt */
1587 1.1.1.1.6.2 yamt if ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) {
1588 1.1.1.1.6.2 yamt MNT_IUNLOCK(mp);
1589 1.1.1.1.6.2 yamt return (EBADF);
1590 1.1.1.1.6.2 yamt }
1591 1.1.1.1.6.2 yamt MNT_IUNLOCK(mp);
1592 1.1.1.1.6.2 yamt
1593 1.1.1.1.6.2 yamt /*
1594 1.1.1.1.6.2 yamt * Force stale buffer cache information to be flushed.
1595 1.1.1.1.6.2 yamt */
1596 1.1.1.1.6.2 yamt loop:
1597 1.1.1.1.6.2 yamt MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
1598 1.1.1.1.6.2 yamt /* XXX Racy bv_cnt check. */
1599 1.1.1.1.6.2 yamt if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1600 1.1.1.1.6.2 yamt waitfor == MNT_LAZY) {
1601 1.1.1.1.6.2 yamt VI_UNLOCK(vp);
1602 1.1.1.1.6.2 yamt continue;
1603 1.1.1.1.6.2 yamt }
1604 1.1.1.1.6.2 yamt if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1605 1.1.1.1.6.2 yamt MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
1606 1.1.1.1.6.2 yamt goto loop;
1607 1.1.1.1.6.2 yamt }
1608 1.1.1.1.6.2 yamt error = VOP_FSYNC(vp, waitfor, td);
1609 1.1.1.1.6.2 yamt if (error)
1610 1.1.1.1.6.2 yamt allerror = error;
1611 1.1.1.1.6.2 yamt NFSVOPUNLOCK(vp, 0);
1612 1.1.1.1.6.2 yamt vrele(vp);
1613 1.1.1.1.6.2 yamt }
1614 1.1.1.1.6.2 yamt return (allerror);
1615 1.1.1.1.6.2 yamt }
1616 1.1.1.1.6.2 yamt
1617 1.1.1.1.6.2 yamt static int
1618 1.1.1.1.6.2 yamt nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1619 1.1.1.1.6.2 yamt {
1620 1.1.1.1.6.2 yamt struct nfsmount *nmp = VFSTONFS(mp);
1621 1.1.1.1.6.2 yamt struct vfsquery vq;
1622 1.1.1.1.6.2 yamt int error;
1623 1.1.1.1.6.2 yamt
1624 1.1.1.1.6.2 yamt bzero(&vq, sizeof(vq));
1625 1.1.1.1.6.2 yamt switch (op) {
1626 1.1.1.1.6.2 yamt #if 0
1627 1.1.1.1.6.2 yamt case VFS_CTL_NOLOCKS:
1628 1.1.1.1.6.2 yamt val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1629 1.1.1.1.6.2 yamt if (req->oldptr != NULL) {
1630 1.1.1.1.6.2 yamt error = SYSCTL_OUT(req, &val, sizeof(val));
1631 1.1.1.1.6.2 yamt if (error)
1632 1.1.1.1.6.2 yamt return (error);
1633 1.1.1.1.6.2 yamt }
1634 1.1.1.1.6.2 yamt if (req->newptr != NULL) {
1635 1.1.1.1.6.2 yamt error = SYSCTL_IN(req, &val, sizeof(val));
1636 1.1.1.1.6.2 yamt if (error)
1637 1.1.1.1.6.2 yamt return (error);
1638 1.1.1.1.6.2 yamt if (val)
1639 1.1.1.1.6.2 yamt nmp->nm_flag |= NFSMNT_NOLOCKS;
1640 1.1.1.1.6.2 yamt else
1641 1.1.1.1.6.2 yamt nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1642 1.1.1.1.6.2 yamt }
1643 1.1.1.1.6.2 yamt break;
1644 1.1.1.1.6.2 yamt #endif
1645 1.1.1.1.6.2 yamt case VFS_CTL_QUERY:
1646 1.1.1.1.6.2 yamt mtx_lock(&nmp->nm_mtx);
1647 1.1.1.1.6.2 yamt if (nmp->nm_state & NFSSTA_TIMEO)
1648 1.1.1.1.6.2 yamt vq.vq_flags |= VQ_NOTRESP;
1649 1.1.1.1.6.2 yamt mtx_unlock(&nmp->nm_mtx);
1650 1.1.1.1.6.2 yamt #if 0
1651 1.1.1.1.6.2 yamt if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1652 1.1.1.1.6.2 yamt (nmp->nm_state & NFSSTA_LOCKTIMEO))
1653 1.1.1.1.6.2 yamt vq.vq_flags |= VQ_NOTRESPLOCK;
1654 1.1.1.1.6.2 yamt #endif
1655 1.1.1.1.6.2 yamt error = SYSCTL_OUT(req, &vq, sizeof(vq));
1656 1.1.1.1.6.2 yamt break;
1657 1.1.1.1.6.2 yamt case VFS_CTL_TIMEO:
1658 1.1.1.1.6.2 yamt if (req->oldptr != NULL) {
1659 1.1.1.1.6.2 yamt error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1660 1.1.1.1.6.2 yamt sizeof(nmp->nm_tprintf_initial_delay));
1661 1.1.1.1.6.2 yamt if (error)
1662 1.1.1.1.6.2 yamt return (error);
1663 1.1.1.1.6.2 yamt }
1664 1.1.1.1.6.2 yamt if (req->newptr != NULL) {
1665 1.1.1.1.6.2 yamt error = vfs_suser(mp, req->td);
1666 1.1.1.1.6.2 yamt if (error)
1667 1.1.1.1.6.2 yamt return (error);
1668 1.1.1.1.6.2 yamt error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1669 1.1.1.1.6.2 yamt sizeof(nmp->nm_tprintf_initial_delay));
1670 1.1.1.1.6.2 yamt if (error)
1671 1.1.1.1.6.2 yamt return (error);
1672 1.1.1.1.6.2 yamt if (nmp->nm_tprintf_initial_delay < 0)
1673 1.1.1.1.6.2 yamt nmp->nm_tprintf_initial_delay = 0;
1674 1.1.1.1.6.2 yamt }
1675 1.1.1.1.6.2 yamt break;
1676 1.1.1.1.6.2 yamt default:
1677 1.1.1.1.6.2 yamt return (ENOTSUP);
1678 1.1.1.1.6.2 yamt }
1679 1.1.1.1.6.2 yamt return (0);
1680 1.1.1.1.6.2 yamt }
1681 1.1.1.1.6.2 yamt
1682 1.1.1.1.6.2 yamt /*
1683 1.1.1.1.6.2 yamt * Purge any RPCs in progress, so that they will all return errors.
1684 1.1.1.1.6.2 yamt * This allows dounmount() to continue as far as VFS_UNMOUNT() for a
1685 1.1.1.1.6.2 yamt * forced dismount.
1686 1.1.1.1.6.2 yamt */
1687 1.1.1.1.6.2 yamt static void
1688 1.1.1.1.6.2 yamt nfs_purge(struct mount *mp)
1689 1.1.1.1.6.2 yamt {
1690 1.1.1.1.6.2 yamt struct nfsmount *nmp = VFSTONFS(mp);
1691 1.1.1.1.6.2 yamt
1692 1.1.1.1.6.2 yamt newnfs_nmcancelreqs(nmp);
1693 1.1.1.1.6.2 yamt }
1694 1.1.1.1.6.2 yamt
1695 1.1.1.1.6.2 yamt /*
1696 1.1.1.1.6.2 yamt * Extract the information needed by the nlm from the nfs vnode.
1697 1.1.1.1.6.2 yamt */
1698 1.1.1.1.6.2 yamt static void
1699 1.1.1.1.6.2 yamt nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1700 1.1.1.1.6.2 yamt struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1701 1.1.1.1.6.2 yamt struct timeval *timeop)
1702 1.1.1.1.6.2 yamt {
1703 1.1.1.1.6.2 yamt struct nfsmount *nmp;
1704 1.1.1.1.6.2 yamt struct nfsnode *np = VTONFS(vp);
1705 1.1.1.1.6.2 yamt
1706 1.1.1.1.6.2 yamt nmp = VFSTONFS(vp->v_mount);
1707 1.1.1.1.6.2 yamt if (fhlenp != NULL)
1708 1.1.1.1.6.2 yamt *fhlenp = (size_t)np->n_fhp->nfh_len;
1709 1.1.1.1.6.2 yamt if (fhp != NULL)
1710 1.1.1.1.6.2 yamt bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1711 1.1.1.1.6.2 yamt if (sp != NULL)
1712 1.1.1.1.6.2 yamt bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1713 1.1.1.1.6.2 yamt if (is_v3p != NULL)
1714 1.1.1.1.6.2 yamt *is_v3p = NFS_ISV3(vp);
1715 1.1.1.1.6.2 yamt if (sizep != NULL)
1716 1.1.1.1.6.2 yamt *sizep = np->n_size;
1717 1.1.1.1.6.2 yamt if (timeop != NULL) {
1718 1.1.1.1.6.2 yamt timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1719 1.1.1.1.6.2 yamt timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);
1720 1.1.1.1.6.2 yamt }
1721 1.1.1.1.6.2 yamt }
1722 1.1.1.1.6.2 yamt
1723 1.1.1.1.6.2 yamt /*
1724 1.1.1.1.6.2 yamt * This function prints out an option name, based on the conditional
1725 1.1.1.1.6.2 yamt * argument.
1726 1.1.1.1.6.2 yamt */
1727 1.1.1.1.6.2 yamt static __inline void nfscl_printopt(struct nfsmount *nmp, int testval,
1728 1.1.1.1.6.2 yamt char *opt, char **buf, size_t *blen)
1729 1.1.1.1.6.2 yamt {
1730 1.1.1.1.6.2 yamt int len;
1731 1.1.1.1.6.2 yamt
1732 1.1.1.1.6.2 yamt if (testval != 0 && *blen > strlen(opt)) {
1733 1.1.1.1.6.2 yamt len = snprintf(*buf, *blen, "%s", opt);
1734 1.1.1.1.6.2 yamt if (len != strlen(opt))
1735 1.1.1.1.6.2 yamt printf("EEK!!\n");
1736 1.1.1.1.6.2 yamt *buf += len;
1737 1.1.1.1.6.2 yamt *blen -= len;
1738 1.1.1.1.6.2 yamt }
1739 1.1.1.1.6.2 yamt }
1740 1.1.1.1.6.2 yamt
1741 1.1.1.1.6.2 yamt /*
1742 1.1.1.1.6.2 yamt * This function printf out an options integer value.
1743 1.1.1.1.6.2 yamt */
1744 1.1.1.1.6.2 yamt static __inline void nfscl_printoptval(struct nfsmount *nmp, int optval,
1745 1.1.1.1.6.2 yamt char *opt, char **buf, size_t *blen)
1746 1.1.1.1.6.2 yamt {
1747 1.1.1.1.6.2 yamt int len;
1748 1.1.1.1.6.2 yamt
1749 1.1.1.1.6.2 yamt if (*blen > strlen(opt) + 1) {
1750 1.1.1.1.6.2 yamt /* Could result in truncated output string. */
1751 1.1.1.1.6.2 yamt len = snprintf(*buf, *blen, "%s=%d", opt, optval);
1752 1.1.1.1.6.2 yamt if (len < *blen) {
1753 1.1.1.1.6.2 yamt *buf += len;
1754 1.1.1.1.6.2 yamt *blen -= len;
1755 1.1.1.1.6.2 yamt }
1756 1.1.1.1.6.2 yamt }
1757 1.1.1.1.6.2 yamt }
1758 1.1.1.1.6.2 yamt
1759 1.1.1.1.6.2 yamt /*
1760 1.1.1.1.6.2 yamt * Load the option flags and values into the buffer.
1761 1.1.1.1.6.2 yamt */
1762 1.1.1.1.6.2 yamt void nfscl_retopts(struct nfsmount *nmp, char *buffer, size_t buflen)
1763 1.1.1.1.6.2 yamt {
1764 1.1.1.1.6.2 yamt char *buf;
1765 1.1.1.1.6.2 yamt size_t blen;
1766 1.1.1.1.6.2 yamt
1767 1.1.1.1.6.2 yamt buf = buffer;
1768 1.1.1.1.6.2 yamt blen = buflen;
1769 1.1.1.1.6.2 yamt nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV4) != 0, "nfsv4", &buf,
1770 1.1.1.1.6.2 yamt &blen);
1771 1.1.1.1.6.2 yamt if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) {
1772 1.1.1.1.6.2 yamt nfscl_printoptval(nmp, nmp->nm_minorvers, ",minorversion", &buf,
1773 1.1.1.1.6.2 yamt &blen);
1774 1.1.1.1.6.2 yamt nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_PNFS) != 0, ",pnfs",
1775 1.1.1.1.6.2 yamt &buf, &blen);
1776 1.1.1.1.6.2 yamt }
1777 1.1.1.1.6.2 yamt nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV3) != 0, "nfsv3", &buf,
1778 1.1.1.1.6.2 yamt &blen);
1779 1.1.1.1.6.2 yamt nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0,
1780 1.1.1.1.6.2 yamt "nfsv2", &buf, &blen);
1781 1.1.1.1.6.2 yamt nfscl_printopt(nmp, nmp->nm_sotype == SOCK_STREAM, ",tcp", &buf, &blen);
1782 1.1.1.1.6.2 yamt nfscl_printopt(nmp, nmp->nm_sotype != SOCK_STREAM, ",udp", &buf, &blen);
1783 1.1.1.1.6.2 yamt nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RESVPORT) != 0, ",resvport",
1784 1.1.1.1.6.2 yamt &buf, &blen);
1785 1.1.1.1.6.2 yamt nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCONN) != 0, ",noconn",
1786 1.1.1.1.6.2 yamt &buf, &blen);
1787 1.1.1.1.6.2 yamt nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) == 0, ",hard", &buf,
1788 1.1.1.1.6.2 yamt &blen);
1789 1.1.1.1.6.2 yamt nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) != 0, ",soft", &buf,
1790 1.1.1.1.6.2 yamt &blen);
1791 1.1.1.1.6.2 yamt nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_INT) != 0, ",intr", &buf,
1792 1.1.1.1.6.2 yamt &blen);
1793 1.1.1.1.6.2 yamt nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) == 0, ",cto", &buf,
1794 1.1.1.1.6.2 yamt &blen);
1795 1.1.1.1.6.2 yamt nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) != 0, ",nocto", &buf,
1796 1.1.1.1.6.2 yamt &blen);
1797 1.1.1.1.6.2 yamt nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
1798 1.1.1.1.6.2 yamt 0, ",lockd", &buf, &blen);
1799 1.1.1.1.6.2 yamt nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
1800 1.1.1.1.6.2 yamt NFSMNT_NOLOCKD, ",nolockd", &buf, &blen);
1801 1.1.1.1.6.2 yamt nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RDIRPLUS) != 0, ",rdirplus",
1802 1.1.1.1.6.2 yamt &buf, &blen);
1803 1.1.1.1.6.2 yamt nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_KERB) == 0, ",sec=sys",
1804 1.1.1.1.6.2 yamt &buf, &blen);
1805 1.1.1.1.6.2 yamt nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
1806 1.1.1.1.6.2 yamt NFSMNT_PRIVACY)) == NFSMNT_KERB, ",sec=krb5", &buf, &blen);
1807 1.1.1.1.6.2 yamt nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
1808 1.1.1.1.6.2 yamt NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_INTEGRITY), ",sec=krb5i",
1809 1.1.1.1.6.2 yamt &buf, &blen);
1810 1.1.1.1.6.2 yamt nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
1811 1.1.1.1.6.2 yamt NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_PRIVACY), ",sec=krb5p",
1812 1.1.1.1.6.2 yamt &buf, &blen);
1813 1.1.1.1.6.2 yamt nfscl_printoptval(nmp, nmp->nm_acdirmin, ",acdirmin", &buf, &blen);
1814 1.1.1.1.6.2 yamt nfscl_printoptval(nmp, nmp->nm_acdirmax, ",acdirmax", &buf, &blen);
1815 1.1.1.1.6.2 yamt nfscl_printoptval(nmp, nmp->nm_acregmin, ",acregmin", &buf, &blen);
1816 1.1.1.1.6.2 yamt nfscl_printoptval(nmp, nmp->nm_acregmax, ",acregmax", &buf, &blen);
1817 1.1.1.1.6.2 yamt nfscl_printoptval(nmp, nmp->nm_nametimeo, ",nametimeo", &buf, &blen);
1818 1.1.1.1.6.2 yamt nfscl_printoptval(nmp, nmp->nm_negnametimeo, ",negnametimeo", &buf,
1819 1.1.1.1.6.2 yamt &blen);
1820 1.1.1.1.6.2 yamt nfscl_printoptval(nmp, nmp->nm_rsize, ",rsize", &buf, &blen);
1821 1.1.1.1.6.2 yamt nfscl_printoptval(nmp, nmp->nm_wsize, ",wsize", &buf, &blen);
1822 1.1.1.1.6.2 yamt nfscl_printoptval(nmp, nmp->nm_readdirsize, ",readdirsize", &buf,
1823 1.1.1.1.6.2 yamt &blen);
1824 1.1.1.1.6.2 yamt nfscl_printoptval(nmp, nmp->nm_readahead, ",readahead", &buf, &blen);
1825 1.1.1.1.6.2 yamt nfscl_printoptval(nmp, nmp->nm_wcommitsize, ",wcommitsize", &buf,
1826 1.1.1.1.6.2 yamt &blen);
1827 1.1.1.1.6.2 yamt nfscl_printoptval(nmp, nmp->nm_timeo, ",timeout", &buf, &blen);
1828 1.1.1.1.6.2 yamt nfscl_printoptval(nmp, nmp->nm_retry, ",retrans", &buf, &blen);
1829 1.1.1.1.6.2 yamt }
1830 1.1.1.1.6.2 yamt
1831