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 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95
37 */
38
39 #include <sys/cdefs.h>
40 __FBSDID("$FreeBSD: releng/5.2/sys/nfsclient/nfs_vfsops.c 122953 2003-11-22 02:21:49Z alfred $");
41
42 #include "opt_bootp.h"
43 #include "opt_nfsroot.h"
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/limits.h>
49 #include <sys/lock.h>
50 #include <sys/malloc.h>
51 #include <sys/mbuf.h>
52 #include <sys/module.h>
53 #include <sys/mount.h>
54 #include <sys/proc.h>
55 #include <sys/socket.h>
56 #include <sys/socketvar.h>
57 #include <sys/sockio.h>
58 #include <sys/sysctl.h>
59 #include <sys/vnode.h>
60
61 #include <vm/vm.h>
62 #include <vm/vm_extern.h>
63 #include <vm/uma.h>
64
65 #include <net/if.h>
66 #include <net/route.h>
67 #include <netinet/in.h>
68
69 #include <rpc/rpcclnt.h>
70
71 #include <nfs/rpcv2.h>
72 #include <nfs/nfsproto.h>
73 #include <nfsclient/nfs.h>
74 #include <nfsclient/nfsnode.h>
75 #include <nfsclient/nfsmount.h>
76 #include <nfs/xdr_subs.h>
77 #include <nfsclient/nfsm_subs.h>
78 #include <nfsclient/nfsdiskless.h>
79
80 MALLOC_DEFINE(M_NFSREQ, "NFS req", "NFS request header");
81 MALLOC_DEFINE(M_NFSBIGFH, "NFSV3 bigfh", "NFS version 3 file handle");
82 MALLOC_DEFINE(M_NFSDIROFF, "NFSV3 diroff", "NFS directory offset data");
83 MALLOC_DEFINE(M_NFSHASH, "NFS hash", "NFS hash tables");
84
85 uma_zone_t nfsmount_zone;
86
87 struct nfsstats nfsstats;
88 SYSCTL_NODE(_vfs, OID_AUTO, nfs, CTLFLAG_RW, 0, "NFS filesystem");
89 SYSCTL_STRUCT(_vfs_nfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RD,
90 &nfsstats, nfsstats, "S,nfsstats");
91 static int nfs_ip_paranoia = 1;
92 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
93 &nfs_ip_paranoia, 0, "");
94 #ifdef NFS_DEBUG
95 int nfs_debug;
96 SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, "");
97 #endif
98
99 static int nfs_iosize(struct nfsmount *nmp);
100 static void nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp);
101 static int mountnfs(struct nfs_args *, struct mount *,
102 struct sockaddr *, char *, char *, struct vnode **,
103 struct ucred *cred);
104 static vfs_mount_t nfs_mount;
105 static vfs_unmount_t nfs_unmount;
106 static vfs_root_t nfs_root;
107 static vfs_statfs_t nfs_statfs;
108 static vfs_sync_t nfs_sync;
109
110 /*
111 * nfs vfs operations.
112 */
113 static struct vfsops nfs_vfsops = {
114 .vfs_init = nfs_init,
115 .vfs_mount = nfs_mount,
116 .vfs_root = nfs_root,
117 .vfs_statfs = nfs_statfs,
118 .vfs_sync = nfs_sync,
119 .vfs_uninit = nfs_uninit,
120 .vfs_unmount = nfs_unmount,
121 };
122 VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK);
123
124 /* So that loader and kldload(2) can find us, wherever we are.. */
125 MODULE_VERSION(nfs, 1);
126
127 static struct nfs_rpcops nfs_rpcops = {
128 nfs_readrpc,
129 nfs_writerpc,
130 nfs_writebp,
131 nfs_readlinkrpc,
132 nfs_invaldir,
133 nfs_commit,
134 };
135
136 /*
137 * This structure must be filled in by a primary bootstrap or bootstrap
138 * server for a diskless/dataless machine. It is initialized below just
139 * to ensure that it is allocated to initialized data (.data not .bss).
140 */
141 struct nfs_diskless nfs_diskless = { { { 0 } } };
142 struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
143 int nfs_diskless_valid = 0;
144
145 SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
146 &nfs_diskless_valid, 0, "");
147
148 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
149 nfsv3_diskless.root_hostnam, 0, "");
150
151 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
152 &nfsv3_diskless.root_saddr, sizeof nfsv3_diskless.root_saddr,
153 "%Ssockaddr_in", "");
154
155
156 void nfsargs_ntoh(struct nfs_args *);
157 static int nfs_mountdiskless(char *, char *, int,
158 struct sockaddr_in *, struct nfs_args *,
159 struct thread *, struct vnode **, struct mount *);
160 static void nfs_convert_diskless(void);
161 static void nfs_convert_oargs(struct nfs_args *args,
162 struct onfs_args *oargs);
163
164 static int
165 nfs_iosize(struct nfsmount *nmp)
166 {
167 int iosize;
168
169 /*
170 * Calculate the size used for io buffers. Use the larger
171 * of the two sizes to minimise nfs requests but make sure
172 * that it is at least one VM page to avoid wasting buffer
173 * space.
174 */
175 iosize = max(nmp->nm_rsize, nmp->nm_wsize);
176 if (iosize < PAGE_SIZE) iosize = PAGE_SIZE;
177 return iosize;
178 }
179
180 static void
181 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
182 {
183
184 args->version = NFS_ARGSVERSION;
185 args->addr = oargs->addr;
186 args->addrlen = oargs->addrlen;
187 args->sotype = oargs->sotype;
188 args->proto = oargs->proto;
189 args->fh = oargs->fh;
190 args->fhsize = oargs->fhsize;
191 args->flags = oargs->flags;
192 args->wsize = oargs->wsize;
193 args->rsize = oargs->rsize;
194 args->readdirsize = oargs->readdirsize;
195 args->timeo = oargs->timeo;
196 args->retrans = oargs->retrans;
197 args->maxgrouplist = oargs->maxgrouplist;
198 args->readahead = oargs->readahead;
199 args->deadthresh = oargs->deadthresh;
200 args->hostname = oargs->hostname;
201 }
202
203 static void
204 nfs_convert_diskless(void)
205 {
206
207 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
208 sizeof(struct ifaliasreq));
209 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
210 sizeof(struct sockaddr_in));
211 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
212 nfsv3_diskless.root_fhsize = NFSX_V2FH;
213 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
214 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
215 sizeof(struct sockaddr_in));
216 bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
217 nfsv3_diskless.root_time = nfs_diskless.root_time;
218 bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
219 MAXHOSTNAMELEN);
220 nfs_diskless_valid = 3;
221 }
222
223 /*
224 * nfs statfs call
225 */
226 static int
227 nfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
228 {
229 struct vnode *vp;
230 struct nfs_statfs *sfp;
231 caddr_t bpos, dpos;
232 struct nfsmount *nmp = VFSTONFS(mp);
233 int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
234 struct mbuf *mreq, *mrep, *md, *mb;
235 struct nfsnode *np;
236 u_quad_t tquad;
237 int bsize;
238
239 #ifndef nolint
240 sfp = NULL;
241 #endif
242 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
243 if (error)
244 return (error);
245 vp = NFSTOV(np);
246 if (v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0)
247 (void)nfs_fsinfo(nmp, vp, td->td_ucred, td);
248 nfsstats.rpccnt[NFSPROC_FSSTAT]++;
249 mreq = nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
250 mb = mreq;
251 bpos = mtod(mb, caddr_t);
252 nfsm_fhtom(vp, v3);
253 nfsm_request(vp, NFSPROC_FSSTAT, td, td->td_ucred);
254 if (v3)
255 nfsm_postop_attr(vp, retattr);
256 if (error) {
257 if (mrep != NULL)
258 m_freem(mrep);
259 goto nfsmout;
260 }
261 sfp = nfsm_dissect(struct nfs_statfs *, NFSX_STATFS(v3));
262 sbp->f_flags = nmp->nm_flag;
263 sbp->f_iosize = nfs_iosize(nmp);
264 if (v3) {
265 for (bsize = NFS_FABLKSIZE; ; bsize *= 2) {
266 sbp->f_bsize = bsize;
267 tquad = fxdr_hyper(&sfp->sf_tbytes);
268 if (((long)(tquad / bsize) > LONG_MAX) ||
269 ((long)(tquad / bsize) < LONG_MIN))
270 continue;
271 sbp->f_blocks = tquad / bsize;
272 tquad = fxdr_hyper(&sfp->sf_fbytes);
273 if (((long)(tquad / bsize) > LONG_MAX) ||
274 ((long)(tquad / bsize) < LONG_MIN))
275 continue;
276 sbp->f_bfree = tquad / bsize;
277 tquad = fxdr_hyper(&sfp->sf_abytes);
278 if (((long)(tquad / bsize) > LONG_MAX) ||
279 ((long)(tquad / bsize) < LONG_MIN))
280 continue;
281 sbp->f_bavail = tquad / bsize;
282 sbp->f_files = (fxdr_unsigned(int32_t,
283 sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff);
284 sbp->f_ffree = (fxdr_unsigned(int32_t,
285 sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff);
286 break;
287 }
288 } else {
289 sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize);
290 sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks);
291 sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree);
292 sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail);
293 sbp->f_files = 0;
294 sbp->f_ffree = 0;
295 }
296 if (sbp != &mp->mnt_stat) {
297 sbp->f_type = mp->mnt_vfc->vfc_typenum;
298 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
299 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
300 }
301 m_freem(mrep);
302 nfsmout:
303 vput(vp);
304 return (error);
305 }
306
307 /*
308 * nfs version 3 fsinfo rpc call
309 */
310 int
311 nfs_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
312 struct thread *td)
313 {
314 struct nfsv3_fsinfo *fsp;
315 u_int32_t pref, max;
316 caddr_t bpos, dpos;
317 int error = 0, retattr;
318 struct mbuf *mreq, *mrep, *md, *mb;
319 u_int64_t maxfsize;
320
321 nfsstats.rpccnt[NFSPROC_FSINFO]++;
322 mreq = nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
323 mb = mreq;
324 bpos = mtod(mb, caddr_t);
325 nfsm_fhtom(vp, 1);
326 nfsm_request(vp, NFSPROC_FSINFO, td, cred);
327 nfsm_postop_attr(vp, retattr);
328 if (!error) {
329 fsp = nfsm_dissect(struct nfsv3_fsinfo *, NFSX_V3FSINFO);
330 pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref);
331 if (pref < nmp->nm_wsize && pref >= NFS_FABLKSIZE)
332 nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
333 ~(NFS_FABLKSIZE - 1);
334 max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax);
335 if (max < nmp->nm_wsize && max > 0) {
336 nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
337 if (nmp->nm_wsize == 0)
338 nmp->nm_wsize = max;
339 }
340 pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref);
341 if (pref < nmp->nm_rsize && pref >= NFS_FABLKSIZE)
342 nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
343 ~(NFS_FABLKSIZE - 1);
344 max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax);
345 if (max < nmp->nm_rsize && max > 0) {
346 nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
347 if (nmp->nm_rsize == 0)
348 nmp->nm_rsize = max;
349 }
350 pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref);
351 if (pref < nmp->nm_readdirsize && pref >= NFS_DIRBLKSIZ)
352 nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) &
353 ~(NFS_DIRBLKSIZ - 1);
354 if (max < nmp->nm_readdirsize && max > 0) {
355 nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
356 if (nmp->nm_readdirsize == 0)
357 nmp->nm_readdirsize = max;
358 }
359 maxfsize = fxdr_hyper(&fsp->fs_maxfilesize);
360 if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize)
361 nmp->nm_maxfilesize = maxfsize;
362 nmp->nm_state |= NFSSTA_GOTFSINFO;
363 }
364 m_freem(mrep);
365 nfsmout:
366 return (error);
367 }
368
369 /*
370 * Mount a remote root fs via. nfs. This depends on the info in the
371 * nfs_diskless structure that has been filled in properly by some primary
372 * bootstrap.
373 * It goes something like this:
374 * - do enough of "ifconfig" by calling ifioctl() so that the system
375 * can talk to the server
376 * - If nfs_diskless.mygateway is filled in, use that address as
377 * a default gateway.
378 * - build the rootfs mount point and call mountnfs() to do the rest.
379 */
380 int
381 nfs_mountroot(struct mount *mp, struct thread *td)
382 {
383 struct nfsv3_diskless *nd = &nfsv3_diskless;
384 struct socket *so;
385 struct vnode *vp;
386 int error, i;
387 u_long l;
388 char buf[128];
389
390 GIANT_REQUIRED; /* XXX until socket locking done */
391
392 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
393 bootpc_init(); /* use bootp to get nfs_diskless filled in */
394 #elif defined(NFS_ROOT)
395 nfs_setup_diskless();
396 #endif
397
398 if (nfs_diskless_valid == 0)
399 return (-1);
400 if (nfs_diskless_valid == 1)
401 nfs_convert_diskless();
402
403 /*
404 * XXX splnet, so networks will receive...
405 */
406 splnet();
407
408 /*
409 * Do enough of ifconfig(8) so that the critical net interface can
410 * talk to the server.
411 */
412 error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0,
413 td->td_ucred, td);
414 if (error)
415 panic("nfs_mountroot: socreate(%04x): %d",
416 nd->myif.ifra_addr.sa_family, error);
417
418 #if 0 /* XXX Bad idea */
419 /*
420 * We might not have been told the right interface, so we pass
421 * over the first ten interfaces of the same kind, until we get
422 * one of them configured.
423 */
424
425 for (i = strlen(nd->myif.ifra_name) - 1;
426 nd->myif.ifra_name[i] >= '' &&
427 nd->myif.ifra_name[i] <= '9';
428 nd->myif.ifra_name[i] ++) {
429 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
430 if(!error)
431 break;
432 }
433 #endif
434 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
435 if (error)
436 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
437 soclose(so);
438
439 /*
440 * If the gateway field is filled in, set it as the default route.
441 * Note that pxeboot will set a default route of 0 if the route
442 * is not set by the DHCP server. Check also for a value of 0
443 * to avoid panicking inappropriately in that situation.
444 */
445 if (nd->mygateway.sin_len != 0 &&
446 nd->mygateway.sin_addr.s_addr != 0) {
447 struct sockaddr_in mask, sin;
448
449 bzero((caddr_t)&mask, sizeof(mask));
450 sin = mask;
451 sin.sin_family = AF_INET;
452 sin.sin_len = sizeof(sin);
453 error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
454 (struct sockaddr *)&nd->mygateway,
455 (struct sockaddr *)&mask,
456 RTF_UP | RTF_GATEWAY, NULL);
457 if (error)
458 panic("nfs_mountroot: RTM_ADD: %d", error);
459 }
460
461 /*
462 * Create the rootfs mount point.
463 */
464 nd->root_args.fh = nd->root_fh;
465 nd->root_args.fhsize = nd->root_fhsize;
466 l = ntohl(nd->root_saddr.sin_addr.s_addr);
467 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
468 (l >> 24) & 0xff, (l >> 16) & 0xff,
469 (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
470 printf("NFS ROOT: %s\n", buf);
471 if ((error = nfs_mountdiskless(buf, "/", MNT_RDONLY,
472 &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
473 return (error);
474 }
475
476 rootvp = vp;
477
478 /*
479 * This is not really an nfs issue, but it is much easier to
480 * set hostname here and then let the "/etc/rc.xxx" files
481 * mount the right /var based upon its preset value.
482 */
483 bcopy(nd->my_hostnam, hostname, MAXHOSTNAMELEN);
484 hostname[MAXHOSTNAMELEN - 1] = '\0';
485 for (i = 0; i < MAXHOSTNAMELEN; i++)
486 if (hostname[i] == '\0')
487 break;
488 inittodr(ntohl(nd->root_time));
489 return (0);
490 }
491
492 /*
493 * Internal version of mount system call for diskless setup.
494 */
495 static int
496 nfs_mountdiskless(char *path, char *which, int mountflag,
497 struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
498 struct vnode **vpp, struct mount *mp)
499 {
500 struct sockaddr *nam;
501 int error;
502
503 mp->mnt_kern_flag = 0;
504 mp->mnt_flag = mountflag;
505 nam = dup_sockaddr((struct sockaddr *)sin, 1);
506 if ((error = mountnfs(args, mp, nam, which, path, vpp,
507 td->td_ucred)) != 0) {
508 printf("nfs_mountroot: mount %s on %s: %d", path, which, error);
509 FREE(nam, M_SONAME);
510 return (error);
511 }
512 (void) copystr(which, mp->mnt_stat.f_mntonname, MNAMELEN - 1, 0);
513 return (0);
514 }
515
516 static void
517 nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp)
518 {
519 int s;
520 int adjsock;
521 int maxio;
522
523 s = splnet();
524 /*
525 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
526 * no sense in that context.
527 */
528 if (argp->sotype == SOCK_STREAM)
529 nmp->nm_flag &= ~NFSMNT_NOCONN;
530
531 /* Also clear RDIRPLUS if not NFSv3, it crashes some servers */
532 if ((argp->flags & NFSMNT_NFSV3) == 0)
533 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
534
535 /* Re-bind if rsrvd port requested and wasn't on one */
536 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
537 && (argp->flags & NFSMNT_RESVPORT);
538 /* Also re-bind if we're switching to/from a connected UDP socket */
539 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
540 (argp->flags & NFSMNT_NOCONN));
541
542 /* Update flags atomically. Don't change the lock bits. */
543 nmp->nm_flag = argp->flags | nmp->nm_flag;
544 splx(s);
545
546 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
547 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
548 if (nmp->nm_timeo < NFS_MINTIMEO)
549 nmp->nm_timeo = NFS_MINTIMEO;
550 else if (nmp->nm_timeo > NFS_MAXTIMEO)
551 nmp->nm_timeo = NFS_MAXTIMEO;
552 }
553
554 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
555 nmp->nm_retry = argp->retrans;
556 if (nmp->nm_retry > NFS_MAXREXMIT)
557 nmp->nm_retry = NFS_MAXREXMIT;
558 }
559
560 if (argp->flags & NFSMNT_NFSV3) {
561 if (argp->sotype == SOCK_DGRAM)
562 maxio = NFS_MAXDGRAMDATA;
563 else
564 maxio = NFS_MAXDATA;
565 } else
566 maxio = NFS_V2MAXDATA;
567
568 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
569 nmp->nm_wsize = argp->wsize;
570 /* Round down to multiple of blocksize */
571 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
572 if (nmp->nm_wsize <= 0)
573 nmp->nm_wsize = NFS_FABLKSIZE;
574 }
575 if (nmp->nm_wsize > maxio)
576 nmp->nm_wsize = maxio;
577 if (nmp->nm_wsize > MAXBSIZE)
578 nmp->nm_wsize = MAXBSIZE;
579
580 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
581 nmp->nm_rsize = argp->rsize;
582 /* Round down to multiple of blocksize */
583 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
584 if (nmp->nm_rsize <= 0)
585 nmp->nm_rsize = NFS_FABLKSIZE;
586 }
587 if (nmp->nm_rsize > maxio)
588 nmp->nm_rsize = maxio;
589 if (nmp->nm_rsize > MAXBSIZE)
590 nmp->nm_rsize = MAXBSIZE;
591
592 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
593 nmp->nm_readdirsize = argp->readdirsize;
594 }
595 if (nmp->nm_readdirsize > maxio)
596 nmp->nm_readdirsize = maxio;
597 if (nmp->nm_readdirsize > nmp->nm_rsize)
598 nmp->nm_readdirsize = nmp->nm_rsize;
599
600 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
601 nmp->nm_acregmin = argp->acregmin;
602 else
603 nmp->nm_acregmin = NFS_MINATTRTIMO;
604 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
605 nmp->nm_acregmax = argp->acregmax;
606 else
607 nmp->nm_acregmax = NFS_MAXATTRTIMO;
608 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
609 nmp->nm_acdirmin = argp->acdirmin;
610 else
611 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
612 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
613 nmp->nm_acdirmax = argp->acdirmax;
614 else
615 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
616 if (nmp->nm_acdirmin > nmp->nm_acdirmax)
617 nmp->nm_acdirmin = nmp->nm_acdirmax;
618 if (nmp->nm_acregmin > nmp->nm_acregmax)
619 nmp->nm_acregmin = nmp->nm_acregmax;
620
621 if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0) {
622 if (argp->maxgrouplist <= NFS_MAXGRPS)
623 nmp->nm_numgrps = argp->maxgrouplist;
624 else
625 nmp->nm_numgrps = NFS_MAXGRPS;
626 }
627 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
628 if (argp->readahead <= NFS_MAXRAHEAD)
629 nmp->nm_readahead = argp->readahead;
630 else
631 nmp->nm_readahead = NFS_MAXRAHEAD;
632 }
633 if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 0) {
634 if (argp->deadthresh <= NFS_MAXDEADTHRESH)
635 nmp->nm_deadthresh = argp->deadthresh;
636 else
637 nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
638 }
639
640 adjsock |= ((nmp->nm_sotype != argp->sotype) ||
641 (nmp->nm_soproto != argp->proto));
642 nmp->nm_sotype = argp->sotype;
643 nmp->nm_soproto = argp->proto;
644
645 if (nmp->nm_so && adjsock) {
646 nfs_safedisconnect(nmp);
647 if (nmp->nm_sotype == SOCK_DGRAM)
648 while (nfs_connect(nmp, NULL)) {
649 printf("nfs_args: retrying connect\n");
650 (void) tsleep((caddr_t)&lbolt,
651 PSOCK, "nfscon", 0);
652 }
653 }
654 }
655
656 /*
657 * VFS Operations.
658 *
659 * mount system call
660 * It seems a bit dumb to copyinstr() the host and path here and then
661 * bcopy() them in mountnfs(), but I wanted to detect errors before
662 * doing the sockargs() call because sockargs() allocates an mbuf and
663 * an error after that means that I have to release the mbuf.
664 */
665 /* ARGSUSED */
666 static int
667 nfs_mount(struct mount *mp, char *path, caddr_t data, struct nameidata *ndp,
668 struct thread *td)
669 {
670 int error;
671 struct nfs_args args;
672 struct sockaddr *nam;
673 struct vnode *vp;
674 char hst[MNAMELEN];
675 size_t len;
676 u_char nfh[NFSX_V3FHMAX];
677
678 if (path == NULL)
679 return (nfs_mountroot(mp, td));
680 error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
681 if (error)
682 return (error);
683 if (args.version != NFS_ARGSVERSION) {
684 #ifdef COMPAT_PRELITE2
685 /*
686 * If the argument version is unknown, then assume the
687 * caller is a pre-lite2 4.4BSD client and convert its
688 * arguments.
689 */
690 struct onfs_args oargs;
691 error = copyin(data, (caddr_t)&oargs, sizeof (struct onfs_args));
692 if (error)
693 return (error);
694 nfs_convert_oargs(&args,&oargs);
695 #else /* !COMPAT_PRELITE2 */
696 return (EPROGMISMATCH);
697 #endif /* COMPAT_PRELITE2 */
698 }
699 if (mp->mnt_flag & MNT_UPDATE) {
700 struct nfsmount *nmp = VFSTONFS(mp);
701
702 if (nmp == NULL)
703 return (EIO);
704 /*
705 * When doing an update, we can't change from or to
706 * v3, switch lockd strategies or change cookie translation
707 */
708 args.flags = (args.flags &
709 ~(NFSMNT_NFSV3 | NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
710 (nmp->nm_flag &
711 (NFSMNT_NFSV3 | NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
712 nfs_decode_args(nmp, &args);
713 return (0);
714 }
715
716 /*
717 * Make the nfs_ip_paranoia sysctl serve as the default connection
718 * or no-connection mode for those protocols that support
719 * no-connection mode (the flag will be cleared later for protocols
720 * that do not support no-connection mode). This will allow a client
721 * to receive replies from a different IP then the request was
722 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
723 * not 0.
724 */
725 if (nfs_ip_paranoia == 0)
726 args.flags |= NFSMNT_NOCONN;
727 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX)
728 return (EINVAL);
729 error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
730 if (error)
731 return (error);
732 error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
733 if (error)
734 return (error);
735 bzero(&hst[len], MNAMELEN - len);
736 /* sockargs() call must be after above copyin() calls */
737 error = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen);
738 if (error)
739 return (error);
740 args.fh = nfh;
741 error = mountnfs(&args, mp, nam, path, hst, &vp, td->td_ucred);
742 return (error);
743 }
744
745 /*
746 * Common code for mount and mountroot
747 */
748 static int
749 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
750 char *pth, char *hst, struct vnode **vpp, struct ucred *cred)
751 {
752 struct nfsmount *nmp;
753 struct nfsnode *np;
754 int error;
755 struct vattr attrs;
756
757 if (mp->mnt_flag & MNT_UPDATE) {
758 nmp = VFSTONFS(mp);
759 /* update paths, file handles, etc, here XXX */
760 FREE(nam, M_SONAME);
761 return (0);
762 } else {
763 nmp = uma_zalloc(nfsmount_zone, M_WAITOK);
764 bzero((caddr_t)nmp, sizeof (struct nfsmount));
765 TAILQ_INIT(&nmp->nm_bufq);
766 mp->mnt_data = (qaddr_t)nmp;
767 }
768 vfs_getnewfsid(mp);
769 nmp->nm_mountp = mp;
770
771 /*
772 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
773 * high, depending on whether we end up with negative offsets in
774 * the client or server somewhere. 2GB-1 may be safer.
775 *
776 * For V3, nfs_fsinfo will adjust this as necessary. Assume maximum
777 * that we can handle until we find out otherwise.
778 * XXX Our "safe" limit on the client is what we can store in our
779 * buffer cache using signed(!) block numbers.
780 */
781 if ((argp->flags & NFSMNT_NFSV3) == 0)
782 nmp->nm_maxfilesize = 0xffffffffLL;
783 else
784 nmp->nm_maxfilesize = (u_int64_t)0x80000000 * DEV_BSIZE - 1;
785
786 nmp->nm_timeo = NFS_TIMEO;
787 nmp->nm_retry = NFS_RETRANS;
788 nmp->nm_wsize = NFS_WSIZE;
789 nmp->nm_rsize = NFS_RSIZE;
790 nmp->nm_readdirsize = NFS_READDIRSIZE;
791 nmp->nm_numgrps = NFS_MAXGRPS;
792 nmp->nm_readahead = NFS_DEFRAHEAD;
793 nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
794 nmp->nm_fhsize = argp->fhsize;
795 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
796 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
797 bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
798 nmp->nm_nam = nam;
799 /* Set up the sockets and per-host congestion */
800 nmp->nm_sotype = argp->sotype;
801 nmp->nm_soproto = argp->proto;
802 nmp->nm_rpcops = &nfs_rpcops;
803
804 nfs_decode_args(nmp, argp);
805
806 /*
807 * For Connection based sockets (TCP,...) defer the connect until
808 * the first request, in case the server is not responding.
809 */
810 if (nmp->nm_sotype == SOCK_DGRAM &&
811 (error = nfs_connect(nmp, NULL)))
812 goto bad;
813
814 /*
815 * This is silly, but it has to be set so that vinifod() works.
816 * We do not want to do an nfs_statfs() here since we can get
817 * stuck on a dead server and we are holding a lock on the mount
818 * point.
819 */
820 mp->mnt_stat.f_iosize = nfs_iosize(nmp);
821 /*
822 * A reference count is needed on the nfsnode representing the
823 * remote root. If this object is not persistent, then backward
824 * traversals of the mount point (i.e. "..") will not work if
825 * the nfsnode gets flushed out of the cache. Ufs does not have
826 * this problem, because one can identify root inodes by their
827 * number == ROOTINO (2).
828 */
829 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
830 if (error)
831 goto bad;
832 *vpp = NFSTOV(np);
833
834 /*
835 * Get file attributes for the mountpoint. This has the side
836 * effect of filling in (*vpp)->v_type with the correct value.
837 */
838 VOP_GETATTR(*vpp, &attrs, curthread->td_ucred, curthread);
839
840 /*
841 * Lose the lock but keep the ref.
842 */
843 VOP_UNLOCK(*vpp, 0, curthread);
844
845 return (0);
846 bad:
847 nfs_disconnect(nmp);
848 uma_zfree(nfsmount_zone, nmp);
849 FREE(nam, M_SONAME);
850 return (error);
851 }
852
853 /*
854 * unmount system call
855 */
856 static int
857 nfs_unmount(struct mount *mp, int mntflags, struct thread *td)
858 {
859 struct nfsmount *nmp;
860 int error, flags = 0;
861
862 if (mntflags & MNT_FORCE)
863 flags |= FORCECLOSE;
864 nmp = VFSTONFS(mp);
865 /*
866 * Goes something like this..
867 * - Call vflush() to clear out vnodes for this filesystem
868 * - Close the socket
869 * - Free up the data structures
870 */
871 /* In the forced case, cancel any outstanding requests. */
872 if (flags & FORCECLOSE) {
873 error = nfs_nmcancelreqs(nmp);
874 if (error)
875 return (error);
876 }
877 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
878 error = vflush(mp, 1, flags);
879 if (error)
880 return (error);
881
882 /*
883 * We are now committed to the unmount.
884 */
885 nfs_disconnect(nmp);
886 FREE(nmp->nm_nam, M_SONAME);
887
888 uma_zfree(nfsmount_zone, nmp);
889 return (0);
890 }
891
892 /*
893 * Return root of a filesystem
894 */
895 static int
896 nfs_root(struct mount *mp, struct vnode **vpp)
897 {
898 struct vnode *vp;
899 struct nfsmount *nmp;
900 struct nfsnode *np;
901 int error;
902
903 nmp = VFSTONFS(mp);
904 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
905 if (error)
906 return (error);
907 vp = NFSTOV(np);
908 if (vp->v_type == VNON)
909 vp->v_type = VDIR;
910 vp->v_vflag |= VV_ROOT;
911 *vpp = vp;
912 return (0);
913 }
914
915 /*
916 * Flush out the buffer cache
917 */
918 /* ARGSUSED */
919 static int
920 nfs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct thread *td)
921 {
922 struct vnode *vp, *vnp;
923 int error, allerror = 0;
924
925 /*
926 * Force stale buffer cache information to be flushed.
927 */
928 MNT_ILOCK(mp);
929 loop:
930 for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
931 vp != NULL;
932 vp = vnp) {
933 /*
934 * If the vnode that we are about to sync is no longer
935 * associated with this mount point, start over.
936 */
937 if (vp->v_mount != mp)
938 goto loop;
939 vnp = TAILQ_NEXT(vp, v_nmntvnodes);
940 VI_LOCK(vp);
941 MNT_IUNLOCK(mp);
942 if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) ||
943 waitfor == MNT_LAZY) {
944 VI_UNLOCK(vp);
945 MNT_ILOCK(mp);
946 continue;
947 }
948 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
949 MNT_ILOCK(mp);
950 goto loop;
951 }
952 error = VOP_FSYNC(vp, cred, waitfor, td);
953 if (error)
954 allerror = error;
955 VOP_UNLOCK(vp, 0, td);
956 vrele(vp);
957
958 MNT_ILOCK(mp);
959 }
960 MNT_IUNLOCK(mp);
961 return (allerror);
962 }
Cache object: 10742934fefa53c90ae7587840567f6b
|