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