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