summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authorrmacklem <rmacklem@FreeBSD.org>2011-05-05 00:11:09 +0000
committerrmacklem <rmacklem@FreeBSD.org>2011-05-05 00:11:09 +0000
commit64f3736572271b799837f8b28cb8b3c95ca9be0f (patch)
tree825458b03b0dacbd607f88b80b230e861e18fc5e /sys/fs
parent3a0f89209ce8f063a162c5c44aa86271d49a17c9 (diff)
downloadFreeBSD-src-64f3736572271b799837f8b28cb8b3c95ca9be0f.zip
FreeBSD-src-64f3736572271b799837f8b28cb8b3c95ca9be0f.tar.gz
Fix the new NFS client so that it handles the 64bit fields
that are now in "struct statfs" for NFSv3 and NFSv4. Since the ffiles value is uint64_t on the wire, I clip the value to INT64_MAX to avoid setting f_ffree negative. Tested by: kib MFC after: 2 weeks
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/nfsclient/nfs_clport.c34
1 files changed, 23 insertions, 11 deletions
diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c
index 2470a8c..0c3a4c9 100644
--- a/sys/fs/nfsclient/nfs_clport.c
+++ b/sys/fs/nfsclient/nfs_clport.c
@@ -838,21 +838,33 @@ void
nfscl_loadsbinfo(struct nfsmount *nmp, struct nfsstatfs *sfp, void *statfs)
{
struct statfs *sbp = (struct statfs *)statfs;
- nfsquad_t tquad;
if (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) {
sbp->f_bsize = NFS_FABLKSIZE;
- tquad.qval = sfp->sf_tbytes;
- sbp->f_blocks = (long)(tquad.qval / ((u_quad_t)NFS_FABLKSIZE));
- tquad.qval = sfp->sf_fbytes;
- sbp->f_bfree = (long)(tquad.qval / ((u_quad_t)NFS_FABLKSIZE));
- tquad.qval = sfp->sf_abytes;
- sbp->f_bavail = (long)(tquad.qval / ((u_quad_t)NFS_FABLKSIZE));
- tquad.qval = sfp->sf_tfiles;
- sbp->f_files = (tquad.lval[0] & 0x7fffffff);
- tquad.qval = sfp->sf_ffiles;
- sbp->f_ffree = (tquad.lval[0] & 0x7fffffff);
+ sbp->f_blocks = sfp->sf_tbytes / NFS_FABLKSIZE;
+ sbp->f_bfree = sfp->sf_fbytes / NFS_FABLKSIZE;
+ /*
+ * Although sf_abytes is uint64_t and f_bavail is int64_t,
+ * the value after dividing by NFS_FABLKSIZE is small
+ * enough that it will fit in 63bits, so it is ok to
+ * assign it to f_bavail without fear that it will become
+ * negative.
+ */
+ sbp->f_bavail = sfp->sf_abytes / NFS_FABLKSIZE;
+ sbp->f_files = sfp->sf_tfiles;
+ /* Since f_ffree is int64_t, clip it to 63bits. */
+ if (sfp->sf_ffiles > INT64_MAX)
+ sbp->f_ffree = INT64_MAX;
+ else
+ sbp->f_ffree = sfp->sf_ffiles;
} else if ((nmp->nm_flag & NFSMNT_NFSV4) == 0) {
+ /*
+ * The type casts to (int32_t) ensure that this code is
+ * compatible with the old NFS client, in that it will
+ * propagate bit31 to the high order bits. This may or may
+ * not be correct for NFSv2, but since it is a legacy
+ * environment, I'd rather retain backwards compatibility.
+ */
sbp->f_bsize = (int32_t)sfp->sf_bsize;
sbp->f_blocks = (int32_t)sfp->sf_blocks;
sbp->f_bfree = (int32_t)sfp->sf_bfree;
OpenPOWER on IntegriCloud