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