summaryrefslogtreecommitdiffstats
path: root/sys/nfsclient/nfs_vfsops.c
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 /sys/nfsclient/nfs_vfsops.c
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.
Diffstat (limited to 'sys/nfsclient/nfs_vfsops.c')
-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