summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2003-04-24 20:36:32 +0000
committerpeter <peter@FreeBSD.org>2003-04-24 20:36:32 +0000
commit88151c4f8ca4d10d745d93aa6b8fd9f458f69446 (patch)
tree75f12fcfbbc9bfe19385974cd98c775ec51abfe9
parentd15e80125318595fdd804ace2f47a363bab6b812 (diff)
downloadFreeBSD-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.c34
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);
OpenPOWER on IntegriCloud