From 91d4f22fdadc39c24db6782857a820bb2a89e4d3 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Fri, 2 Oct 2009 17:09:13 -0700 Subject: [PATCH] NFS - Fix BIO size panics * NFS calculates the BIO block size and stores it in mnt_stat.f_iosize. This field was getting overwritten with default values by STATFS being passing &mp->mnt_stat from the kernel. Conditionalize the field so it no longer gets overwritten, and also correct nm_rsize/nm_wsize tests to use the smaller of the two specifications for the BIO block size. * Fixes diskless NFS root mounts, and NFS mounts which use smaller blocksizes. Reported-by: Rumko , and others --- sys/vfs/nfs/nfs_vfsops.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/sys/vfs/nfs/nfs_vfsops.c b/sys/vfs/nfs/nfs_vfsops.c index fd3988fbf0..e1152bac3b 100644 --- a/sys/vfs/nfs/nfs_vfsops.c +++ b/sys/vfs/nfs/nfs_vfsops.c @@ -334,7 +334,6 @@ nfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred) } NULLOUT(sfp = nfsm_dissect(&info, NFSX_STATFS(info.v3))); sbp->f_flags = nmp->nm_flag; - sbp->f_iosize = nfs_iosize(info.v3, nmp->nm_sotype); if (info.v3) { sbp->f_bsize = NFS_FABLKSIZE; @@ -356,9 +355,16 @@ nfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred) sbp->f_files = 0; sbp->f_ffree = 0; } + + /* + * Some values are pre-set in mnt_stat. Note in particular f_iosize + * cannot be changed once the filesystem is mounted as it is used + * as the basis for BIOs. + */ if (sbp != &mp->mnt_stat) { sbp->f_type = mp->mnt_vfc->vfc_typenum; bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); + sbp->f_iosize = mp->mnt_stat.f_iosize; } m_freem(info.mrep); info.mrep = NULL; @@ -500,6 +506,14 @@ nfs_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct thread *td) if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize) nmp->nm_maxfilesize = maxfsize; nmp->nm_state |= NFSSTA_GOTFSINFO; + + /* + * Use the smaller of rsize/wsize for the biosize. + */ + if (nmp->nm_rsize < nmp->nm_wsize) + nmp->nm_mountp->mnt_stat.f_iosize = nmp->nm_rsize; + else + nmp->nm_mountp->mnt_stat.f_iosize = nmp->nm_wsize; } m_freem(info.mrep); info.mrep = NULL; @@ -1218,11 +1232,14 @@ nfs_root(struct mount *mp, struct vnode **vpp) /* * Get transfer parameters and root vnode attributes + * + * NOTE: nfs_fsinfo() is expected to override the default + * f_iosize we set. */ if ((nmp->nm_state & NFSSTA_GOTFSINFO) == 0) { if (nmp->nm_flag & NFSMNT_NFSV3) { - error = nfs_fsinfo(nmp, vp, curthread); mp->mnt_stat.f_iosize = nfs_iosize(1, nmp->nm_sotype); + error = nfs_fsinfo(nmp, vp, curthread); } else { if ((error = VOP_GETATTR(vp, &attrs)) == 0) nmp->nm_state |= NFSSTA_GOTFSINFO; -- 2.11.4.GIT