diff options
author | peter <peter@FreeBSD.org> | 2003-04-24 20:36:32 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2003-04-24 20:36:32 +0000 |
commit | 88151c4f8ca4d10d745d93aa6b8fd9f458f69446 (patch) | |
tree | 75f12fcfbbc9bfe19385974cd98c775ec51abfe9 | |
parent | d15e80125318595fdd804ace2f47a363bab6b812 (diff) | |
download | FreeBSD-src-88151c4f8ca4d10d745d93aa6b8fd9f458f69446.zip FreeBSD-src-88151c4f8ca4d10d745d93aa6b8fd9f458f69446.tar.gz |
Fix a bug with df on large (>1TB) nfsv3 file servers on 32 bit client
machines where the 'long' number of blocks in struct statfs wont fit.
Instead of chosing an artificial 512 byte block size, simply scale it up
until we avoid an overflow. NFSv3 reports the sizes in bytes, and the
blocksize is a figment of nfsclient's imagination.
-rw-r--r-- | sys/nfsclient/nfs_vfsops.c | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c index cee1ec8..acef9ea 100644 --- a/sys/nfsclient/nfs_vfsops.c +++ b/sys/nfsclient/nfs_vfsops.c @@ -74,6 +74,8 @@ __FBSDID("$FreeBSD$"); #include <nfsclient/nfsm_subs.h> #include <nfsclient/nfsdiskless.h> +#include <machine/limits.h> + MALLOC_DEFINE(M_NFSREQ, "NFS req", "NFS request header"); MALLOC_DEFINE(M_NFSBIGFH, "NFSV3 bigfh", "NFS version 3 file handle"); MALLOC_DEFINE(M_NFSDIROFF, "NFSV3 diroff", "NFS directory offset data"); @@ -245,6 +247,7 @@ nfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td) struct mbuf *mreq, *mrep, *md, *mb; struct nfsnode *np; u_quad_t tquad; + int bsize; #ifndef nolint sfp = NULL; @@ -272,17 +275,26 @@ nfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td) sbp->f_flags = nmp->nm_flag; sbp->f_iosize = nfs_iosize(nmp); if (v3) { - sbp->f_bsize = NFS_FABLKSIZE; - tquad = fxdr_hyper(&sfp->sf_tbytes); - sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); - tquad = fxdr_hyper(&sfp->sf_fbytes); - sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); - tquad = fxdr_hyper(&sfp->sf_abytes); - sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); - sbp->f_files = (fxdr_unsigned(int32_t, - sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff); - sbp->f_ffree = (fxdr_unsigned(int32_t, - sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff); + for (bsize = NFS_FABLKSIZE; ; bsize *= 2) { + sbp->f_bsize = bsize; + tquad = fxdr_hyper(&sfp->sf_tbytes); + if ((tquad / bsize) > LONG_MAX) + continue; + sbp->f_blocks = tquad / bsize; + tquad = fxdr_hyper(&sfp->sf_fbytes); + if ((tquad / bsize) > LONG_MAX) + continue; + sbp->f_bfree = tquad / bsize; + tquad = fxdr_hyper(&sfp->sf_abytes); + if ((tquad / bsize) > LONG_MAX) + continue; + sbp->f_bavail = tquad / bsize; + sbp->f_files = (fxdr_unsigned(int32_t, + sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff); + sbp->f_ffree = (fxdr_unsigned(int32_t, + sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff); + break; + } } else { sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize); sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks); |