It may happen, that the first execution of 'rmmod module_name' may fail for some reason (like the module is in use for some short time).
Changed tst_module_unload() to execute 'rmmod module_name' multiple times with the total number limited by a timeout. Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmansk...@oracle.com> --- include/tst_module.h | 11 ++++++++ lib/tst_module.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 1 deletions(-) diff --git a/include/tst_module.h b/include/tst_module.h index c50efec..f6b699a 100644 --- a/include/tst_module.h +++ b/include/tst_module.h @@ -48,6 +48,17 @@ void tst_module_exist(void (cleanup_fn)(void), const char *mod_name, char **mod_path); /* + * Check if the module is loaded. + * + * @mod_name: the module's name or file name + * + * Returns 1 if the module is loaded, 0 - if it's not. + * + * In case of failure calls cleanup_fn and exits with TBROK. + */ +int tst_module_is_loaded(void (cleanup_fn)(void), const char *mod_name); + +/* * Load a module using insmod program. * * @mod_name: module's file name. diff --git a/lib/tst_module.c b/lib/tst_module.c index 8104582..49c9bd0 100644 --- a/lib/tst_module.c +++ b/lib/tst_module.c @@ -74,6 +74,59 @@ void tst_module_exists(void (cleanup_fn)(void), free(buf); } +int tst_module_is_loaded(void (cleanup_fn)(void), + const char *mod_name) +{ + FILE *f; + char *pos; + char mod_name_can[64]; + char mod_name_read[64]; + char buf[128]; + int ret = 0; + + if (strlen(mod_name) + 1 > sizeof(mod_name_can)) + tst_brkm(TBROK, cleanup_fn, "Too long module name: '%s'", + mod_name); + + /* + * modify the module name to compare with names in /proc/modules + */ + strcpy(mod_name_can, mod_name); + + pos = strstr(mod_name_can, ".ko"); + if (pos != NULL) + *pos = '\0'; + + pos = mod_name_can; + while (*pos) { + if (*pos == '-') + *pos = '_'; + pos++; + } + + f = fopen("/proc/modules", "r"); + if (f == NULL) + tst_brkm(TBROK | TERRNO, cleanup_fn, + "Failed to open /proc/modules at %s:%d", + __FILE__, __LINE__); + + while (fgets(buf, sizeof(buf), f) != NULL) { + if (sscanf(buf, "%63s", mod_name_read) != 1) { + fclose(f); + tst_brkm(TBROK | TERRNO, cleanup_fn, + "Failed to parse /proc/modules at %s:%d", + __FILE__, __LINE__); + } + + if (!strcmp(mod_name_can, mod_name_read)) { + ret = 1; + break; + } + } + + return ret; +} + void tst_module_load(void (cleanup_fn)(void), const char *mod_name, char *const argv[]) { @@ -100,6 +153,21 @@ void tst_module_load(void (cleanup_fn)(void), void tst_module_unload(void (cleanup_fn)(void), const char *mod_name) { + int i; + int loaded; + const char *const argv[] = { "rmmod", mod_name, NULL }; - tst_run_cmd(cleanup_fn, argv, NULL, NULL, 0); + + loaded = 1; + for (i = 0; i < 50; i++) { + tst_run_cmd(NULL, argv, "/dev/null", "/dev/null", 1); + + loaded = tst_module_is_loaded(cleanup_fn, mod_name); + if (!loaded) + break; + } + + if (loaded) + tst_brkm(TBROK, cleanup_fn, + "could not unload %s module", mod_name); } -- 1.7.1 ------------------------------------------------------------------------------ Dive into the World of Parallel Programming. The Go Parallel Website, sponsored by Intel and developed in partnership with Slashdot Media, is your hub for all things parallel software development, from weekly thought leadership blogs to news, videos, case studies, tutorials and more. Take a look and join the conversation now. http://goparallel.sourceforge.net/ _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list