diff --git a/System/Posix/Files.hsc b/System/Posix/Files.hsc
--- a/System/Posix/Files.hsc
+++ b/System/Posix/Files.hsc
@@ -66,6 +66,7 @@
     -- * Extended file status
     ExtendedFileStatus(..),
     CAttributes(..),
+    haveStatx,
     -- ** Obtaining extended file status
     getExtendedFileStatus,
     -- ** Flags
diff --git a/System/Posix/Files/ByteString.hsc b/System/Posix/Files/ByteString.hsc
--- a/System/Posix/Files/ByteString.hsc
+++ b/System/Posix/Files/ByteString.hsc
@@ -66,6 +66,7 @@
     -- * Extended file status
     ExtendedFileStatus(..),
     CAttributes(..),
+    haveStatx,
     -- ** Obtaining extended file status
     getExtendedFileStatus,
     -- ** Flags
diff --git a/System/Posix/Files/Common.hsc b/System/Posix/Files/Common.hsc
--- a/System/Posix/Files/Common.hsc
+++ b/System/Posix/Files/Common.hsc
@@ -122,6 +122,7 @@
     isDirectoryX,
     isSymbolicLinkX,
     isSocketX,
+    haveStatx,
 
     -- * Setting file sizes
     setFdSize,
@@ -939,7 +940,7 @@
 
 -- | Want @stx_mnt_id@.
 pattern StatxMntId :: StatxMask
-#ifdef STATX_MNT_ID
+#ifdef HAVE_STATX_MNT_ID
 pattern StatxMntId = StatxMask (#const STATX_MNT_ID)
 #else
 pattern StatxMntId = StatxMask 0
@@ -1159,11 +1160,11 @@
 {-# WARNING specialDeviceIDX "specialDeviceIDX: not available on this platform, will throw error (CPP guard: @#if HAVE_SYS_SYSMACROS_H@)" #-}
 specialDeviceIDX _ = error "specialDeviceIDX not available on this platform"
 #endif
-#ifdef STATX_MNT_ID
+#ifdef HAVE_STATX_MNT_ID
 mountIDX (ExtendedFileStatus statx) =
   unsafePerformIO $ withForeignPtr statx $ (#peek struct statx, stx_mnt_id)
 #else
-{-# WARNING mountIDX "mountIDX: not available on this platform, will throw error (CPP guard: @#if STATX_MNT_ID@)" #-}
+{-# WARNING mountIDX "mountIDX: not available on this platform, will throw error (CPP guard: @#if HAVE_STATX_MNT_ID@)" #-}
 mountIDX _ = error "mountIDX not available on this platform"
 #endif
 fileBlockSizeX (ExtendedFileStatus statx) = unsafePerformIO $ do
@@ -1346,3 +1347,11 @@
 getExtendedFileStatus_ _ _ _ _ = ioError (ioeSetLocation unsupportedOperation "getExtendedFileStatus")
 #endif
 
+-- | Whether 'statx' is available on this platform and 'getExtendedFileStatus' and
+-- related functions will work.
+haveStatx :: Bool
+#ifdef HAVE_STATX
+haveStatx = True
+#else
+haveStatx = False
+#endif
diff --git a/System/Posix/Files/PosixString.hsc b/System/Posix/Files/PosixString.hsc
--- a/System/Posix/Files/PosixString.hsc
+++ b/System/Posix/Files/PosixString.hsc
@@ -62,6 +62,7 @@
     -- * Extended file status
     ExtendedFileStatus(..),
     CAttributes(..),
+    haveStatx,
     -- ** Obtaining extended file status
     getExtendedFileStatus,
     -- ** Flags
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,10 @@
 # Changelog for [`unix` package](http://hackage.haskell.org/package/unix)
 
+## 2.8.4.0 *Dec 2023*
+
+  * add `haveStatx`
+  * fix `statx.stx_mnt_id` detection on buggy glibc, see [GHC #24072](https://gitlab.haskell.org/ghc/ghc/-/issues/24072)
+
 ## 2.8.3.0 *Oct 2023*
 
   * add `getExtendedFileStatus` (based on `statx`) style functions
diff --git a/configure b/configure
--- a/configure
+++ b/configure
@@ -666,7 +666,6 @@
 docdir
 oldincludedir
 includedir
-runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -738,7 +737,6 @@
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
-runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -991,15 +989,6 @@
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
-  -runstatedir | --runstatedir | --runstatedi | --runstated \
-  | --runstate | --runstat | --runsta | --runst | --runs \
-  | --run | --ru | --r)
-    ac_prev=runstatedir ;;
-  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
-  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
-  | --run=* | --ru=* | --r=*)
-    runstatedir=$ac_optarg ;;
-
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1137,7 +1126,7 @@
 for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
 		datadir sysconfdir sharedstatedir localstatedir includedir \
 		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-		libdir localedir mandir runstatedir
+		libdir localedir mandir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1290,7 +1279,6 @@
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
-  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
@@ -3824,7 +3812,7 @@
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -3870,7 +3858,7 @@
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -3894,7 +3882,7 @@
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -3939,7 +3927,7 @@
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -3963,7 +3951,7 @@
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -4284,6 +4272,42 @@
 $as_echo "#define HAVE_STRUCT_STATX 1" >>confdefs.h
 
 fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for statx.stx_mnt_id" >&5
+$as_echo_n "checking for statx.stx_mnt_id... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/stat.h>
+int
+main ()
+{
+
+struct statx statxbuf;
+statx(0, "", 0, STATX_BASIC_STATS | STATX_MNT_ID, &statxbuf);
+return statxbuf.stx_mnt_id;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_STATX_MNT_ID 1" >>confdefs.h
+
+
+else
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for F_GETLK from fcntl.h" >&5
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -50,6 +50,23 @@
 # check for statx
 AC_CHECK_FUNC([statx], [AC_DEFINE([HAVE_STATX_FUN],[1],[HAVE_STATX_FUN])],[],[#include <sys/stat.h>])
 AC_CHECK_TYPE([struct statx],[AC_DEFINE([HAVE_STRUCT_STATX],[1],[HAVE_STRUCT_STATX])],[],[#include <sys/stat.h>])
+AC_MSG_CHECKING(for statx.stx_mnt_id)
+AC_LINK_IFELSE([
+AC_LANG_PROGRAM([[#include <sys/stat.h>]],
+[[
+struct statx statxbuf;
+statx(0, "", 0, STATX_BASIC_STATS | STATX_MNT_ID, &statxbuf);
+return statxbuf.stx_mnt_id;
+]])],
+[
+AC_MSG_RESULT(yes)
+AC_DEFINE([HAVE_STATX_MNT_ID], [1], [Define to 1 if statx.stx_mnt_id is available.])
+],
+[
+AC_MSG_RESULT(no)
+]
+)
+
 
 AC_MSG_CHECKING(for F_GETLK from fcntl.h)
 AC_EGREP_CPP(yes,
diff --git a/include/HsUnixConfig.h.in b/include/HsUnixConfig.h.in
--- a/include/HsUnixConfig.h.in
+++ b/include/HsUnixConfig.h.in
@@ -309,6 +309,9 @@
 /* HAVE_STATX_FUN */
 #undef HAVE_STATX_FUN
 
+/* Define to 1 if statx.stx_mnt_id is available. */
+#undef HAVE_STATX_MNT_ID
+
 /* Define to 1 if you have the <stdint.h> header file. */
 #undef HAVE_STDINT_H
 
diff --git a/unix.cabal b/unix.cabal
--- a/unix.cabal
+++ b/unix.cabal
@@ -1,6 +1,6 @@
 cabal-version:  1.12
 name:           unix
-version:        2.8.3.0
+version:        2.8.4.0
 -- NOTE: Don't forget to update ./changelog.md
 
 license:        BSD3
