Index: nfs_vfsops.c =================================================================== RCS file: /scratch/dcvs/src/sys/vfs/nfs/nfs_vfsops.c,v retrieving revision 1.9 diff -u -r1.9 nfs_vfsops.c --- nfs_vfsops.c 10 Oct 2003 22:01:13 -0000 1.9 +++ nfs_vfsops.c 24 Oct 2003 11:21:04 -0000 @@ -98,6 +98,14 @@ SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, ""); #endif +/* + * Tunable to determine the Read/Write unit size. Maximum + * value is NFS_MAXDATA (default). + */ +static int nfs_io_size = NFS_MAXDATA; +SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_io_size, CTLFLAG_RW, + &nfs_io_size, 0, "NFS optimal I/O unit size"); + static int nfs_iosize (struct nfsmount *nmp); static void nfs_decode_args (struct nfsmount *nmp, struct nfs_args *argp); @@ -170,7 +178,7 @@ static void nfs_convert_oargs (struct nfs_args *args, struct onfs_args *oargs); -static int +static __inline int nfs_iosize(nmp) struct nfsmount* nmp; { @@ -182,8 +190,21 @@ * that it is at least one VM page to avoid wasting buffer * space. */ - iosize = max(nmp->nm_rsize, nmp->nm_wsize); - if (iosize < PAGE_SIZE) iosize = PAGE_SIZE; + + /* + * Also make sure that nfs_io_size does not exceeed + * NFS_MAXDATA. No point having a SYSCTL_PROC() as it + * adds lot of unwanted overhead. + */ + if (nfs_io_size > NFS_MAXDATA) + iosize = NFS_MAXDATA; + else + iosize = nfs_io_size; + + /* iosize = max(nmp->nm_rsize, nmp->nm_wsize); */ + if (nfs_io_size < PAGE_SIZE) + iosize = PAGE_SIZE; + return iosize; } @@ -283,7 +304,16 @@ } nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3)); sbp->f_flags = nmp->nm_flag; - sbp->f_iosize = nfs_iosize(nmp); + + if (v3) { + if (nmp->nm_sotype == SOCK_STREAM) + sbp->f_iosize = nfs_iosize(nmp); + else + sbp->f_iosize = NFS_MAXDGRAMDATA; + } else { + sbp->f_iosize = NFS_V2MAXDATA; + } + if (v3) { sbp->f_bsize = NFS_FABLKSIZE; tquad = fxdr_hyper(&sfp->sf_tbytes); @@ -640,7 +670,7 @@ if (argp->sotype == SOCK_DGRAM) maxio = NFS_MAXDGRAMDATA; else - maxio = NFS_MAXDATA; + maxio = nfs_iosize(nmp); /* SOCK_STREAM case */ } else maxio = NFS_V2MAXDATA; @@ -842,7 +872,6 @@ struct nfsmount *nmp; struct nfsnode *np; int error; - struct vattr attrs; if (mp->mnt_flag & MNT_UPDATE) { nmp = VFSTONFS(mp); @@ -884,8 +913,16 @@ nmp->nm_timeo = NFS_TIMEO; nmp->nm_retry = NFS_RETRANS; - nmp->nm_wsize = NFS_WSIZE; - nmp->nm_rsize = NFS_RSIZE; + if (argp->flags & NFSMNT_NFSV3) { + if (argp->sotype == SOCK_STREAM) { + nmp->nm_wsize = nmp->nm_rsize = nfs_iosize(nmp); + } else { + nmp->nm_wsize = nmp->nm_rsize = NFS_MAXDGRAMDATA; + } + } else { + nmp->nm_wsize = NFS_WSIZE; + nmp->nm_rsize = NFS_RSIZE; + } nmp->nm_readdirsize = NFS_READDIRSIZE; nmp->nm_numgrps = NFS_MAXGRPS; nmp->nm_readahead = NFS_DEFRAHEAD; @@ -934,10 +971,16 @@ *vpp = NFSTOV(np); /* - * Get file attributes for the mountpoint. This has the side - * effect of filling in (*vpp)->v_type with the correct value. + * Retrieval of mountpoint attributes is delayed until nfs_rot + * or nfs_statfs are first called. This will happen either when + * we first traverse the mount point or if somebody does a df(1). + * + * NFSSTA_GOTFSINFO is used to flag if we have successfully + * retreived mountpoint attributes. In the case of NFSv3 we + * also flag static fsinfo. */ - VOP_GETATTR(*vpp, &attrs, curthread); + if (*vpp != NULL) + (*vpp)->v_type = VNON; /* * Lose the lock but keep the ref. @@ -1033,6 +1076,23 @@ if (error) return (error); vp = NFSTOV(np); + /* + * Get transfer parameters and root vnode attributes. + */ + if ((nmp->nm_state & NFSSTA_GOTFSINFO) == 0) { + if (nmp->nm_flag & NFSMNT_NFSV3) { + nfs_fsinfo(nmp, vp, curthread); + if (nmp->nm_sotype == SOCK_STREAM) + mp->mnt_stat.f_iosize = nfs_iosize(nmp); + else + mp->mnt_stat.f_iosize = NFS_MAXDGRAMDATA; + } else { + struct vattr attrs; + error = VOP_GETATTR(vp, &attrs, curthread); + if (!error) + nmp->nm_state |= NFSSTA_GOTFSINFO; + } + } if (vp->v_type == VNON) vp->v_type = VDIR; vp->v_flag = VROOT;