1 /* $NetBSD: nfs_vfsops.c,v 1.121 2003/02/01 06:23:49 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993, 1995 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Rick Macklem at The University of Guelph. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95 39 */ 40 41 #include <sys/cdefs.h> 42 __KERNEL_RCSID(0, "$NetBSD: nfs_vfsops.c,v 1.121 2003/02/01 06:23:49 thorpej Exp $"); 43 44 #if defined(_KERNEL_OPT) 45 #include "opt_compat_netbsd.h" 46 #include "opt_nfs.h" 47 #endif 48 49 #include <sys/param.h> 50 #include <sys/ioctl.h> 51 #include <sys/signal.h> 52 #include <sys/proc.h> 53 #include <sys/namei.h> 54 #include <sys/device.h> 55 #include <sys/vnode.h> 56 #include <sys/kernel.h> 57 #include <sys/mount.h> 58 #include <sys/buf.h> 59 #include <sys/mbuf.h> 60 #include <sys/socket.h> 61 #include <sys/socketvar.h> 62 #include <sys/sysctl.h> 63 #include <sys/systm.h> 64 65 #include <net/if.h> 66 #include <net/route.h> 67 #include <netinet/in.h> 68 69 #include <nfs/rpcv2.h> 70 #include <nfs/nfsproto.h> 71 #include <nfs/nfsnode.h> 72 #include <nfs/nfs.h> 73 #include <nfs/nfsmount.h> 74 #include <nfs/xdr_subs.h> 75 #include <nfs/nfsm_subs.h> 76 #include <nfs/nfsdiskless.h> 77 #include <nfs/nqnfs.h> 78 #include <nfs/nfs_var.h> 79 80 extern struct nfsstats nfsstats; 81 extern int nfs_ticks; 82 83 MALLOC_DEFINE(M_NFSMNT, "NFS mount", "NFS mount structure"); 84 85 int nfs_sysctl __P((int *, u_int, void *, size_t *, void *, size_t, 86 struct proc *)); 87 88 /* 89 * nfs vfs operations. 90 */ 91 92 extern const struct vnodeopv_desc nfsv2_vnodeop_opv_desc; 93 extern const struct vnodeopv_desc spec_nfsv2nodeop_opv_desc; 94 extern const struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc; 95 96 const struct vnodeopv_desc * const nfs_vnodeopv_descs[] = { 97 &nfsv2_vnodeop_opv_desc, 98 &spec_nfsv2nodeop_opv_desc, 99 &fifo_nfsv2nodeop_opv_desc, 100 NULL, 101 }; 102 103 struct vfsops nfs_vfsops = { 104 MOUNT_NFS, 105 nfs_mount, 106 nfs_start, 107 nfs_unmount, 108 nfs_root, 109 nfs_quotactl, 110 nfs_statfs, 111 nfs_sync, 112 nfs_vget, 113 nfs_fhtovp, 114 nfs_vptofh, 115 nfs_vfs_init, 116 nfs_vfs_reinit, 117 nfs_vfs_done, 118 nfs_sysctl, 119 nfs_mountroot, 120 nfs_checkexp, 121 nfs_vnodeopv_descs, 122 }; 123 124 extern u_int32_t nfs_procids[NFS_NPROCS]; 125 extern u_int32_t nfs_prog, nfs_vers; 126 127 static int nfs_mount_diskless __P((struct nfs_dlmount *, const char *, 128 struct mount **, struct vnode **, struct proc *)); 129 130 #define TRUE 1 131 #define FALSE 0 132 133 /* 134 * nfs statfs call 135 */ 136 int 137 nfs_statfs(mp, sbp, p) 138 struct mount *mp; 139 struct statfs *sbp; 140 struct proc *p; 141 { 142 struct vnode *vp; 143 struct nfs_statfs *sfp; 144 caddr_t cp; 145 u_int32_t *tl; 146 int32_t t1, t2; 147 caddr_t bpos, dpos, cp2; 148 struct nfsmount *nmp = VFSTONFS(mp); 149 int error = 0, retattr; 150 #ifdef NFS_V2_ONLY 151 const int v3 = 0; 152 #else 153 int v3 = (nmp->nm_flag & NFSMNT_NFSV3); 154 #endif 155 struct mbuf *mreq, *mrep = NULL, *md, *mb, *mb2; 156 struct ucred *cred; 157 u_quad_t tquad; 158 159 #ifndef nolint 160 sfp = (struct nfs_statfs *)0; 161 #endif 162 vp = nmp->nm_vnode; 163 cred = crget(); 164 cred->cr_ngroups = 0; 165 #ifndef NFS_V2_ONLY 166 if (v3 && (nmp->nm_iflag & NFSMNT_GOTFSINFO) == 0) 167 (void)nfs_fsinfo(nmp, vp, cred, p); 168 #endif 169 nfsstats.rpccnt[NFSPROC_FSSTAT]++; 170 nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3)); 171 nfsm_fhtom(vp, v3); 172 nfsm_request(vp, NFSPROC_FSSTAT, p, cred); 173 if (v3) 174 nfsm_postop_attr(vp, retattr, 0); 175 if (error) { 176 if (mrep != NULL) 177 m_free(mrep); 178 goto nfsmout; 179 } 180 nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3)); 181 #ifdef COMPAT_09 182 sbp->f_type = 2; 183 #else 184 sbp->f_type = 0; 185 #endif 186 sbp->f_flags = nmp->nm_flag; 187 sbp->f_iosize = min(nmp->nm_rsize, nmp->nm_wsize); 188 if (v3) { 189 sbp->f_bsize = NFS_FABLKSIZE; 190 tquad = fxdr_hyper(&sfp->sf_tbytes); 191 sbp->f_blocks = (long)((quad_t)tquad / (quad_t)NFS_FABLKSIZE); 192 tquad = fxdr_hyper(&sfp->sf_fbytes); 193 sbp->f_bfree = (long)((quad_t)tquad / (quad_t)NFS_FABLKSIZE); 194 tquad = fxdr_hyper(&sfp->sf_abytes); 195 sbp->f_bavail = (long)((quad_t)tquad / (quad_t)NFS_FABLKSIZE); 196 tquad = fxdr_hyper(&sfp->sf_tfiles); 197 sbp->f_files = (long)tquad; 198 tquad = fxdr_hyper(&sfp->sf_ffiles); 199 sbp->f_ffree = (long)tquad; 200 } else { 201 sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize); 202 sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks); 203 sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree); 204 sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail); 205 sbp->f_files = 0; 206 sbp->f_ffree = 0; 207 } 208 if (sbp != &mp->mnt_stat) { 209 memcpy(sbp->f_mntonname, mp->mnt_stat.f_mntonname, MNAMELEN); 210 memcpy(sbp->f_mntfromname, mp->mnt_stat.f_mntfromname, MNAMELEN); 211 } 212 strncpy(&sbp->f_fstypename[0], mp->mnt_op->vfs_name, MFSNAMELEN); 213 nfsm_reqdone; 214 crfree(cred); 215 return (error); 216 } 217 218 #ifndef NFS_V2_ONLY 219 /* 220 * nfs version 3 fsinfo rpc call 221 */ 222 int 223 nfs_fsinfo(nmp, vp, cred, p) 224 struct nfsmount *nmp; 225 struct vnode *vp; 226 struct ucred *cred; 227 struct proc *p; 228 { 229 struct nfsv3_fsinfo *fsp; 230 caddr_t cp; 231 int32_t t1, t2; 232 u_int32_t *tl, pref, max; 233 caddr_t bpos, dpos, cp2; 234 int error = 0, retattr; 235 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 236 u_int64_t maxfsize; 237 238 nfsstats.rpccnt[NFSPROC_FSINFO]++; 239 nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1)); 240 nfsm_fhtom(vp, 1); 241 nfsm_request(vp, NFSPROC_FSINFO, p, cred); 242 nfsm_postop_attr(vp, retattr, 0); 243 if (!error) { 244 nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO); 245 pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref); 246 if (pref < nmp->nm_wsize && pref >= NFS_FABLKSIZE) 247 nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) & 248 ~(NFS_FABLKSIZE - 1); 249 max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax); 250 if (max < nmp->nm_wsize && max > 0) { 251 nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1); 252 if (nmp->nm_wsize == 0) 253 nmp->nm_wsize = max; 254 } 255 pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref); 256 if (pref < nmp->nm_rsize && pref >= NFS_FABLKSIZE) 257 nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) & 258 ~(NFS_FABLKSIZE - 1); 259 max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax); 260 if (max < nmp->nm_rsize && max > 0) { 261 nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1); 262 if (nmp->nm_rsize == 0) 263 nmp->nm_rsize = max; 264 } 265 pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref); 266 if (pref < nmp->nm_readdirsize && pref >= NFS_DIRFRAGSIZ) 267 nmp->nm_readdirsize = (pref + NFS_DIRFRAGSIZ - 1) & 268 ~(NFS_DIRFRAGSIZ - 1); 269 if (max < nmp->nm_readdirsize && max > 0) { 270 nmp->nm_readdirsize = max & ~(NFS_DIRFRAGSIZ - 1); 271 if (nmp->nm_readdirsize == 0) 272 nmp->nm_readdirsize = max; 273 } 274 /* XXX */ 275 nmp->nm_maxfilesize = (u_int64_t)0x80000000 * DEV_BSIZE - 1; 276 maxfsize = fxdr_hyper(&fsp->fs_maxfilesize); 277 if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize) 278 nmp->nm_maxfilesize = maxfsize; 279 nmp->nm_iflag |= NFSMNT_GOTFSINFO; 280 } 281 nfsm_reqdone; 282 return (error); 283 } 284 #endif 285 286 /* 287 * Mount a remote root fs via. NFS. It goes like this: 288 * - Call nfs_boot_init() to fill in the nfs_diskless struct 289 * - build the rootfs mount point and call mountnfs() to do the rest. 290 */ 291 int 292 nfs_mountroot() 293 { 294 struct nfs_diskless *nd; 295 struct vattr attr; 296 struct mount *mp; 297 struct vnode *vp; 298 struct proc *procp; 299 long n; 300 int error; 301 302 procp = curproc; /* XXX */ 303 304 if (root_device->dv_class != DV_IFNET) 305 return (ENODEV); 306 307 /* 308 * XXX time must be non-zero when we init the interface or else 309 * the arp code will wedge. [Fixed now in if_ether.c] 310 * However, the NFS attribute cache gives false "hits" when 311 * time.tv_sec < NFS_ATTRTIMEO(np) so keep this in for now. 312 */ 313 if (time.tv_sec < NFS_MAXATTRTIMO) 314 time.tv_sec = NFS_MAXATTRTIMO; 315 316 /* 317 * Call nfs_boot_init() to fill in the nfs_diskless struct. 318 * Side effect: Finds and configures a network interface. 319 */ 320 nd = malloc(sizeof(*nd), M_NFSMNT, M_WAITOK); 321 memset((caddr_t)nd, 0, sizeof(*nd)); 322 error = nfs_boot_init(nd, procp); 323 if (error) { 324 free(nd, M_NFSMNT); 325 return (error); 326 } 327 328 /* 329 * Create the root mount point. 330 */ 331 error = nfs_mount_diskless(&nd->nd_root, "/", &mp, &vp, procp); 332 if (error) 333 goto out; 334 printf("root on %s\n", nd->nd_root.ndm_host); 335 336 /* 337 * Link it into the mount list. 338 */ 339 simple_lock(&mountlist_slock); 340 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); 341 simple_unlock(&mountlist_slock); 342 rootvp = vp; 343 mp->mnt_vnodecovered = NULLVP; 344 vfs_unbusy(mp); 345 346 /* Get root attributes (for the time). */ 347 error = VOP_GETATTR(vp, &attr, procp->p_ucred, procp); 348 if (error) 349 panic("nfs_mountroot: getattr for root"); 350 n = attr.va_atime.tv_sec; 351 #ifdef DEBUG 352 printf("root time: 0x%lx\n", n); 353 #endif 354 inittodr(n); 355 356 out: 357 if (error) 358 nfs_boot_cleanup(nd, procp); 359 free(nd, M_NFSMNT); 360 return (error); 361 } 362 363 /* 364 * Internal version of mount system call for diskless setup. 365 * Separate function because we used to call it twice. 366 * (once for root and once for swap) 367 */ 368 static int 369 nfs_mount_diskless(ndmntp, mntname, mpp, vpp, p) 370 struct nfs_dlmount *ndmntp; 371 const char *mntname; /* mount point name */ 372 struct mount **mpp; 373 struct vnode **vpp; 374 struct proc *p; 375 { 376 struct mount *mp; 377 struct mbuf *m; 378 int error; 379 380 vfs_rootmountalloc(MOUNT_NFS, (char *)mntname, &mp); 381 382 mp->mnt_op = &nfs_vfsops; 383 384 /* 385 * Historical practice expects NFS root file systems to 386 * be initially mounted r/w. 387 */ 388 mp->mnt_flag &= ~MNT_RDONLY; 389 390 /* Get mbuf for server sockaddr. */ 391 m = m_get(M_WAIT, MT_SONAME); 392 if (m == NULL) 393 panic("nfs_mountroot: mget soname for %s", mntname); 394 memcpy(mtod(m, caddr_t), (caddr_t)ndmntp->ndm_args.addr, 395 (m->m_len = ndmntp->ndm_args.addr->sa_len)); 396 397 error = mountnfs(&ndmntp->ndm_args, mp, m, mntname, 398 ndmntp->ndm_args.hostname, vpp, p); 399 if (error) { 400 mp->mnt_op->vfs_refcount--; 401 vfs_unbusy(mp); 402 printf("nfs_mountroot: mount %s failed: %d\n", 403 mntname, error); 404 free(mp, M_MOUNT); 405 } else 406 *mpp = mp; 407 408 return (error); 409 } 410 411 void 412 nfs_decode_args(nmp, argp) 413 struct nfsmount *nmp; 414 struct nfs_args *argp; 415 { 416 int s; 417 int adjsock; 418 int maxio; 419 420 s = splsoftnet(); 421 422 /* 423 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes 424 * no sense in that context. 425 */ 426 if (argp->sotype == SOCK_STREAM) 427 argp->flags &= ~NFSMNT_NOCONN; 428 429 /* 430 * Cookie translation is not needed for v2, silently ignore it. 431 */ 432 if ((argp->flags & (NFSMNT_XLATECOOKIE|NFSMNT_NFSV3)) == 433 NFSMNT_XLATECOOKIE) 434 argp->flags &= ~NFSMNT_XLATECOOKIE; 435 436 /* Re-bind if rsrvd port requested and wasn't on one */ 437 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT) 438 && (argp->flags & NFSMNT_RESVPORT); 439 /* Also re-bind if we're switching to/from a connected UDP socket */ 440 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) != 441 (argp->flags & NFSMNT_NOCONN)); 442 443 /* Update flags. */ 444 nmp->nm_flag = argp->flags; 445 splx(s); 446 447 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) { 448 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10; 449 if (nmp->nm_timeo < NFS_MINTIMEO) 450 nmp->nm_timeo = NFS_MINTIMEO; 451 else if (nmp->nm_timeo > NFS_MAXTIMEO) 452 nmp->nm_timeo = NFS_MAXTIMEO; 453 } 454 455 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) { 456 nmp->nm_retry = argp->retrans; 457 if (nmp->nm_retry > NFS_MAXREXMIT) 458 nmp->nm_retry = NFS_MAXREXMIT; 459 } 460 461 #ifndef NFS_V2_ONLY 462 if (argp->flags & NFSMNT_NFSV3) { 463 if (argp->sotype == SOCK_DGRAM) 464 maxio = NFS_MAXDGRAMDATA; 465 else 466 maxio = NFS_MAXDATA; 467 } else 468 #endif 469 maxio = NFS_V2MAXDATA; 470 471 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) { 472 int osize = nmp->nm_wsize; 473 nmp->nm_wsize = argp->wsize; 474 /* Round down to multiple of blocksize */ 475 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1); 476 if (nmp->nm_wsize <= 0) 477 nmp->nm_wsize = NFS_FABLKSIZE; 478 adjsock |= (nmp->nm_wsize != osize); 479 } 480 if (nmp->nm_wsize > maxio) 481 nmp->nm_wsize = maxio; 482 if (nmp->nm_wsize > MAXBSIZE) 483 nmp->nm_wsize = MAXBSIZE; 484 485 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) { 486 int osize = nmp->nm_rsize; 487 nmp->nm_rsize = argp->rsize; 488 /* Round down to multiple of blocksize */ 489 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1); 490 if (nmp->nm_rsize <= 0) 491 nmp->nm_rsize = NFS_FABLKSIZE; 492 adjsock |= (nmp->nm_rsize != osize); 493 } 494 if (nmp->nm_rsize > maxio) 495 nmp->nm_rsize = maxio; 496 if (nmp->nm_rsize > MAXBSIZE) 497 nmp->nm_rsize = MAXBSIZE; 498 499 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) { 500 nmp->nm_readdirsize = argp->readdirsize; 501 /* Round down to multiple of minimum blocksize */ 502 nmp->nm_readdirsize &= ~(NFS_DIRFRAGSIZ - 1); 503 if (nmp->nm_readdirsize < NFS_DIRFRAGSIZ) 504 nmp->nm_readdirsize = NFS_DIRFRAGSIZ; 505 /* Bigger than buffer size makes no sense */ 506 if (nmp->nm_readdirsize > NFS_DIRBLKSIZ) 507 nmp->nm_readdirsize = NFS_DIRBLKSIZ; 508 } else if (argp->flags & NFSMNT_RSIZE) 509 nmp->nm_readdirsize = nmp->nm_rsize; 510 511 if (nmp->nm_readdirsize > maxio) 512 nmp->nm_readdirsize = maxio; 513 514 if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 && 515 argp->maxgrouplist <= NFS_MAXGRPS) 516 nmp->nm_numgrps = argp->maxgrouplist; 517 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0 && 518 argp->readahead <= NFS_MAXRAHEAD) 519 nmp->nm_readahead = argp->readahead; 520 if ((argp->flags & NFSMNT_LEASETERM) && argp->leaseterm >= 2 && 521 argp->leaseterm <= NQ_MAXLEASE) 522 nmp->nm_leaseterm = argp->leaseterm; 523 if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1 && 524 argp->deadthresh <= NQ_NEVERDEAD) 525 nmp->nm_deadthresh = argp->deadthresh; 526 527 adjsock |= ((nmp->nm_sotype != argp->sotype) || 528 (nmp->nm_soproto != argp->proto)); 529 nmp->nm_sotype = argp->sotype; 530 nmp->nm_soproto = argp->proto; 531 532 if (nmp->nm_so && adjsock) { 533 nfs_safedisconnect(nmp); 534 if (nmp->nm_sotype == SOCK_DGRAM) 535 while (nfs_connect(nmp, (struct nfsreq *)0)) { 536 printf("nfs_args: retrying connect\n"); 537 (void) tsleep((caddr_t)&lbolt, 538 PSOCK, "nfscn3", 0); 539 } 540 } 541 } 542 543 /* 544 * VFS Operations. 545 * 546 * mount system call 547 * It seems a bit dumb to copyinstr() the host and path here and then 548 * memcpy() them in mountnfs(), but I wanted to detect errors before 549 * doing the sockargs() call because sockargs() allocates an mbuf and 550 * an error after that means that I have to release the mbuf. 551 */ 552 /* ARGSUSED */ 553 int 554 nfs_mount(mp, path, data, ndp, p) 555 struct mount *mp; 556 const char *path; 557 void *data; 558 struct nameidata *ndp; 559 struct proc *p; 560 { 561 int error; 562 struct nfs_args args; 563 struct mbuf *nam; 564 struct nfsmount *nmp = VFSTONFS(mp); 565 struct sockaddr *sa; 566 struct vnode *vp; 567 char *pth, *hst; 568 size_t len; 569 u_char *nfh; 570 571 error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args)); 572 if (error) 573 return (error); 574 575 if (mp->mnt_flag & MNT_GETARGS) { 576 577 if (nmp == NULL) 578 return (EIO); 579 if (args.addr != NULL) { 580 sa = mtod(nmp->nm_nam, struct sockaddr *); 581 error = copyout(sa, args.addr, sa->sa_len); 582 if (error) 583 return (error); 584 args.addrlen = sa->sa_len; 585 } else 586 args.addrlen = 0; 587 588 args.version = NFS_ARGSVERSION; 589 args.sotype = nmp->nm_sotype; 590 args.proto = nmp->nm_soproto; 591 args.fh = NULL; 592 args.fhsize = 0; 593 args.flags = nmp->nm_flag; 594 args.wsize = nmp->nm_wsize; 595 args.rsize = nmp->nm_rsize; 596 args.readdirsize = nmp->nm_readdirsize; 597 args.timeo = nmp->nm_timeo; 598 args.retrans = nmp->nm_retry; 599 args.maxgrouplist = nmp->nm_numgrps; 600 args.readahead = nmp->nm_readahead; 601 args.leaseterm = nmp->nm_leaseterm; 602 args.deadthresh = nmp->nm_deadthresh; 603 args.hostname = NULL; 604 return (copyout(&args, data, sizeof(args))); 605 } 606 607 if (args.version != NFS_ARGSVERSION) 608 return (EPROGMISMATCH); 609 #ifdef NFS_V2_ONLY 610 if (args.flags & NFSMNT_NQNFS) 611 return (EPROGUNAVAIL); 612 if (args.flags & NFSMNT_NFSV3) 613 return (EPROGMISMATCH); 614 #endif 615 if (mp->mnt_flag & MNT_UPDATE) { 616 if (nmp == NULL) 617 return (EIO); 618 /* 619 * When doing an update, we can't change from or to 620 * v3 and/or nqnfs, or change cookie translation 621 */ 622 args.flags = (args.flags & 623 ~(NFSMNT_NFSV3|NFSMNT_NQNFS|NFSMNT_XLATECOOKIE)) | 624 (nmp->nm_flag & 625 (NFSMNT_NFSV3|NFSMNT_NQNFS|NFSMNT_XLATECOOKIE)); 626 nfs_decode_args(nmp, &args); 627 return (0); 628 } 629 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) 630 return (EINVAL); 631 MALLOC(nfh, u_char *, NFSX_V3FHMAX, M_TEMP, M_WAITOK); 632 error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize); 633 if (error) 634 return (error); 635 MALLOC(pth, char *, MNAMELEN, M_TEMP, M_WAITOK); 636 error = copyinstr(path, pth, MNAMELEN - 1, &len); 637 if (error) 638 goto free_nfh; 639 memset(&pth[len], 0, MNAMELEN - len); 640 MALLOC(hst, char *, MNAMELEN, M_TEMP, M_WAITOK); 641 error = copyinstr(args.hostname, hst, MNAMELEN - 1, &len); 642 if (error) 643 goto free_pth; 644 memset(&hst[len], 0, MNAMELEN - len); 645 /* sockargs() call must be after above copyin() calls */ 646 error = sockargs(&nam, (caddr_t)args.addr, args.addrlen, MT_SONAME); 647 if (error) 648 goto free_hst; 649 args.fh = nfh; 650 error = mountnfs(&args, mp, nam, pth, hst, &vp, p); 651 652 free_hst: 653 FREE(hst, M_TEMP); 654 free_pth: 655 FREE(pth, M_TEMP); 656 free_nfh: 657 FREE(nfh, M_TEMP); 658 659 return (error); 660 } 661 662 /* 663 * Common code for mount and mountroot 664 */ 665 int 666 mountnfs(argp, mp, nam, pth, hst, vpp, p) 667 struct nfs_args *argp; 668 struct mount *mp; 669 struct mbuf *nam; 670 const char *pth, *hst; 671 struct vnode **vpp; 672 struct proc *p; 673 { 674 struct nfsmount *nmp; 675 struct nfsnode *np; 676 int error; 677 struct vattr *attrs; 678 struct ucred *cr; 679 680 /* 681 * If the number of nfs iothreads to use has never 682 * been set, create a reasonable number of them. 683 */ 684 685 if (nfs_niothreads < 0) { 686 nfs_niothreads = NFS_DEFAULT_NIOTHREADS; 687 nfs_getset_niothreads(TRUE); 688 } 689 690 if (mp->mnt_flag & MNT_UPDATE) { 691 nmp = VFSTONFS(mp); 692 /* update paths, file handles, etc, here XXX */ 693 m_freem(nam); 694 return (0); 695 } else { 696 MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount), 697 M_NFSMNT, M_WAITOK); 698 memset((caddr_t)nmp, 0, sizeof (struct nfsmount)); 699 mp->mnt_data = nmp; 700 TAILQ_INIT(&nmp->nm_uidlruhead); 701 TAILQ_INIT(&nmp->nm_bufq); 702 } 703 vfs_getnewfsid(mp); 704 nmp->nm_mountp = mp; 705 706 #ifndef NFS_V2_ONLY 707 if (argp->flags & NFSMNT_NQNFS) 708 /* 709 * We have to set mnt_maxsymlink to a non-zero value so 710 * that COMPAT_43 routines will know that we are setting 711 * the d_type field in directories (and can zero it for 712 * unsuspecting binaries). 713 */ 714 mp->mnt_maxsymlinklen = 1; 715 #endif 716 717 #ifndef NFS_V2_ONLY 718 if ((argp->flags & NFSMNT_NFSV3) == 0) 719 #endif 720 /* 721 * V2 can only handle 32 bit filesizes. For v3, nfs_fsinfo 722 * will fill this in. 723 */ 724 nmp->nm_maxfilesize = 0xffffffffLL; 725 726 nmp->nm_timeo = NFS_TIMEO; 727 nmp->nm_retry = NFS_RETRANS; 728 nmp->nm_wsize = NFS_WSIZE; 729 nmp->nm_rsize = NFS_RSIZE; 730 nmp->nm_readdirsize = NFS_READDIRSIZE; 731 nmp->nm_numgrps = NFS_MAXGRPS; 732 nmp->nm_readahead = NFS_DEFRAHEAD; 733 nmp->nm_leaseterm = NQ_DEFLEASE; 734 nmp->nm_deadthresh = NQ_DEADTHRESH; 735 CIRCLEQ_INIT(&nmp->nm_timerhead); 736 nmp->nm_inprog = NULLVP; 737 #ifdef COMPAT_09 738 mp->mnt_stat.f_type = 2; 739 #else 740 mp->mnt_stat.f_type = 0; 741 #endif 742 strncpy(&mp->mnt_stat.f_fstypename[0], mp->mnt_op->vfs_name, 743 MFSNAMELEN); 744 memcpy(mp->mnt_stat.f_mntfromname, hst, MNAMELEN); 745 memcpy(mp->mnt_stat.f_mntonname, pth, MNAMELEN); 746 nmp->nm_nam = nam; 747 748 /* Set up the sockets and per-host congestion */ 749 nmp->nm_sotype = argp->sotype; 750 nmp->nm_soproto = argp->proto; 751 752 nfs_decode_args(nmp, argp); 753 754 mp->mnt_fs_bshift = ffs(MIN(nmp->nm_rsize, nmp->nm_wsize)) - 1; 755 mp->mnt_dev_bshift = DEV_BSHIFT; 756 757 /* 758 * For Connection based sockets (TCP,...) defer the connect until 759 * the first request, in case the server is not responding. 760 */ 761 if (nmp->nm_sotype == SOCK_DGRAM && 762 (error = nfs_connect(nmp, (struct nfsreq *)0))) 763 goto bad; 764 765 /* 766 * This is silly, but it has to be set so that vinifod() works. 767 * We do not want to do an nfs_statfs() here since we can get 768 * stuck on a dead server and we are holding a lock on the mount 769 * point. 770 */ 771 mp->mnt_stat.f_iosize = NFS_MAXDGRAMDATA; 772 error = nfs_nget(mp, (nfsfh_t *)argp->fh, argp->fhsize, &np); 773 if (error) 774 goto bad; 775 *vpp = NFSTOV(np); 776 MALLOC(attrs, struct vattr *, sizeof(struct vattr), M_TEMP, M_WAITOK); 777 VOP_GETATTR(*vpp, attrs, p->p_ucred, p); 778 if ((nmp->nm_flag & NFSMNT_NFSV3) && ((*vpp)->v_type == VDIR)) { 779 cr = crget(); 780 cr->cr_uid = attrs->va_uid; 781 cr->cr_gid = attrs->va_gid; 782 cr->cr_ngroups = 0; 783 nfs_cookieheuristic(*vpp, &nmp->nm_iflag, p, cr); 784 crfree(cr); 785 } 786 FREE(attrs, M_TEMP); 787 788 /* 789 * A reference count is needed on the nfsnode representing the 790 * remote root. If this object is not persistent, then backward 791 * traversals of the mount point (i.e. "..") will not work if 792 * the nfsnode gets flushed out of the cache. Ufs does not have 793 * this problem, because one can identify root inodes by their 794 * number == ROOTINO (2). So, just unlock, but no rele. 795 */ 796 797 nmp->nm_vnode = *vpp; 798 VOP_UNLOCK(*vpp, 0); 799 800 return (0); 801 bad: 802 nfs_disconnect(nmp); 803 free((caddr_t)nmp, M_NFSMNT); 804 m_freem(nam); 805 return (error); 806 } 807 808 /* 809 * unmount system call 810 */ 811 int 812 nfs_unmount(mp, mntflags, p) 813 struct mount *mp; 814 int mntflags; 815 struct proc *p; 816 { 817 struct nfsmount *nmp; 818 struct vnode *vp; 819 int error, flags = 0; 820 821 if (mntflags & MNT_FORCE) 822 flags |= FORCECLOSE; 823 nmp = VFSTONFS(mp); 824 /* 825 * Goes something like this.. 826 * - Check for activity on the root vnode (other than ourselves). 827 * - Call vflush() to clear out vnodes for this file system, 828 * except for the root vnode. 829 * - Decrement reference on the vnode representing remote root. 830 * - Close the socket 831 * - Free up the data structures 832 */ 833 /* 834 * We need to decrement the ref. count on the nfsnode representing 835 * the remote root. See comment in mountnfs(). The VFS unmount() 836 * has done vput on this vnode, otherwise we would get deadlock! 837 */ 838 vp = nmp->nm_vnode; 839 error = vget(vp, LK_EXCLUSIVE | LK_RETRY); 840 if (error != 0) 841 return error; 842 843 if ((mntflags & MNT_FORCE) == 0 && vp->v_usecount > 2) { 844 vput(vp); 845 return (EBUSY); 846 } 847 848 /* 849 * Must handshake with nqnfs_clientd() if it is active. 850 */ 851 nmp->nm_iflag |= NFSMNT_DISMINPROG; 852 while (nmp->nm_inprog != NULLVP) 853 (void) tsleep((caddr_t)&lbolt, PSOCK, "nfsdism", 0); 854 error = vflush(mp, vp, flags); 855 if (error) { 856 vput(vp); 857 nmp->nm_iflag &= ~NFSMNT_DISMINPROG; 858 return (error); 859 } 860 861 /* 862 * We are now committed to the unmount; mark the mount structure 863 * as doomed so that any sleepers kicked awake by nfs_disconnect 864 * will go away cleanly. 865 */ 866 nmp->nm_iflag |= NFSMNT_DISMNT; 867 868 /* 869 * There are two reference counts to get rid of here 870 * (see comment in mountnfs()). 871 */ 872 vrele(vp); 873 vput(vp); 874 vgone(vp); 875 nfs_disconnect(nmp); 876 m_freem(nmp->nm_nam); 877 878 /* 879 * For NQNFS, let the server daemon free the nfsmount structure. 880 */ 881 if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) == 0) 882 free((caddr_t)nmp, M_NFSMNT); 883 return (0); 884 } 885 886 /* 887 * Return root of a filesystem 888 */ 889 int 890 nfs_root(mp, vpp) 891 struct mount *mp; 892 struct vnode **vpp; 893 { 894 struct vnode *vp; 895 struct nfsmount *nmp; 896 int error; 897 898 nmp = VFSTONFS(mp); 899 vp = nmp->nm_vnode; 900 error = vget(vp, LK_EXCLUSIVE | LK_RETRY); 901 if (error != 0) 902 return error; 903 if (vp->v_type == VNON) 904 vp->v_type = VDIR; 905 vp->v_flag = VROOT; 906 *vpp = vp; 907 return (0); 908 } 909 910 extern int syncprt; 911 912 /* 913 * Flush out the buffer cache 914 */ 915 /* ARGSUSED */ 916 int 917 nfs_sync(mp, waitfor, cred, p) 918 struct mount *mp; 919 int waitfor; 920 struct ucred *cred; 921 struct proc *p; 922 { 923 struct vnode *vp; 924 int error, allerror = 0; 925 926 /* 927 * Force stale buffer cache information to be flushed. 928 */ 929 loop: 930 for (vp = mp->mnt_vnodelist.lh_first; 931 vp != NULL; 932 vp = vp->v_mntvnodes.le_next) { 933 /* 934 * If the vnode that we are about to sync is no longer 935 * associated with this mount point, start over. 936 */ 937 if (vp->v_mount != mp) 938 goto loop; 939 if (waitfor == MNT_LAZY || VOP_ISLOCKED(vp) || 940 (LIST_EMPTY(&vp->v_dirtyblkhd) && 941 vp->v_uobj.uo_npages == 0)) 942 continue; 943 if (vget(vp, LK_EXCLUSIVE)) 944 goto loop; 945 error = VOP_FSYNC(vp, cred, 946 waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0, p); 947 if (error) 948 allerror = error; 949 vput(vp); 950 } 951 return (allerror); 952 } 953 954 /* 955 * NFS flat namespace lookup. 956 * Currently unsupported. 957 */ 958 /* ARGSUSED */ 959 int 960 nfs_vget(mp, ino, vpp) 961 struct mount *mp; 962 ino_t ino; 963 struct vnode **vpp; 964 { 965 966 return (EOPNOTSUPP); 967 } 968 969 /* 970 * Do that sysctl thang... 971 */ 972 int 973 nfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 974 int *name; 975 u_int namelen; 976 void *oldp; 977 size_t *oldlenp; 978 void *newp; 979 size_t newlen; 980 struct proc *p; 981 { 982 int rv; 983 984 /* 985 * All names at this level are terminal. 986 */ 987 if(namelen > 1) 988 return ENOTDIR; /* overloaded */ 989 990 switch(name[0]) { 991 case NFS_NFSSTATS: 992 if(!oldp) { 993 *oldlenp = sizeof nfsstats; 994 return 0; 995 } 996 997 if(*oldlenp < sizeof nfsstats) { 998 *oldlenp = sizeof nfsstats; 999 return ENOMEM; 1000 } 1001 1002 rv = copyout(&nfsstats, oldp, sizeof nfsstats); 1003 if(rv) return rv; 1004 1005 if(newp && newlen != sizeof nfsstats) 1006 return EINVAL; 1007 1008 if(newp) { 1009 return copyin(newp, &nfsstats, sizeof nfsstats); 1010 } 1011 return 0; 1012 1013 case NFS_IOTHREADS: 1014 nfs_getset_niothreads(0); 1015 1016 rv = (sysctl_int(oldp, oldlenp, newp, newlen, 1017 &nfs_niothreads)); 1018 1019 if (newp) 1020 nfs_getset_niothreads(1); 1021 1022 return rv; 1023 1024 default: 1025 return EOPNOTSUPP; 1026 } 1027 } 1028 1029 1030 /* 1031 * At this point, this should never happen 1032 */ 1033 /* ARGSUSED */ 1034 int 1035 nfs_fhtovp(mp, fhp, vpp) 1036 struct mount *mp; 1037 struct fid *fhp; 1038 struct vnode **vpp; 1039 { 1040 1041 return (EINVAL); 1042 } 1043 1044 /* ARGSUSED */ 1045 int 1046 nfs_checkexp(mp, nam, exflagsp, credanonp) 1047 struct mount *mp; 1048 struct mbuf *nam; 1049 int *exflagsp; 1050 struct ucred **credanonp; 1051 { 1052 1053 return (EINVAL); 1054 } 1055 1056 /* 1057 * Vnode pointer to File handle, should never happen either 1058 */ 1059 /* ARGSUSED */ 1060 int 1061 nfs_vptofh(vp, fhp) 1062 struct vnode *vp; 1063 struct fid *fhp; 1064 { 1065 1066 return (EINVAL); 1067 } 1068 1069 /* 1070 * Vfs start routine, a no-op. 1071 */ 1072 /* ARGSUSED */ 1073 int 1074 nfs_start(mp, flags, p) 1075 struct mount *mp; 1076 int flags; 1077 struct proc *p; 1078 { 1079 1080 return (0); 1081 } 1082 1083 /* 1084 * Do operations associated with quotas, not supported 1085 */ 1086 /* ARGSUSED */ 1087 int 1088 nfs_quotactl(mp, cmd, uid, arg, p) 1089 struct mount *mp; 1090 int cmd; 1091 uid_t uid; 1092 caddr_t arg; 1093 struct proc *p; 1094 { 1095 1096 return (EOPNOTSUPP); 1097 } 1098