]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfsprogs: introduce liburcu support
authorDave Chinner <dchinner@redhat.com>
Wed, 29 Sep 2021 20:48:03 +0000 (16:48 -0400)
committerEric Sandeen <sandeen@sandeen.net>
Wed, 29 Sep 2021 20:48:03 +0000 (16:48 -0400)
The upcoming buffer cache rework/kerenl sync-up requires atomic
variables. I could use C++11 atomics build into GCC, but they are a
pain to work with and shoe-horn into the kernel atomic variable API.

Much easier is to introduce a dependency on liburcu - the userspace
RCU library. This provides atomic variables that very closely match
the kernel atomic variable API, and it provides a very similar
memory model and memory barrier support to the kernel. And we get
RCU support that has an identical interface to the kernel and works
the same way.

Hence kernel code written with RCU algorithms and atomic variables
will just slot straight into the userspace xfsprogs code without us
having to think about whether the lockless algorithms will work in
userspace or not. This reduces glue and hoop jumping, and gets us
a step closer to having the entire userspace libxfs code MT safe.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
[chandan.babu@oracle.com: Add m4 macros to detect availability of liburcu]
Signed-off-by: Chandan Babu R <chandan.babu@oracle.com>
[sandeen: use dchinner's m4 macros]
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
21 files changed:
configure.ac
copy/Makefile
copy/xfs_copy.c
db/Makefile
debian/control
growfs/Makefile
include/builddefs.in
include/platform_defs.h.in
libfrog/workqueue.c
libxfs/init.c
libxfs/libxfs_priv.h
logprint/Makefile
m4/Makefile
m4/package_urcu.m4 [new file with mode: 0644]
mdrestore/Makefile
mkfs/Makefile
repair/Makefile
repair/prefetch.c
repair/progress.c
scrub/Makefile
scrub/progress.c

index 5687174515d97c6a47f7edb3bf0048625fffe164..9725a4ff177a10a15c10f6bf8998af41be695f8d 100644 (file)
@@ -154,6 +154,9 @@ AC_PACKAGE_NEED_UUIDCOMPARE
 AC_PACKAGE_NEED_PTHREAD_H
 AC_PACKAGE_NEED_PTHREADMUTEXINIT
 
+AC_PACKAGE_NEED_URCU_H
+AC_PACKAGE_NEED_RCU_INIT
+
 AC_HAVE_FADVISE
 AC_HAVE_MADVISE
 AC_HAVE_MINCORE
index 449b235fad4097831223cf5c96ab35cb1dfc3eca..1b00cd0d5743459426f0d5846110e0afd9fd9eef 100644 (file)
@@ -9,7 +9,8 @@ LTCOMMAND = xfs_copy
 CFILES = xfs_copy.c
 HFILES = xfs_copy.h
 
-LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBFROG) $(LIBUUID) $(LIBPTHREAD) $(LIBRT)
+LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBFROG) $(LIBUUID) $(LIBPTHREAD) $(LIBRT) \
+         $(LIBURCU)
 LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG) $(LIBFROG)
 LLDFLAGS = -static-libtool-libs
 
index fc7d225fe6a2792a75e0a10467d7810c34203bc9..f5eff96976d77c735aee8402b84bac7bd603e962 100644 (file)
@@ -110,6 +110,7 @@ do_message(int flags, int code, const char *fmt, ...)
                fprintf(stderr,
                        _("Aborting XFS copy -- logfile error -- reason: %s\n"),
                        strerror(errno));
+               rcu_unregister_thread();
                pthread_exit(NULL);
        }
 }
@@ -224,6 +225,7 @@ begin_reader(void *arg)
 {
        thread_args     *args = arg;
 
+       rcu_register_thread();
        for (;;) {
                pthread_mutex_lock(&args->wait);
                if (do_write(args, NULL))
@@ -243,6 +245,7 @@ handle_error:
        if (--glob_masks.num_working == 0)
                pthread_mutex_unlock(&mainwait);
        pthread_mutex_unlock(&glob_masks.mutex);
+       rcu_unregister_thread();
        pthread_exit(NULL);
        return NULL;
 }
index beafb105826932dba892c7e23f79239c36cb4502..5c017898289bd97fd0b7789bc17ac3bba6b33261 100644 (file)
@@ -18,7 +18,8 @@ CFILES = $(HFILES:.h=.c) btdump.c btheight.c convert.c info.c namei.c \
        timelimit.c
 LSRCFILES = xfs_admin.sh xfs_ncheck.sh xfs_metadump.sh
 
-LLDLIBS        = $(LIBXFS) $(LIBXLOG) $(LIBFROG) $(LIBUUID) $(LIBRT) $(LIBPTHREAD)
+LLDLIBS        = $(LIBXFS) $(LIBXLOG) $(LIBFROG) $(LIBUUID) $(LIBRT) $(LIBPTHREAD) \
+         $(LIBURCU)
 LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG) $(LIBFROG)
 LLDFLAGS += -static-libtool-libs
 
index e4ec897cc48832bbc1774ef76f33d69ed9b2fffe..71c0816753b4aa85cadb85985677f56887a88010 100644 (file)
@@ -3,7 +3,7 @@ Section: admin
 Priority: optional
 Maintainer: XFS Development Team <linux-xfs@vger.kernel.org>
 Uploaders: Nathan Scott <nathans@debian.org>, Anibal Monsalve Salazar <anibal@debian.org>, Bastian Germann <bastiangermann@fishpost.de>
-Build-Depends: libinih-dev (>= 53), uuid-dev, dh-autoreconf, debhelper (>= 5), gettext, libtool, libedit-dev, libblkid-dev (>= 2.17), linux-libc-dev, libdevmapper-dev, libattr1-dev, libicu-dev, pkg-config
+Build-Depends: libinih-dev (>= 53), uuid-dev, dh-autoreconf, debhelper (>= 5), gettext, libtool, libedit-dev, libblkid-dev (>= 2.17), linux-libc-dev, libdevmapper-dev, libattr1-dev, libicu-dev, pkg-config, liburcu-dev
 Standards-Version: 4.0.0
 Homepage: https://xfs.wiki.kernel.org/
 
index a107d348ab6d6cde947e898599de0c28db833acd..08601de77ab37eff6189fb476bedfee2a3d2d844 100644 (file)
@@ -9,7 +9,8 @@ LTCOMMAND = xfs_growfs
 
 CFILES = xfs_growfs.c
 
-LLDLIBS = $(LIBXFS) $(LIBXCMD) $(LIBFROG) $(LIBUUID) $(LIBRT) $(LIBPTHREAD)
+LLDLIBS = $(LIBXFS) $(LIBXCMD) $(LIBFROG) $(LIBUUID) $(LIBRT) $(LIBPTHREAD) \
+         $(LIBURCU)
 
 ifeq ($(ENABLE_EDITLINE),yes)
 LLDLIBS += $(LIBEDITLINE) $(LIBTERMCAP)
index e8f447f92baf3b8d510e5eca198b816617a5cfa1..78eddf4a9852fc8df252bcae113a283d331356fe 100644 (file)
@@ -22,6 +22,7 @@ LDFLAGS =
 
 LIBRT = @librt@
 LIBUUID = @libuuid@
+LIBURCU = @liburcu@
 LIBPTHREAD = @libpthread@
 LIBTERMCAP = @libtermcap@
 LIBEDITLINE = @libeditline@
@@ -125,7 +126,8 @@ CROND_DIR = @crond_dir@
 GCCFLAGS = -funsigned-char -fno-strict-aliasing -Wall
 #         -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-decl
 
-PCFLAGS = -D_GNU_SOURCE $(GCCFLAGS)
+# _LGPL_SOURCE is for liburcu to work correctly with GPL/LGPL programs
+PCFLAGS = -D_LGPL_SOURCE -D_GNU_SOURCE $(GCCFLAGS)
 ifeq ($(HAVE_UMODE_T),yes)
 PCFLAGS += -DHAVE_UMODE_T
 endif
index 539bdbecf6e0b9fe051f9e2dd3ab68b8c0c735dd..7c6b3ada0bb4132579e4d8d883c36bb3f0d54d3d 100644 (file)
@@ -23,6 +23,7 @@
 #include <limits.h>
 #include <stdbool.h>
 #include <libgen.h>
+#include <urcu.h>
 
 typedef struct filldir         filldir_t;
 
index 8c1a163e145f421d7d5ed743fe947807ddc25346..702a53e2f3c0a3e7f5ad3456ec741c347f65abf1 100644 (file)
@@ -11,6 +11,7 @@
 #include <stdbool.h>
 #include <errno.h>
 #include <assert.h>
+#include <urcu.h>
 #include "workqueue.h"
 
 /* Main processing thread */
@@ -24,6 +25,7 @@ workqueue_thread(void *arg)
         * Loop pulling work from the passed in work queue.
         * Check for notification to exit after every chunk of work.
         */
+       rcu_register_thread();
        while (1) {
                pthread_mutex_lock(&wq->lock);
 
@@ -60,6 +62,7 @@ workqueue_thread(void *arg)
                (wi->function)(wi->queue, wi->index, wi->arg);
                free(wi);
        }
+       rcu_unregister_thread();
 
        return NULL;
 }
index 1ec837911df72cf80e38ef3348a0e736a0a521c3..b06faf8acddeee4398a2296ae73cf83a55e48ff3 100644 (file)
@@ -310,6 +310,8 @@ libxfs_init(libxfs_init_t *a)
        fd = -1;
        flags = (a->isreadonly | a->isdirect);
 
+       rcu_init();
+       rcu_register_thread();
        radix_tree_init();
 
        if (a->volname) {
@@ -1023,6 +1025,7 @@ libxfs_destroy(
        libxfs_bcache_free();
        cache_destroy(libxfs_bcache);
        leaked = destroy_zones();
+       rcu_unregister_thread();
        if (getenv("LIBXFS_LEAK_CHECK") && leaked)
                exit(1);
 }
index 7181a858931224f6af4374e4fd85c612450139aa..db90e173f36e8740ebadb5004acde8215427d3d5 100644 (file)
@@ -210,8 +210,7 @@ enum ce { CE_DEBUG, CE_CONT, CE_NOTE, CE_WARN, CE_ALERT, CE_PANIC };
 #define spin_unlock(a)         ((void) 0)
 #define likely(x)              (x)
 #define unlikely(x)            (x)
-#define rcu_read_lock()                ((void) 0)
-#define rcu_read_unlock()      ((void) 0)
+
 /* Need to be able to handle this bare or in control flow */
 static inline bool WARN_ON(bool expr) {
        return (expr);
index 758504b39f0f2879f91a0d058bdcfd7dc728bc8b..cdedbd0dbe82275e49dc8984e3a8da67f9b00549 100644 (file)
@@ -12,7 +12,8 @@ CFILES = logprint.c \
         log_copy.c log_dump.c log_misc.c \
         log_print_all.c log_print_trans.c log_redo.c
 
-LLDLIBS        = $(LIBXFS) $(LIBXLOG) $(LIBFROG) $(LIBUUID) $(LIBRT) $(LIBPTHREAD)
+LLDLIBS        = $(LIBXFS) $(LIBXLOG) $(LIBFROG) $(LIBUUID) $(LIBRT) $(LIBPTHREAD) \
+         $(LIBURCU)
 LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG) $(LIBFROG)
 LLDFLAGS = -static-libtool-libs
 
index c6c73dc9bbee754c0f911899d7d31e233dd63438..7312053039f456d1b28c12f2ac901b797f4bb0e1 100644 (file)
@@ -24,6 +24,7 @@ LSRCFILES = \
        package_services.m4 \
        package_types.m4 \
        package_icu.m4 \
+       package_urcu.m4 \
        package_utilies.m4 \
        package_uuiddev.m4 \
        multilib.m4 \
diff --git a/m4/package_urcu.m4 b/m4/package_urcu.m4
new file mode 100644 (file)
index 0000000..f0337f3
--- /dev/null
@@ -0,0 +1,22 @@
+AC_DEFUN([AC_PACKAGE_NEED_URCU_H],
+  [ AC_CHECK_HEADERS(urcu.h)
+    if test $ac_cv_header_urcu_h = no; then
+       AC_CHECK_HEADERS(urcu.h,, [
+       echo
+       echo 'FATAL ERROR: could not find a valid urcu header.'
+       exit 1])
+    fi
+  ])
+
+AC_DEFUN([AC_PACKAGE_NEED_RCU_INIT],
+  [ AC_MSG_CHECKING([for liburcu])
+    AC_TRY_COMPILE([
+#define _GNU_SOURCE
+#include <urcu.h>
+    ], [
+       rcu_init();
+    ], liburcu=-lurcu
+       AC_MSG_RESULT(yes),
+       AC_MSG_RESULT(no))
+    AC_SUBST(liburcu)
+  ])
index d946955b0517eca64d803826a74ba795a5270641..8f28ddab326bacf4943e9b20685de79449cf08b4 100644 (file)
@@ -8,7 +8,8 @@ include $(TOPDIR)/include/builddefs
 LTCOMMAND = xfs_mdrestore
 CFILES = xfs_mdrestore.c
 
-LLDLIBS = $(LIBXFS) $(LIBFROG) $(LIBRT) $(LIBPTHREAD) $(LIBUUID)
+LLDLIBS = $(LIBXFS) $(LIBFROG) $(LIBRT) $(LIBPTHREAD) $(LIBUUID) \
+         $(LIBURCU)
 LTDEPENDENCIES = $(LIBXFS) $(LIBFROG)
 LLDFLAGS = -static
 
index b8805f7e1ea157ccda6f4ec171bb9d8cb5d6e5d4..811ba9dbe29b3bd4153b126fbb37ba38986edb6c 100644 (file)
@@ -11,7 +11,7 @@ HFILES =
 CFILES = proto.c xfs_mkfs.c
 
 LLDLIBS += $(LIBXFS) $(LIBXCMD) $(LIBFROG) $(LIBRT) $(LIBPTHREAD) $(LIBBLKID) \
-       $(LIBUUID) $(LIBINIH)
+       $(LIBUUID) $(LIBINIH) $(LIBURCU)
 LTDEPENDENCIES += $(LIBXFS) $(LIBXCMD) $(LIBFROG)
 LLDFLAGS = -static-libtool-libs
 
index 5f0764d1c3cdec33d491f98761698ad112bc2f04..47536ca1cc11825b4e44327c7b563152c1d46ff2 100644 (file)
@@ -72,7 +72,7 @@ CFILES = \
        xfs_repair.c
 
 LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBXCMD) $(LIBFROG) $(LIBUUID) $(LIBRT) \
-       $(LIBPTHREAD) $(LIBBLKID)
+       $(LIBPTHREAD) $(LIBBLKID) $(LIBURCU)
 LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG) $(LIBXCMD) $(LIBFROG)
 LLDFLAGS = -static-libtool-libs
 
index 48affa1869f8d4a53374316bd892d97eb2f59d2c..22a0c0c902d9781ae02b4ead39a3a4aa15d4cb92 100644 (file)
@@ -660,6 +660,7 @@ pf_io_worker(
        if (buf == NULL)
                return NULL;
 
+       rcu_register_thread();
        pthread_mutex_lock(&args->lock);
        while (!args->queuing_done || !btree_is_empty(args->io_queue)) {
                pftrace("waiting to start prefetch I/O for AG %d", args->agno);
@@ -682,6 +683,7 @@ pf_io_worker(
        free(buf);
 
        pftrace("finished prefetch I/O for AG %d", args->agno);
+       rcu_unregister_thread();
 
        return NULL;
 }
@@ -726,6 +728,8 @@ pf_queuing_worker(
        struct xfs_ino_geometry *igeo = M_IGEO(mp);
        unsigned long long      cluster_mask;
 
+       rcu_register_thread();
+
        cluster_mask = (1ULL << igeo->inodes_per_cluster) - 1;
 
        for (i = 0; i < PF_THREAD_COUNT; i++) {
@@ -739,7 +743,7 @@ pf_queuing_worker(
                        args->io_threads[i] = 0;
                        if (i == 0) {
                                pf_skip_prefetch_thread(args);
-                               return NULL;
+                               goto out;
                        }
                        /*
                         * since we have at least one I/O thread, use them for
@@ -779,7 +783,6 @@ pf_queuing_worker(
                         * Start processing as well, in case everything so
                         * far was already prefetched and the queue is empty.
                         */
-                       
                        pf_start_io_workers(args);
                        pf_start_processing(args);
                        sem_wait(&args->ra_count);
@@ -841,6 +844,8 @@ pf_queuing_worker(
        if (next_args)
                pf_create_prefetch_thread(next_args);
 
+out:
+       rcu_unregister_thread();
        return NULL;
 }
 
index e5a9c1efa822b2ad0a722d29a1f62e1a5ddffd34..f6c4d988444eea10ad671d0987af628725aacbf6 100644 (file)
@@ -182,6 +182,7 @@ progress_rpt_thread (void *p)
                do_error (_("progress_rpt: cannot malloc progress msg buffer\n"));
 
        running = 1;
+       rcu_register_thread();
 
        /*
         * Specify a repeating timer that fires each MSG_INTERVAL seconds.
@@ -286,7 +287,8 @@ progress_rpt_thread (void *p)
                do_warn(_("cannot delete timer\n"));
 
        free (msgbuf);
-       return (NULL);
+       rcu_unregister_thread();
+       return NULL;
 }
 
 int
index 47c887eb79a12e779c6da4ba88e733a9befc29b4..849e3afd5af36c13cfeddf5963dd981b19fa9912 100644 (file)
@@ -71,7 +71,8 @@ spacemap.c \
 vfs.c \
 xfs_scrub.c
 
-LLDLIBS += $(LIBHANDLE) $(LIBFROG) $(LIBPTHREAD) $(LIBICU_LIBS) $(LIBRT)
+LLDLIBS += $(LIBHANDLE) $(LIBFROG) $(LIBPTHREAD) $(LIBICU_LIBS) $(LIBRT) \
+       $(LIBURCU)
 LTDEPENDENCIES += $(LIBHANDLE) $(LIBFROG)
 LLDFLAGS = -static
 
index 15247b7c6d1b1db7cb18cc0ebbc90d5a8f1f0560..a3d096f98e2c8548d9583aebd4f476ce30d9215e 100644 (file)
@@ -116,6 +116,7 @@ progress_report_thread(void *arg)
        struct timespec         abstime;
        int                     ret;
 
+       rcu_register_thread();
        pthread_mutex_lock(&pt.lock);
        while (1) {
                uint64_t        progress_val;
@@ -139,6 +140,7 @@ progress_report_thread(void *arg)
                        progress_report(progress_val);
        }
        pthread_mutex_unlock(&pt.lock);
+       rcu_unregister_thread();
        return NULL;
 }