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