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