git: 3e60d3d3c4b3 - stable/13 - linux(4): Rework statfs conversion routine.

From: Dmitry Chagin <dchagin_at_FreeBSD.org>
Date: Mon, 06 Feb 2023 19:07:39 UTC
The branch stable/13 has been updated by dchagin:

URL: https://cgit.FreeBSD.org/src/commit/?id=3e60d3d3c4b3e9690c0f1a77fa163e3d07c9b245

commit 3e60d3d3c4b3e9690c0f1a77fa163e3d07c9b245
Author:     Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2023-01-28 10:19:41 +0000
Commit:     Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2023-02-06 19:06:29 +0000

    linux(4): Rework statfs conversion routine.
    
    Rework the routines to convert a native statfs structure (with fixed-size 64-bit
    counters) to a Linux statfs structure (with long-sized counters) for 32-bit apps.
    
    Instead of following Linux and return an EOVERFLOW error from statfs() family of
    syscalls when actual fs stat value(s) are large enough to not fit into 32 bits,
    apply scale logics used by FreeBSD to convert a 5.x statfs structure to a 4.x
    statfs structure.
    
    For more details see cc479dda.
    
    Tested by:              glebius
    MFC after:              1 week
    
    (cherry picked from commit 953688e823a67c3e9c0096252c33b1e7ecf9a095)
---
 sys/compat/linux/linux_stats.c | 18 +++++++-----------
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c
index fb2dd2fe01ef..63a5c37e1acf 100644
--- a/sys/compat/linux/linux_stats.c
+++ b/sys/compat/linux/linux_stats.c
@@ -413,26 +413,22 @@ bsd_to_linux_ftype(const char *fstypename)
 static int
 bsd_to_linux_statfs(struct statfs *bsd_statfs, struct l_statfs *linux_statfs)
 {
-#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
-	uint64_t tmp;
-
-#define	LINUX_HIBITS	0xffffffff00000000ULL
 
-	tmp = bsd_statfs->f_blocks | bsd_statfs->f_bfree | bsd_statfs->f_files |
-	    bsd_statfs->f_bsize;
-	if ((bsd_statfs->f_bavail != -1 && (bsd_statfs->f_bavail & LINUX_HIBITS)) ||
-	    (bsd_statfs->f_ffree != -1 && (bsd_statfs->f_ffree & LINUX_HIBITS)) ||
-	    (tmp & LINUX_HIBITS))
-		return (EOVERFLOW);
-#undef	LINUX_HIBITS
+#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
+	statfs_scale_blocks(bsd_statfs, INT32_MAX);
 #endif
 	linux_statfs->f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
 	linux_statfs->f_bsize = bsd_statfs->f_bsize;
 	linux_statfs->f_blocks = bsd_statfs->f_blocks;
 	linux_statfs->f_bfree = bsd_statfs->f_bfree;
 	linux_statfs->f_bavail = bsd_statfs->f_bavail;
+#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
+	linux_statfs->f_ffree = MIN(bsd_statfs->f_ffree, INT32_MAX);
+	linux_statfs->f_files = MIN(bsd_statfs->f_files, INT32_MAX);
+#else
 	linux_statfs->f_ffree = bsd_statfs->f_ffree;
 	linux_statfs->f_files = bsd_statfs->f_files;
+#endif
 	linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
 	linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
 	linux_statfs->f_namelen = MAXNAMLEN;