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