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