[dm-devel] [PATCH 3/5] libmultipath: change loading and resetting in directio
Benjamin Marzinski
bmarzins at redhat.com
Wed Feb 19 06:54:31 UTC 2020
The directio checker previously made sure to always keep an aio_group
around after loading or resetting the checker. There is no need to do
this, and removing this code simplifies the checker. With this change,
there is no longer a need for a load or unload checker function, only a
reset function which is run when the checker is reset or unloaded.
Changing this broke a number of tests, so the unit tests have been
updated as well.
Signed-off-by: Benjamin Marzinski <bmarzins at redhat.com>
---
libmultipath/checkers.c | 26 ++---
libmultipath/checkers.h | 2 +-
libmultipath/checkers/directio.c | 43 +-------
tests/directio.c | 177 +++++++++++++------------------
4 files changed, 81 insertions(+), 167 deletions(-)
diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c
index 5c7d3004..8d2be8a9 100644
--- a/libmultipath/checkers.c
+++ b/libmultipath/checkers.c
@@ -18,9 +18,7 @@ struct checker_class {
int (*init)(struct checker *); /* to allocate the context */
int (*mp_init)(struct checker *); /* to allocate the mpcontext */
void (*free)(struct checker *); /* to free the context */
- int (*load)(void); /* to allocate global variables */
- void (*unload)(void); /* to free global variables */
- int (*reset)(void); /* to reset the global variables */
+ void (*reset)(void); /* to reset the global variables */
const char **msgtable;
short msgtable_size;
};
@@ -69,8 +67,8 @@ void free_checker_class(struct checker_class *c)
}
condlog(3, "unloading %s checker", c->name);
list_del(&c->node);
- if (c->unload)
- c->unload();
+ if (c->reset)
+ c->reset();
if (c->handle) {
if (dlclose(c->handle) != 0) {
condlog(0, "Cannot unload checker %s: %s",
@@ -103,16 +101,14 @@ static struct checker_class *checker_class_lookup(const char *name)
return NULL;
}
-int reset_checker_classes(void)
+void reset_checker_classes(void)
{
- int ret = 0;
struct checker_class *c;
list_for_each_entry(c, &checkers, node) {
if (c->reset)
- ret = ret? ret : c->reset();
+ c->reset();
}
- return ret;
}
static struct checker_class *add_checker_class(const char *multipath_dir,
@@ -159,10 +155,8 @@ static struct checker_class *add_checker_class(const char *multipath_dir,
goto out;
c->mp_init = (int (*)(struct checker *)) dlsym(c->handle, "libcheck_mp_init");
- c->load = (int (*)(void)) dlsym(c->handle, "libcheck_load");
- c->unload = (void (*)(void)) dlsym(c->handle, "libcheck_unload");
- c->reset = (int (*)(void)) dlsym(c->handle, "libcheck_reset");
- /* These 4 functions can be NULL. call dlerror() to clear out any
+ c->reset = (void (*)(void)) dlsym(c->handle, "libcheck_reset");
+ /* These 2 functions can be NULL. call dlerror() to clear out any
* error string */
dlerror();
@@ -189,12 +183,6 @@ static struct checker_class *add_checker_class(const char *multipath_dir,
condlog(3, "checker %s: message table size = %d",
c->name, c->msgtable_size);
- if (c->load && c->load() != 0) {
- condlog(0, "%s: failed to load checker", c->name);
- c->unload = NULL;
- goto out;
- }
-
done:
c->sync = 1;
list_add(&c->node, &checkers);
diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h
index d9930467..b458118d 100644
--- a/libmultipath/checkers.h
+++ b/libmultipath/checkers.h
@@ -150,7 +150,7 @@ void checker_disable (struct checker *);
int checker_check (struct checker *, int);
int checker_is_sync(const struct checker *);
const char *checker_name (const struct checker *);
-int reset_checker_classes(void);
+void reset_checker_classes(void);
/*
* This returns a string that's best prepended with "$NAME checker",
* where $NAME is the return value of checker_name().
diff --git a/libmultipath/checkers/directio.c b/libmultipath/checkers/directio.c
index 813e61e2..6ad7c885 100644
--- a/libmultipath/checkers/directio.c
+++ b/libmultipath/checkers/directio.c
@@ -138,23 +138,11 @@ check_orphaned_group(struct aio_group *aio_grp)
return;
list_for_each(item, &aio_grp->orphans)
count++;
- if (count >= AIO_GROUP_SIZE) {
+ if (count >= AIO_GROUP_SIZE)
remove_aio_group(aio_grp);
- if (list_empty(&aio_grp_list))
- add_aio_group();
- }
}
-int libcheck_load (void)
-{
- if (add_aio_group() == NULL) {
- LOG(1, "libcheck_load failed: %s", strerror(errno));
- return 1;
- }
- return 0;
-}
-
-void libcheck_unload (void)
+void libcheck_reset (void)
{
struct aio_group *aio_grp, *tmp;
@@ -162,33 +150,6 @@ void libcheck_unload (void)
remove_aio_group(aio_grp);
}
-int libcheck_reset (void)
-{
- struct aio_group *aio_grp, *tmp, *reset_grp = NULL;
-
- /* If a clean existing aio_group exists, use that. Otherwise add a
- * new one */
- list_for_each_entry(aio_grp, &aio_grp_list, node) {
- if (aio_grp->holders == 0 &&
- list_empty(&aio_grp->orphans)) {
- reset_grp = aio_grp;
- break;
- }
- }
- if (!reset_grp)
- reset_grp = add_aio_group();
- if (!reset_grp) {
- LOG(1, "checker reset failed");
- return 1;
- }
-
- list_for_each_entry_safe(aio_grp, tmp, &aio_grp_list, node) {
- if (aio_grp != reset_grp)
- remove_aio_group(aio_grp);
- }
- return 0;
-}
-
int libcheck_init (struct checker * c)
{
unsigned long pgsize = getpagesize();
diff --git a/tests/directio.c b/tests/directio.c
index 236c514b..23fd2da9 100644
--- a/tests/directio.c
+++ b/tests/directio.c
@@ -217,7 +217,7 @@ void do_check_state(struct checker *c, int sync, int timeout, int chk_state)
memset(mock_events, 0, sizeof(mock_events));
}
-void do_libcheck_unload(int nr_aio_grps)
+void do_libcheck_reset(int nr_aio_grps)
{
int count = 0;
struct aio_group *aio_grp;
@@ -227,7 +227,7 @@ void do_libcheck_unload(int nr_aio_grps)
assert_int_equal(count, nr_aio_grps);
for (count = 0; count < nr_aio_grps; count++)
will_return(__wrap_io_destroy, 0);
- libcheck_unload();
+ libcheck_reset();
assert_true(list_empty(&aio_grp_list));
assert_int_equal(ioctx_count, 0);
}
@@ -278,31 +278,38 @@ static void check_aio_grp(struct aio_group *aio_grp, int holders,
assert_int_equal(orphans, count);
}
-static void do_libcheck_load(void)
+/* simple resetting test */
+static void test_reset(void **state)
{
- int count = 0;
- struct aio_group *aio_grp;
-
assert_true(list_empty(&aio_grp_list));
- will_return(__wrap_io_setup, 0);
- assert_int_equal(libcheck_load(), 0);
- list_for_each_entry(aio_grp, &aio_grp_list, node) {
- assert_int_equal(aio_grp->holders, 0);
- count++;
- }
- assert_int_equal(count, 1);
+ do_libcheck_reset(0);
}
-/* simple loading resetting and unloading test */
-static void test_load_reset_unload(void **state)
+/* tests initializing, then resetting, and then initializing again */
+static void test_init_reset_init(void **state)
{
- struct list_head *item;
- do_libcheck_load();
- item = aio_grp_list.next;
- assert_int_equal(libcheck_reset(), 0);
- assert_false(list_empty(&aio_grp_list));
- assert_true(item == aio_grp_list.next);
- do_libcheck_unload(1);
+ struct checker c = {0};
+ struct aio_group *aio_grp, *tmp_grp;
+
+ assert_true(list_empty(&aio_grp_list));
+ will_return(__wrap_io_setup, 0);
+ do_libcheck_init(&c, 4096, NULL);
+ aio_grp = get_aio_grp(&c);
+ check_aio_grp(aio_grp, 1, 0);
+ list_for_each_entry(tmp_grp, &aio_grp_list, node)
+ assert_ptr_equal(aio_grp, tmp_grp);
+ libcheck_free(&c);
+ check_aio_grp(aio_grp, 0, 0);
+ do_libcheck_reset(1);
+ will_return(__wrap_io_setup, 0);
+ do_libcheck_init(&c, 4096, NULL);
+ aio_grp = get_aio_grp(&c);
+ check_aio_grp(aio_grp, 1, 0);
+ list_for_each_entry(tmp_grp, &aio_grp_list, node)
+ assert_ptr_equal(aio_grp, tmp_grp);
+ libcheck_free(&c);
+ check_aio_grp(aio_grp, 0, 0);
+ do_libcheck_reset(1);
}
/* test initializing and then freeing 4096 checkers */
@@ -312,8 +319,8 @@ static void test_init_free(void **state)
struct checker c[4096] = {0};
struct aio_group *aio_grp;
- do_libcheck_load();
- aio_grp = list_entry(aio_grp_list.next, typeof(*aio_grp), node);
+ assert_true(list_empty(&aio_grp_list));
+ will_return(__wrap_io_setup, 0);
will_return(__wrap_io_setup, 0);
will_return(__wrap_io_setup, 0);
will_return(__wrap_io_setup, 0);
@@ -328,7 +335,7 @@ static void test_init_free(void **state)
do_libcheck_init(&c[i], 4096, NULL);
ct = (struct directio_context *)c[i].context;
assert_non_null(ct->aio_grp);
- if (i && (i & 1023) == 0)
+ if ((i & 1023) == 0)
aio_grp = ct->aio_grp;
else {
assert_ptr_equal(ct->aio_grp, aio_grp);
@@ -346,17 +353,9 @@ static void test_init_free(void **state)
libcheck_free(&c[i]);
assert_int_equal(aio_grp->holders, 1023 - (i & 1023));
}
- count = 0;
- list_for_each_entry(aio_grp, &aio_grp_list, node) {
+ list_for_each_entry(aio_grp, &aio_grp_list, node)
assert_int_equal(aio_grp->holders, 0);
- count++;
- }
- assert_int_equal(count, 4);
- will_return(__wrap_io_destroy, 0);
- will_return(__wrap_io_destroy, 0);
- will_return(__wrap_io_destroy, 0);
- assert_int_equal(libcheck_reset(), 0);
- do_libcheck_unload(1);
+ do_libcheck_reset(4);
}
/* check mixed initializing and freeing 4096 checkers */
@@ -366,7 +365,8 @@ static void test_multi_init_free(void **state)
struct checker c[4096] = {0};
struct aio_group *aio_grp;
- do_libcheck_load();
+ assert_true(list_empty(&aio_grp_list));
+ will_return(__wrap_io_setup, 0);
will_return(__wrap_io_setup, 0);
will_return(__wrap_io_setup, 0);
will_return(__wrap_io_setup, 0);
@@ -396,7 +396,7 @@ static void test_multi_init_free(void **state)
i++;
}
}
- do_libcheck_unload(4);
+ do_libcheck_reset(4);
}
/* simple single checker sync test */
@@ -406,12 +406,13 @@ static void test_check_state_simple(void **state)
struct async_req *req;
int res = 0;
- do_libcheck_load();
+ assert_true(list_empty(&aio_grp_list));
+ will_return(__wrap_io_setup, 0);
do_libcheck_init(&c, 4096, &req);
return_io_getevents_nr(NULL, 1, &req, &res);
do_check_state(&c, 1, 30, PATH_UP);
libcheck_free(&c);
- do_libcheck_unload(1);
+ do_libcheck_reset(1);
}
/* test sync timeout */
@@ -420,7 +421,8 @@ static void test_check_state_timeout(void **state)
struct checker c = {0};
struct aio_group *aio_grp;
- do_libcheck_load();
+ assert_true(list_empty(&aio_grp_list));
+ will_return(__wrap_io_setup, 0);
do_libcheck_init(&c, 4096, NULL);
aio_grp = get_aio_grp(&c);
return_io_getevents_none();
@@ -433,7 +435,7 @@ static void test_check_state_timeout(void **state)
will_return(__wrap_io_cancel, 0);
#endif
libcheck_free(&c);
- do_libcheck_unload(1);
+ do_libcheck_reset(1);
}
/* test async timeout */
@@ -442,7 +444,8 @@ static void test_check_state_async_timeout(void **state)
struct checker c = {0};
struct aio_group *aio_grp;
- do_libcheck_load();
+ assert_true(list_empty(&aio_grp_list));
+ will_return(__wrap_io_setup, 0);
do_libcheck_init(&c, 4096, NULL);
aio_grp = get_aio_grp(&c);
return_io_getevents_none();
@@ -459,7 +462,7 @@ static void test_check_state_async_timeout(void **state)
will_return(__wrap_io_cancel, 0);
#endif
libcheck_free(&c);
- do_libcheck_unload(1);
+ do_libcheck_reset(1);
}
/* test freeing checkers with outstanding requests */
@@ -470,7 +473,8 @@ static void test_free_with_pending(void **state)
struct async_req *req;
int res = 0;
- do_libcheck_load();
+ assert_true(list_empty(&aio_grp_list));
+ will_return(__wrap_io_setup, 0);
do_libcheck_init(&c[0], 4096, &req);
do_libcheck_init(&c[1], 4096, NULL);
aio_grp = get_aio_grp(c);
@@ -491,7 +495,7 @@ static void test_free_with_pending(void **state)
#else
check_aio_grp(aio_grp, 0, 0);
#endif
- do_libcheck_unload(1);
+ do_libcheck_reset(1);
}
/* test removing orpahed aio_group on free */
@@ -501,7 +505,8 @@ static void test_orphaned_aio_group(void **state)
struct aio_group *aio_grp, *tmp_grp;
int i;
- do_libcheck_load();
+ assert_true(list_empty(&aio_grp_list));
+ will_return(__wrap_io_setup, 0);
for (i = 0; i < AIO_GROUP_SIZE; i++) {
do_libcheck_init(&c[i], 4096, NULL);
return_io_getevents_none();
@@ -519,17 +524,10 @@ static void test_orphaned_aio_group(void **state)
if (i == AIO_GROUP_SIZE - 1) {
/* remove the orphaned group and create a new one */
will_return(__wrap_io_destroy, 0);
- will_return(__wrap_io_setup, 0);
}
libcheck_free(&c[i]);
}
- i = 0;
- list_for_each_entry(tmp_grp, &aio_grp_list, node) {
- i++;
- check_aio_grp(aio_grp, 0, 0);
- }
- assert_int_equal(i, 1);
- do_libcheck_unload(1);
+ do_libcheck_reset(0);
}
/* test sync timeout with failed cancel and cleanup by another
@@ -542,7 +540,8 @@ static void test_timeout_cancel_failed(void **state)
int res[] = {0,0};
int i;
- do_libcheck_load();
+ assert_true(list_empty(&aio_grp_list));
+ will_return(__wrap_io_setup, 0);
for (i = 0; i < 2; i++)
do_libcheck_init(&c[i], 4096, &reqs[i]);
aio_grp = get_aio_grp(c);
@@ -563,7 +562,7 @@ static void test_timeout_cancel_failed(void **state)
assert_false(is_checker_running(&c[i]));
libcheck_free(&c[i]);
}
- do_libcheck_unload(1);
+ do_libcheck_reset(1);
}
/* test async timeout with failed cancel and cleanup by another
@@ -575,7 +574,8 @@ static void test_async_timeout_cancel_failed(void **state)
int res[] = {0,0};
int i;
- do_libcheck_load();
+ assert_true(list_empty(&aio_grp_list));
+ will_return(__wrap_io_setup, 0);
for (i = 0; i < 2; i++)
do_libcheck_init(&c[i], 4096, &reqs[i]);
return_io_getevents_none();
@@ -605,7 +605,7 @@ static void test_async_timeout_cancel_failed(void **state)
assert_false(is_checker_running(&c[i]));
libcheck_free(&c[i]);
}
- do_libcheck_unload(1);
+ do_libcheck_reset(1);
}
/* test orphaning a request, and having another checker clean it up */
@@ -617,7 +617,8 @@ static void test_orphan_checker_cleanup(void **state)
struct aio_group *aio_grp;
int i;
- do_libcheck_load();
+ assert_true(list_empty(&aio_grp_list));
+ will_return(__wrap_io_setup, 0);
for (i = 0; i < 2; i++)
do_libcheck_init(&c[i], 4096, &reqs[i]);
aio_grp = get_aio_grp(c);
@@ -632,7 +633,7 @@ static void test_orphan_checker_cleanup(void **state)
check_aio_grp(aio_grp, 1, 0);
libcheck_free(&c[1]);
check_aio_grp(aio_grp, 0, 0);
- do_libcheck_unload(1);
+ do_libcheck_reset(1);
}
/* test orphaning a request, and having reset clean it up */
@@ -642,46 +643,8 @@ static void test_orphan_reset_cleanup(void **state)
struct aio_group *orphan_aio_grp, *tmp_aio_grp;
int found, count;
- do_libcheck_load();
- do_libcheck_init(&c, 4096, NULL);
- orphan_aio_grp = get_aio_grp(&c);
- return_io_getevents_none();
- do_check_state(&c, 0, 30, PATH_PENDING);
- will_return(__wrap_io_cancel, -1);
- check_aio_grp(orphan_aio_grp, 1, 0);
- libcheck_free(&c);
- check_aio_grp(orphan_aio_grp, 1, 1);
- found = count = 0;
- list_for_each_entry(tmp_aio_grp, &aio_grp_list, node) {
- count++;
- if (tmp_aio_grp == orphan_aio_grp)
- found = 1;
- }
- assert_int_equal(count, 1);
- assert_int_equal(found, 1);
+ assert_true(list_empty(&aio_grp_list));
will_return(__wrap_io_setup, 0);
- will_return(__wrap_io_destroy, 0);
- assert_int_equal(libcheck_reset(), 0);
- found = count = 0;
- list_for_each_entry(tmp_aio_grp, &aio_grp_list, node) {
- count++;
- check_aio_grp(tmp_aio_grp, 0, 0);
- if (tmp_aio_grp == orphan_aio_grp)
- found = 1;
- }
- assert_int_equal(count, 1);
- assert_int_equal(found, 0);
- do_libcheck_unload(1);
-}
-
-/* test orphaning a request, and having unload clean it up */
-static void test_orphan_unload_cleanup(void **state)
-{
- struct checker c;
- struct aio_group *orphan_aio_grp, *tmp_aio_grp;
- int found, count;
-
- do_libcheck_load();
do_libcheck_init(&c, 4096, NULL);
orphan_aio_grp = get_aio_grp(&c);
return_io_getevents_none();
@@ -698,7 +661,7 @@ static void test_orphan_unload_cleanup(void **state)
}
assert_int_equal(count, 1);
assert_int_equal(found, 1);
- do_libcheck_unload(1);
+ do_libcheck_reset(1);
}
/* test checkers with different blocksizes */
@@ -716,7 +679,8 @@ static void test_check_state_blksize(void **state)
int chk_state[] = {PATH_UP, PATH_DOWN, PATH_UP};
#endif
- do_libcheck_load();
+ assert_true(list_empty(&aio_grp_list));
+ will_return(__wrap_io_setup, 0);
for (i = 0; i < 3; i++)
do_libcheck_init(&c[i], blksize[i], &reqs[i]);
for (i = 0; i < 3; i++) {
@@ -727,7 +691,7 @@ static void test_check_state_blksize(void **state)
assert_false(is_checker_running(&c[i]));
libcheck_free(&c[i]);
}
- do_libcheck_unload(1);
+ do_libcheck_reset(1);
}
/* test async checkers pending and getting resovled by another checker
@@ -739,7 +703,8 @@ static void test_check_state_async(void **state)
struct async_req *reqs[257];
int res[257] = {0};
- do_libcheck_load();
+ assert_true(list_empty(&aio_grp_list));
+ will_return(__wrap_io_setup, 0);
for (i = 0; i < 257; i++)
do_libcheck_init(&c[i], 4096, &reqs[i]);
for (i = 0; i < 256; i++) {
@@ -757,7 +722,7 @@ static void test_check_state_async(void **state)
assert_false(is_checker_running(&c[i]));
libcheck_free(&c[i]);
}
- do_libcheck_unload(1);
+ do_libcheck_reset(1);
}
static int setup(void **state)
@@ -782,7 +747,8 @@ static int teardown(void **state)
int test_directio(void)
{
const struct CMUnitTest tests[] = {
- cmocka_unit_test(test_load_reset_unload),
+ cmocka_unit_test(test_reset),
+ cmocka_unit_test(test_init_reset_init),
cmocka_unit_test(test_init_free),
cmocka_unit_test(test_multi_init_free),
cmocka_unit_test(test_check_state_simple),
@@ -793,7 +759,6 @@ int test_directio(void)
cmocka_unit_test(test_async_timeout_cancel_failed),
cmocka_unit_test(test_orphan_checker_cleanup),
cmocka_unit_test(test_orphan_reset_cleanup),
- cmocka_unit_test(test_orphan_unload_cleanup),
cmocka_unit_test(test_check_state_blksize),
cmocka_unit_test(test_check_state_async),
cmocka_unit_test(test_orphaned_aio_group),
--
2.17.2
More information about the dm-devel
mailing list