]> git-server-git.apps.pok.os.sepia.ceph.com Git - xfsprogs-dev.git/commitdiff
libfrog: hoist some utilities from libxfs
authorDarrick J. Wong <djwong@kernel.org>
Sun, 22 Feb 2026 22:41:02 +0000 (14:41 -0800)
committerAndrey Albershteyn <aalbersh@kernel.org>
Wed, 8 Apr 2026 19:39:56 +0000 (21:39 +0200)
This started with a desire to move the duplicate cmn_err declarations in
libxfs into libfrog/util.h ahead of the patch that renames libxfs_priv.h
to xfs_platform.h.

Then this patch expanded in scope when I realized that there were
several other utility functions that weren't specific to xfs; those go
in libfrog.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
include/libxfs.h
include/platform_defs.h
include/xfs_fs_compat.h
libfrog/Makefile
libfrog/util.c
libfrog/util.h
libxfs/Makefile
libxfs/libxfs_priv.h
libxfs/util.c

index 1e0d1a48fbb698fbb60d449dd04a0e6f7a33cb17..68d1f351f70093bd2b6364878cdc7c52482212fb 100644 (file)
@@ -26,6 +26,7 @@
 #include "libfrog/radix-tree.h"
 #include "libfrog/bitmask.h"
 #include "libfrog/div64.h"
+#include "libfrog/util.h"
 #include "atomic.h"
 #include "spinlock.h"
 
@@ -187,12 +188,6 @@ int        libxfs_alloc_file_space(struct xfs_inode *ip, xfs_off_t offset,
 int    libxfs_file_write(struct xfs_inode *ip, void *buf, off_t pos,
                size_t len);
 
-/* XXX: this is messy and needs fixing */
-#ifndef __LIBXFS_INTERNAL_XFS_H__
-extern void cmn_err(int, char *, ...);
-enum ce { CE_DEBUG, CE_CONT, CE_NOTE, CE_WARN, CE_ALERT, CE_PANIC };
-#endif
-
 #include "xfs_ialloc.h"
 
 #include "xfs_attr_leaf.h"
index 09129e0f22dcba985f04dbc5c1ec29f04e330d03..b2d80597a83aa4fc0d30b6827cb6ce8d76f17be0 100644 (file)
@@ -74,6 +74,14 @@ typedef unsigned short umode_t;
 
 extern int     platform_nproc(void);
 
+/* 64-bit seconds counter that works independently of the C library time_t. */
+typedef long long int time64_t;
+
+struct timespec64 {
+       time64_t        tv_sec;                 /* seconds */
+       long            tv_nsec;                /* nanoseconds */
+};
+
 #define NSEC_PER_SEC   (1000000000ULL)
 #define NSEC_PER_USEC  (1000ULL)
 
index 0077f00cb9490421ca5a348f07e2d82fc6508e65..ccf00424b1b85afa07db2225bb0c1f4784f79f81 100644 (file)
@@ -85,14 +85,6 @@ struct xfs_extent_data {
 #define XFS_IOC_CLONE_RANGE     _IOW (0x94, 13, struct xfs_clone_args)
 #define XFS_IOC_FILE_EXTENT_SAME _IOWR(0x94, 54, struct xfs_extent_data)
 
-/* 64-bit seconds counter that works independently of the C library time_t. */
-typedef long long int time64_t;
-
-struct timespec64 {
-       time64_t        tv_sec;                 /* seconds */
-       long            tv_nsec;                /* nanoseconds */
-};
-
 #define U32_MAX                ((uint32_t)~0U)
 #define S32_MAX                ((int32_t)(U32_MAX >> 1))
 #define S32_MIN                ((int32_t)(-S32_MAX - 1))
index 9f405ffe347566661cc0f16c47e1c1dc91fae60b..927bd8d0957fabf3bf566af12594809e36147c31 100644 (file)
@@ -82,6 +82,10 @@ else
 HAVE_GETTEXT = False
 endif
 
+ifeq ($(HAVE_GETRANDOM_NONBLOCK),yes)
+LCFLAGS += -DHAVE_GETRANDOM_NONBLOCK
+endif
+
 default: ltdepend $(LTLIBRARY) $(GETTEXT_PY)
 
 crc32table.h: gen_crc32table.c crc32defs.h
index 4e130c884c17a2124bb5da1085f04400cea3f65e..d49cf72426f6c8c967ab36f70ab6dbde863d8d6b 100644 (file)
@@ -6,6 +6,12 @@
 #include "platform_defs.h"
 #include "util.h"
 
+#ifdef HAVE_GETRANDOM_NONBLOCK
+#include <sys/random.h>
+#endif
+
+extern char *progname;
+
 /*
  * libfrog is a collection of miscellaneous userspace utilities.
  * It's a library of Funny Random Oddball Gunk <cough>.
@@ -48,3 +54,163 @@ log2_rounddown(unsigned long long i)
        }
        return rval;
 }
+
+/*
+ * current_fixed_time() tries to detect if SOURCE_DATE_EPOCH is in our
+ * environment, and set input timespec's timestamp to that value.
+ *
+ * Returns true on success, fail otherwise.
+ */
+bool
+current_fixed_time(
+       struct timespec64       *tv)
+{
+       /*
+        * To avoid many getenv() we'll use an initialization static flag, so
+        * we only read once.
+        */
+       static bool             enabled = false;
+       static bool             read_env = false;
+       static time64_t         epoch;
+       char                    *endp;
+       char                    *source_date_epoch;
+
+       if (!read_env) {
+               read_env = true;
+               source_date_epoch = getenv("SOURCE_DATE_EPOCH");
+               if (source_date_epoch && source_date_epoch[0] != '\0') {
+                       errno = 0;
+                       epoch = strtoll(source_date_epoch, &endp, 10);
+                       if (errno != 0 || *endp != '\0') {
+                               fprintf(stderr,
+                       "%s: SOURCE_DATE_EPOCH '%s' invalid timestamp, ignoring.\n",
+                               progname, source_date_epoch);
+
+                               return false;
+                       }
+
+                       enabled = true;
+               }
+       }
+
+       /*
+        * This will happen only if we successfully read a valid
+        * SOURCE_DATE_EPOCH and properly initiated the epoch value.
+        */
+       if (read_env && enabled) {
+               tv->tv_sec = epoch;
+               tv->tv_nsec = 0;
+               return true;
+       }
+
+       /*
+        * We initialized but had no valid SOURCE_DATE_EPOCH so we fall back
+        * to regular behaviour.
+        */
+       return false;
+}
+
+void
+cmn_err(int level, char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       vfprintf(stderr, fmt, ap);
+       fputs("\n", stderr);
+       va_end(ap);
+}
+
+unsigned int
+hweight8(unsigned int w)
+{
+       unsigned int res = w - ((w >> 1) & 0x55);
+       res = (res & 0x33) + ((res >> 2) & 0x33);
+       return (res + (res >> 4)) & 0x0F;
+}
+
+unsigned int
+hweight32(unsigned int w)
+{
+       unsigned int res = w - ((w >> 1) & 0x55555555);
+       res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
+       res = (res + (res >> 4)) & 0x0F0F0F0F;
+       res = res + (res >> 8);
+       return (res + (res >> 16)) & 0x000000FF;
+}
+
+unsigned int
+hweight64(uint64_t w)
+{
+       return hweight32((unsigned int)w) +
+              hweight32((unsigned int)(w >> 32));
+}
+
+/*
+ * get_deterministic_seed() tries to detect if DETERMINISTIC_SEED=1 is in our
+ * environment, and set our result to 0x53454544 (SEED) instead of
+ * extracting from getrandom().
+ *
+ * Returns true on success, fail otherwise.
+ */
+bool
+get_deterministic_seed(
+       uint32_t        *result)
+{
+       /*
+        * To avoid many getenv() we'll use an initialization static flag, so
+        * we only read once.
+        */
+       static bool     enabled = false;
+       static bool     read_env = false;
+       static uint32_t deterministic_seed = 0x53454544; /* SEED */
+       char            *seed_env;
+
+       if (!read_env) {
+               read_env = true;
+               seed_env = getenv("DETERMINISTIC_SEED");
+               if (seed_env && strcmp(seed_env, "1") == 0)
+                       enabled = true;
+       }
+
+       /*
+        * This will happen only if we successfully read DETERMINISTIC_SEED=1.
+        */
+       if (read_env && enabled) {
+               *result = deterministic_seed;
+
+               return true;
+       }
+
+       /*
+        * We initialized but had no DETERMINISTIC_SEED=1 in env so we fall
+        * back to regular behaviour.
+        */
+       return false;
+}
+
+#ifdef HAVE_GETRANDOM_NONBLOCK
+uint32_t
+get_random_u32(void)
+{
+       uint32_t        ret;
+       ssize_t         sz;
+
+       /*
+        * Check for DETERMINISTIC_SEED in environment, it means we're
+        * creating a reproducible filesystem.
+        * If it fails, fall back to returning getrandom() like we used to do.
+        */
+       if (get_deterministic_seed(&ret))
+               return ret;
+       /*
+        * Try to extract a u32 of randomness from /dev/urandom.  If that
+        * fails, fall back to returning zero like we used to do.
+        */
+       sz = getrandom(&ret, sizeof(ret), GRND_NONBLOCK);
+       if (sz != sizeof(ret))
+               return 0;
+
+       return ret;
+}
+#endif
index d1c4dd40fc926c0c64964604078d5b8455a9f2a0..48df6a691a8f6d67eddc923dd5fe15ba9eea5279 100644 (file)
@@ -7,6 +7,8 @@
 #define __LIBFROG_UTIL_H__
 
 #include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
 
 unsigned int   log2_roundup(unsigned int i);
 unsigned int   log2_rounddown(unsigned long long i);
@@ -18,4 +20,23 @@ unsigned int log2_rounddown(unsigned long long i);
 
 void *memchr_inv(const void *start, int c, size_t bytes);
 
+struct timespec64;
+
+bool current_fixed_time(struct timespec64 *tv);
+bool get_deterministic_seed(uint32_t *result);
+
+#ifdef HAVE_GETRANDOM_NONBLOCK
+uint32_t get_random_u32(void);
+#else
+#define get_random_u32()       (0)
+#endif
+
+extern void cmn_err(int, char *, ...);
+enum ce { CE_DEBUG, CE_CONT, CE_NOTE, CE_WARN, CE_ALERT, CE_PANIC };
+
+typedef unsigned char u8;
+unsigned int hweight8(unsigned int w);
+unsigned int hweight32(unsigned int w);
+unsigned int hweight64(uint64_t w);
+
 #endif /* __LIBFROG_UTIL_H__ */
index 61c43529b532b6fa79056c357dbc8006c62eac2c..c5e2161c33096ac5bc62757ef440114fe73848ba 100644 (file)
@@ -169,7 +169,7 @@ endif
 
 FCFLAGS = -I.
 
-LTLIBS = $(LIBPTHREAD) $(LIBRT)
+LTLIBS = $(LIBPTHREAD) $(LIBRT) $(LIBFROG)
 
 # don't try linking xfs_repair with a debug libxfs.
 DEBUG = -DNDEBUG
index f72f07fabdf21ea48e9ca02201f2017e6687fb0a..32b86b1df677c2e7ee8106aacaf34e4156a9fd87 100644 (file)
@@ -65,9 +65,6 @@
 #include "libfrog/crc32c.h"
 
 #include <sys/xattr.h>
-#ifdef HAVE_GETRANDOM_NONBLOCK
-#include <sys/random.h>
-#endif
 
 /* Zones used in libxfs allocations that aren't in shared header files */
 extern struct kmem_cache *xfs_buf_item_cache;
@@ -133,9 +130,6 @@ extern char    *progname;
 #define XFS_IGET_CREATE                        0x1
 #define XFS_IGET_UNTRUSTED             0x2
 
-extern void cmn_err(int, char *, ...);
-enum ce { CE_DEBUG, CE_CONT, CE_NOTE, CE_WARN, CE_ALERT, CE_PANIC };
-
 #define xfs_info(mp,fmt,args...)       cmn_err(CE_CONT, _(fmt), ## args)
 #define xfs_info_ratelimited(mp,fmt,args...) cmn_err(CE_CONT, _(fmt), ## args)
 #define xfs_notice(mp,fmt,args...)     cmn_err(CE_NOTE, _(fmt), ## args)
@@ -214,12 +208,6 @@ static inline bool WARN_ON(bool expr) {
 #define percpu_counter_read_positive(x)        ((*x) > 0 ? (*x) : 0)
 #define percpu_counter_sum_positive(x) ((*x) > 0 ? (*x) : 0)
 
-#ifdef HAVE_GETRANDOM_NONBLOCK
-uint32_t get_random_u32(void);
-#else
-#define get_random_u32()       (0)
-#endif
-
 #define PAGE_SIZE              getpagesize()
 extern unsigned int PAGE_SHIFT;
 
@@ -567,11 +555,6 @@ void xfs_log_item_init(struct xfs_mount *mp, struct xfs_log_item *lip, int type,
 #define XFS_STATS_INC_OFF(mp, off)
 #define XFS_STATS_ADD_OFF(mp, off, val)
 
-typedef unsigned char u8;
-unsigned int hweight8(unsigned int w);
-unsigned int hweight32(unsigned int w);
-unsigned int hweight64(__u64 w);
-
 #define xfs_buf_cache_init(bch)                (0)
 #define xfs_buf_cache_destroy(bch)     ((void)0)
 
index 2b1c32efc4709a0a8c3b39ffdf10f313d632435c..14b746ec7050921377fe96f14fb5fb9aedb12063 100644 (file)
@@ -137,61 +137,6 @@ xfs_log_calc_unit_res(
        return unit_bytes;
 }
 
-/*
- * current_fixed_time() tries to detect if SOURCE_DATE_EPOCH is in our
- * environment, and set input timespec's timestamp to that value.
- *
- * Returns true on success, fail otherwise.
- */
-static bool
-current_fixed_time(
-       struct                  timespec64 *tv)
-{
-       /*
-        * To avoid many getenv() we'll use an initialization static flag, so
-        * we only read once.
-        */
-       static bool             enabled = false;
-       static bool             read_env = false;
-       static time64_t         epoch;
-       char                    *endp;
-       char                    *source_date_epoch;
-
-       if (!read_env) {
-               read_env = true;
-               source_date_epoch = getenv("SOURCE_DATE_EPOCH");
-               if (source_date_epoch && source_date_epoch[0] != '\0') {
-                       errno = 0;
-                       epoch = strtoll(source_date_epoch, &endp, 10);
-                       if (errno != 0 || *endp != '\0') {
-                               fprintf(stderr,
-                       "%s: SOURCE_DATE_EPOCH '%s' invalid timestamp, ignoring.\n",
-                               progname, source_date_epoch);
-
-                               return false;
-                       }
-
-                       enabled = true;
-               }
-       }
-
-       /*
-        * This will happen only if we successfully read a valid
-        * SOURCE_DATE_EPOCH and properly initiated the epoch value.
-        */
-       if (read_env && enabled) {
-               tv->tv_sec = epoch;
-               tv->tv_nsec = 0;
-               return true;
-       }
-
-       /*
-        * We initialized but had no valid SOURCE_DATE_EPOCH so we fall back
-        * to regular behaviour.
-        */
-       return false;
-}
-
 struct timespec64
 current_time(struct inode *inode)
 {
@@ -364,17 +309,6 @@ error:
        return error;
 }
 
-void
-cmn_err(int level, char *fmt, ...)
-{
-       va_list ap;
-
-       va_start(ap, fmt);
-       vfprintf(stderr, fmt, ap);
-       fputs("\n", stderr);
-       va_end(ap);
-}
-
 /*
  * Warnings specifically for verifier errors.  Differentiate CRC vs. invalid
  * values, and omit the stack trace unless the error level is tuned high.
@@ -513,31 +447,6 @@ libxfs_zero_extent(
        return libxfs_device_zero(xfs_find_bdev_for_inode(ip), sector, size);
 }
 
-unsigned int
-hweight8(unsigned int w)
-{
-       unsigned int res = w - ((w >> 1) & 0x55);
-       res = (res & 0x33) + ((res >> 2) & 0x33);
-       return (res + (res >> 4)) & 0x0F;
-}
-
-unsigned int
-hweight32(unsigned int w)
-{
-       unsigned int res = w - ((w >> 1) & 0x55555555);
-       res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
-       res = (res + (res >> 4)) & 0x0F0F0F0F;
-       res = res + (res >> 8);
-       return (res + (res >> 16)) & 0x000000FF;
-}
-
-unsigned int
-hweight64(__u64 w)
-{
-       return hweight32((unsigned int)w) +
-              hweight32((unsigned int)(w >> 32));
-}
-
 /* xfs_health.c */
 
 /* Mark a per-fs metadata healed. */
@@ -579,75 +488,6 @@ void xfs_dirattr_mark_sick(struct xfs_inode *ip, int whichfork) { }
 void xfs_da_mark_sick(struct xfs_da_args *args) { }
 void xfs_inode_mark_sick(struct xfs_inode *ip, unsigned int mask) { }
 
-/*
- * get_deterministic_seed() tries to detect if DETERMINISTIC_SEED=1 is in our
- * environment, and set our result to 0x53454544 (SEED) instead of
- * extracting from getrandom().
- *
- * Returns true on success, fail otherwise.
- */
-static bool
-get_deterministic_seed(
-       uint32_t        *result)
-{
-       /*
-        * To avoid many getenv() we'll use an initialization static flag, so
-        * we only read once.
-        */
-       static bool     enabled = false;
-       static bool     read_env = false;
-       static uint32_t deterministic_seed = 0x53454544; /* SEED */
-       char            *seed_env;
-
-       if (!read_env) {
-               read_env = true;
-               seed_env = getenv("DETERMINISTIC_SEED");
-               if (seed_env && strcmp(seed_env, "1") == 0)
-                       enabled = true;
-       }
-
-       /*
-        * This will happen only if we successfully read DETERMINISTIC_SEED=1.
-        */
-       if (read_env && enabled) {
-               *result = deterministic_seed;
-
-               return true;
-       }
-
-       /*
-        * We initialized but had no DETERMINISTIC_SEED=1 in env so we fall
-        * back to regular behaviour.
-        */
-       return false;
-}
-
-#ifdef HAVE_GETRANDOM_NONBLOCK
-uint32_t
-get_random_u32(void)
-{
-       uint32_t        ret;
-       ssize_t         sz;
-
-       /*
-        * Check for DETERMINISTIC_SEED in environment, it means we're
-        * creating a reproducible filesystem.
-        * If it fails, fall back to returning getrandom() like we used to do.
-        */
-       if (get_deterministic_seed(&ret))
-               return ret;
-       /*
-        * Try to extract a u32 of randomness from /dev/urandom.  If that
-        * fails, fall back to returning zero like we used to do.
-        */
-       sz = getrandom(&ret, sizeof(ret), GRND_NONBLOCK);
-       if (sz != sizeof(ret))
-               return 0;
-
-       return ret;
-}
-#endif
-
 /*
  * Write a buffer to a file on the data device.  There must not be sparse holes
  * or unwritten extents, and the blocks underneath the file range will be