* [LTP] [RFC PATCH] Asynchronous module unloading and tst_run_cmd @ 2015-01-16 16:43 Stanislav Kholmanskikh 2015-01-19 14:52 ` Cyril Hrubis 0 siblings, 1 reply; 12+ messages in thread From: Stanislav Kholmanskikh @ 2015-01-16 16:43 UTC (permalink / raw) To: ltp-list; +Cc: vasily.isaenko There is one more issue with tbio. :( Sometimes it may fail with: ltp_tbio 0 TINFO : Device opened successfully ltp_tbio 1 TPASS : success on LTP_TBIO_ALLOC test ltp_tbio 2 TPASS : success on LTP_TBIO_CLONE test ltp_tbio 3 TPASS : success on LTP_TBIO_GET_NR_VECS test ltp_tbio 4 TPASS : success on LTP_TBIO_ADD_PAGE test ltp_tbio 5 TPASS : success on LTP_TBIO_SPLIT:write to dev ltp_tbio 6 TPASS : success on LTP_TBIO_DO_IO:write to dev ltp_tbio 7 TPASS : success on LTP_TBIO_DO_IO:read from dev ltp_tbio 8 TPASS : success on LTP_TBIO_PUT test ERROR: Module ltp_tbio is in use ltp_tbio 9 TBROK : tst_run_cmd.c:84: failed to exec cmd 'rmmod' at tst_run_cmd.c:84 ltp_tbio 10 TBROK : tst_run_cmd.c:84: Remaining cases broken This is a rfc patch which fixes this problem. The main idea is to execute rmmod up to a timeout, and check if the module has been unloaded after each execution of rmmod. Summary of changes: * introduce tst_module_is_loaded() - checks if the module is in /proc/modules * change a bit interfaces of tst_run_cmd and cmd_run_cmd_fds (to conditionally check the program exit code to be able to continue the test if the program failed) * introducing a loop into tst_module_unload I would like somebody to review the general idea. If it's ok, I'll split this patch into several logically coupled ones and resend them. I'm really unsure if the changes to tst_run_cmd and cmd_run_cmd_fds are acceptable. Thanks! Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com> --- include/test.h | 8 ++- include/tst_module.h | 11 ++++ lib/tst_mkfs.c | 2 +- lib/tst_module.c | 73 +++++++++++++++++++++++++- lib/tst_run_cmd.c | 15 ++++-- testcases/kernel/syscalls/swapon/libswapon.c | 2 +- 6 files changed, 101 insertions(+), 10 deletions(-) diff --git a/include/test.h b/include/test.h index 326b686..5234aa5 100644 --- a/include/test.h +++ b/include/test.h @@ -283,22 +283,26 @@ long tst_ncpus_max(void); * redirection is not needed. * @stderr_fd: file descriptor where to redirect stderr. Set -1 if * redirection is not needed. + * @check_code: set to a non-zero value to check the program exit code. */ void tst_run_cmd_fds(void (cleanup_fn)(void), const char *const argv[], int stdout_fd, - int stderr_fd); + int stderr_fd, + int check_code); /* Executes tst_run_cmd_fds() and redirects its output to a file * @stdout_path: path where to redirect stdout. Set NULL if redirection is * not needed. * @stderr_path: path where to redirect stderr. Set NULL if redirection is * not needed. + * @check_code: set to a non-zero value to check the program exit code. */ void tst_run_cmd(void (cleanup_fn)(void), const char *const argv[], const char *stdout_path, - const char *stderr_path); + const char *stderr_path, + int check_code); /* Wrapper function for system(3), ignorcing SIGCLD signal. * @command: the command to be run. diff --git a/include/tst_module.h b/include/tst_module.h index c50efec..d9b7e80 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_mkfs.c b/lib/tst_mkfs.c index 46e924c..a0261c7 100644 --- a/lib/tst_mkfs.c +++ b/lib/tst_mkfs.c @@ -72,7 +72,7 @@ void tst_mkfs(void (cleanup_fn)(void), const char *dev, tst_resm(TINFO, "Formatting %s with %s extra opts='%s'", dev, fs_type, fs_opts_str); - tst_run_cmd(cleanup_fn, argv, "/dev/null", NULL); + tst_run_cmd(cleanup_fn, argv, "/dev/null", NULL, 1); } const char *tst_dev_fs_type(void) diff --git a/lib/tst_module.c b/lib/tst_module.c index 028af0e..d71b62b 100644 --- a/lib/tst_module.c +++ b/lib/tst_module.c @@ -20,9 +20,12 @@ */ #define _GNU_SOURCE +#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> #include "test.h" #include "ltp_priv.h" @@ -74,6 +77,57 @@ 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, + "fopen(\"/proc/modules\") failed"); + + while (fgets(buf, sizeof(buf), f) != NULL) { + if (sscanf(buf, "%63s", mod_name_read) != 1) { + fclose(f); + tst_brkm(TBROK, cleanup_fn, + "Failed to parse /proc/modules"); + } + + 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[]) { @@ -94,12 +148,27 @@ void tst_module_load(void (cleanup_fn)(void), for (i = offset; i < size; ++i) mod_argv[i] = argv[i - offset]; - tst_run_cmd(cleanup_fn, mod_argv, NULL, NULL); + tst_run_cmd(cleanup_fn, mod_argv, NULL, NULL, 1); free(mod_path); } 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); + + loaded = 1; + for (i = 0; i < 50; i++) { + tst_run_cmd(NULL, argv, "/dev/null", "/dev/null", 0); +/* tst_system("rmmod ltp_tbio &> /dev/null"); */ + 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); } diff --git a/lib/tst_run_cmd.c b/lib/tst_run_cmd.c index 5a02db0..bbee729 100644 --- a/lib/tst_run_cmd.c +++ b/lib/tst_run_cmd.c @@ -34,7 +34,8 @@ void tst_run_cmd_fds(void (cleanup_fn)(void), const char *const argv[], int stdout_fd, - int stderr_fd) + int stderr_fd, + int check_code) { if (argv == NULL || argv[0] == NULL) { tst_brkm(TBROK, cleanup_fn, @@ -79,16 +80,22 @@ void tst_run_cmd_fds(void (cleanup_fn)(void), signal(SIGCHLD, old_handler); - if (!WIFEXITED(ret) || WEXITSTATUS(ret) != 0) { + if (!WIFEXITED(ret)) { tst_brkm(TBROK, cleanup_fn, "failed to exec cmd '%s' at %s:%d", argv[0], __FILE__, __LINE__); } + + if (check_code && (WEXITSTATUS(ret) != 0)) + tst_brkm(TBROK, cleanup_fn, + "'%s' exited with a non-zero code at %s:%d", + argv[0], __FILE__, __LINE__); } void tst_run_cmd(void (cleanup_fn)(void), const char *const argv[], const char *stdout_path, - const char *stderr_path) + const char *stderr_path, + int check_code) { int stdout_fd = -1; int stderr_fd = -1; @@ -113,7 +120,7 @@ void tst_run_cmd(void (cleanup_fn)(void), stderr_path, __FILE__, __LINE__); } - tst_run_cmd_fds(cleanup_fn, argv, stdout_fd, stderr_fd); + tst_run_cmd_fds(cleanup_fn, argv, stdout_fd, stderr_fd, check_code); if ((stdout_fd != -1) && (close(stdout_fd) == -1)) tst_resm(TWARN | TERRNO, diff --git a/testcases/kernel/syscalls/swapon/libswapon.c b/testcases/kernel/syscalls/swapon/libswapon.c index ac0be57..a17e623 100644 --- a/testcases/kernel/syscalls/swapon/libswapon.c +++ b/testcases/kernel/syscalls/swapon/libswapon.c @@ -45,5 +45,5 @@ void make_swapfile(void (cleanup)(void), const char *swapfile) argv[1] = swapfile; argv[2] = NULL; - tst_run_cmd(cleanup, argv, "/dev/null", "/dev/null"); + tst_run_cmd(cleanup, argv, "/dev/null", "/dev/null", 1); } -- 1.7.1 ------------------------------------------------------------------------------ New Year. New Location. New Benefits. New Data Center in Ashburn, VA. GigeNET is offering a free month of service with a new server in Ashburn. Choose from 2 high performing configs, both with 100TB of bandwidth. Higher redundancy.Lower latency.Increased capacity.Completely compliant. http://p.sf.net/sfu/gigenet _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [LTP] [RFC PATCH] Asynchronous module unloading and tst_run_cmd 2015-01-16 16:43 [LTP] [RFC PATCH] Asynchronous module unloading and tst_run_cmd Stanislav Kholmanskikh @ 2015-01-19 14:52 ` Cyril Hrubis [not found] ` <54BE2EF3.3010604@oracle.com> 0 siblings, 1 reply; 12+ messages in thread From: Cyril Hrubis @ 2015-01-19 14:52 UTC (permalink / raw) To: Stanislav Kholmanskikh; +Cc: vasily.isaenko, ltp-list Hi! > There is one more issue with tbio. :( > > Sometimes it may fail with: > > ltp_tbio 0 TINFO : Device opened successfully > ltp_tbio 1 TPASS : success on LTP_TBIO_ALLOC test > ltp_tbio 2 TPASS : success on LTP_TBIO_CLONE test > ltp_tbio 3 TPASS : success on LTP_TBIO_GET_NR_VECS test > ltp_tbio 4 TPASS : success on LTP_TBIO_ADD_PAGE test > ltp_tbio 5 TPASS : success on LTP_TBIO_SPLIT:write to dev > ltp_tbio 6 TPASS : success on LTP_TBIO_DO_IO:write to dev > ltp_tbio 7 TPASS : success on LTP_TBIO_DO_IO:read from dev > ltp_tbio 8 TPASS : success on LTP_TBIO_PUT test > ERROR: Module ltp_tbio is in use > ltp_tbio 9 TBROK : tst_run_cmd.c:84: failed to exec cmd 'rmmod' at tst_run_cmd.c:84 > ltp_tbio 10 TBROK : tst_run_cmd.c:84: Remaining cases broken Hmm, would switch to modprobe -r fix that? I've been told several times that rrmod should not be used anymore because modprobe handles things better... Or will modprobe -r fail the same way? > This is a rfc patch which fixes this problem. > > The main idea is to execute rmmod up to a timeout, and check if the module > has been unloaded after each execution of rmmod. > > Summary of changes: > * introduce tst_module_is_loaded() - checks if the module is in /proc/modules > * change a bit interfaces of tst_run_cmd and cmd_run_cmd_fds (to conditionally > check the program exit code to be able to continue the test if the program failed) > * introducing a loop into tst_module_unload > That sounds reasonably. > I would like somebody to review the general idea. If it's ok, I'll split this patch > into several logically coupled ones and resend them. > > I'm really unsure if the changes to tst_run_cmd and cmd_run_cmd_fds are acceptable. I'm OK with adding the flag, it would need a better name though. -- Cyril Hrubis chrubis@suse.cz ------------------------------------------------------------------------------ New Year. New Location. New Benefits. New Data Center in Ashburn, VA. GigeNET is offering a free month of service with a new server in Ashburn. Choose from 2 high performing configs, both with 100TB of bandwidth. Higher redundancy.Lower latency.Increased capacity.Completely compliant. http://p.sf.net/sfu/gigenet _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list ^ permalink raw reply [flat|nested] 12+ messages in thread
[parent not found: <54BE2EF3.3010604@oracle.com>]
* Re: [LTP] [RFC PATCH] Asynchronous module unloading and tst_run_cmd [not found] ` <54BE2EF3.3010604@oracle.com> @ 2015-01-20 11:43 ` Cyril Hrubis 2015-01-26 10:15 ` [LTP] [PATCH 1/2] tst_run_cmd: add an option to pass the program exit code Stanislav Kholmanskikh 2015-01-26 10:15 ` [LTP] [PATCH 2/2] tst_module: introduce a timeout to unload modules Stanislav Kholmanskikh 0 siblings, 2 replies; 12+ messages in thread From: Cyril Hrubis @ 2015-01-20 11:43 UTC (permalink / raw) To: Stanislav Kholmanskikh; +Cc: vasily.isaenko, ltp-list Hi! > >> There is one more issue with tbio. :( > >> > >> Sometimes it may fail with: > >> > >> ltp_tbio 0 TINFO : Device opened successfully > >> ltp_tbio 1 TPASS : success on LTP_TBIO_ALLOC test > >> ltp_tbio 2 TPASS : success on LTP_TBIO_CLONE test > >> ltp_tbio 3 TPASS : success on LTP_TBIO_GET_NR_VECS test > >> ltp_tbio 4 TPASS : success on LTP_TBIO_ADD_PAGE test > >> ltp_tbio 5 TPASS : success on LTP_TBIO_SPLIT:write to dev > >> ltp_tbio 6 TPASS : success on LTP_TBIO_DO_IO:write to dev > >> ltp_tbio 7 TPASS : success on LTP_TBIO_DO_IO:read from dev > >> ltp_tbio 8 TPASS : success on LTP_TBIO_PUT test > >> ERROR: Module ltp_tbio is in use > >> ltp_tbio 9 TBROK : tst_run_cmd.c:84: failed to exec cmd 'rmmod' at tst_run_cmd.c:84 > >> ltp_tbio 10 TBROK : tst_run_cmd.c:84: Remaining cases broken > > > > Hmm, would switch to modprobe -r fix that? > > > > I've been told several times that rrmod should not be used anymore > > because modprobe handles things better... > > > > Or will modprobe -r fail the same way? > > Yes, modprobe -r will fail the same way. And using modprobe complicates > the module loading/unloading wrappers, because we will need to place > modules in /lib/modules/`uname-r`. Ok, then we need this patchset to fix that. Just side note, for modprobe -r the path for loading modules should not matter and for loading modules we pass right path with -d. > >> This is a rfc patch which fixes this problem. > >> > >> The main idea is to execute rmmod up to a timeout, and check if the module > >> has been unloaded after each execution of rmmod. > >> > >> Summary of changes: > >> * introduce tst_module_is_loaded() - checks if the module is in /proc/modules > >> * change a bit interfaces of tst_run_cmd and cmd_run_cmd_fds (to conditionally > >> check the program exit code to be able to continue the test if the program failed) > >> * introducing a loop into tst_module_unload > >> > > > > That sounds reasonably. > > > >> I would like somebody to review the general idea. If it's ok, I'll split this patch > >> into several logically coupled ones and resend them. > >> > >> I'm really unsure if the changes to tst_run_cmd and cmd_run_cmd_fds are acceptable. > > > > I'm OK with adding the flag, it would need a better name though. > > > > int check_exit_status ? check if it's set to a non-zero value Maybe we can change the functions to pass the exit value (return int) in case that it's not used internally and name the flag pass_exit_val. -- Cyril Hrubis chrubis@suse.cz ------------------------------------------------------------------------------ New Year. New Location. New Benefits. New Data Center in Ashburn, VA. GigeNET is offering a free month of service with a new server in Ashburn. Choose from 2 high performing configs, both with 100TB of bandwidth. Higher redundancy.Lower latency.Increased capacity.Completely compliant. http://p.sf.net/sfu/gigenet _______________________________________________ Ltp-list mailing list Ltp-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ltp-list ^ permalink raw reply [flat|nested] 12+ messages in thread
* [LTP] [PATCH 1/2] tst_run_cmd: add an option to pass the program exit code 2015-01-20 11:43 ` Cyril Hrubis @ 2015-01-26 10:15 ` Stanislav Kholmanskikh 2015-01-26 13:04 ` Cyril Hrubis 2015-01-26 10:15 ` [LTP] [PATCH 2/2] tst_module: introduce a timeout to unload modules Stanislav Kholmanskikh 1 sibling, 1 reply; 12+ messages in thread From: Stanislav Kholmanskikh @ 2015-01-26 10:15 UTC (permalink / raw) To: ltp-list; +Cc: vasily.isaenko Added an option to pass the program exit code to the caller. This may be needed if we want to run a program with tst_run_cmd(), but handle failures manually (i.e. not call cleanup). Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com> --- include/test.h | 16 ++++++++++--- lib/tst_mkfs.c | 2 +- lib/tst_module.c | 4 +- lib/tst_run_cmd.c | 29 ++++++++++++++++++++----- testcases/kernel/syscalls/swapon/libswapon.c | 2 +- 5 files changed, 39 insertions(+), 14 deletions(-) diff --git a/include/test.h b/include/test.h index 326b686..9078f37 100644 --- a/include/test.h +++ b/include/test.h @@ -283,22 +283,30 @@ long tst_ncpus_max(void); * redirection is not needed. * @stderr_fd: file descriptor where to redirect stderr. Set -1 if * redirection is not needed. + * @pass_exit_val: if it's non-zero, this function will return the program + * exit code, otherwise it will call cleanup_fn() if the program + * exit code is not zero. */ -void tst_run_cmd_fds(void (cleanup_fn)(void), +int tst_run_cmd_fds(void (cleanup_fn)(void), const char *const argv[], int stdout_fd, - int stderr_fd); + int stderr_fd, + int pass_exit_val); /* Executes tst_run_cmd_fds() and redirects its output to a file * @stdout_path: path where to redirect stdout. Set NULL if redirection is * not needed. * @stderr_path: path where to redirect stderr. Set NULL if redirection is * not needed. + * @pass_exit_val: if it's non-zero, this function will return the program + * exit code, otherwise it will call cleanup_fn() if the program + * exit code is not zero. */ -void tst_run_cmd(void (cleanup_fn)(void), +int tst_run_cmd(void (cleanup_fn)(void), const char *const argv[], const char *stdout_path, - const char *stderr_path); + const char *stderr_path, + int pass_exit_val); /* Wrapper function for system(3), ignorcing SIGCLD signal. * @command: the command to be run. diff --git a/lib/tst_mkfs.c b/lib/tst_mkfs.c index 46e924c..c01cdf3 100644 --- a/lib/tst_mkfs.c +++ b/lib/tst_mkfs.c @@ -72,7 +72,7 @@ void tst_mkfs(void (cleanup_fn)(void), const char *dev, tst_resm(TINFO, "Formatting %s with %s extra opts='%s'", dev, fs_type, fs_opts_str); - tst_run_cmd(cleanup_fn, argv, "/dev/null", NULL); + tst_run_cmd(cleanup_fn, argv, "/dev/null", NULL, 0); } const char *tst_dev_fs_type(void) diff --git a/lib/tst_module.c b/lib/tst_module.c index 028af0e..8104582 100644 --- a/lib/tst_module.c +++ b/lib/tst_module.c @@ -94,12 +94,12 @@ void tst_module_load(void (cleanup_fn)(void), for (i = offset; i < size; ++i) mod_argv[i] = argv[i - offset]; - tst_run_cmd(cleanup_fn, mod_argv, NULL, NULL); + tst_run_cmd(cleanup_fn, mod_argv, NULL, NULL, 0); free(mod_path); } void tst_module_unload(void (cleanup_fn)(void), const char *mod_name) { const char *const argv[] = { "rmmod", mod_name, NULL }; - tst_run_cmd(cleanup_fn, argv, NULL, NULL); + tst_run_cmd(cleanup_fn, argv, NULL, NULL, 0); } diff --git a/lib/tst_run_cmd.c b/lib/tst_run_cmd.c index 5a02db0..c0dd944 100644 --- a/lib/tst_run_cmd.c +++ b/lib/tst_run_cmd.c @@ -31,11 +31,14 @@ #define OPEN_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) #define OPEN_FLAGS (O_WRONLY | O_APPEND | O_CREAT) -void tst_run_cmd_fds(void (cleanup_fn)(void), +int tst_run_cmd_fds(void (cleanup_fn)(void), const char *const argv[], int stdout_fd, - int stderr_fd) + int stderr_fd, + int pass_exit_val) { + int rc; + if (argv == NULL || argv[0] == NULL) { tst_brkm(TBROK, cleanup_fn, "argument list is empty at %s:%d", __FILE__, __LINE__); @@ -79,19 +82,30 @@ void tst_run_cmd_fds(void (cleanup_fn)(void), signal(SIGCHLD, old_handler); - if (!WIFEXITED(ret) || WEXITSTATUS(ret) != 0) { + if (!WIFEXITED(ret)) { tst_brkm(TBROK, cleanup_fn, "failed to exec cmd '%s' at %s:%d", argv[0], __FILE__, __LINE__); } + + rc = WEXITSTATUS(ret); + + if ((!pass_exit_val) && rc) + tst_brkm(TBROK, cleanup_fn, + "'%s' exited with a non-zero code %d at %s:%d", + argv[0], rc, __FILE__, __LINE__); + + return rc; } -void tst_run_cmd(void (cleanup_fn)(void), +int tst_run_cmd(void (cleanup_fn)(void), const char *const argv[], const char *stdout_path, - const char *stderr_path) + const char *stderr_path, + int pass_exit_val) { int stdout_fd = -1; int stderr_fd = -1; + int rc; if (stdout_path != NULL) { stdout_fd = open(stdout_path, @@ -113,7 +127,8 @@ void tst_run_cmd(void (cleanup_fn)(void), stderr_path, __FILE__, __LINE__); } - tst_run_cmd_fds(cleanup_fn, argv, stdout_fd, stderr_fd); + rc = tst_run_cmd_fds(cleanup_fn, argv, stdout_fd, stderr_fd, + pass_exit_val); if ((stdout_fd != -1) && (close(stdout_fd) == -1)) tst_resm(TWARN | TERRNO, @@ -124,6 +139,8 @@ void tst_run_cmd(void (cleanup_fn)(void), tst_resm(TWARN | TERRNO, "close() on %s failed at %s:%d", stderr_path, __FILE__, __LINE__); + + return rc; } int tst_system(const char *command) diff --git a/testcases/kernel/syscalls/swapon/libswapon.c b/testcases/kernel/syscalls/swapon/libswapon.c index ac0be57..cf6a988 100644 --- a/testcases/kernel/syscalls/swapon/libswapon.c +++ b/testcases/kernel/syscalls/swapon/libswapon.c @@ -45,5 +45,5 @@ void make_swapfile(void (cleanup)(void), const char *swapfile) argv[1] = swapfile; argv[2] = NULL; - tst_run_cmd(cleanup, argv, "/dev/null", "/dev/null"); + tst_run_cmd(cleanup, argv, "/dev/null", "/dev/null", 0); } -- 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 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [LTP] [PATCH 1/2] tst_run_cmd: add an option to pass the program exit code 2015-01-26 10:15 ` [LTP] [PATCH 1/2] tst_run_cmd: add an option to pass the program exit code Stanislav Kholmanskikh @ 2015-01-26 13:04 ` Cyril Hrubis 2015-02-02 14:01 ` [LTP] [PATCH] doc: document tst_run_cmd Stanislav Kholmanskikh 0 siblings, 1 reply; 12+ messages in thread From: Cyril Hrubis @ 2015-01-26 13:04 UTC (permalink / raw) To: Stanislav Kholmanskikh; +Cc: vasily.isaenko, ltp-list Hi! > Added an option to pass the program exit code to the caller. > This may be needed if we want to run a program with tst_run_cmd(), > but handle failures manually (i.e. not call cleanup). Looks good, acked. BTW: There does not seems to be any documentation for the tst_run_cmd() function in the Test Writing Guidelines, can we add that please? -- Cyril Hrubis chrubis@suse.cz ------------------------------------------------------------------------------ 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 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [LTP] [PATCH] doc: document tst_run_cmd 2015-01-26 13:04 ` Cyril Hrubis @ 2015-02-02 14:01 ` Stanislav Kholmanskikh 2015-02-03 14:35 ` Cyril Hrubis 0 siblings, 1 reply; 12+ messages in thread From: Stanislav Kholmanskikh @ 2015-02-02 14:01 UTC (permalink / raw) To: ltp-list; +Cc: vasily.isaenko Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com> --- Sorry for late response. doc/test-writing-guidelines.txt | 27 +++++++++++++++++++++++++++ 1 files changed, 27 insertions(+), 0 deletions(-) diff --git a/doc/test-writing-guidelines.txt b/doc/test-writing-guidelines.txt index 4d70a1b..a0004d8 100644 --- a/doc/test-writing-guidelines.txt +++ b/doc/test-writing-guidelines.txt @@ -994,6 +994,33 @@ exactly as 'umount(2)' but retries several times on a failure. IMPORTANT: All testcases should use 'tst_umount()' instead of 'umount(2)' to umount filesystems. +2.2.20 Executing a file +^^^^^^^^^^^^^^^^^^^^^^^ + +[source,c] +------------------------------------------------------------------------------- +#include "test.h" + +int tst_run_cmd(void (cleanup_fn)(void), + const char *const argv[], + const char *stdout_path, + const char *stderr_path, + int pass_exit_val); +------------------------------------------------------------------------------- + +'tst_run_cmd' is a wrapper for 'vfork() + execvp()' which provides a way to execute +an external program. + +'argv[]' is a NULL-terminated list of pointers to the program name and its optional +arguments. + +A non-zero 'pass_exit_val' makes 'tst_run_cmd' return the program exit code to +the caller. A zero for 'pass_exit_val' makes 'tst_run_cmd' call 'cleanup_fn' +in case the program exits with a non-zero code. + +'stdout_path' and 'stderr_path' detirmine where to redirect the program +stdout and stderr I/O streams. + 2.3 Writing a testcase in shell ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- 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 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [LTP] [PATCH] doc: document tst_run_cmd 2015-02-02 14:01 ` [LTP] [PATCH] doc: document tst_run_cmd Stanislav Kholmanskikh @ 2015-02-03 14:35 ` Cyril Hrubis [not found] ` <54D0E4C2.6030004@oracle.com> 0 siblings, 1 reply; 12+ messages in thread From: Cyril Hrubis @ 2015-02-03 14:35 UTC (permalink / raw) To: Stanislav Kholmanskikh; +Cc: vasily.isaenko, ltp-list Hi! > +2.2.20 Executing a file > +^^^^^^^^^^^^^^^^^^^^^^^ Maybe "Running executables" would be a bit better, as it is the title looks strange to me. > +[source,c] > +------------------------------------------------------------------------------- > +#include "test.h" > + > +int tst_run_cmd(void (cleanup_fn)(void), > + const char *const argv[], > + const char *stdout_path, > + const char *stderr_path, > + int pass_exit_val); > +------------------------------------------------------------------------------- > + > +'tst_run_cmd' is a wrapper for 'vfork() + execvp()' which provides a way to execute > +an external program. > + > +'argv[]' is a NULL-terminated list of pointers to the program name and its optional > +arguments. Maybe it would be better: NULL-terminated array of strings starting with the program name which is followed by optional arguments. And maybe we can include an example to make it clear. What about: .Example [source,c] ------------------------------------------------------------------------------- #include "test.h" const char *cmd[] = {"ls", "-l", NULL}; ... /* Store output of 'ls -l' into a log.txt */ tst_run_cmd(cleanup, cmd, "log.txt", NULL, 0); ... ------------------------------------------------------------------------------- > + > +A non-zero 'pass_exit_val' makes 'tst_run_cmd' return the program exit code to > +the caller. A zero for 'pass_exit_val' makes 'tst_run_cmd' call 'cleanup_fn' Maybe better: makes 'tst_run_cmd' exit the tests on failure and call 'cleanup_fn' (if not NULL) beforehand. > +in case the program exits with a non-zero code. > + > +'stdout_path' and 'stderr_path' detirmine where to redirect the program ^ determine > +stdout and stderr I/O streams. > + -- Cyril Hrubis chrubis@suse.cz ------------------------------------------------------------------------------ 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 ^ permalink raw reply [flat|nested] 12+ messages in thread
[parent not found: <54D0E4C2.6030004@oracle.com>]
* [LTP] [PATCH V2] doc: document tst_run_cmd [not found] ` <54D0E4C2.6030004@oracle.com> @ 2015-02-03 16:00 ` Stanislav Kholmanskikh 2015-02-03 16:12 ` Cyril Hrubis 2015-02-03 16:08 ` [LTP] [PATCH] " Cyril Hrubis 1 sibling, 1 reply; 12+ messages in thread From: Stanislav Kholmanskikh @ 2015-02-03 16:00 UTC (permalink / raw) To: ltp-list; +Cc: vasily.isaenko Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com> --- Changes since V1: * Applied all comments from V1 * Added one more const to cmd[] in Example doc/test-writing-guidelines.txt | 40 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 40 insertions(+), 0 deletions(-) diff --git a/doc/test-writing-guidelines.txt b/doc/test-writing-guidelines.txt index 4d70a1b..22eb318 100644 --- a/doc/test-writing-guidelines.txt +++ b/doc/test-writing-guidelines.txt @@ -994,6 +994,46 @@ exactly as 'umount(2)' but retries several times on a failure. IMPORTANT: All testcases should use 'tst_umount()' instead of 'umount(2)' to umount filesystems. +2.2.20 Running executables +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +[source,c] +------------------------------------------------------------------------------- +#include "test.h" + +int tst_run_cmd(void (cleanup_fn)(void), + const char *const argv[], + const char *stdout_path, + const char *stderr_path, + int pass_exit_val); +------------------------------------------------------------------------------- + +'tst_run_cmd' is a wrapper for 'vfork() + execvp()' which provides a way +to execute an external program. + +'argv[]' is a NULL-terminated array of strings starting with the program name +which is followed by optional arguments. + +A non-zero 'pass_exit_val' makes 'tst_run_cmd' return the program exit code to +the caller. A zero for 'pass_exit_val' makes 'tst_run_cmd' exit the tests +on failure and call 'cleanup_fn' (if not NULL) beforehand. + +'stdout_path' and 'stderr_path' determine where to redirect the program +stdout and stderr I/O streams. + +.Example +[source,c] +------------------------------------------------------------------------------- +#include "test.h" + +const char *const cmd[] = { "ls", "-l", NULL }; + +... + /* Store output of 'ls -l' into log.txt */ + tst_run_cmd(cleanup, cmd, "log.txt", NULL, 0); +... +------------------------------------------------------------------------------- + 2.3 Writing a testcase in shell ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- 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 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [LTP] [PATCH V2] doc: document tst_run_cmd 2015-02-03 16:00 ` [LTP] [PATCH V2] " Stanislav Kholmanskikh @ 2015-02-03 16:12 ` Cyril Hrubis 0 siblings, 0 replies; 12+ messages in thread From: Cyril Hrubis @ 2015-02-03 16:12 UTC (permalink / raw) To: Stanislav Kholmanskikh; +Cc: vasily.isaenko, ltp-list Hi! > Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com> > --- > Changes since V1: > * Applied all comments from V1 > * Added one more const to cmd[] in Example Acked. -- Cyril Hrubis chrubis@suse.cz ------------------------------------------------------------------------------ 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 ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [LTP] [PATCH] doc: document tst_run_cmd [not found] ` <54D0E4C2.6030004@oracle.com> 2015-02-03 16:00 ` [LTP] [PATCH V2] " Stanislav Kholmanskikh @ 2015-02-03 16:08 ` Cyril Hrubis 1 sibling, 0 replies; 12+ messages in thread From: Cyril Hrubis @ 2015-02-03 16:08 UTC (permalink / raw) To: Stanislav Kholmanskikh; +Cc: vasily.isaenko, ltp-list Hi! > >> +2.2.20 Executing a file > >> +^^^^^^^^^^^^^^^^^^^^^^^ > > > > Maybe "Running executables" would be a bit better, as it is the title > > looks strange to me. > > I stole it from 'man 3 execvp' :) No problem:) That only proves that I'm not enlighted enough to see the beauty of the 'man pages' english... ;) -- Cyril Hrubis chrubis@suse.cz ------------------------------------------------------------------------------ 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 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [LTP] [PATCH 2/2] tst_module: introduce a timeout to unload modules 2015-01-20 11:43 ` Cyril Hrubis 2015-01-26 10:15 ` [LTP] [PATCH 1/2] tst_run_cmd: add an option to pass the program exit code Stanislav Kholmanskikh @ 2015-01-26 10:15 ` Stanislav Kholmanskikh 2015-01-26 13:11 ` Cyril Hrubis 1 sibling, 1 reply; 12+ messages in thread From: Stanislav Kholmanskikh @ 2015-01-26 10:15 UTC (permalink / raw) To: ltp-list; +Cc: vasily.isaenko 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.kholmanskikh@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 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [LTP] [PATCH 2/2] tst_module: introduce a timeout to unload modules 2015-01-26 10:15 ` [LTP] [PATCH 2/2] tst_module: introduce a timeout to unload modules Stanislav Kholmanskikh @ 2015-01-26 13:11 ` Cyril Hrubis 0 siblings, 0 replies; 12+ messages in thread From: Cyril Hrubis @ 2015-01-26 13:11 UTC (permalink / raw) To: Stanislav Kholmanskikh; +Cc: vasily.isaenko, ltp-list Hi! > /* > + * 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); Can we trust the return value from the rrmod? Because if it's correctly propagated we can simplify this loop to just checking the return value here. > + loaded = tst_module_is_loaded(cleanup_fn, mod_name); > + if (!loaded) > + break; What about adding usleep(20000) here? Because otherwise this is bussy loop that does not give much chances to other processes to run (on a single CPU machine). > + } > + > + if (loaded) > + tst_brkm(TBROK, cleanup_fn, > + "could not unload %s module", mod_name); > } -- Cyril Hrubis chrubis@suse.cz ------------------------------------------------------------------------------ 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 ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2015-02-03 16:12 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-01-16 16:43 [LTP] [RFC PATCH] Asynchronous module unloading and tst_run_cmd Stanislav Kholmanskikh
2015-01-19 14:52 ` Cyril Hrubis
[not found] ` <54BE2EF3.3010604@oracle.com>
2015-01-20 11:43 ` Cyril Hrubis
2015-01-26 10:15 ` [LTP] [PATCH 1/2] tst_run_cmd: add an option to pass the program exit code Stanislav Kholmanskikh
2015-01-26 13:04 ` Cyril Hrubis
2015-02-02 14:01 ` [LTP] [PATCH] doc: document tst_run_cmd Stanislav Kholmanskikh
2015-02-03 14:35 ` Cyril Hrubis
[not found] ` <54D0E4C2.6030004@oracle.com>
2015-02-03 16:00 ` [LTP] [PATCH V2] " Stanislav Kholmanskikh
2015-02-03 16:12 ` Cyril Hrubis
2015-02-03 16:08 ` [LTP] [PATCH] " Cyril Hrubis
2015-01-26 10:15 ` [LTP] [PATCH 2/2] tst_module: introduce a timeout to unload modules Stanislav Kholmanskikh
2015-01-26 13:11 ` Cyril Hrubis
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox