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