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