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