2 * Copyright (c) 1989, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
36 * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95
37 * $FreeBSD: src/sys/nfs/nfs_vfsops.c,v 1.91.2.7 2003/01/27 20:04:08 dillon Exp $
38 * $DragonFly: src/sys/vfs/nfs/nfs_vfsops.c,v 1.54 2008/07/31 20:23:40 swildner Exp $
41 #include "opt_bootp.h"
42 #include "opt_nfsroot.h"
44 #include <sys/param.h>
45 #include <sys/sockio.h>
47 #include <sys/vnode.h>
48 #include <sys/fcntl.h>
49 #include <sys/kernel.h>
50 #include <sys/sysctl.h>
51 #include <sys/malloc.h>
52 #include <sys/mount.h>
54 #include <sys/socket.h>
55 #include <sys/socketvar.h>
56 #include <sys/systm.h>
59 #include <vm/vm_extern.h>
60 #include <vm/vm_zone.h>
63 #include <net/route.h>
64 #include <netinet/in.h>
66 #include <sys/thread2.h>
67 #include <sys/mutex2.h>
75 #include "nfsm_subs.h"
76 #include "nfsdiskless.h"
77 #include "nfsmountrpc.h"
79 extern int nfs_mountroot(struct mount
*mp
);
80 extern void bootpc_init(void);
82 extern struct vop_ops nfsv2_vnode_vops
;
83 extern struct vop_ops nfsv2_fifo_vops
;
84 extern struct vop_ops nfsv2_spec_vops
;
86 MALLOC_DEFINE(M_NFSREQ
, "NFS req", "NFS request header");
87 MALLOC_DEFINE(M_NFSBIGFH
, "NFSV3 bigfh", "NFS version 3 file handle");
88 MALLOC_DEFINE(M_NFSD
, "NFS daemon", "Nfs server daemon structure");
89 MALLOC_DEFINE(M_NFSDIROFF
, "NFSV3 diroff", "NFS directory offset data");
90 MALLOC_DEFINE(M_NFSRVDESC
, "NFSV3 srvdesc", "NFS server socket descriptor");
91 MALLOC_DEFINE(M_NFSUID
, "NFS uid", "Nfs uid mapping structure");
92 MALLOC_DEFINE(M_NFSHASH
, "NFS hash", "NFS hash tables");
94 vm_zone_t nfsmount_zone
;
96 struct nfsstats nfsstats
;
97 SYSCTL_NODE(_vfs
, OID_AUTO
, nfs
, CTLFLAG_RW
, 0, "NFS filesystem");
98 SYSCTL_STRUCT(_vfs_nfs
, NFS_NFSSTATS
, nfsstats
, CTLFLAG_RD
,
99 &nfsstats
, nfsstats
, "");
100 static int nfs_ip_paranoia
= 1;
101 SYSCTL_INT(_vfs_nfs
, OID_AUTO
, nfs_ip_paranoia
, CTLFLAG_RW
,
102 &nfs_ip_paranoia
, 0, "");
105 SYSCTL_INT(_vfs_nfs
, OID_AUTO
, debug
, CTLFLAG_RW
, &nfs_debug
, 0, "");
109 * Tunable to determine the Read/Write unit size. Maximum value
110 * is NFS_MAXDATA. We also default to NFS_MAXDATA.
112 static int nfs_io_size
= NFS_MAXDATA
;
113 SYSCTL_INT(_vfs_nfs
, OID_AUTO
, nfs_io_size
, CTLFLAG_RW
,
114 &nfs_io_size
, 0, "NFS optimal I/O unit size");
116 static void nfs_decode_args (struct nfsmount
*nmp
,
117 struct nfs_args
*argp
);
118 static int mountnfs (struct nfs_args
*,struct mount
*,
119 struct sockaddr
*,char *,char *,struct vnode
**);
120 static int nfs_mount ( struct mount
*mp
, char *path
, caddr_t data
,
122 static int nfs_unmount ( struct mount
*mp
, int mntflags
);
123 static int nfs_root ( struct mount
*mp
, struct vnode
**vpp
);
124 static int nfs_statfs ( struct mount
*mp
, struct statfs
*sbp
,
126 static int nfs_statvfs(struct mount
*mp
, struct statvfs
*sbp
,
128 static int nfs_sync ( struct mount
*mp
, int waitfor
);
131 * nfs vfs operations.
133 static struct vfsops nfs_vfsops
= {
134 .vfs_mount
= nfs_mount
,
135 .vfs_unmount
= nfs_unmount
,
136 .vfs_root
= nfs_root
,
137 .vfs_statfs
= nfs_statfs
,
138 .vfs_statvfs
= nfs_statvfs
,
139 .vfs_sync
= nfs_sync
,
140 .vfs_init
= nfs_init
,
141 .vfs_uninit
= nfs_uninit
143 VFS_SET(nfs_vfsops
, nfs
, VFCF_NETWORK
);
146 * This structure must be filled in by a primary bootstrap or bootstrap
147 * server for a diskless/dataless machine. It is initialized below just
148 * to ensure that it is allocated to initialized data (.data not .bss).
150 struct nfs_diskless nfs_diskless
= { { { 0 } } };
151 struct nfsv3_diskless nfsv3_diskless
= { { { 0 } } };
152 int nfs_diskless_valid
= 0;
154 SYSCTL_INT(_vfs_nfs
, OID_AUTO
, diskless_valid
, CTLFLAG_RD
,
155 &nfs_diskless_valid
, 0, "");
157 SYSCTL_STRING(_vfs_nfs
, OID_AUTO
, diskless_rootpath
, CTLFLAG_RD
,
158 nfsv3_diskless
.root_hostnam
, 0, "");
160 SYSCTL_OPAQUE(_vfs_nfs
, OID_AUTO
, diskless_rootaddr
, CTLFLAG_RD
,
161 &nfsv3_diskless
.root_saddr
, sizeof nfsv3_diskless
.root_saddr
,
162 "%Ssockaddr_in", "");
164 SYSCTL_STRING(_vfs_nfs
, OID_AUTO
, diskless_swappath
, CTLFLAG_RD
,
165 nfsv3_diskless
.swap_hostnam
, 0, "");
167 SYSCTL_OPAQUE(_vfs_nfs
, OID_AUTO
, diskless_swapaddr
, CTLFLAG_RD
,
168 &nfsv3_diskless
.swap_saddr
, sizeof nfsv3_diskless
.swap_saddr
,
172 void nfsargs_ntoh (struct nfs_args
*);
173 static int nfs_mountdiskless (char *, char *, int,
174 struct sockaddr_in
*, struct nfs_args
*,
175 struct thread
*, struct vnode
**,
177 static void nfs_convert_diskless (void);
178 static void nfs_convert_oargs (struct nfs_args
*args
,
179 struct onfs_args
*oargs
);
182 * Calculate the buffer I/O block size to use. The maximum V2 block size
183 * is typically 8K, the maximum datagram size is typically 16K, and the
184 * maximum V3 block size is typically 32K. The buffer cache tends to work
185 * best with 16K blocks but we allow 32K for TCP connections.
187 * We force the block size to be at least a page for buffer cache efficiency.
190 nfs_iosize(int v3
, int sotype
)
196 if (sotype
== SOCK_STREAM
)
199 iomax
= NFS_MAXDGRAMDATA
;
201 iomax
= NFS_V2MAXDATA
;
203 if ((iosize
= nfs_io_size
) > iomax
)
205 if (iosize
< PAGE_SIZE
)
209 * This is an aweful hack but until the buffer cache is rewritten
210 * we need it. The problem is that when you combine write() with
211 * mmap() the vm_page->valid bits can become weird looking
212 * (e.g. 0xfc). This occurs because NFS uses piecemeal buffers
213 * at the file EOF. To solve the problem the BIO system needs to
214 * be guarenteed that the NFS iosize for regular files will be a
215 * multiple of PAGE_SIZE so it can invalidate the whole page
216 * rather then just the piece of it owned by the buffer when
217 * NFS does vinvalbuf() calls.
219 if (iosize
& PAGE_MASK
)
220 iosize
= (iosize
& ~PAGE_MASK
) + PAGE_SIZE
;
225 nfs_convert_oargs(struct nfs_args
*args
, struct onfs_args
*oargs
)
227 args
->version
= NFS_ARGSVERSION
;
228 args
->addr
= oargs
->addr
;
229 args
->addrlen
= oargs
->addrlen
;
230 args
->sotype
= oargs
->sotype
;
231 args
->proto
= oargs
->proto
;
232 args
->fh
= oargs
->fh
;
233 args
->fhsize
= oargs
->fhsize
;
234 args
->flags
= oargs
->flags
;
235 args
->wsize
= oargs
->wsize
;
236 args
->rsize
= oargs
->rsize
;
237 args
->readdirsize
= oargs
->readdirsize
;
238 args
->timeo
= oargs
->timeo
;
239 args
->retrans
= oargs
->retrans
;
240 args
->maxgrouplist
= oargs
->maxgrouplist
;
241 args
->readahead
= oargs
->readahead
;
242 args
->deadthresh
= oargs
->deadthresh
;
243 args
->hostname
= oargs
->hostname
;
247 nfs_convert_diskless(void)
251 bcopy(&nfs_diskless
.myif
, &nfsv3_diskless
.myif
,
252 sizeof(struct ifaliasreq
));
253 bcopy(&nfs_diskless
.mygateway
, &nfsv3_diskless
.mygateway
,
254 sizeof(struct sockaddr_in
));
255 nfs_convert_oargs(&nfsv3_diskless
.swap_args
,&nfs_diskless
.swap_args
);
257 bcopy(nfs_diskless
.swap_fh
,nfsv3_diskless
.swap_fh
,NFSX_V2FH
);
258 nfsv3_diskless
.swap_fhsize
= NFSX_V2FH
;
259 for (i
= NFSX_V2FH
- 1; i
>= 0; --i
) {
260 if (nfs_diskless
.swap_fh
[i
])
264 nfsv3_diskless
.swap_fhsize
= 0;
266 bcopy(&nfs_diskless
.swap_saddr
,&nfsv3_diskless
.swap_saddr
,
267 sizeof(struct sockaddr_in
));
268 bcopy(nfs_diskless
.swap_hostnam
,nfsv3_diskless
.swap_hostnam
, MNAMELEN
);
269 nfsv3_diskless
.swap_nblks
= nfs_diskless
.swap_nblks
;
270 bcopy(&nfs_diskless
.swap_ucred
, &nfsv3_diskless
.swap_ucred
,
271 sizeof(struct ucred
));
272 nfs_convert_oargs(&nfsv3_diskless
.root_args
,&nfs_diskless
.root_args
);
274 bcopy(nfs_diskless
.root_fh
,nfsv3_diskless
.root_fh
,NFSX_V2FH
);
275 nfsv3_diskless
.root_fhsize
= NFSX_V2FH
;
276 for (i
= NFSX_V2FH
- 1; i
>= 0; --i
) {
277 if (nfs_diskless
.root_fh
[i
])
281 nfsv3_diskless
.root_fhsize
= 0;
283 bcopy(&nfs_diskless
.root_saddr
,&nfsv3_diskless
.root_saddr
,
284 sizeof(struct sockaddr_in
));
285 bcopy(nfs_diskless
.root_hostnam
,nfsv3_diskless
.root_hostnam
, MNAMELEN
);
286 nfsv3_diskless
.root_time
= nfs_diskless
.root_time
;
287 bcopy(nfs_diskless
.my_hostnam
,nfsv3_diskless
.my_hostnam
,
289 nfs_diskless_valid
= 3;
296 nfs_statfs(struct mount
*mp
, struct statfs
*sbp
, struct ucred
*cred
)
299 struct nfs_statfs
*sfp
;
300 struct nfsmount
*nmp
= VFSTONFS(mp
);
301 thread_t td
= curthread
;
302 int error
= 0, retattr
;
305 struct nfsm_info info
;
308 info
.v3
= (nmp
->nm_flag
& NFSMNT_NFSV3
);
313 error
= nfs_nget(mp
, (nfsfh_t
*)nmp
->nm_fh
, nmp
->nm_fhsize
, &np
);
317 /* ignore the passed cred */
319 cred
->cr_ngroups
= 1;
320 if (info
.v3
&& (nmp
->nm_state
& NFSSTA_GOTFSINFO
) == 0)
321 (void)nfs_fsinfo(nmp
, vp
, td
);
322 nfsstats
.rpccnt
[NFSPROC_FSSTAT
]++;
323 nfsm_reqhead(&info
, vp
, NFSPROC_FSSTAT
, NFSX_FH(info
.v3
));
324 ERROROUT(nfsm_fhtom(&info
, vp
));
325 NEGKEEPOUT(nfsm_request(&info
, vp
, NFSPROC_FSSTAT
, td
, cred
, &error
));
327 ERROROUT(nfsm_postop_attr(&info
, vp
, &retattr
,
328 NFS_LATTR_NOSHRINK
));
331 if (info
.mrep
!= NULL
)
335 NULLOUT(sfp
= nfsm_dissect(&info
, NFSX_STATFS(info
.v3
)));
336 sbp
->f_flags
= nmp
->nm_flag
;
339 sbp
->f_bsize
= NFS_FABLKSIZE
;
340 tquad
= fxdr_hyper(&sfp
->sf_tbytes
);
341 sbp
->f_blocks
= (long)(tquad
/ ((u_quad_t
)NFS_FABLKSIZE
));
342 tquad
= fxdr_hyper(&sfp
->sf_fbytes
);
343 sbp
->f_bfree
= (long)(tquad
/ ((u_quad_t
)NFS_FABLKSIZE
));
344 tquad
= fxdr_hyper(&sfp
->sf_abytes
);
345 sbp
->f_bavail
= (long)(tquad
/ ((u_quad_t
)NFS_FABLKSIZE
));
346 sbp
->f_files
= (fxdr_unsigned(int32_t,
347 sfp
->sf_tfiles
.nfsuquad
[1]) & 0x7fffffff);
348 sbp
->f_ffree
= (fxdr_unsigned(int32_t,
349 sfp
->sf_ffiles
.nfsuquad
[1]) & 0x7fffffff);
351 sbp
->f_bsize
= fxdr_unsigned(int32_t, sfp
->sf_bsize
);
352 sbp
->f_blocks
= fxdr_unsigned(int32_t, sfp
->sf_blocks
);
353 sbp
->f_bfree
= fxdr_unsigned(int32_t, sfp
->sf_bfree
);
354 sbp
->f_bavail
= fxdr_unsigned(int32_t, sfp
->sf_bavail
);
360 * Some values are pre-set in mnt_stat. Note in particular f_iosize
361 * cannot be changed once the filesystem is mounted as it is used
362 * as the basis for BIOs.
364 if (sbp
!= &mp
->mnt_stat
) {
365 sbp
->f_type
= mp
->mnt_vfc
->vfc_typenum
;
366 bcopy(mp
->mnt_stat
.f_mntfromname
, sbp
->f_mntfromname
, MNAMELEN
);
367 sbp
->f_iosize
= mp
->mnt_stat
.f_iosize
;
378 nfs_statvfs(struct mount
*mp
, struct statvfs
*sbp
, struct ucred
*cred
)
381 struct nfs_statfs
*sfp
;
382 struct nfsmount
*nmp
= VFSTONFS(mp
);
383 thread_t td
= curthread
;
384 int error
= 0, retattr
;
386 struct nfsm_info info
;
389 info
.v3
= (nmp
->nm_flag
& NFSMNT_NFSV3
);
394 error
= nfs_nget(mp
, (nfsfh_t
*)nmp
->nm_fh
, nmp
->nm_fhsize
, &np
);
398 /* ignore the passed cred */
400 cred
->cr_ngroups
= 1;
401 if (info
.v3
&& (nmp
->nm_state
& NFSSTA_GOTFSINFO
) == 0)
402 (void)nfs_fsinfo(nmp
, vp
, td
);
403 nfsstats
.rpccnt
[NFSPROC_FSSTAT
]++;
404 nfsm_reqhead(&info
, vp
, NFSPROC_FSSTAT
, NFSX_FH(info
.v3
));
405 ERROROUT(nfsm_fhtom(&info
, vp
));
406 NEGKEEPOUT(nfsm_request(&info
, vp
, NFSPROC_FSSTAT
, td
, cred
, &error
));
408 ERROROUT(nfsm_postop_attr(&info
, vp
, &retattr
,
409 NFS_LATTR_NOSHRINK
));
412 if (info
.mrep
!= NULL
)
416 NULLOUT(sfp
= nfsm_dissect(&info
, NFSX_STATFS(info
.v3
)));
417 sbp
->f_flag
= nmp
->nm_flag
;
418 sbp
->f_owner
= nmp
->nm_cred
->cr_ruid
;
421 sbp
->f_bsize
= NFS_FABLKSIZE
;
422 sbp
->f_frsize
= NFS_FABLKSIZE
;
423 sbp
->f_blocks
= (fxdr_hyper(&sfp
->sf_tbytes
) /
424 ((u_quad_t
)NFS_FABLKSIZE
));
425 sbp
->f_bfree
= (fxdr_hyper(&sfp
->sf_fbytes
) /
426 ((u_quad_t
)NFS_FABLKSIZE
));
427 sbp
->f_bavail
= (fxdr_hyper(&sfp
->sf_abytes
) /
428 ((u_quad_t
)NFS_FABLKSIZE
));
429 sbp
->f_files
= fxdr_hyper(&sfp
->sf_tfiles
);
430 sbp
->f_ffree
= fxdr_hyper(&sfp
->sf_ffiles
);
431 sbp
->f_favail
= fxdr_hyper(&sfp
->sf_afiles
);
433 sbp
->f_bsize
= fxdr_unsigned(int32_t, sfp
->sf_bsize
);
434 sbp
->f_blocks
= fxdr_unsigned(int32_t, sfp
->sf_blocks
);
435 sbp
->f_bfree
= fxdr_unsigned(int32_t, sfp
->sf_bfree
);
436 sbp
->f_bavail
= fxdr_unsigned(int32_t, sfp
->sf_bavail
);
441 sbp
->f_syncreads
= 0;
442 sbp
->f_syncwrites
= 0;
443 sbp
->f_asyncreads
= 0;
444 sbp
->f_asyncwrites
= 0;
445 sbp
->f_type
= mp
->mnt_vfc
->vfc_typenum
;
456 * nfs version 3 fsinfo rpc call
459 nfs_fsinfo(struct nfsmount
*nmp
, struct vnode
*vp
, struct thread
*td
)
461 struct nfsv3_fsinfo
*fsp
;
463 int error
= 0, retattr
;
465 struct nfsm_info info
;
468 nfsstats
.rpccnt
[NFSPROC_FSINFO
]++;
469 nfsm_reqhead(&info
, vp
, NFSPROC_FSINFO
, NFSX_FH(1));
470 ERROROUT(nfsm_fhtom(&info
, vp
));
471 NEGKEEPOUT(nfsm_request(&info
, vp
, NFSPROC_FSINFO
, td
,
472 nfs_vpcred(vp
, ND_READ
), &error
));
473 ERROROUT(nfsm_postop_attr(&info
, vp
, &retattr
, NFS_LATTR_NOSHRINK
));
475 NULLOUT(fsp
= nfsm_dissect(&info
, NFSX_V3FSINFO
));
476 pref
= fxdr_unsigned(u_int32_t
, fsp
->fs_wtpref
);
477 if (pref
< nmp
->nm_wsize
&& pref
>= NFS_FABLKSIZE
)
478 nmp
->nm_wsize
= (pref
+ NFS_FABLKSIZE
- 1) &
479 ~(NFS_FABLKSIZE
- 1);
480 max
= fxdr_unsigned(u_int32_t
, fsp
->fs_wtmax
);
481 if (max
< nmp
->nm_wsize
&& max
> 0) {
482 nmp
->nm_wsize
= max
& ~(NFS_FABLKSIZE
- 1);
483 if (nmp
->nm_wsize
== 0)
486 pref
= fxdr_unsigned(u_int32_t
, fsp
->fs_rtpref
);
487 if (pref
< nmp
->nm_rsize
&& pref
>= NFS_FABLKSIZE
)
488 nmp
->nm_rsize
= (pref
+ NFS_FABLKSIZE
- 1) &
489 ~(NFS_FABLKSIZE
- 1);
490 max
= fxdr_unsigned(u_int32_t
, fsp
->fs_rtmax
);
491 if (max
< nmp
->nm_rsize
&& max
> 0) {
492 nmp
->nm_rsize
= max
& ~(NFS_FABLKSIZE
- 1);
493 if (nmp
->nm_rsize
== 0)
496 pref
= fxdr_unsigned(u_int32_t
, fsp
->fs_dtpref
);
497 if (pref
< nmp
->nm_readdirsize
&& pref
>= NFS_DIRBLKSIZ
)
498 nmp
->nm_readdirsize
= (pref
+ NFS_DIRBLKSIZ
- 1) &
499 ~(NFS_DIRBLKSIZ
- 1);
500 if (max
< nmp
->nm_readdirsize
&& max
> 0) {
501 nmp
->nm_readdirsize
= max
& ~(NFS_DIRBLKSIZ
- 1);
502 if (nmp
->nm_readdirsize
== 0)
503 nmp
->nm_readdirsize
= max
;
505 maxfsize
= fxdr_hyper(&fsp
->fs_maxfilesize
);
506 if (maxfsize
> 0 && maxfsize
< nmp
->nm_maxfilesize
)
507 nmp
->nm_maxfilesize
= maxfsize
;
508 nmp
->nm_state
|= NFSSTA_GOTFSINFO
;
511 * Use the smaller of rsize/wsize for the biosize.
513 if (nmp
->nm_rsize
< nmp
->nm_wsize
)
514 nmp
->nm_mountp
->mnt_stat
.f_iosize
= nmp
->nm_rsize
;
516 nmp
->nm_mountp
->mnt_stat
.f_iosize
= nmp
->nm_wsize
;
525 * Mount a remote root fs via. nfs. This depends on the info in the
526 * nfs_diskless structure that has been filled in properly by some primary
528 * It goes something like this:
529 * - do enough of "ifconfig" by calling ifioctl() so that the system
530 * can talk to the server
531 * - If nfs_diskless.mygateway is filled in, use that address as
533 * - build the rootfs mount point and call mountnfs() to do the rest.
536 nfs_mountroot(struct mount
*mp
)
538 struct mount
*swap_mp
;
539 struct nfsv3_diskless
*nd
= &nfsv3_diskless
;
542 struct thread
*td
= curthread
; /* XXX */
547 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
548 bootpc_init(); /* use bootp to get nfs_diskless filled in */
552 * XXX time must be non-zero when we init the interface or else
553 * the arp code will wedge...
555 while (mycpu
->gd_time_seconds
== 0)
556 tsleep(mycpu
, 0, "arpkludge", 10);
559 * The boot code may have passed us a diskless structure.
561 if (nfs_diskless_valid
== 1)
562 nfs_convert_diskless();
564 #define SINP(sockaddr) ((struct sockaddr_in *)(sockaddr))
565 kprintf("nfs_mountroot: interface %s ip %s",
567 inet_ntoa(SINP(&nd
->myif
.ifra_addr
)->sin_addr
));
569 inet_ntoa(SINP(&nd
->myif
.ifra_broadaddr
)->sin_addr
));
570 kprintf(" mask %s\n",
571 inet_ntoa(SINP(&nd
->myif
.ifra_mask
)->sin_addr
));
575 * XXX splnet, so networks will receive...
580 * BOOTP does not necessarily have to be compiled into the kernel
581 * for an NFS root to work. If we inherited the network
582 * configuration for PXEBOOT then pxe_setup_nfsdiskless() has figured
583 * out our interface for us and all we need to do is ifconfig the
584 * interface. We only do this if the interface has not already been
585 * ifconfig'd by e.g. BOOTP.
587 error
= socreate(nd
->myif
.ifra_addr
.sa_family
, &so
, SOCK_DGRAM
, 0, td
);
589 panic("nfs_mountroot: socreate(%04x): %d",
590 nd
->myif
.ifra_addr
.sa_family
, error
);
593 error
= ifioctl(so
, SIOCAIFADDR
, (caddr_t
)&nd
->myif
, proc0
.p_ucred
);
595 panic("nfs_mountroot: SIOCAIFADDR: %d", error
);
597 soclose(so
, FNONBLOCK
);
600 * If the gateway field is filled in, set it as the default route.
602 if (nd
->mygateway
.sin_len
!= 0) {
603 struct sockaddr_in mask
, sin
;
605 bzero((caddr_t
)&mask
, sizeof(mask
));
607 sin
.sin_family
= AF_INET
;
608 sin
.sin_len
= sizeof(sin
);
609 kprintf("nfs_mountroot: gateway %s\n",
610 inet_ntoa(nd
->mygateway
.sin_addr
));
611 error
= rtrequest_global(RTM_ADD
, (struct sockaddr
*)&sin
,
612 (struct sockaddr
*)&nd
->mygateway
,
613 (struct sockaddr
*)&mask
,
614 RTF_UP
| RTF_GATEWAY
);
616 kprintf("nfs_mountroot: unable to set gateway, error %d, continuing anyway\n", error
);
620 * Create the rootfs mount point.
622 nd
->root_args
.fh
= nd
->root_fh
;
623 nd
->root_args
.fhsize
= nd
->root_fhsize
;
624 l
= ntohl(nd
->root_saddr
.sin_addr
.s_addr
);
625 ksnprintf(buf
, sizeof(buf
), "%ld.%ld.%ld.%ld:%s",
626 (l
>> 24) & 0xff, (l
>> 16) & 0xff,
627 (l
>> 8) & 0xff, (l
>> 0) & 0xff,nd
->root_hostnam
);
628 kprintf("NFS_ROOT: %s\n",buf
);
629 if ((error
= nfs_mountdiskless(buf
, "/", MNT_RDONLY
,
630 &nd
->root_saddr
, &nd
->root_args
, td
, &vp
, &mp
)) != 0) {
631 mp
->mnt_vfc
->vfc_refcount
--;
637 if (nd
->swap_nblks
) {
639 /* Convert to DEV_BSIZE instead of Kilobyte */
643 * Create a fake mount point just for the swap vnode so that the
644 * swap file can be on a different server from the rootfs.
646 nd
->swap_args
.fh
= nd
->swap_fh
;
647 nd
->swap_args
.fhsize
= nd
->swap_fhsize
;
648 l
= ntohl(nd
->swap_saddr
.sin_addr
.s_addr
);
649 ksnprintf(buf
, sizeof(buf
), "%ld.%ld.%ld.%ld:%s",
650 (l
>> 24) & 0xff, (l
>> 16) & 0xff,
651 (l
>> 8) & 0xff, (l
>> 0) & 0xff,nd
->swap_hostnam
);
652 kprintf("NFS SWAP: %s\n",buf
);
653 if ((error
= nfs_mountdiskless(buf
, "/swap", 0,
654 &nd
->swap_saddr
, &nd
->swap_args
, td
, &vp
, &swap_mp
)) != 0) {
660 VTONFS(vp
)->n_size
= VTONFS(vp
)->n_vattr
.va_size
=
661 nd
->swap_nblks
* DEV_BSIZE
;
664 * Since the swap file is not the root dir of a file system,
665 * hack it to a regular file.
667 vclrflags(vp
, VROOT
);
669 nfs_setvtype(vp
, VREG
);
670 swaponvp(td
, vp
, nd
->swap_nblks
);
673 mp
->mnt_flag
|= MNT_ROOTFS
;
677 * This is not really an nfs issue, but it is much easier to
678 * set hostname here and then let the "/etc/rc.xxx" files
679 * mount the right /var based upon its preset value.
681 bcopy(nd
->my_hostnam
, hostname
, MAXHOSTNAMELEN
);
682 hostname
[MAXHOSTNAMELEN
- 1] = '\0';
683 for (i
= 0; i
< MAXHOSTNAMELEN
; i
++)
684 if (hostname
[i
] == '\0')
686 inittodr(ntohl(nd
->root_time
));
692 * Internal version of mount system call for diskless setup.
695 nfs_mountdiskless(char *path
, char *which
, int mountflag
,
696 struct sockaddr_in
*sin
, struct nfs_args
*args
, struct thread
*td
,
697 struct vnode
**vpp
, struct mount
**mpp
)
700 struct sockaddr
*nam
;
707 if ((error
= vfs_rootmountalloc("nfs", path
, &mp
)) != 0) {
708 kprintf("nfs_mountroot: NFS not configured");
713 mp
->mnt_kern_flag
= 0;
714 mp
->mnt_flag
= mountflag
;
715 nam
= dup_sockaddr((struct sockaddr
*)sin
);
717 #if defined(BOOTP) || defined(NFS_ROOT)
718 if (args
->fhsize
== 0) {
721 kprintf("NFS_ROOT: No FH passed from loader, attempting mount rpc...");
722 while (*xpath
&& *xpath
!= ':')
727 error
= md_mount(sin
, xpath
, args
->fh
, &args
->fhsize
, args
, td
);
729 kprintf("failed error %d.\n", error
);
732 kprintf("success!\n");
736 if ((error
= mountnfs(args
, mp
, nam
, which
, path
, vpp
)) != 0) {
737 #if defined(BOOTP) || defined(NFS_ROOT)
740 kprintf("nfs_mountroot: mount %s on %s: %d", path
, which
, error
);
741 mp
->mnt_vfc
->vfc_refcount
--;
753 nfs_decode_args(struct nfsmount
*nmp
, struct nfs_args
*argp
)
760 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
761 * no sense in that context.
763 if (nmp
->nm_sotype
== SOCK_STREAM
)
764 nmp
->nm_flag
&= ~NFSMNT_NOCONN
;
766 /* Also clear RDIRPLUS if not NFSv3, it crashes some servers */
767 if ((argp
->flags
& NFSMNT_NFSV3
) == 0)
768 nmp
->nm_flag
&= ~NFSMNT_RDIRPLUS
;
771 * Re-bind if rsrvd port flag has changed
773 adjsock
= (nmp
->nm_flag
& NFSMNT_RESVPORT
) !=
774 (argp
->flags
& NFSMNT_RESVPORT
);
776 /* Update flags atomically. Don't change the lock bits. */
777 nmp
->nm_flag
= argp
->flags
| nmp
->nm_flag
;
780 if ((argp
->flags
& NFSMNT_TIMEO
) && argp
->timeo
> 0) {
781 nmp
->nm_timeo
= (argp
->timeo
* NFS_HZ
+ 5) / 10;
782 if (nmp
->nm_timeo
< NFS_MINTIMEO
)
783 nmp
->nm_timeo
= NFS_MINTIMEO
;
784 else if (nmp
->nm_timeo
> NFS_MAXTIMEO
)
785 nmp
->nm_timeo
= NFS_MAXTIMEO
;
788 if ((argp
->flags
& NFSMNT_RETRANS
) && argp
->retrans
> 1) {
789 nmp
->nm_retry
= argp
->retrans
;
790 if (nmp
->nm_retry
> NFS_MAXREXMIT
)
791 nmp
->nm_retry
= NFS_MAXREXMIT
;
795 * These parameters effect the buffer cache and cannot be changed
796 * once we've successfully mounted.
798 if ((nmp
->nm_state
& NFSSTA_GOTFSINFO
) == 0) {
799 maxio
= nfs_iosize(argp
->flags
& NFSMNT_NFSV3
, nmp
->nm_sotype
);
801 if ((argp
->flags
& NFSMNT_WSIZE
) && argp
->wsize
> 0) {
802 nmp
->nm_wsize
= argp
->wsize
;
803 /* Round down to multiple of blocksize */
804 nmp
->nm_wsize
&= ~(NFS_FABLKSIZE
- 1);
805 if (nmp
->nm_wsize
<= 0)
806 nmp
->nm_wsize
= NFS_FABLKSIZE
;
808 if (nmp
->nm_wsize
> maxio
)
809 nmp
->nm_wsize
= maxio
;
810 if (nmp
->nm_wsize
> MAXBSIZE
)
811 nmp
->nm_wsize
= MAXBSIZE
;
813 if ((argp
->flags
& NFSMNT_RSIZE
) && argp
->rsize
> 0) {
814 nmp
->nm_rsize
= argp
->rsize
;
815 /* Round down to multiple of blocksize */
816 nmp
->nm_rsize
&= ~(NFS_FABLKSIZE
- 1);
817 if (nmp
->nm_rsize
<= 0)
818 nmp
->nm_rsize
= NFS_FABLKSIZE
;
820 if (nmp
->nm_rsize
> maxio
)
821 nmp
->nm_rsize
= maxio
;
822 if (nmp
->nm_rsize
> MAXBSIZE
)
823 nmp
->nm_rsize
= MAXBSIZE
;
825 if ((argp
->flags
& NFSMNT_READDIRSIZE
) &&
826 argp
->readdirsize
> 0) {
827 nmp
->nm_readdirsize
= argp
->readdirsize
;
829 if (nmp
->nm_readdirsize
> maxio
)
830 nmp
->nm_readdirsize
= maxio
;
831 if (nmp
->nm_readdirsize
> nmp
->nm_rsize
)
832 nmp
->nm_readdirsize
= nmp
->nm_rsize
;
835 if ((argp
->flags
& NFSMNT_ACREGMIN
) && argp
->acregmin
>= 0)
836 nmp
->nm_acregmin
= argp
->acregmin
;
838 nmp
->nm_acregmin
= NFS_MINATTRTIMO
;
839 if ((argp
->flags
& NFSMNT_ACREGMAX
) && argp
->acregmax
>= 0)
840 nmp
->nm_acregmax
= argp
->acregmax
;
842 nmp
->nm_acregmax
= NFS_MAXATTRTIMO
;
843 if ((argp
->flags
& NFSMNT_ACDIRMIN
) && argp
->acdirmin
>= 0)
844 nmp
->nm_acdirmin
= argp
->acdirmin
;
846 nmp
->nm_acdirmin
= NFS_MINDIRATTRTIMO
;
847 if ((argp
->flags
& NFSMNT_ACDIRMAX
) && argp
->acdirmax
>= 0)
848 nmp
->nm_acdirmax
= argp
->acdirmax
;
850 nmp
->nm_acdirmax
= NFS_MAXDIRATTRTIMO
;
851 if (nmp
->nm_acdirmin
> nmp
->nm_acdirmax
)
852 nmp
->nm_acdirmin
= nmp
->nm_acdirmax
;
853 if (nmp
->nm_acregmin
> nmp
->nm_acregmax
)
854 nmp
->nm_acregmin
= nmp
->nm_acregmax
;
856 if ((argp
->flags
& NFSMNT_MAXGRPS
) && argp
->maxgrouplist
>= 0) {
857 if (argp
->maxgrouplist
<= NFS_MAXGRPS
)
858 nmp
->nm_numgrps
= argp
->maxgrouplist
;
860 nmp
->nm_numgrps
= NFS_MAXGRPS
;
862 if ((argp
->flags
& NFSMNT_READAHEAD
) && argp
->readahead
>= 0) {
863 if (argp
->readahead
<= NFS_MAXRAHEAD
)
864 nmp
->nm_readahead
= argp
->readahead
;
866 nmp
->nm_readahead
= NFS_MAXRAHEAD
;
868 if ((argp
->flags
& NFSMNT_DEADTHRESH
) && argp
->deadthresh
>= 1) {
869 if (argp
->deadthresh
<= NFS_NEVERDEAD
)
870 nmp
->nm_deadthresh
= argp
->deadthresh
;
872 nmp
->nm_deadthresh
= NFS_NEVERDEAD
;
875 if (nmp
->nm_so
&& adjsock
) {
876 nfs_safedisconnect(nmp
);
877 if (nmp
->nm_sotype
== SOCK_DGRAM
)
878 while (nfs_connect(nmp
, NULL
)) {
879 kprintf("nfs_args: retrying connect\n");
880 (void) tsleep((caddr_t
)&lbolt
, 0, "nfscon", 0);
889 * It seems a bit dumb to copyinstr() the host and path here and then
890 * bcopy() them in mountnfs(), but I wanted to detect errors before
891 * doing the sockargs() call because sockargs() allocates an mbuf and
892 * an error after that means that I have to release the mbuf.
896 nfs_mount(struct mount
*mp
, char *path
, caddr_t data
, struct ucred
*cred
)
899 struct nfs_args args
;
900 struct sockaddr
*nam
;
902 char pth
[MNAMELEN
], hst
[MNAMELEN
];
904 u_char nfh
[NFSX_V3FHMAX
];
910 error
= copyin(data
, (caddr_t
)&args
, sizeof (struct nfs_args
));
913 if (args
.version
!= NFS_ARGSVERSION
) {
914 #ifdef COMPAT_PRELITE2
916 * If the argument version is unknown, then assume the
917 * caller is a pre-lite2 4.4BSD client and convert its
920 struct onfs_args oargs
;
921 error
= copyin(data
, (caddr_t
)&oargs
, sizeof (struct onfs_args
));
924 nfs_convert_oargs(&args
,&oargs
);
925 #else /* !COMPAT_PRELITE2 */
926 return (EPROGMISMATCH
);
927 #endif /* COMPAT_PRELITE2 */
929 if (mp
->mnt_flag
& MNT_UPDATE
) {
930 struct nfsmount
*nmp
= VFSTONFS(mp
);
935 * When doing an update, we can't change from or to
936 * v3, or change cookie translation, or rsize or wsize.
938 args
.flags
&= ~(NFSMNT_NFSV3
| NFSMNT_RSIZE
| NFSMNT_WSIZE
);
939 args
.flags
|= nmp
->nm_flag
& (NFSMNT_NFSV3
);
940 nfs_decode_args(nmp
, &args
);
945 * Make the nfs_ip_paranoia sysctl serve as the default connection
946 * or no-connection mode for those protocols that support
947 * no-connection mode (the flag will be cleared later for protocols
948 * that do not support no-connection mode). This will allow a client
949 * to receive replies from a different IP then the request was
950 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
953 if (nfs_ip_paranoia
== 0)
954 args
.flags
|= NFSMNT_NOCONN
;
955 if (args
.fhsize
< 0 || args
.fhsize
> NFSX_V3FHMAX
)
957 error
= copyin((caddr_t
)args
.fh
, (caddr_t
)nfh
, args
.fhsize
);
960 error
= copyinstr(path
, pth
, MNAMELEN
-1, &len
);
963 bzero(&pth
[len
], MNAMELEN
- len
);
964 error
= copyinstr(args
.hostname
, hst
, MNAMELEN
-1, &len
);
967 bzero(&hst
[len
], MNAMELEN
- len
);
968 /* sockargs() call must be after above copyin() calls */
969 error
= getsockaddr(&nam
, (caddr_t
)args
.addr
, args
.addrlen
);
973 error
= mountnfs(&args
, mp
, nam
, pth
, hst
, &vp
);
978 * Common code for mount and mountroot
981 mountnfs(struct nfs_args
*argp
, struct mount
*mp
, struct sockaddr
*nam
,
982 char *pth
, char *hst
, struct vnode
**vpp
)
984 struct nfsmount
*nmp
;
990 if (mp
->mnt_flag
& MNT_UPDATE
) {
992 /* update paths, file handles, etc, here XXX */
996 nmp
= zalloc(nfsmount_zone
);
997 bzero((caddr_t
)nmp
, sizeof (struct nfsmount
));
998 mtx_init(&nmp
->nm_rxlock
);
999 mtx_init(&nmp
->nm_txlock
);
1000 TAILQ_INIT(&nmp
->nm_uidlruhead
);
1001 TAILQ_INIT(&nmp
->nm_bioq
);
1002 TAILQ_INIT(&nmp
->nm_reqq
);
1003 TAILQ_INIT(&nmp
->nm_reqtxq
);
1004 TAILQ_INIT(&nmp
->nm_reqrxq
);
1005 mp
->mnt_data
= (qaddr_t
)nmp
;
1008 nmp
->nm_mountp
= mp
;
1011 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1012 * high, depending on whether we end up with negative offsets in
1013 * the client or server somewhere. 2GB-1 may be safer.
1015 * For V3, nfs_fsinfo will adjust this as necessary. Assume maximum
1016 * that we can handle until we find out otherwise.
1017 * XXX Our "safe" limit on the client is what we can store in our
1018 * buffer cache using signed(!) block numbers.
1020 if ((argp
->flags
& NFSMNT_NFSV3
) == 0)
1021 nmp
->nm_maxfilesize
= 0xffffffffLL
;
1023 nmp
->nm_maxfilesize
= (u_int64_t
)0x80000000 * DEV_BSIZE
- 1;
1025 nmp
->nm_timeo
= NFS_TIMEO
;
1026 nmp
->nm_retry
= NFS_RETRANS
;
1027 nmp
->nm_wsize
= nfs_iosize(argp
->flags
& NFSMNT_NFSV3
, argp
->sotype
);
1028 nmp
->nm_rsize
= nmp
->nm_wsize
;
1029 nmp
->nm_readdirsize
= NFS_READDIRSIZE
;
1030 nmp
->nm_numgrps
= NFS_MAXGRPS
;
1031 nmp
->nm_readahead
= NFS_DEFRAHEAD
;
1032 nmp
->nm_deadthresh
= NFS_DEADTHRESH
;
1033 nmp
->nm_fhsize
= argp
->fhsize
;
1034 bcopy((caddr_t
)argp
->fh
, (caddr_t
)nmp
->nm_fh
, argp
->fhsize
);
1035 bcopy(hst
, mp
->mnt_stat
.f_mntfromname
, MNAMELEN
);
1037 /* Set up the sockets and per-host congestion */
1038 nmp
->nm_sotype
= argp
->sotype
;
1039 nmp
->nm_soproto
= argp
->proto
;
1040 nmp
->nm_cred
= crhold(proc0
.p_ucred
);
1042 nfs_decode_args(nmp
, argp
);
1045 * For Connection based sockets (TCP,...) defer the connect until
1046 * the first request, in case the server is not responding.
1048 if (nmp
->nm_sotype
== SOCK_DGRAM
&&
1049 (error
= nfs_connect(nmp
, NULL
)))
1053 * This is silly, but it has to be set so that vinifod() works.
1054 * We do not want to do an nfs_statfs() here since we can get
1055 * stuck on a dead server and we are holding a lock on the mount
1058 mp
->mnt_stat
.f_iosize
=
1059 nfs_iosize(nmp
->nm_flag
& NFSMNT_NFSV3
, nmp
->nm_sotype
);
1062 * Install vop_ops for our vnops
1064 vfs_add_vnodeops(mp
, &nfsv2_vnode_vops
, &mp
->mnt_vn_norm_ops
);
1065 vfs_add_vnodeops(mp
, &nfsv2_spec_vops
, &mp
->mnt_vn_spec_ops
);
1066 vfs_add_vnodeops(mp
, &nfsv2_fifo_vops
, &mp
->mnt_vn_fifo_ops
);
1069 * A reference count is needed on the nfsnode representing the
1070 * remote root. If this object is not persistent, then backward
1071 * traversals of the mount point (i.e. "..") will not work if
1072 * the nfsnode gets flushed out of the cache. Ufs does not have
1073 * this problem, because one can identify root inodes by their
1074 * number == ROOTINO (2).
1076 error
= nfs_nget(mp
, (nfsfh_t
*)nmp
->nm_fh
, nmp
->nm_fhsize
, &np
);
1082 * Retrieval of mountpoint attributes is delayed until nfs_rot
1083 * or nfs_statfs are first called. This will happen either when
1084 * we first traverse the mount point or if somebody does a df(1).
1086 * NFSSTA_GOTFSINFO is used to flag if we have successfully
1087 * retrieved mountpoint attributes. In the case of NFSv3 we
1088 * also flag static fsinfo.
1091 (*vpp
)->v_type
= VNON
;
1094 * Lose the lock but keep the ref.
1097 TAILQ_INSERT_TAIL(&nfs_mountq
, nmp
, nm_entry
);
1121 * Start the reader and writer threads.
1123 lwkt_create(nfssvc_iod_reader
, nmp
, &nmp
->nm_rxthread
,
1124 NULL
, 0, rxcpu
, "nfsiod_rx");
1125 lwkt_create(nfssvc_iod_writer
, nmp
, &nmp
->nm_txthread
,
1126 NULL
, 0, txcpu
, "nfsiod_tx");
1130 nfs_disconnect(nmp
);
1131 nfs_free_mount(nmp
);
1136 * unmount system call
1139 nfs_unmount(struct mount
*mp
, int mntflags
)
1141 struct nfsmount
*nmp
;
1142 int error
, flags
= 0;
1145 if (mntflags
& MNT_FORCE
) {
1146 flags
|= FORCECLOSE
;
1147 nmp
->nm_flag
|= NFSMNT_FORCE
;
1151 * Goes something like this..
1152 * - Call vflush() to clear out vnodes for this file system
1153 * - Close the socket
1154 * - Free up the data structures
1156 /* In the forced case, cancel any outstanding requests. */
1157 if (flags
& FORCECLOSE
) {
1158 error
= nfs_nmcancelreqs(nmp
);
1160 kprintf("NFS: %s: Unable to cancel all requests\n",
1161 mp
->mnt_stat
.f_mntfromname
);
1162 /* continue anyway */
1167 * Must handshake with nfs_clientd() if it is active. XXX
1169 nmp
->nm_state
|= NFSSTA_DISMINPROG
;
1172 * We hold 1 extra ref on the root vnode; see comment in mountnfs().
1174 * If this doesn't work and we are doing a forced unmount we continue
1177 error
= vflush(mp
, 1, flags
);
1179 nmp
->nm_state
&= ~NFSSTA_DISMINPROG
;
1180 if ((flags
& FORCECLOSE
) == 0)
1185 * We are now committed to the unmount.
1186 * For NQNFS, let the server daemon free the nfsmount structure.
1188 if (nmp
->nm_flag
& NFSMNT_KERB
)
1189 nmp
->nm_state
|= NFSSTA_DISMNT
;
1190 nfssvc_iod_stop1(nmp
);
1191 nfs_disconnect(nmp
);
1192 nfssvc_iod_stop2(nmp
);
1193 TAILQ_REMOVE(&nfs_mountq
, nmp
, nm_entry
);
1195 if ((nmp
->nm_flag
& NFSMNT_KERB
) == 0) {
1196 nfs_free_mount(nmp
);
1202 nfs_free_mount(struct nfsmount
*nmp
)
1205 crfree(nmp
->nm_cred
);
1206 nmp
->nm_cred
= NULL
;
1209 FREE(nmp
->nm_nam
, M_SONAME
);
1212 zfree(nfsmount_zone
, nmp
);
1216 * Return root of a filesystem
1219 nfs_root(struct mount
*mp
, struct vnode
**vpp
)
1222 struct nfsmount
*nmp
;
1228 error
= nfs_nget(mp
, (nfsfh_t
*)nmp
->nm_fh
, nmp
->nm_fhsize
, &np
);
1234 * Get transfer parameters and root vnode attributes
1236 * NOTE: nfs_fsinfo() is expected to override the default
1239 if ((nmp
->nm_state
& NFSSTA_GOTFSINFO
) == 0) {
1240 if (nmp
->nm_flag
& NFSMNT_NFSV3
) {
1241 mp
->mnt_stat
.f_iosize
= nfs_iosize(1, nmp
->nm_sotype
);
1242 error
= nfs_fsinfo(nmp
, vp
, curthread
);
1244 if ((error
= VOP_GETATTR(vp
, &attrs
)) == 0)
1245 nmp
->nm_state
|= NFSSTA_GOTFSINFO
;
1250 * The root vnode is usually cached by the namecache so do not
1251 * try to avoid going over the wire even if we have previous
1252 * information cached. A stale NFS mount can loop
1253 * forever resolving the root vnode if we return no-error when
1254 * there is in fact an error.
1256 np
->n_attrstamp
= 0;
1257 error
= VOP_GETATTR(vp
, &attrs
);
1259 if (vp
->v_type
== VNON
)
1260 nfs_setvtype(vp
, VDIR
);
1261 vsetflags(vp
, VROOT
);
1275 static int nfs_sync_scan1(struct mount
*mp
, struct vnode
*vp
, void *data
);
1276 static int nfs_sync_scan2(struct mount
*mp
, struct vnode
*vp
, void *data
);
1279 * Flush out the buffer cache
1283 nfs_sync(struct mount
*mp
, int waitfor
)
1285 struct scaninfo scaninfo
;
1288 scaninfo
.rescan
= 1;
1289 scaninfo
.waitfor
= waitfor
;
1290 scaninfo
.allerror
= 0;
1293 * Force stale buffer cache information to be flushed.
1296 while (error
== 0 && scaninfo
.rescan
) {
1297 scaninfo
.rescan
= 0;
1298 error
= vmntvnodescan(mp
, VMSC_GETVP
, nfs_sync_scan1
,
1299 nfs_sync_scan2
, &scaninfo
);
1305 nfs_sync_scan1(struct mount
*mp
, struct vnode
*vp
, void *data
)
1307 struct scaninfo
*info
= data
;
1309 if (vn_islocked(vp
) || RB_EMPTY(&vp
->v_rbdirty_tree
))
1311 if (info
->waitfor
== MNT_LAZY
)
1317 nfs_sync_scan2(struct mount
*mp
, struct vnode
*vp
, void *data
)
1319 struct scaninfo
*info
= data
;
1322 error
= VOP_FSYNC(vp
, info
->waitfor
, 0);
1324 info
->allerror
= error
;