[PATCH 06/18] libmultipath: use shared_ptr for checker classes
Martin Wilck <[email protected]>
| Newsgroups | dev.linux.lists.dm-devel |
|---|---|
| Message-ID | <[email protected]> |
Utilize the share_ptr code for tracking the refcount of checker classes. Signed-off-by: Martin Wilck <[email protected]> --- libmultipath/checkers.c | 98 +++++++++-------------------------------- libmultipath/checkers.h | 2 - 2 files changed, 20 insertions(+), 80 deletions(-) diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c index 8f18ca6..a3b9cc8 100644 --- a/libmultipath/checkers.c +++ b/libmultipath/checkers.c @@ -39,41 +39,11 @@ const char *checker_state_name(int i) return checker_state_names[i]; } -static struct checker_class *alloc_checker_class(void) +static void free_checker_class(void *ptr) { - struct checker_class *c; - - c = calloc(1, sizeof(struct checker_class)); - if (c) { - INIT_LIST_HEAD(&c->node); - uatomic_set(&c->refcount, 1); - } - return c; -} - -/* Use uatomic_{sub,add}_return() to ensure proper memory barriers */ -static int checker_class_ref(struct checker_class *cls) -{ - return uatomic_add_return(&cls->refcount, 1); -} - -static int checker_class_unref(struct checker_class *cls) -{ - return uatomic_sub_return(&cls->refcount, 1); -} - -void free_checker_class(struct checker_class *c) -{ - int cnt; - + struct checker_class *c = ptr; if (!c) return; - cnt = checker_class_unref(c); - if (cnt != 0) { - condlog(cnt < 0 ? 1 : 4, "%s checker refcount %d", - c->name, cnt); - return; - } condlog(3, "unloading %s checker", c->name); list_del(&c->node); if (c->reset) @@ -84,7 +54,18 @@ void free_checker_class(struct checker_class *c) c->name, dlerror()); } } - free(c); +} + +static struct checker_class *alloc_checker_class(void) +{ + struct checker_class *c; + + c = alloc_shared_ptr(sizeof(*c), free_checker_class); + if (c) { + memset(c, 0, sizeof(*c)); + INIT_LIST_HEAD(&c->node); + } + return c; } void cleanup_checkers (void) @@ -92,9 +73,8 @@ void cleanup_checkers (void) struct checker_class *checker_loop; struct checker_class *checker_temp; - list_for_each_entry_safe(checker_loop, checker_temp, &checkers, node) { - free_checker_class(checker_loop); - } + list_for_each_entry_safe(checker_loop, checker_temp, &checkers, node) + put_shared_ptr(checker_loop); } static struct checker_class *checker_class_lookup(const char *name) @@ -163,8 +143,7 @@ static struct checker_class *add_checker_class(const char *name) goto out; c->mp_init = (int (*)(struct checker *)) dlsym(c->handle, "libcheck_mp_init"); - c->reset = (void (*)(void)) dlsym(c->handle, "libcheck_reset"); - c->thread = (void *(*)(void*)) dlsym(c->handle, "libcheck_thread"); + c->reset = (void (*)(void))dlsym(c->handle, "libcheck_reset"); c->pending = (int (*)(struct checker *)) dlsym(c->handle, "libcheck_pending"); c->need_wait = (bool (*)(struct checker *)) dlsym(c->handle, "libcheck_need_wait"); /* These 5 functions can be NULL. call dlerror() to clear out any @@ -199,7 +178,7 @@ done: list_add(&c->node, &checkers); return c; out: - free_checker_class(c); + put_shared_ptr(c); return NULL; } @@ -285,7 +264,7 @@ void checker_put (struct checker * dst) if (src && src->free) src->free(dst); checker_clear(dst); - free_checker_class(src); + put_shared_ptr(src); } int checker_get_state(struct checker *c) @@ -371,43 +350,6 @@ bad_id: return generic_msg[CHECKER_MSGID_NONE]; } -static void checker_cleanup_thread(void *arg) -{ - struct checker_class *cls = arg; - - free_checker_class(cls); - rcu_unregister_thread(); -} - -static void *checker_thread_entry(void *arg) -{ - struct checker_context *ctx = arg; - void *rv; - - rcu_register_thread(); - pthread_cleanup_push(checker_cleanup_thread, ctx->cls); - rv = ctx->cls->thread(ctx); - pthread_cleanup_pop(1); - return rv; -} - -int start_checker_thread(pthread_t *thread, const pthread_attr_t *attr, - struct checker_context *ctx) -{ - int rv; - - assert(ctx && ctx->cls && ctx->cls->thread); - /* Take a ref here, lest the class be freed before the thread starts */ - (void)checker_class_ref(ctx->cls); - rv = pthread_create(thread, attr, checker_thread_entry, ctx); - if (rv != 0) { - condlog(1, "failed to start checker thread for %s: %m", - ctx->cls->name); - checker_class_unref(ctx->cls); - } - return rv; -} - void checker_clear_message (struct checker *c) { if (!c) @@ -431,7 +373,7 @@ void checker_get(struct checker *dst, const char *name) if (!src) return; - (void)checker_class_ref(dst->cls); + get_shared_ptr(dst->cls); } int init_checkers(void) diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h index 694dfa3..630e987 100644 --- a/libmultipath/checkers.h +++ b/libmultipath/checkers.h @@ -135,7 +135,6 @@ struct checker; struct checker_class { struct list_head node; void *handle; - int refcount; int sync; char name[CHECKER_NAME_LEN]; int (*check)(struct checker *); @@ -143,7 +142,6 @@ struct checker_class { int (*mp_init)(struct checker *); /* to allocate the mpcontext */ void (*free)(struct checker *); /* to free the context */ void (*reset)(void); /* to reset the global variables */ - void *(*thread)(void *); /* async thread entry point */ int (*pending)(struct checker *); /* to recheck pending paths */ bool (*need_wait)(struct checker *); /* checker needs waiting for */ const char **msgtable; -- 2.54.0