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.
This commit is contained in:
parent
9d6adf55ce
commit
283995afb1
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user