thread-cond-var.o \
thread-device.o \
thread-registry.o \
+ thread-utils.o \
uds-sysfs.o \
- uds-threads.o \
vdo.o \
vio.o \
volume-index.o \
#include "memory-alloc.h"
#include "numeric.h"
#include "string-utils.h"
-#include "uds-threads.h"
+#include "thread-utils.h"
static const u8 INDEX_CONFIG_MAGIC[] = "ALBIC";
static const u8 INDEX_CONFIG_VERSION_6_02[] = "06.02";
#include "funnel-queue.h"
#include "logger.h"
#include "memory-alloc.h"
-#include "uds-threads.h"
+#include "thread-utils.h"
/*
* This queue will attempt to handle requests in reasonably sized batches instead of reacting
#include "numeric.h"
#include "permassert.h"
#include "string-utils.h"
-#include "uds-threads.h"
+#include "thread-utils.h"
#include "uds.h"
/*
#include <linux/cache.h>
#include "config.h"
-#include "uds-threads.h"
+#include "thread-utils.h"
#include "uds.h"
/*
#include <linux/sched.h>
#include "thread-device.h"
-#include "uds-threads.h"
+#include "thread-utils.h"
struct priority_name {
const char *name;
#include "errors.h"
#include "logger.h"
#include "permassert.h"
-#include "uds-threads.h"
+#include "thread-utils.h"
const struct error_info vdo_status_list[] = {
{ "VDO_NOT_IMPLEMENTED", "Not implemented" },
#include <linux/minmax.h>
#include "errors.h"
+#include "thread-utils.h"
#include "time-utils.h"
-#include "uds-threads.h"
int uds_init_cond(struct cond_var *cv)
{
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2023 Red Hat
+ */
+
+#include "thread-utils.h"
+
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+
+#include "errors.h"
+#include "logger.h"
+#include "memory-alloc.h"
+
+static struct hlist_head thread_list;
+static struct mutex thread_mutex;
+static atomic_t thread_once = ATOMIC_INIT(0);
+
+struct thread {
+ void (*thread_function)(void *thread_data);
+ void *thread_data;
+ struct hlist_node thread_links;
+ struct task_struct *thread_task;
+ struct completion thread_done;
+};
+
+enum {
+ ONCE_NOT_DONE = 0,
+ ONCE_IN_PROGRESS = 1,
+ ONCE_COMPLETE = 2,
+};
+
+/* Run a function once only, and record that fact in the atomic value. */
+void uds_perform_once(atomic_t *once, void (*function)(void))
+{
+ for (;;) {
+ switch (atomic_cmpxchg(once, ONCE_NOT_DONE, ONCE_IN_PROGRESS)) {
+ case ONCE_NOT_DONE:
+ function();
+ atomic_set_release(once, ONCE_COMPLETE);
+ return;
+ case ONCE_IN_PROGRESS:
+ cond_resched();
+ break;
+ case ONCE_COMPLETE:
+ return;
+ default:
+ return;
+ }
+ }
+}
+
+static void thread_init(void)
+{
+ mutex_init(&thread_mutex);
+}
+
+static int thread_starter(void *arg)
+{
+ struct registered_thread allocating_thread;
+ struct thread *thread = arg;
+
+ thread->thread_task = current;
+ uds_perform_once(&thread_once, thread_init);
+ mutex_lock(&thread_mutex);
+ hlist_add_head(&thread->thread_links, &thread_list);
+ mutex_unlock(&thread_mutex);
+ uds_register_allocating_thread(&allocating_thread, NULL);
+ thread->thread_function(thread->thread_data);
+ uds_unregister_allocating_thread();
+ complete(&thread->thread_done);
+ return 0;
+}
+
+int uds_create_thread(void (*thread_function)(void *), void *thread_data,
+ const char *name, struct thread **new_thread)
+{
+ char *name_colon = strchr(name, ':');
+ char *my_name_colon = strchr(current->comm, ':');
+ struct task_struct *task;
+ struct thread *thread;
+ int result;
+
+ result = uds_allocate(1, struct thread, __func__, &thread);
+ if (result != UDS_SUCCESS) {
+ uds_log_warning("Error allocating memory for %s", name);
+ return result;
+ }
+
+ thread->thread_function = thread_function;
+ thread->thread_data = thread_data;
+ init_completion(&thread->thread_done);
+ /*
+ * Start the thread, with an appropriate thread name.
+ *
+ * If the name supplied contains a colon character, use that name. This causes uds module
+ * threads to have names like "uds:callbackW" and the main test runner thread to be named
+ * "zub:runtest".
+ *
+ * Otherwise if the current thread has a name containing a colon character, prefix the name
+ * supplied with the name of the current thread up to (and including) the colon character.
+ * Thus when the "kvdo0:dedupeQ" thread opens an index session, all the threads associated
+ * with that index will have names like "kvdo0:foo".
+ *
+ * Otherwise just use the name supplied. This should be a rare occurrence.
+ */
+ if ((name_colon == NULL) && (my_name_colon != NULL)) {
+ task = kthread_run(thread_starter, thread, "%.*s:%s",
+ (int) (my_name_colon - current->comm), current->comm,
+ name);
+ } else {
+ task = kthread_run(thread_starter, thread, "%s", name);
+ }
+
+ if (IS_ERR(task)) {
+ uds_free(thread);
+ return PTR_ERR(task);
+ }
+
+ *new_thread = thread;
+ return UDS_SUCCESS;
+}
+
+int uds_join_threads(struct thread *thread)
+{
+ while (wait_for_completion_interruptible(&thread->thread_done))
+ fsleep(1000);
+
+ mutex_lock(&thread_mutex);
+ hlist_del(&thread->thread_links);
+ mutex_unlock(&thread_mutex);
+ uds_free(thread);
+ return UDS_SUCCESS;
+}
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright 2023 Red Hat
+ */
+
+#ifndef THREAD_UTILS_H
+#define THREAD_UTILS_H
+
+#include <linux/atomic.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/mutex.h>
+#include <linux/semaphore.h>
+#include <linux/wait.h>
+
+#include "errors.h"
+
+/* Thread and synchronization utilities for UDS */
+
+struct cond_var {
+ wait_queue_head_t wait_queue;
+};
+
+struct thread;
+
+
+int __must_check uds_create_thread(void (*thread_function)(void *), void *thread_data,
+ const char *name, struct thread **new_thread);
+
+void uds_perform_once(atomic_t *once_state, void (*function) (void));
+
+int uds_join_threads(struct thread *thread);
+
+int __must_check uds_init_cond(struct cond_var *cond);
+int uds_signal_cond(struct cond_var *cond);
+int uds_broadcast_cond(struct cond_var *cond);
+int uds_wait_cond(struct cond_var *cond, struct mutex *mutex);
+int uds_destroy_cond(struct cond_var *cond);
+
+static inline int __must_check uds_init_mutex(struct mutex *mutex)
+{
+ mutex_init(mutex);
+ return UDS_SUCCESS;
+}
+
+static inline int uds_destroy_mutex(struct mutex *mutex)
+{
+ return UDS_SUCCESS;
+}
+
+static inline void uds_lock_mutex(struct mutex *mutex)
+{
+ mutex_lock(mutex);
+}
+
+static inline void uds_unlock_mutex(struct mutex *mutex)
+{
+ mutex_unlock(mutex);
+}
+
+
+#endif /* UDS_THREADS_H */
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright 2023 Red Hat
- */
-
-#include "uds-threads.h"
-
-#include <linux/completion.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-
-#include "errors.h"
-#include "logger.h"
-#include "memory-alloc.h"
-
-static struct hlist_head thread_list;
-static struct mutex thread_mutex;
-static atomic_t thread_once = ATOMIC_INIT(0);
-
-struct thread {
- void (*thread_function)(void *thread_data);
- void *thread_data;
- struct hlist_node thread_links;
- struct task_struct *thread_task;
- struct completion thread_done;
-};
-
-enum {
- ONCE_NOT_DONE = 0,
- ONCE_IN_PROGRESS = 1,
- ONCE_COMPLETE = 2,
-};
-
-/* Run a function once only, and record that fact in the atomic value. */
-void uds_perform_once(atomic_t *once, void (*function)(void))
-{
- for (;;) {
- switch (atomic_cmpxchg(once, ONCE_NOT_DONE, ONCE_IN_PROGRESS)) {
- case ONCE_NOT_DONE:
- function();
- atomic_set_release(once, ONCE_COMPLETE);
- return;
- case ONCE_IN_PROGRESS:
- cond_resched();
- break;
- case ONCE_COMPLETE:
- return;
- default:
- return;
- }
- }
-}
-
-static void thread_init(void)
-{
- mutex_init(&thread_mutex);
-}
-
-static int thread_starter(void *arg)
-{
- struct registered_thread allocating_thread;
- struct thread *thread = arg;
-
- thread->thread_task = current;
- uds_perform_once(&thread_once, thread_init);
- mutex_lock(&thread_mutex);
- hlist_add_head(&thread->thread_links, &thread_list);
- mutex_unlock(&thread_mutex);
- uds_register_allocating_thread(&allocating_thread, NULL);
- thread->thread_function(thread->thread_data);
- uds_unregister_allocating_thread();
- complete(&thread->thread_done);
- return 0;
-}
-
-int uds_create_thread(void (*thread_function)(void *), void *thread_data,
- const char *name, struct thread **new_thread)
-{
- char *name_colon = strchr(name, ':');
- char *my_name_colon = strchr(current->comm, ':');
- struct task_struct *task;
- struct thread *thread;
- int result;
-
- result = uds_allocate(1, struct thread, __func__, &thread);
- if (result != UDS_SUCCESS) {
- uds_log_warning("Error allocating memory for %s", name);
- return result;
- }
-
- thread->thread_function = thread_function;
- thread->thread_data = thread_data;
- init_completion(&thread->thread_done);
- /*
- * Start the thread, with an appropriate thread name.
- *
- * If the name supplied contains a colon character, use that name. This causes uds module
- * threads to have names like "uds:callbackW" and the main test runner thread to be named
- * "zub:runtest".
- *
- * Otherwise if the current thread has a name containing a colon character, prefix the name
- * supplied with the name of the current thread up to (and including) the colon character.
- * Thus when the "kvdo0:dedupeQ" thread opens an index session, all the threads associated
- * with that index will have names like "kvdo0:foo".
- *
- * Otherwise just use the name supplied. This should be a rare occurrence.
- */
- if ((name_colon == NULL) && (my_name_colon != NULL)) {
- task = kthread_run(thread_starter, thread, "%.*s:%s",
- (int) (my_name_colon - current->comm), current->comm,
- name);
- } else {
- task = kthread_run(thread_starter, thread, "%s", name);
- }
-
- if (IS_ERR(task)) {
- uds_free(thread);
- return PTR_ERR(task);
- }
-
- *new_thread = thread;
- return UDS_SUCCESS;
-}
-
-int uds_join_threads(struct thread *thread)
-{
- while (wait_for_completion_interruptible(&thread->thread_done))
- fsleep(1000);
-
- mutex_lock(&thread_mutex);
- hlist_del(&thread->thread_links);
- mutex_unlock(&thread_mutex);
- uds_free(thread);
- return UDS_SUCCESS;
-}
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright 2023 Red Hat
- */
-
-#ifndef UDS_THREADS_H
-#define UDS_THREADS_H
-
-#include <linux/atomic.h>
-#include <linux/delay.h>
-#include <linux/jiffies.h>
-#include <linux/mutex.h>
-#include <linux/semaphore.h>
-#include <linux/wait.h>
-
-#include "errors.h"
-#include "time-utils.h"
-
-/* Thread and synchronization utilities for UDS */
-
-struct cond_var {
- wait_queue_head_t wait_queue;
-};
-
-struct thread;
-
-
-int __must_check uds_create_thread(void (*thread_function)(void *), void *thread_data,
- const char *name, struct thread **new_thread);
-
-void uds_perform_once(atomic_t *once_state, void (*function) (void));
-
-int uds_join_threads(struct thread *thread);
-
-int __must_check uds_init_cond(struct cond_var *cond);
-int uds_signal_cond(struct cond_var *cond);
-int uds_broadcast_cond(struct cond_var *cond);
-int uds_wait_cond(struct cond_var *cond, struct mutex *mutex);
-int uds_destroy_cond(struct cond_var *cond);
-
-static inline int __must_check uds_init_mutex(struct mutex *mutex)
-{
- mutex_init(mutex);
- return UDS_SUCCESS;
-}
-
-static inline int uds_destroy_mutex(struct mutex *mutex)
-{
- return UDS_SUCCESS;
-}
-
-static inline void uds_lock_mutex(struct mutex *mutex)
-{
- mutex_lock(mutex);
-}
-
-static inline void uds_unlock_mutex(struct mutex *mutex)
-{
- mutex_unlock(mutex);
-}
-
-
-#endif /* UDS_THREADS_H */
#include "memory-alloc.h"
#include "numeric.h"
#include "permassert.h"
+#include "thread-utils.h"
#include "uds.h"
-#include "uds-threads.h"
/*
* The volume index is a combination of two separate subindexes, one containing sparse hook entries
#include "config.h"
#include "delta-index.h"
+#include "thread-utils.h"
#include "uds.h"
-#include "uds-threads.h"
/*
* The volume index is the primary top-level index for UDS. It contains records which map a record
#include "permassert.h"
#include "sparse-cache.h"
#include "string-utils.h"
-#include "uds-threads.h"
+#include "thread-utils.h"
/*
* The first block of the volume layout is reserved for the volume header, which is no longer used.
#include "permassert.h"
#include "radix-sort.h"
#include "sparse-cache.h"
+#include "thread-utils.h"
#include "uds.h"
-#include "uds-threads.h"
/*
* The volume manages deduplication records on permanent storage. The term "volume" can also refer