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
;
337 sbp
->f_iosize
= nfs_iosize(info
.v3
, nmp
->nm_sotype
);
340 sbp
->f_bsize
= NFS_FABLKSIZE
;
341 tquad
= fxdr_hyper(&sfp
->sf_tbytes
);
342 sbp
->f_blocks
= (long)(tquad
/ ((u_quad_t
)NFS_FABLKSIZE
));
343 tquad
= fxdr_hyper(&sfp
->sf_fbytes
);
344 sbp
->f_bfree
= (long)(tquad
/ ((u_quad_t
)NFS_FABLKSIZE
));
345 tquad
= fxdr_hyper(&sfp
->sf_abytes
);
346 sbp
->f_bavail
= (long)(tquad
/ ((u_quad_t
)NFS_FABLKSIZE
));
347 sbp
->f_files
= (fxdr_unsigned(int32_t,
348 sfp
->sf_tfiles
.nfsuquad
[1]) & 0x7fffffff);
349 sbp
->f_ffree
= (fxdr_unsigned(int32_t,
350 sfp
->sf_ffiles
.nfsuquad
[1]) & 0x7fffffff);
352 sbp
->f_bsize
= fxdr_unsigned(int32_t, sfp
->sf_bsize
);
353 sbp
->f_blocks
= fxdr_unsigned(int32_t, sfp
->sf_blocks
);
354 sbp
->f_bfree
= fxdr_unsigned(int32_t, sfp
->sf_bfree
);
355 sbp
->f_bavail
= fxdr_unsigned(int32_t, sfp
->sf_bavail
);
359 if (sbp
!= &mp
->mnt_stat
) {
360 sbp
->f_type
= mp
->mnt_vfc
->vfc_typenum
;
361 bcopy(mp
->mnt_stat
.f_mntfromname
, sbp
->f_mntfromname
, MNAMELEN
);
372 nfs_statvfs(struct mount
*mp
, struct statvfs
*sbp
, struct ucred
*cred
)
375 struct nfs_statfs
*sfp
;
376 struct nfsmount
*nmp
= VFSTONFS(mp
);
377 thread_t td
= curthread
;
378 int error
= 0, retattr
;
380 struct nfsm_info info
;
383 info
.v3
= (nmp
->nm_flag
& NFSMNT_NFSV3
);
388 error
= nfs_nget(mp
, (nfsfh_t
*)nmp
->nm_fh
, nmp
->nm_fhsize
, &np
);
392 /* ignore the passed cred */
394 cred
->cr_ngroups
= 1;
395 if (info
.v3
&& (nmp
->nm_state
& NFSSTA_GOTFSINFO
) == 0)
396 (void)nfs_fsinfo(nmp
, vp
, td
);
397 nfsstats
.rpccnt
[NFSPROC_FSSTAT
]++;
398 nfsm_reqhead(&info
, vp
, NFSPROC_FSSTAT
, NFSX_FH(info
.v3
));
399 ERROROUT(nfsm_fhtom(&info
, vp
));
400 NEGKEEPOUT(nfsm_request(&info
, vp
, NFSPROC_FSSTAT
, td
, cred
, &error
));
402 ERROROUT(nfsm_postop_attr(&info
, vp
, &retattr
,
403 NFS_LATTR_NOSHRINK
));
406 if (info
.mrep
!= NULL
)
410 NULLOUT(sfp
= nfsm_dissect(&info
, NFSX_STATFS(info
.v3
)));
411 sbp
->f_flag
= nmp
->nm_flag
;
412 sbp
->f_owner
= nmp
->nm_cred
->cr_ruid
;
415 sbp
->f_bsize
= NFS_FABLKSIZE
;
416 sbp
->f_frsize
= NFS_FABLKSIZE
;
417 sbp
->f_blocks
= (fxdr_hyper(&sfp
->sf_tbytes
) /
418 ((u_quad_t
)NFS_FABLKSIZE
));
419 sbp
->f_bfree
= (fxdr_hyper(&sfp
->sf_fbytes
) /
420 ((u_quad_t
)NFS_FABLKSIZE
));
421 sbp
->f_bavail
= (fxdr_hyper(&sfp
->sf_abytes
) /
422 ((u_quad_t
)NFS_FABLKSIZE
));
423 sbp
->f_files
= fxdr_hyper(&sfp
->sf_tfiles
);
424 sbp
->f_ffree
= fxdr_hyper(&sfp
->sf_ffiles
);
425 sbp
->f_favail
= fxdr_hyper(&sfp
->sf_afiles
);
427 sbp
->f_bsize
= fxdr_unsigned(int32_t, sfp
->sf_bsize
);
428 sbp
->f_blocks
= fxdr_unsigned(int32_t, sfp
->sf_blocks
);
429 sbp
->f_bfree
= fxdr_unsigned(int32_t, sfp
->sf_bfree
);
430 sbp
->f_bavail
= fxdr_unsigned(int32_t, sfp
->sf_bavail
);
435 sbp
->f_syncreads
= 0;
436 sbp
->f_syncwrites
= 0;
437 sbp
->f_asyncreads
= 0;
438 sbp
->f_asyncwrites
= 0;
439 sbp
->f_type
= mp
->mnt_vfc
->vfc_typenum
;
450 * nfs version 3 fsinfo rpc call
453 nfs_fsinfo(struct nfsmount
*nmp
, struct vnode
*vp
, struct thread
*td
)
455 struct nfsv3_fsinfo
*fsp
;
457 int error
= 0, retattr
;
459 struct nfsm_info info
;
462 nfsstats
.rpccnt
[NFSPROC_FSINFO
]++;
463 nfsm_reqhead(&info
, vp
, NFSPROC_FSINFO
, NFSX_FH(1));
464 ERROROUT(nfsm_fhtom(&info
, vp
));
465 NEGKEEPOUT(nfsm_request(&info
, vp
, NFSPROC_FSINFO
, td
,
466 nfs_vpcred(vp
, ND_READ
), &error
));
467 ERROROUT(nfsm_postop_attr(&info
, vp
, &retattr
, NFS_LATTR_NOSHRINK
));
469 NULLOUT(fsp
= nfsm_dissect(&info
, NFSX_V3FSINFO
));
470 pref
= fxdr_unsigned(u_int32_t
, fsp
->fs_wtpref
);
471 if (pref
< nmp
->nm_wsize
&& pref
>= NFS_FABLKSIZE
)
472 nmp
->nm_wsize
= (pref
+ NFS_FABLKSIZE
- 1) &
473 ~(NFS_FABLKSIZE
- 1);
474 max
= fxdr_unsigned(u_int32_t
, fsp
->fs_wtmax
);
475 if (max
< nmp
->nm_wsize
&& max
> 0) {
476 nmp
->nm_wsize
= max
& ~(NFS_FABLKSIZE
- 1);
477 if (nmp
->nm_wsize
== 0)
480 pref
= fxdr_unsigned(u_int32_t
, fsp
->fs_rtpref
);
481 if (pref
< nmp
->nm_rsize
&& pref
>= NFS_FABLKSIZE
)
482 nmp
->nm_rsize
= (pref
+ NFS_FABLKSIZE
- 1) &
483 ~(NFS_FABLKSIZE
- 1);
484 max
= fxdr_unsigned(u_int32_t
, fsp
->fs_rtmax
);
485 if (max
< nmp
->nm_rsize
&& max
> 0) {
486 nmp
->nm_rsize
= max
& ~(NFS_FABLKSIZE
- 1);
487 if (nmp
->nm_rsize
== 0)
490 pref
= fxdr_unsigned(u_int32_t
, fsp
->fs_dtpref
);
491 if (pref
< nmp
->nm_readdirsize
&& pref
>= NFS_DIRBLKSIZ
)
492 nmp
->nm_readdirsize
= (pref
+ NFS_DIRBLKSIZ
- 1) &
493 ~(NFS_DIRBLKSIZ
- 1);
494 if (max
< nmp
->nm_readdirsize
&& max
> 0) {
495 nmp
->nm_readdirsize
= max
& ~(NFS_DIRBLKSIZ
- 1);
496 if (nmp
->nm_readdirsize
== 0)
497 nmp
->nm_readdirsize
= max
;
499 maxfsize
= fxdr_hyper(&fsp
->fs_maxfilesize
);
500 if (maxfsize
> 0 && maxfsize
< nmp
->nm_maxfilesize
)
501 nmp
->nm_maxfilesize
= maxfsize
;
502 nmp
->nm_state
|= NFSSTA_GOTFSINFO
;
511 * Mount a remote root fs via. nfs. This depends on the info in the
512 * nfs_diskless structure that has been filled in properly by some primary
514 * It goes something like this:
515 * - do enough of "ifconfig" by calling ifioctl() so that the system
516 * can talk to the server
517 * - If nfs_diskless.mygateway is filled in, use that address as
519 * - build the rootfs mount point and call mountnfs() to do the rest.
522 nfs_mountroot(struct mount
*mp
)
524 struct mount
*swap_mp
;
525 struct nfsv3_diskless
*nd
= &nfsv3_diskless
;
528 struct thread
*td
= curthread
; /* XXX */
533 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
534 bootpc_init(); /* use bootp to get nfs_diskless filled in */
538 * XXX time must be non-zero when we init the interface or else
539 * the arp code will wedge...
541 while (mycpu
->gd_time_seconds
== 0)
542 tsleep(mycpu
, 0, "arpkludge", 10);
545 * The boot code may have passed us a diskless structure.
547 if (nfs_diskless_valid
== 1)
548 nfs_convert_diskless();
550 #define SINP(sockaddr) ((struct sockaddr_in *)(sockaddr))
551 kprintf("nfs_mountroot: interface %s ip %s",
553 inet_ntoa(SINP(&nd
->myif
.ifra_addr
)->sin_addr
));
555 inet_ntoa(SINP(&nd
->myif
.ifra_broadaddr
)->sin_addr
));
556 kprintf(" mask %s\n",
557 inet_ntoa(SINP(&nd
->myif
.ifra_mask
)->sin_addr
));
561 * XXX splnet, so networks will receive...
566 * BOOTP does not necessarily have to be compiled into the kernel
567 * for an NFS root to work. If we inherited the network
568 * configuration for PXEBOOT then pxe_setup_nfsdiskless() has figured
569 * out our interface for us and all we need to do is ifconfig the
570 * interface. We only do this if the interface has not already been
571 * ifconfig'd by e.g. BOOTP.
573 error
= socreate(nd
->myif
.ifra_addr
.sa_family
, &so
, SOCK_DGRAM
, 0, td
);
575 panic("nfs_mountroot: socreate(%04x): %d",
576 nd
->myif
.ifra_addr
.sa_family
, error
);
579 error
= ifioctl(so
, SIOCAIFADDR
, (caddr_t
)&nd
->myif
, proc0
.p_ucred
);
581 panic("nfs_mountroot: SIOCAIFADDR: %d", error
);
583 soclose(so
, FNONBLOCK
);
586 * If the gateway field is filled in, set it as the default route.
588 if (nd
->mygateway
.sin_len
!= 0) {
589 struct sockaddr_in mask
, sin
;
591 bzero((caddr_t
)&mask
, sizeof(mask
));
593 sin
.sin_family
= AF_INET
;
594 sin
.sin_len
= sizeof(sin
);
595 kprintf("nfs_mountroot: gateway %s\n",
596 inet_ntoa(nd
->mygateway
.sin_addr
));
597 error
= rtrequest_global(RTM_ADD
, (struct sockaddr
*)&sin
,
598 (struct sockaddr
*)&nd
->mygateway
,
599 (struct sockaddr
*)&mask
,
600 RTF_UP
| RTF_GATEWAY
);
602 kprintf("nfs_mountroot: unable to set gateway, error %d, continuing anyway\n", error
);
606 * Create the rootfs mount point.
608 nd
->root_args
.fh
= nd
->root_fh
;
609 nd
->root_args
.fhsize
= nd
->root_fhsize
;
610 l
= ntohl(nd
->root_saddr
.sin_addr
.s_addr
);
611 ksnprintf(buf
, sizeof(buf
), "%ld.%ld.%ld.%ld:%s",
612 (l
>> 24) & 0xff, (l
>> 16) & 0xff,
613 (l
>> 8) & 0xff, (l
>> 0) & 0xff,nd
->root_hostnam
);
614 kprintf("NFS_ROOT: %s\n",buf
);
615 if ((error
= nfs_mountdiskless(buf
, "/", MNT_RDONLY
,
616 &nd
->root_saddr
, &nd
->root_args
, td
, &vp
, &mp
)) != 0) {
617 mp
->mnt_vfc
->vfc_refcount
--;
623 if (nd
->swap_nblks
) {
625 /* Convert to DEV_BSIZE instead of Kilobyte */
629 * Create a fake mount point just for the swap vnode so that the
630 * swap file can be on a different server from the rootfs.
632 nd
->swap_args
.fh
= nd
->swap_fh
;
633 nd
->swap_args
.fhsize
= nd
->swap_fhsize
;
634 l
= ntohl(nd
->swap_saddr
.sin_addr
.s_addr
);
635 ksnprintf(buf
, sizeof(buf
), "%ld.%ld.%ld.%ld:%s",
636 (l
>> 24) & 0xff, (l
>> 16) & 0xff,
637 (l
>> 8) & 0xff, (l
>> 0) & 0xff,nd
->swap_hostnam
);
638 kprintf("NFS SWAP: %s\n",buf
);
639 if ((error
= nfs_mountdiskless(buf
, "/swap", 0,
640 &nd
->swap_saddr
, &nd
->swap_args
, td
, &vp
, &swap_mp
)) != 0) {
646 VTONFS(vp
)->n_size
= VTONFS(vp
)->n_vattr
.va_size
=
647 nd
->swap_nblks
* DEV_BSIZE
;
650 * Since the swap file is not the root dir of a file system,
651 * hack it to a regular file.
655 nfs_setvtype(vp
, VREG
);
656 swaponvp(td
, vp
, nd
->swap_nblks
);
659 mp
->mnt_flag
|= MNT_ROOTFS
;
663 * This is not really an nfs issue, but it is much easier to
664 * set hostname here and then let the "/etc/rc.xxx" files
665 * mount the right /var based upon its preset value.
667 bcopy(nd
->my_hostnam
, hostname
, MAXHOSTNAMELEN
);
668 hostname
[MAXHOSTNAMELEN
- 1] = '\0';
669 for (i
= 0; i
< MAXHOSTNAMELEN
; i
++)
670 if (hostname
[i
] == '\0')
672 inittodr(ntohl(nd
->root_time
));
678 * Internal version of mount system call for diskless setup.
681 nfs_mountdiskless(char *path
, char *which
, int mountflag
,
682 struct sockaddr_in
*sin
, struct nfs_args
*args
, struct thread
*td
,
683 struct vnode
**vpp
, struct mount
**mpp
)
686 struct sockaddr
*nam
;
693 if ((error
= vfs_rootmountalloc("nfs", path
, &mp
)) != 0) {
694 kprintf("nfs_mountroot: NFS not configured");
699 mp
->mnt_kern_flag
= 0;
700 mp
->mnt_flag
= mountflag
;
701 nam
= dup_sockaddr((struct sockaddr
*)sin
);
703 #if defined(BOOTP) || defined(NFS_ROOT)
704 if (args
->fhsize
== 0) {
707 kprintf("NFS_ROOT: No FH passed from loader, attempting mount rpc...");
708 while (*xpath
&& *xpath
!= ':')
713 error
= md_mount(sin
, xpath
, args
->fh
, &args
->fhsize
, args
, td
);
715 kprintf("failed error %d.\n", error
);
718 kprintf("success!\n");
722 if ((error
= mountnfs(args
, mp
, nam
, which
, path
, vpp
)) != 0) {
723 #if defined(BOOTP) || defined(NFS_ROOT)
726 kprintf("nfs_mountroot: mount %s on %s: %d", path
, which
, error
);
727 mp
->mnt_vfc
->vfc_refcount
--;
739 nfs_decode_args(struct nfsmount
*nmp
, struct nfs_args
*argp
)
746 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
747 * no sense in that context.
749 if (nmp
->nm_sotype
== SOCK_STREAM
)
750 nmp
->nm_flag
&= ~NFSMNT_NOCONN
;
752 /* Also clear RDIRPLUS if not NFSv3, it crashes some servers */
753 if ((argp
->flags
& NFSMNT_NFSV3
) == 0)
754 nmp
->nm_flag
&= ~NFSMNT_RDIRPLUS
;
757 * Re-bind if rsrvd port flag has changed
759 adjsock
= (nmp
->nm_flag
& NFSMNT_RESVPORT
) !=
760 (argp
->flags
& NFSMNT_RESVPORT
);
762 /* Update flags atomically. Don't change the lock bits. */
763 nmp
->nm_flag
= argp
->flags
| nmp
->nm_flag
;
766 if ((argp
->flags
& NFSMNT_TIMEO
) && argp
->timeo
> 0) {
767 nmp
->nm_timeo
= (argp
->timeo
* NFS_HZ
+ 5) / 10;
768 if (nmp
->nm_timeo
< NFS_MINTIMEO
)
769 nmp
->nm_timeo
= NFS_MINTIMEO
;
770 else if (nmp
->nm_timeo
> NFS_MAXTIMEO
)
771 nmp
->nm_timeo
= NFS_MAXTIMEO
;
774 if ((argp
->flags
& NFSMNT_RETRANS
) && argp
->retrans
> 1) {
775 nmp
->nm_retry
= argp
->retrans
;
776 if (nmp
->nm_retry
> NFS_MAXREXMIT
)
777 nmp
->nm_retry
= NFS_MAXREXMIT
;
781 * These parameters effect the buffer cache and cannot be changed
782 * once we've successfully mounted.
784 if ((nmp
->nm_state
& NFSSTA_GOTFSINFO
) == 0) {
785 maxio
= nfs_iosize(argp
->flags
& NFSMNT_NFSV3
, nmp
->nm_sotype
);
787 if ((argp
->flags
& NFSMNT_WSIZE
) && argp
->wsize
> 0) {
788 nmp
->nm_wsize
= argp
->wsize
;
789 /* Round down to multiple of blocksize */
790 nmp
->nm_wsize
&= ~(NFS_FABLKSIZE
- 1);
791 if (nmp
->nm_wsize
<= 0)
792 nmp
->nm_wsize
= NFS_FABLKSIZE
;
794 if (nmp
->nm_wsize
> maxio
)
795 nmp
->nm_wsize
= maxio
;
796 if (nmp
->nm_wsize
> MAXBSIZE
)
797 nmp
->nm_wsize
= MAXBSIZE
;
799 if ((argp
->flags
& NFSMNT_RSIZE
) && argp
->rsize
> 0) {
800 nmp
->nm_rsize
= argp
->rsize
;
801 /* Round down to multiple of blocksize */
802 nmp
->nm_rsize
&= ~(NFS_FABLKSIZE
- 1);
803 if (nmp
->nm_rsize
<= 0)
804 nmp
->nm_rsize
= NFS_FABLKSIZE
;
806 if (nmp
->nm_rsize
> maxio
)
807 nmp
->nm_rsize
= maxio
;
808 if (nmp
->nm_rsize
> MAXBSIZE
)
809 nmp
->nm_rsize
= MAXBSIZE
;
811 if ((argp
->flags
& NFSMNT_READDIRSIZE
) &&
812 argp
->readdirsize
> 0) {
813 nmp
->nm_readdirsize
= argp
->readdirsize
;
815 if (nmp
->nm_readdirsize
> maxio
)
816 nmp
->nm_readdirsize
= maxio
;
817 if (nmp
->nm_readdirsize
> nmp
->nm_rsize
)
818 nmp
->nm_readdirsize
= nmp
->nm_rsize
;
821 if ((argp
->flags
& NFSMNT_ACREGMIN
) && argp
->acregmin
>= 0)
822 nmp
->nm_acregmin
= argp
->acregmin
;
824 nmp
->nm_acregmin
= NFS_MINATTRTIMO
;
825 if ((argp
->flags
& NFSMNT_ACREGMAX
) && argp
->acregmax
>= 0)
826 nmp
->nm_acregmax
= argp
->acregmax
;
828 nmp
->nm_acregmax
= NFS_MAXATTRTIMO
;
829 if ((argp
->flags
& NFSMNT_ACDIRMIN
) && argp
->acdirmin
>= 0)
830 nmp
->nm_acdirmin
= argp
->acdirmin
;
832 nmp
->nm_acdirmin
= NFS_MINDIRATTRTIMO
;
833 if ((argp
->flags
& NFSMNT_ACDIRMAX
) && argp
->acdirmax
>= 0)
834 nmp
->nm_acdirmax
= argp
->acdirmax
;
836 nmp
->nm_acdirmax
= NFS_MAXDIRATTRTIMO
;
837 if (nmp
->nm_acdirmin
> nmp
->nm_acdirmax
)
838 nmp
->nm_acdirmin
= nmp
->nm_acdirmax
;
839 if (nmp
->nm_acregmin
> nmp
->nm_acregmax
)
840 nmp
->nm_acregmin
= nmp
->nm_acregmax
;
842 if ((argp
->flags
& NFSMNT_MAXGRPS
) && argp
->maxgrouplist
>= 0) {
843 if (argp
->maxgrouplist
<= NFS_MAXGRPS
)
844 nmp
->nm_numgrps
= argp
->maxgrouplist
;
846 nmp
->nm_numgrps
= NFS_MAXGRPS
;
848 if ((argp
->flags
& NFSMNT_READAHEAD
) && argp
->readahead
>= 0) {
849 if (argp
->readahead
<= NFS_MAXRAHEAD
)
850 nmp
->nm_readahead
= argp
->readahead
;
852 nmp
->nm_readahead
= NFS_MAXRAHEAD
;
854 if ((argp
->flags
& NFSMNT_DEADTHRESH
) && argp
->deadthresh
>= 1) {
855 if (argp
->deadthresh
<= NFS_NEVERDEAD
)
856 nmp
->nm_deadthresh
= argp
->deadthresh
;
858 nmp
->nm_deadthresh
= NFS_NEVERDEAD
;
861 if (nmp
->nm_so
&& adjsock
) {
862 nfs_safedisconnect(nmp
);
863 if (nmp
->nm_sotype
== SOCK_DGRAM
)
864 while (nfs_connect(nmp
, NULL
)) {
865 kprintf("nfs_args: retrying connect\n");
866 (void) tsleep((caddr_t
)&lbolt
, 0, "nfscon", 0);
875 * It seems a bit dumb to copyinstr() the host and path here and then
876 * bcopy() them in mountnfs(), but I wanted to detect errors before
877 * doing the sockargs() call because sockargs() allocates an mbuf and
878 * an error after that means that I have to release the mbuf.
882 nfs_mount(struct mount
*mp
, char *path
, caddr_t data
, struct ucred
*cred
)
885 struct nfs_args args
;
886 struct sockaddr
*nam
;
888 char pth
[MNAMELEN
], hst
[MNAMELEN
];
890 u_char nfh
[NFSX_V3FHMAX
];
896 error
= copyin(data
, (caddr_t
)&args
, sizeof (struct nfs_args
));
899 if (args
.version
!= NFS_ARGSVERSION
) {
900 #ifdef COMPAT_PRELITE2
902 * If the argument version is unknown, then assume the
903 * caller is a pre-lite2 4.4BSD client and convert its
906 struct onfs_args oargs
;
907 error
= copyin(data
, (caddr_t
)&oargs
, sizeof (struct onfs_args
));
910 nfs_convert_oargs(&args
,&oargs
);
911 #else /* !COMPAT_PRELITE2 */
912 return (EPROGMISMATCH
);
913 #endif /* COMPAT_PRELITE2 */
915 if (mp
->mnt_flag
& MNT_UPDATE
) {
916 struct nfsmount
*nmp
= VFSTONFS(mp
);
921 * When doing an update, we can't change from or to
922 * v3, or change cookie translation, or rsize or wsize.
924 args
.flags
&= ~(NFSMNT_NFSV3
| NFSMNT_RSIZE
| NFSMNT_WSIZE
);
925 args
.flags
|= nmp
->nm_flag
& (NFSMNT_NFSV3
);
926 nfs_decode_args(nmp
, &args
);
931 * Make the nfs_ip_paranoia sysctl serve as the default connection
932 * or no-connection mode for those protocols that support
933 * no-connection mode (the flag will be cleared later for protocols
934 * that do not support no-connection mode). This will allow a client
935 * to receive replies from a different IP then the request was
936 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
939 if (nfs_ip_paranoia
== 0)
940 args
.flags
|= NFSMNT_NOCONN
;
941 if (args
.fhsize
< 0 || args
.fhsize
> NFSX_V3FHMAX
)
943 error
= copyin((caddr_t
)args
.fh
, (caddr_t
)nfh
, args
.fhsize
);
946 error
= copyinstr(path
, pth
, MNAMELEN
-1, &len
);
949 bzero(&pth
[len
], MNAMELEN
- len
);
950 error
= copyinstr(args
.hostname
, hst
, MNAMELEN
-1, &len
);
953 bzero(&hst
[len
], MNAMELEN
- len
);
954 /* sockargs() call must be after above copyin() calls */
955 error
= getsockaddr(&nam
, (caddr_t
)args
.addr
, args
.addrlen
);
959 error
= mountnfs(&args
, mp
, nam
, pth
, hst
, &vp
);
964 * Common code for mount and mountroot
967 mountnfs(struct nfs_args
*argp
, struct mount
*mp
, struct sockaddr
*nam
,
968 char *pth
, char *hst
, struct vnode
**vpp
)
970 struct nfsmount
*nmp
;
976 if (mp
->mnt_flag
& MNT_UPDATE
) {
978 /* update paths, file handles, etc, here XXX */
982 nmp
= zalloc(nfsmount_zone
);
983 bzero((caddr_t
)nmp
, sizeof (struct nfsmount
));
984 mtx_init(&nmp
->nm_rxlock
);
985 mtx_init(&nmp
->nm_txlock
);
986 TAILQ_INIT(&nmp
->nm_uidlruhead
);
987 TAILQ_INIT(&nmp
->nm_bioq
);
988 TAILQ_INIT(&nmp
->nm_reqq
);
989 TAILQ_INIT(&nmp
->nm_reqtxq
);
990 TAILQ_INIT(&nmp
->nm_reqrxq
);
991 mp
->mnt_data
= (qaddr_t
)nmp
;
997 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
998 * high, depending on whether we end up with negative offsets in
999 * the client or server somewhere. 2GB-1 may be safer.
1001 * For V3, nfs_fsinfo will adjust this as necessary. Assume maximum
1002 * that we can handle until we find out otherwise.
1003 * XXX Our "safe" limit on the client is what we can store in our
1004 * buffer cache using signed(!) block numbers.
1006 if ((argp
->flags
& NFSMNT_NFSV3
) == 0)
1007 nmp
->nm_maxfilesize
= 0xffffffffLL
;
1009 nmp
->nm_maxfilesize
= (u_int64_t
)0x80000000 * DEV_BSIZE
- 1;
1011 nmp
->nm_timeo
= NFS_TIMEO
;
1012 nmp
->nm_retry
= NFS_RETRANS
;
1013 nmp
->nm_wsize
= nfs_iosize(argp
->flags
& NFSMNT_NFSV3
, argp
->sotype
);
1014 nmp
->nm_rsize
= nmp
->nm_wsize
;
1015 nmp
->nm_readdirsize
= NFS_READDIRSIZE
;
1016 nmp
->nm_numgrps
= NFS_MAXGRPS
;
1017 nmp
->nm_readahead
= NFS_DEFRAHEAD
;
1018 nmp
->nm_deadthresh
= NFS_DEADTHRESH
;
1019 nmp
->nm_fhsize
= argp
->fhsize
;
1020 bcopy((caddr_t
)argp
->fh
, (caddr_t
)nmp
->nm_fh
, argp
->fhsize
);
1021 bcopy(hst
, mp
->mnt_stat
.f_mntfromname
, MNAMELEN
);
1023 /* Set up the sockets and per-host congestion */
1024 nmp
->nm_sotype
= argp
->sotype
;
1025 nmp
->nm_soproto
= argp
->proto
;
1026 nmp
->nm_cred
= crhold(proc0
.p_ucred
);
1028 nfs_decode_args(nmp
, argp
);
1031 * For Connection based sockets (TCP,...) defer the connect until
1032 * the first request, in case the server is not responding.
1034 if (nmp
->nm_sotype
== SOCK_DGRAM
&&
1035 (error
= nfs_connect(nmp
, NULL
)))
1039 * This is silly, but it has to be set so that vinifod() works.
1040 * We do not want to do an nfs_statfs() here since we can get
1041 * stuck on a dead server and we are holding a lock on the mount
1044 mp
->mnt_stat
.f_iosize
=
1045 nfs_iosize(nmp
->nm_flag
& NFSMNT_NFSV3
, nmp
->nm_sotype
);
1048 * Install vop_ops for our vnops
1050 vfs_add_vnodeops(mp
, &nfsv2_vnode_vops
, &mp
->mnt_vn_norm_ops
);
1051 vfs_add_vnodeops(mp
, &nfsv2_spec_vops
, &mp
->mnt_vn_spec_ops
);
1052 vfs_add_vnodeops(mp
, &nfsv2_fifo_vops
, &mp
->mnt_vn_fifo_ops
);
1055 * A reference count is needed on the nfsnode representing the
1056 * remote root. If this object is not persistent, then backward
1057 * traversals of the mount point (i.e. "..") will not work if
1058 * the nfsnode gets flushed out of the cache. Ufs does not have
1059 * this problem, because one can identify root inodes by their
1060 * number == ROOTINO (2).
1062 error
= nfs_nget(mp
, (nfsfh_t
*)nmp
->nm_fh
, nmp
->nm_fhsize
, &np
);
1068 * Retrieval of mountpoint attributes is delayed until nfs_rot
1069 * or nfs_statfs are first called. This will happen either when
1070 * we first traverse the mount point or if somebody does a df(1).
1072 * NFSSTA_GOTFSINFO is used to flag if we have successfully
1073 * retrieved mountpoint attributes. In the case of NFSv3 we
1074 * also flag static fsinfo.
1077 (*vpp
)->v_type
= VNON
;
1080 * Lose the lock but keep the ref.
1083 TAILQ_INSERT_TAIL(&nfs_mountq
, nmp
, nm_entry
);
1107 * Start the reader and writer threads.
1109 lwkt_create(nfssvc_iod_reader
, nmp
, &nmp
->nm_rxthread
,
1110 NULL
, 0, rxcpu
, "nfsiod_rx");
1111 lwkt_create(nfssvc_iod_writer
, nmp
, &nmp
->nm_txthread
,
1112 NULL
, 0, txcpu
, "nfsiod_tx");
1116 nfs_disconnect(nmp
);
1117 nfs_free_mount(nmp
);
1122 * unmount system call
1125 nfs_unmount(struct mount
*mp
, int mntflags
)
1127 struct nfsmount
*nmp
;
1128 int error
, flags
= 0;
1131 if (mntflags
& MNT_FORCE
) {
1132 flags
|= FORCECLOSE
;
1133 nmp
->nm_flag
|= NFSMNT_FORCE
;
1137 * Goes something like this..
1138 * - Call vflush() to clear out vnodes for this file system
1139 * - Close the socket
1140 * - Free up the data structures
1142 /* In the forced case, cancel any outstanding requests. */
1143 if (flags
& FORCECLOSE
) {
1144 error
= nfs_nmcancelreqs(nmp
);
1146 kprintf("NFS: %s: Unable to cancel all requests\n",
1147 mp
->mnt_stat
.f_mntfromname
);
1148 /* continue anyway */
1153 * Must handshake with nfs_clientd() if it is active. XXX
1155 nmp
->nm_state
|= NFSSTA_DISMINPROG
;
1158 * We hold 1 extra ref on the root vnode; see comment in mountnfs().
1160 * If this doesn't work and we are doing a forced unmount we continue
1163 error
= vflush(mp
, 1, flags
);
1165 nmp
->nm_state
&= ~NFSSTA_DISMINPROG
;
1166 if ((flags
& FORCECLOSE
) == 0)
1171 * We are now committed to the unmount.
1172 * For NQNFS, let the server daemon free the nfsmount structure.
1174 if (nmp
->nm_flag
& NFSMNT_KERB
)
1175 nmp
->nm_state
|= NFSSTA_DISMNT
;
1176 nfssvc_iod_stop1(nmp
);
1177 nfs_disconnect(nmp
);
1178 nfssvc_iod_stop2(nmp
);
1179 TAILQ_REMOVE(&nfs_mountq
, nmp
, nm_entry
);
1181 if ((nmp
->nm_flag
& NFSMNT_KERB
) == 0) {
1182 nfs_free_mount(nmp
);
1188 nfs_free_mount(struct nfsmount
*nmp
)
1191 crfree(nmp
->nm_cred
);
1192 nmp
->nm_cred
= NULL
;
1195 FREE(nmp
->nm_nam
, M_SONAME
);
1198 zfree(nfsmount_zone
, nmp
);
1202 * Return root of a filesystem
1205 nfs_root(struct mount
*mp
, struct vnode
**vpp
)
1208 struct nfsmount
*nmp
;
1214 error
= nfs_nget(mp
, (nfsfh_t
*)nmp
->nm_fh
, nmp
->nm_fhsize
, &np
);
1220 * Get transfer parameters and root vnode attributes
1222 if ((nmp
->nm_state
& NFSSTA_GOTFSINFO
) == 0) {
1223 if (nmp
->nm_flag
& NFSMNT_NFSV3
) {
1224 error
= nfs_fsinfo(nmp
, vp
, curthread
);
1225 mp
->mnt_stat
.f_iosize
= nfs_iosize(1, nmp
->nm_sotype
);
1227 if ((error
= VOP_GETATTR(vp
, &attrs
)) == 0)
1228 nmp
->nm_state
|= NFSSTA_GOTFSINFO
;
1233 * The root vnode is usually cached by the namecache so do not
1234 * try to avoid going over the wire even if we have previous
1235 * information cached. A stale NFS mount can loop
1236 * forever resolving the root vnode if we return no-error when
1237 * there is in fact an error.
1239 np
->n_attrstamp
= 0;
1240 error
= VOP_GETATTR(vp
, &attrs
);
1242 if (vp
->v_type
== VNON
)
1243 nfs_setvtype(vp
, VDIR
);
1258 static int nfs_sync_scan1(struct mount
*mp
, struct vnode
*vp
, void *data
);
1259 static int nfs_sync_scan2(struct mount
*mp
, struct vnode
*vp
, void *data
);
1262 * Flush out the buffer cache
1266 nfs_sync(struct mount
*mp
, int waitfor
)
1268 struct scaninfo scaninfo
;
1271 scaninfo
.rescan
= 1;
1272 scaninfo
.waitfor
= waitfor
;
1273 scaninfo
.allerror
= 0;
1276 * Force stale buffer cache information to be flushed.
1279 while (error
== 0 && scaninfo
.rescan
) {
1280 scaninfo
.rescan
= 0;
1281 error
= vmntvnodescan(mp
, VMSC_GETVP
, nfs_sync_scan1
,
1282 nfs_sync_scan2
, &scaninfo
);
1288 nfs_sync_scan1(struct mount
*mp
, struct vnode
*vp
, void *data
)
1290 struct scaninfo
*info
= data
;
1292 if (vn_islocked(vp
) || RB_EMPTY(&vp
->v_rbdirty_tree
))
1294 if (info
->waitfor
== MNT_LAZY
)
1300 nfs_sync_scan2(struct mount
*mp
, struct vnode
*vp
, void *data
)
1302 struct scaninfo
*info
= data
;
1305 error
= VOP_FSYNC(vp
, info
->waitfor
, 0);
1307 info
->allerror
= error
;