diff options
Diffstat (limited to 'module/zfs/zpl_super.c')
-rw-r--r-- | module/zfs/zpl_super.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/module/zfs/zpl_super.c b/module/zfs/zpl_super.c index 5c426b0a9..216c79401 100644 --- a/module/zfs/zpl_super.c +++ b/module/zfs/zpl_super.c @@ -181,6 +181,28 @@ zpl_statfs(struct dentry *dentry, struct kstatfs *statp) spl_fstrans_unmark(cookie); ASSERT3S(error, <=, 0); + /* + * If required by a 32-bit system call, dynamically scale the + * block size up to 16MiB and decrease the block counts. This + * allows for a maximum size of 64EiB to be reported. The file + * counts must be artificially capped at 2^32-1. + */ + if (unlikely(zpl_is_32bit_api())) { + while (statp->f_blocks > UINT32_MAX && + statp->f_bsize < SPA_MAXBLOCKSIZE) { + statp->f_frsize <<= 1; + statp->f_bsize <<= 1; + + statp->f_blocks >>= 1; + statp->f_bfree >>= 1; + statp->f_bavail >>= 1; + } + + uint64_t usedobjs = statp->f_files - statp->f_ffree; + statp->f_ffree = MIN(statp->f_ffree, UINT32_MAX - usedobjs); + statp->f_files = statp->f_ffree + usedobjs; + } + return (error); } |