* [LTP] [PATCH 0/3] checkpoint: Refactor and unify shell/C reinit support
@ 2025-06-16 10:26 Li Wang via ltp
2025-06-16 10:26 ` [LTP] [PATCH 1/3] shell/lib: refactor checkpoint with shared path for exec() support Li Wang via ltp
` (3 more replies)
0 siblings, 4 replies; 13+ messages in thread
From: Li Wang via ltp @ 2025-06-16 10:26 UTC (permalink / raw)
To: ltp
This patch series refactors the internal checkpointing mechanism to better
support mixed shell and C test cases, especially when using exec() based
processes that synchronize via shared memory.
The changes address long-standing issues with inconsistent reinitialization
of checkpoint files across exec() boundaries, and unify the logic for both
C and Shell initialized checkpoint files.
With this patch series, the following now works correctly:
Shell-C mixed:
C: init checkpoint + fork()
Shell: tst_run_script() + tst_checkpint wait 1000 0
C: TST_CHECKPOINT_WAKE(0)
Shell test:
TST_NEEDS_CHECKPOINT=1
Process1: TST_CHECKPOINT_WAIT(0)
process2: TST_CHECKPOINT_WAKE(0)
C test:
.needs_checkpoint=1
fork() + exec("child test") + TST_CHECKPOINT_WAIT(0)
TST_CHECKPOINT_WAKE(0)
Li Wang (3):
shell/lib: refactor checkpoint with shared path for exec() support
kernel/pec: switch to new checkpoint wait/wake interface
tst_checkpoint: Detect and reinit shell or C style checkpoint file
include/tst_checkpoint_fn.h | 20 +++++-
lib/tst_checkpoint.c | 70 +++++++++++++------
.../kernel/connectors/pec/event_generator.c | 3 +-
.../kernel/connectors/pec/pec_listener.c | 3 +-
testcases/lib/tst_checkpoint.c | 62 +++++++++++++---
testcases/lib/tst_test.sh | 2 +
6 files changed, 122 insertions(+), 38 deletions(-)
--
2.49.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 13+ messages in thread* [LTP] [PATCH 1/3] shell/lib: refactor checkpoint with shared path for exec() support 2025-06-16 10:26 [LTP] [PATCH 0/3] checkpoint: Refactor and unify shell/C reinit support Li Wang via ltp @ 2025-06-16 10:26 ` Li Wang via ltp 2025-06-17 12:18 ` Avinesh Kumar 2025-06-16 10:26 ` [LTP] [PATCH 2/3] kernel/pec: switch to new checkpoint wait/wake interface Li Wang via ltp ` (2 subsequent siblings) 3 siblings, 1 reply; 13+ messages in thread From: Li Wang via ltp @ 2025-06-16 10:26 UTC (permalink / raw) To: ltp This patch refactors shell checkpoint mechanism to support exec() based process synchronization by introducing support for a shared futex region via a configurable path. Key changes: - Introduce LTP_IPC_PATH environment variable to specify the futex shared memory file used for checkpoint synchronization. - Add magic header "LTPM" to validate the shared memory file content. - Add checkpoint_reinit() to re-attach futex mapping for wait/wake operations in exec()'ed processes. - Update tst_checkpoint CLI tool to support "init", "wait", and "wake" commands with a unified interface. Signed-off-by: Li Wang <liwang@redhat.com> --- include/tst_checkpoint_fn.h | 20 +++++++++- lib/tst_checkpoint.c | 70 +++++++++++++++++++++++----------- testcases/lib/tst_checkpoint.c | 27 +++++++------ testcases/lib/tst_test.sh | 2 + 4 files changed, 83 insertions(+), 36 deletions(-) diff --git a/include/tst_checkpoint_fn.h b/include/tst_checkpoint_fn.h index 3a010d616..209296fe0 100644 --- a/include/tst_checkpoint_fn.h +++ b/include/tst_checkpoint_fn.h @@ -6,13 +6,29 @@ #define TST_CHECKPOINT_FN__ /* - * Checkpoint initializaton, must be done first. + * Checkpoint initialization. * - * NOTE: tst_tmpdir() must be called beforehand. + * This function sets up the shared memory region used for process + * synchronization via futexes. It must be called before any checkpoint + * operations such as tst_checkpoint_wait() or tst_checkpoint_wake(). */ void tst_checkpoint_init(const char *file, const int lineno, void (*cleanup_fn)(void)); +/* + * Checkpoint reinitialization. + * + * This function re-attaches to an existing shared memory checkpoint region + * pointed to by the LTP_IPC_PATH environment variable. It is typically used + * in child processes (e.g., shell scripts) to synchronize with the main test. + * + * The function verifies the magic header in the shared memory file and maps + * the futex array into memory. It must be called before using checkpoint + * operations in a process that did not perform the original initialization. + */ +void tst_checkpoint_reinit(const char *file, const int lineno, + void (*cleanup_fn)(void)); + /* * Waits for wakeup. * diff --git a/lib/tst_checkpoint.c b/lib/tst_checkpoint.c index 6a294b28b..5efbf98d2 100644 --- a/lib/tst_checkpoint.c +++ b/lib/tst_checkpoint.c @@ -38,8 +38,9 @@ unsigned int tst_max_futexes; void tst_checkpoint_init(const char *file, const int lineno, void (*cleanup_fn)(void)) { + char *path = getenv("LTP_IPC_PATH"); + size_t page_size = getpagesize(); int fd; - unsigned int page_size; if (tst_futexes) { tst_brkm_(file, lineno, TBROK, cleanup_fn, @@ -47,35 +48,58 @@ void tst_checkpoint_init(const char *file, const int lineno, return; } - /* - * The parent test process is responsible for creating the temporary - * directory and therefore must pass non-zero cleanup (to remove the - * directory if something went wrong). - * - * We cannot do this check unconditionally because if we need to init - * the checkpoint from a binary that was started by exec() the - * tst_tmpdir_created() will return false because the tmpdir was - * created by parent. In this case we expect the subprogram can call - * the init as a first function with NULL as cleanup function. - */ - if (cleanup_fn && !tst_tmpdir_created()) { - tst_brkm_(file, lineno, TBROK, cleanup_fn, - "You have to create test temporary directory " - "first (call tst_tmpdir())"); - return; + if (!path) { + char *tmp_path = NULL; + + if (!tst_tmpdir_created()) + tst_tmpdir(); + + safe_asprintf(__FILE__, __LINE__, cleanup_fn, &tmp_path, + "%s/ltp_checkpoint", tst_get_tmpdir()); + path = tmp_path; } - page_size = getpagesize(); + fd = SAFE_OPEN(cleanup_fn, path, O_RDWR | O_CREAT, 0666); + SAFE_WRITE(cleanup_fn, 1, fd, "LTPM", 4); + + tst_futexes = SAFE_MMAP(cleanup_fn, NULL, page_size, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + tst_futexes = (futex_t *)((char *)tst_futexes + 4); + tst_max_futexes = (page_size - 4) / sizeof(futex_t); + + SAFE_CLOSE(cleanup_fn, fd); +} + +void tst_checkpoint_reinit(const char *file, const int lineno, + void (*cleanup_fn)(void)) +{ + const char *path = getenv("LTP_IPC_PATH"); + size_t page_size = getpagesize(); + int fd; - fd = SAFE_OPEN(cleanup_fn, "checkpoint_futex_base_file", - O_RDWR | O_CREAT, 0666); + if (!path) { + tst_brkm_(file, lineno, TBROK, cleanup_fn, + "LTP_IPC_PATH is not defined"); + } - SAFE_FTRUNCATE(cleanup_fn, fd, page_size); + if (access(path, F_OK)) { + tst_brkm_(file, lineno, TBROK, cleanup_fn, + "File %s does not exist!", path); + } + fd = SAFE_OPEN(cleanup_fn, path, O_RDWR); tst_futexes = SAFE_MMAP(cleanup_fn, NULL, page_size, - PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + char *ptr = (char *)tst_futexes; + if (memcmp(ptr, "LTPM", 4) != 0) { + tst_brkm_(file, lineno, TBROK, cleanup_fn, + "Invalid shared memory region (bad magic)"); + } - tst_max_futexes = page_size / sizeof(uint32_t); + tst_futexes = (futex_t *)((char *)tst_futexes + 4); + tst_max_futexes = (page_size - 4) / sizeof(futex_t); SAFE_CLOSE(cleanup_fn, fd); } diff --git a/testcases/lib/tst_checkpoint.c b/testcases/lib/tst_checkpoint.c index c70c4e8e5..35a0c0dfa 100644 --- a/testcases/lib/tst_checkpoint.c +++ b/testcases/lib/tst_checkpoint.c @@ -9,11 +9,14 @@ #include <stdlib.h> #define TST_NO_DEFAULT_MAIN #include "tst_test.h" +#include "tst_checkpoint.h" static void print_help(void) { - printf("Usage: tst_checkpoint wait TIMEOUT ID\n"); + printf("Usage: tst_checkpoint init\n"); + printf(" or: tst_checkpoint wait TIMEOUT ID\n"); printf(" or: tst_checkpoint wake TIMEOUT ID NR_WAKE\n"); + printf("Arguments:\n"); printf(" TIMEOUT - timeout in ms\n"); printf(" ID - checkpoint id\n"); printf(" NR_WAKE - number of processes to wake up\n"); @@ -43,8 +46,13 @@ int main(int argc, char *argv[]) int ret; int type; - if (argc < 3) - goto help; + if (!strcmp(argv[1], "init")) { + if (argc != 2) + goto help; + + tst_checkpoint_init(__FILE__, __LINE__, NULL); + return 0; + } if (!strcmp(argv[1], "wait")) { type = 0; @@ -70,17 +78,14 @@ int main(int argc, char *argv[]) goto help; } - tst_reinit(); + tst_checkpoint_reinit(__FILE__, __LINE__, NULL); - if (type) - ret = tst_checkpoint_wake(id, nr_wake, timeout); - else + if (type == 0) ret = tst_checkpoint_wait(id, timeout); - - if (ret) - return 1; else - return 0; + ret = tst_checkpoint_wake(id, nr_wake, timeout); + + return ret ? 1 : 0; help: print_help(); diff --git a/testcases/lib/tst_test.sh b/testcases/lib/tst_test.sh index c32bd8b19..e5e76067b 100644 --- a/testcases/lib/tst_test.sh +++ b/testcases/lib/tst_test.sh @@ -629,6 +629,8 @@ _tst_init_checkpoints() ROD_SILENT dd if=/dev/zero of="$LTP_IPC_PATH" bs="$pagesize" count=1 ROD_SILENT chmod 600 "$LTP_IPC_PATH" export LTP_IPC_PATH + + tst_checkpoint init } _prepare_device() -- 2.49.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [LTP] [PATCH 1/3] shell/lib: refactor checkpoint with shared path for exec() support 2025-06-16 10:26 ` [LTP] [PATCH 1/3] shell/lib: refactor checkpoint with shared path for exec() support Li Wang via ltp @ 2025-06-17 12:18 ` Avinesh Kumar 0 siblings, 0 replies; 13+ messages in thread From: Avinesh Kumar @ 2025-06-17 12:18 UTC (permalink / raw) To: Li Wang; +Cc: ltp Hi Li, Thank you for this refactoring and fixing the pec test regression, I tested this patchset. Tested-by: Avinesh Kumar <akumar@suse.de> Regards, Avinesh On Monday, June 16, 2025 12:26:17 PM CEST Li Wang via ltp wrote: > This patch refactors shell checkpoint mechanism to support exec() > based process synchronization by introducing support for a shared > futex region via a configurable path. > > Key changes: > > - Introduce LTP_IPC_PATH environment variable to specify the futex > shared memory file used for checkpoint synchronization. > - Add magic header "LTPM" to validate the shared memory file content. > - Add checkpoint_reinit() to re-attach futex mapping for wait/wake > operations in exec()'ed processes. > - Update tst_checkpoint CLI tool to support "init", "wait", and "wake" > commands with a unified interface. > > Signed-off-by: Li Wang <liwang@redhat.com> > --- > include/tst_checkpoint_fn.h | 20 +++++++++- > lib/tst_checkpoint.c | 70 +++++++++++++++++++++++----------- > testcases/lib/tst_checkpoint.c | 27 +++++++------ > testcases/lib/tst_test.sh | 2 + > 4 files changed, 83 insertions(+), 36 deletions(-) > > diff --git a/include/tst_checkpoint_fn.h b/include/tst_checkpoint_fn.h > index 3a010d616..209296fe0 100644 > --- a/include/tst_checkpoint_fn.h > +++ b/include/tst_checkpoint_fn.h > @@ -6,13 +6,29 @@ > #define TST_CHECKPOINT_FN__ > > /* > - * Checkpoint initializaton, must be done first. > + * Checkpoint initialization. > * > - * NOTE: tst_tmpdir() must be called beforehand. > + * This function sets up the shared memory region used for process > + * synchronization via futexes. It must be called before any checkpoint > + * operations such as tst_checkpoint_wait() or tst_checkpoint_wake(). > */ > void tst_checkpoint_init(const char *file, const int lineno, > void (*cleanup_fn)(void)); > > +/* > + * Checkpoint reinitialization. > + * > + * This function re-attaches to an existing shared memory checkpoint region > + * pointed to by the LTP_IPC_PATH environment variable. It is typically used > + * in child processes (e.g., shell scripts) to synchronize with the main test. > + * > + * The function verifies the magic header in the shared memory file and maps > + * the futex array into memory. It must be called before using checkpoint > + * operations in a process that did not perform the original initialization. > + */ > +void tst_checkpoint_reinit(const char *file, const int lineno, > + void (*cleanup_fn)(void)); > + > /* > * Waits for wakeup. > * > diff --git a/lib/tst_checkpoint.c b/lib/tst_checkpoint.c > index 6a294b28b..5efbf98d2 100644 > --- a/lib/tst_checkpoint.c > +++ b/lib/tst_checkpoint.c > @@ -38,8 +38,9 @@ unsigned int tst_max_futexes; > void tst_checkpoint_init(const char *file, const int lineno, > void (*cleanup_fn)(void)) > { > + char *path = getenv("LTP_IPC_PATH"); > + size_t page_size = getpagesize(); > int fd; > - unsigned int page_size; > > if (tst_futexes) { > tst_brkm_(file, lineno, TBROK, cleanup_fn, > @@ -47,35 +48,58 @@ void tst_checkpoint_init(const char *file, const int lineno, > return; > } > > - /* > - * The parent test process is responsible for creating the temporary > - * directory and therefore must pass non-zero cleanup (to remove the > - * directory if something went wrong). > - * > - * We cannot do this check unconditionally because if we need to init > - * the checkpoint from a binary that was started by exec() the > - * tst_tmpdir_created() will return false because the tmpdir was > - * created by parent. In this case we expect the subprogram can call > - * the init as a first function with NULL as cleanup function. > - */ > - if (cleanup_fn && !tst_tmpdir_created()) { > - tst_brkm_(file, lineno, TBROK, cleanup_fn, > - "You have to create test temporary directory " > - "first (call tst_tmpdir())"); > - return; > + if (!path) { > + char *tmp_path = NULL; > + > + if (!tst_tmpdir_created()) > + tst_tmpdir(); > + > + safe_asprintf(__FILE__, __LINE__, cleanup_fn, &tmp_path, > + "%s/ltp_checkpoint", tst_get_tmpdir()); > + path = tmp_path; > } > > - page_size = getpagesize(); > + fd = SAFE_OPEN(cleanup_fn, path, O_RDWR | O_CREAT, 0666); > + SAFE_WRITE(cleanup_fn, 1, fd, "LTPM", 4); > + > + tst_futexes = SAFE_MMAP(cleanup_fn, NULL, page_size, > + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); > + > + tst_futexes = (futex_t *)((char *)tst_futexes + 4); > + tst_max_futexes = (page_size - 4) / sizeof(futex_t); > + > + SAFE_CLOSE(cleanup_fn, fd); > +} > + > +void tst_checkpoint_reinit(const char *file, const int lineno, > + void (*cleanup_fn)(void)) > +{ > + const char *path = getenv("LTP_IPC_PATH"); > + size_t page_size = getpagesize(); > + int fd; > > - fd = SAFE_OPEN(cleanup_fn, "checkpoint_futex_base_file", > - O_RDWR | O_CREAT, 0666); > + if (!path) { > + tst_brkm_(file, lineno, TBROK, cleanup_fn, > + "LTP_IPC_PATH is not defined"); > + } > > - SAFE_FTRUNCATE(cleanup_fn, fd, page_size); > + if (access(path, F_OK)) { > + tst_brkm_(file, lineno, TBROK, cleanup_fn, > + "File %s does not exist!", path); > + } > > + fd = SAFE_OPEN(cleanup_fn, path, O_RDWR); > tst_futexes = SAFE_MMAP(cleanup_fn, NULL, page_size, > - PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); > + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); > + > + char *ptr = (char *)tst_futexes; > + if (memcmp(ptr, "LTPM", 4) != 0) { > + tst_brkm_(file, lineno, TBROK, cleanup_fn, > + "Invalid shared memory region (bad magic)"); > + } > > - tst_max_futexes = page_size / sizeof(uint32_t); > + tst_futexes = (futex_t *)((char *)tst_futexes + 4); > + tst_max_futexes = (page_size - 4) / sizeof(futex_t); > > SAFE_CLOSE(cleanup_fn, fd); > } > diff --git a/testcases/lib/tst_checkpoint.c b/testcases/lib/tst_checkpoint.c > index c70c4e8e5..35a0c0dfa 100644 > --- a/testcases/lib/tst_checkpoint.c > +++ b/testcases/lib/tst_checkpoint.c > @@ -9,11 +9,14 @@ > #include <stdlib.h> > #define TST_NO_DEFAULT_MAIN > #include "tst_test.h" > +#include "tst_checkpoint.h" > > static void print_help(void) > { > - printf("Usage: tst_checkpoint wait TIMEOUT ID\n"); > + printf("Usage: tst_checkpoint init\n"); > + printf(" or: tst_checkpoint wait TIMEOUT ID\n"); > printf(" or: tst_checkpoint wake TIMEOUT ID NR_WAKE\n"); > + printf("Arguments:\n"); > printf(" TIMEOUT - timeout in ms\n"); > printf(" ID - checkpoint id\n"); > printf(" NR_WAKE - number of processes to wake up\n"); > @@ -43,8 +46,13 @@ int main(int argc, char *argv[]) > int ret; > int type; > > - if (argc < 3) > - goto help; > + if (!strcmp(argv[1], "init")) { > + if (argc != 2) > + goto help; > + > + tst_checkpoint_init(__FILE__, __LINE__, NULL); > + return 0; > + } > > if (!strcmp(argv[1], "wait")) { > type = 0; > @@ -70,17 +78,14 @@ int main(int argc, char *argv[]) > goto help; > } > > - tst_reinit(); > + tst_checkpoint_reinit(__FILE__, __LINE__, NULL); > > - if (type) > - ret = tst_checkpoint_wake(id, nr_wake, timeout); > - else > + if (type == 0) > ret = tst_checkpoint_wait(id, timeout); > - > - if (ret) > - return 1; > else > - return 0; > + ret = tst_checkpoint_wake(id, nr_wake, timeout); > + > + return ret ? 1 : 0; > > help: > print_help(); > diff --git a/testcases/lib/tst_test.sh b/testcases/lib/tst_test.sh > index c32bd8b19..e5e76067b 100644 > --- a/testcases/lib/tst_test.sh > +++ b/testcases/lib/tst_test.sh > @@ -629,6 +629,8 @@ _tst_init_checkpoints() > ROD_SILENT dd if=/dev/zero of="$LTP_IPC_PATH" bs="$pagesize" count=1 > ROD_SILENT chmod 600 "$LTP_IPC_PATH" > export LTP_IPC_PATH > + > + tst_checkpoint init > } > > _prepare_device() > -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 13+ messages in thread
* [LTP] [PATCH 2/3] kernel/pec: switch to new checkpoint wait/wake interface 2025-06-16 10:26 [LTP] [PATCH 0/3] checkpoint: Refactor and unify shell/C reinit support Li Wang via ltp 2025-06-16 10:26 ` [LTP] [PATCH 1/3] shell/lib: refactor checkpoint with shared path for exec() support Li Wang via ltp @ 2025-06-16 10:26 ` Li Wang via ltp 2025-06-16 10:26 ` [LTP] [PATCH 3/3] tst_checkpoint: Detect and reinit shell or C style checkpoint file Li Wang via ltp 2025-06-26 13:26 ` [LTP] [PATCH 0/3] checkpoint: Refactor and unify shell/C reinit support Cyril Hrubis 3 siblings, 0 replies; 13+ messages in thread From: Li Wang via ltp @ 2025-06-16 10:26 UTC (permalink / raw) To: ltp Some PEC tests were failing due to incorrect checkpoint reinitialization. This issue was introduced by commit bf9589d5bd ("lib: moves test infrastructure states into a shared context structure"), where the new tst_reinit() added magic validation and can no longer be used in a standalone process. For example: cn_pec 1 TINFO: Test process events connector cn_pec 1 TINFO: Testing fork event (nevents=10) tst_test.c:203: TBROK: Invalid shared memory region (bad magic) cn_pec 1 TBROK: tst_checkpoint wait 10000 0 failed This patch updates the PEC test components to use the new futex-based checkpoint mechanism via `tst_checkpoint.h`, which supports inter-process synchronization across exec() boundaries. Changes: - Replace legacy `tst_reinit()` with `TST_CHECKPOINT_WAIT(id)` and `TST_CHECKPOINT_WAKE(0)` - Remove unnecessary braces - Add `#include "tst_checkpoint.h"` This improves robustness and aligns with the refactored checkpoint infrastructure based on shared futex memory. Follow-up: bf9589d5bd ("lib: moves test infrastructure states into a shared context structure") Reported-by: Avinesh Kumar <akumar@suse.de> Signed-off-by: Li Wang <liwang@redhat.com> --- testcases/kernel/connectors/pec/event_generator.c | 3 ++- testcases/kernel/connectors/pec/pec_listener.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/testcases/kernel/connectors/pec/event_generator.c b/testcases/kernel/connectors/pec/event_generator.c index 4945058ff..3110512ca 100644 --- a/testcases/kernel/connectors/pec/event_generator.c +++ b/testcases/kernel/connectors/pec/event_generator.c @@ -18,6 +18,7 @@ #define TST_NO_DEFAULT_MAIN #include "tst_test.h" +#include "tst_checkpoint.h" extern struct tst_test *tst_test; static struct tst_test test = { @@ -186,7 +187,7 @@ int main(int argc, char **argv) /* ready to generate events */ if (checkpoint_id != -1) { - tst_reinit(); + tst_checkpoint_reinit(__FILE__, __LINE__, NULL); TST_CHECKPOINT_WAIT(checkpoint_id); } diff --git a/testcases/kernel/connectors/pec/pec_listener.c b/testcases/kernel/connectors/pec/pec_listener.c index 01ee91d43..2d04b2842 100644 --- a/testcases/kernel/connectors/pec/pec_listener.c +++ b/testcases/kernel/connectors/pec/pec_listener.c @@ -19,6 +19,7 @@ #include <signal.h> #include <linux/types.h> #include <linux/netlink.h> + #define TST_NO_DEFAULT_MAIN #include "tst_test.h" #include "tst_checkpoint.h" @@ -307,7 +308,7 @@ int main(int argc, char * const argv[]) /* ready to receive events */ if (checkpoint_id != -1) { - tst_reinit(); + tst_checkpoint_reinit(__FILE__, __LINE__, NULL); TST_CHECKPOINT_WAKE(0); } -- 2.49.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [LTP] [PATCH 3/3] tst_checkpoint: Detect and reinit shell or C style checkpoint file 2025-06-16 10:26 [LTP] [PATCH 0/3] checkpoint: Refactor and unify shell/C reinit support Li Wang via ltp 2025-06-16 10:26 ` [LTP] [PATCH 1/3] shell/lib: refactor checkpoint with shared path for exec() support Li Wang via ltp 2025-06-16 10:26 ` [LTP] [PATCH 2/3] kernel/pec: switch to new checkpoint wait/wake interface Li Wang via ltp @ 2025-06-16 10:26 ` Li Wang via ltp 2025-06-26 13:26 ` [LTP] [PATCH 0/3] checkpoint: Refactor and unify shell/C reinit support Cyril Hrubis 3 siblings, 0 replies; 13+ messages in thread From: Li Wang via ltp @ 2025-06-16 10:26 UTC (permalink / raw) To: ltp Add support to distinguish whether the checkpoint file pointed to by $LTP_IPC_PATH was initialized by a shell-based or C-based test case. This ensures the correct reinit is used based on the file format. To avoids errors when crossing between shell and C checkpoints. # ./shell_test05 shell_test05.c:14: TINFO: Waiting for shell to sleep on checkpoint! shell_test05.c:18: TINFO: Waking shell child! shell_test_checkpoint.sh:7: TINFO: Waiting for a checkpoint 0 (null) 1 TBROK : tst_checkpoint.c:113: Set test.needs_checkpoints = 1 (null) 2 TBROK : tst_checkpoint.c:113: Remaining cases broken shell_test_checkpoint.sh:9: TPASS: Continuing after checkpoint shell_test05.c:20: TBROK: tst_checkpoint_wake(0, 1, 10000) failed: ETIMEDOUT (110) tst_test.c:1864: TINFO: Killed the leftover descendant processes Signed-off-by: Li Wang <liwang@redhat.com> --- testcases/lib/tst_checkpoint.c | 37 +++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/testcases/lib/tst_checkpoint.c b/testcases/lib/tst_checkpoint.c index 35a0c0dfa..55ded7e7d 100644 --- a/testcases/lib/tst_checkpoint.c +++ b/testcases/lib/tst_checkpoint.c @@ -40,6 +40,37 @@ static int get_val(const char *name, const char *arg, unsigned int *val) return 0; } +static int is_shell_checkpoint_file(void) +{ + int fd; + char magic_buf[4]; + const char *path = getenv("LTP_IPC_PATH"); + + if (!path) + tst_brk(TBROK, "LTP_IPC_PATH is not set"); + + fd = SAFE_OPEN(path, O_RDONLY); + SAFE_READ(1, fd, magic_buf, 4); + SAFE_CLOSE(fd); + + if (!memcmp(magic_buf, "LTPM", 4)) { + tst_res(TINFO, "Detected Shell checkpoint file (magic = LTPM)"); + return 1; + } else { + uint32_t magic_val; + memcpy(&magic_val, magic_buf, sizeof(uint32_t)); + + if (magic_val == 0x4C54504D) { + tst_res(TINFO, "Detected C checkpoint file (magic = 0x4C54504D)"); + return 0; + } + + tst_brk(TBROK, "Unrecognized checkpoint file magic: 0x%08X", magic_val); + } + + return -1; +} + int main(int argc, char *argv[]) { unsigned int id, timeout, nr_wake; @@ -78,7 +109,11 @@ int main(int argc, char *argv[]) goto help; } - tst_checkpoint_reinit(__FILE__, __LINE__, NULL); + /* Re-init checkpoint file based on its format (Shell or C) */ + if (is_shell_checkpoint_file()) + tst_checkpoint_reinit(__FILE__, __LINE__, NULL); + else + tst_reinit(); if (type == 0) ret = tst_checkpoint_wait(id, timeout); -- 2.49.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [LTP] [PATCH 0/3] checkpoint: Refactor and unify shell/C reinit support 2025-06-16 10:26 [LTP] [PATCH 0/3] checkpoint: Refactor and unify shell/C reinit support Li Wang via ltp ` (2 preceding siblings ...) 2025-06-16 10:26 ` [LTP] [PATCH 3/3] tst_checkpoint: Detect and reinit shell or C style checkpoint file Li Wang via ltp @ 2025-06-26 13:26 ` Cyril Hrubis 2025-06-26 15:09 ` Li Wang via ltp 3 siblings, 1 reply; 13+ messages in thread From: Cyril Hrubis @ 2025-06-26 13:26 UTC (permalink / raw) To: Li Wang; +Cc: ltp Hi! I think that the root of the problem is that the shell function _tst_init_checkpoints() does not create the IPC region with the magic. What about this patch: diff --git a/testcases/lib/tst_test.sh b/testcases/lib/tst_test.sh index c32bd8b19..a310d3922 100644 --- a/testcases/lib/tst_test.sh +++ b/testcases/lib/tst_test.sh @@ -627,6 +627,7 @@ _tst_init_checkpoints() tst_brk TBROK "tst_getconf PAGESIZE failed" fi ROD_SILENT dd if=/dev/zero of="$LTP_IPC_PATH" bs="$pagesize" count=1 + ROD_SILENT printf LTPM | dd of="$LTP_IPC_PATH" bs=1 seek=0 conv=notrunc ROD_SILENT chmod 600 "$LTP_IPC_PATH" export LTP_IPC_PATH } -- Cyril Hrubis chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [LTP] [PATCH 0/3] checkpoint: Refactor and unify shell/C reinit support 2025-06-26 13:26 ` [LTP] [PATCH 0/3] checkpoint: Refactor and unify shell/C reinit support Cyril Hrubis @ 2025-06-26 15:09 ` Li Wang via ltp 2025-06-27 7:49 ` Cyril Hrubis 0 siblings, 1 reply; 13+ messages in thread From: Li Wang via ltp @ 2025-06-26 15:09 UTC (permalink / raw) To: Cyril Hrubis; +Cc: ltp Hi Cyril, On Thu, Jun 26, 2025 at 9:26 PM Cyril Hrubis <chrubis@suse.cz> wrote: > Hi! > I think that the root of the problem is that the shell function > _tst_init_checkpoints() does not create the IPC region with the magic. > > What about this patch: > > diff --git a/testcases/lib/tst_test.sh b/testcases/lib/tst_test.sh > index c32bd8b19..a310d3922 100644 > --- a/testcases/lib/tst_test.sh > +++ b/testcases/lib/tst_test.sh > @@ -627,6 +627,7 @@ _tst_init_checkpoints() > tst_brk TBROK "tst_getconf PAGESIZE failed" > fi > ROD_SILENT dd if=/dev/zero of="$LTP_IPC_PATH" bs="$pagesize" > count=1 > + ROD_SILENT printf LTPM | dd of="$LTP_IPC_PATH" bs=1 seek=0 > conv=notrunc > No, I'm afraid this won't work as expected. The PEC failure wasn't caused by the shell checkpoint missing the "LTPM" magic. Instead, the root cause was that the reinitialization logic (tst_reinit()) expected a different IPC format. The current fix was to detect the checkpoint type (shell vs. C) and use tst_checkpoint_reinit() accordingly during re-attachment. > ROD_SILENT chmod 600 "$LTP_IPC_PATH" > export LTP_IPC_PATH > } > > -- > Cyril Hrubis > chrubis@suse.cz > > -- Regards, Li Wang -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [LTP] [PATCH 0/3] checkpoint: Refactor and unify shell/C reinit support 2025-06-26 15:09 ` Li Wang via ltp @ 2025-06-27 7:49 ` Cyril Hrubis 2025-06-27 9:25 ` Li Wang via ltp 0 siblings, 1 reply; 13+ messages in thread From: Cyril Hrubis @ 2025-06-27 7:49 UTC (permalink / raw) To: Li Wang; +Cc: ltp Hi! > > I think that the root of the problem is that the shell function > > _tst_init_checkpoints() does not create the IPC region with the magic. > > > > What about this patch: > > > > diff --git a/testcases/lib/tst_test.sh b/testcases/lib/tst_test.sh > > index c32bd8b19..a310d3922 100644 > > --- a/testcases/lib/tst_test.sh > > +++ b/testcases/lib/tst_test.sh > > @@ -627,6 +627,7 @@ _tst_init_checkpoints() > > tst_brk TBROK "tst_getconf PAGESIZE failed" > > fi > > ROD_SILENT dd if=/dev/zero of="$LTP_IPC_PATH" bs="$pagesize" > > count=1 > > + ROD_SILENT printf LTPM | dd of="$LTP_IPC_PATH" bs=1 seek=0 > > conv=notrunc > > > > No, I'm afraid this won't work as expected. > > The PEC failure wasn't caused by the shell checkpoint missing the "LTPM" > magic. Instead, the root cause was that the reinitialization logic > (tst_reinit()) > expected a different IPC format. I do not think so, both the PEC C helpers and the tst_checkpoint.c call tst_reinit() so as long as the function succeeds the memory layout will be the same. The checkpoints will start at some offset in the page of the IPC memory, but that was always the case. And it turns out that the patch I've send yesterday does not work because of endianity. The magic in the IPC region is MPTL on little endian. This patch actually works: diff --git a/lib/tst_test.c b/lib/tst_test.c index 495e022f7..17ce91932 100644 --- a/lib/tst_test.c +++ b/lib/tst_test.c @@ -52,7 +52,13 @@ const char *TCID __attribute__((weak)); #define CVE_DB_URL "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-" #define DEFAULT_TIMEOUT 30 -#define LTP_MAGIC 0x4C54504D /* Magic number is "LTPM" */ + +/* Magic number is "LTPM" */ +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define LTP_MAGIC 0x4C54504D +#else +# define LTP_MAGIC 0x4D50544C +#endif struct tst_test *tst_test; diff --git a/testcases/lib/tst_test.sh b/testcases/lib/tst_test.sh index c32bd8b19..4be10a4f9 100644 --- a/testcases/lib/tst_test.sh +++ b/testcases/lib/tst_test.sh @@ -627,6 +627,7 @@ _tst_init_checkpoints() tst_brk TBROK "tst_getconf PAGESIZE failed" fi ROD_SILENT dd if=/dev/zero of="$LTP_IPC_PATH" bs="$pagesize" count=1 + ROD_SILENT "printf LTPM | dd of="$LTP_IPC_PATH" bs=1 seek=0 conv=notrunc" ROD_SILENT chmod 600 "$LTP_IPC_PATH" export LTP_IPC_PATH } -- Cyril Hrubis chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [LTP] [PATCH 0/3] checkpoint: Refactor and unify shell/C reinit support 2025-06-27 7:49 ` Cyril Hrubis @ 2025-06-27 9:25 ` Li Wang via ltp 2025-06-27 10:20 ` Cyril Hrubis 0 siblings, 1 reply; 13+ messages in thread From: Li Wang via ltp @ 2025-06-27 9:25 UTC (permalink / raw) To: Cyril Hrubis; +Cc: ltp On Fri, Jun 27, 2025 at 3:49 PM Cyril Hrubis <chrubis@suse.cz> wrote: > Hi! > > > I think that the root of the problem is that the shell function > > > _tst_init_checkpoints() does not create the IPC region with the magic. > > > > > > What about this patch: > > > > > > diff --git a/testcases/lib/tst_test.sh b/testcases/lib/tst_test.sh > > > index c32bd8b19..a310d3922 100644 > > > --- a/testcases/lib/tst_test.sh > > > +++ b/testcases/lib/tst_test.sh > > > @@ -627,6 +627,7 @@ _tst_init_checkpoints() > > > tst_brk TBROK "tst_getconf PAGESIZE failed" > > > fi > > > ROD_SILENT dd if=/dev/zero of="$LTP_IPC_PATH" bs="$pagesize" > > > count=1 > > > + ROD_SILENT printf LTPM | dd of="$LTP_IPC_PATH" bs=1 seek=0 > > > conv=notrunc > > > > > > > No, I'm afraid this won't work as expected. > > > > The PEC failure wasn't caused by the shell checkpoint missing the "LTPM" > > magic. Instead, the root cause was that the reinitialization logic > > (tst_reinit()) > > expected a different IPC format. > > I do not think so, both the PEC C helpers and the tst_checkpoint.c call > tst_reinit() so as long as the function succeeds the memory layout will > be the same. The checkpoints will start at some offset in the page of > the IPC memory, but that was always the case. > > And it turns out that the patch I've send yesterday does not work > because of endianity. The magic in the IPC region is MPTL on little > endian. > The endianity issue sounds reasonable, I thought about it a bit and tested it on my x86_64/s390x, it turns out you're right, tst_checkpoint.c uses tst_reinit() to make the IPC layout work for shell tests as well. My new tst_checkpoint_reinit method is actually a bit more complicated, requiring the introduction of two separate IPCs for C and shell. This is somewhat unnecessary. So, will you send a new patch (or I do that in my next version)? -- Regards, Li Wang -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [LTP] [PATCH 0/3] checkpoint: Refactor and unify shell/C reinit support 2025-06-27 9:25 ` Li Wang via ltp @ 2025-06-27 10:20 ` Cyril Hrubis 2025-06-27 10:28 ` Li Wang via ltp 0 siblings, 1 reply; 13+ messages in thread From: Cyril Hrubis @ 2025-06-27 10:20 UTC (permalink / raw) To: Li Wang; +Cc: ltp Hi! > So, will you send a new patch (or I do that in my next version)? I will send the patchset. -- Cyril Hrubis chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [LTP] [PATCH 0/3] checkpoint: Refactor and unify shell/C reinit support 2025-06-27 10:20 ` Cyril Hrubis @ 2025-06-27 10:28 ` Li Wang via ltp 2025-06-27 10:43 ` Cyril Hrubis 0 siblings, 1 reply; 13+ messages in thread From: Li Wang via ltp @ 2025-06-27 10:28 UTC (permalink / raw) To: Cyril Hrubis; +Cc: ltp On Fri, Jun 27, 2025 at 6:20 PM Cyril Hrubis <chrubis@suse.cz> wrote: > Hi! > > So, will you send a new patch (or I do that in my next version)? > > I will send the patchset. > Thanks! And one more question: The tst_checkpoint_init() in tst_checkpoint.c is not used by any test and library, should we delete it (and declare that the IPC only init/reinit by the tst_test.c function)? -- Regards, Li Wang -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [LTP] [PATCH 0/3] checkpoint: Refactor and unify shell/C reinit support 2025-06-27 10:28 ` Li Wang via ltp @ 2025-06-27 10:43 ` Cyril Hrubis 2025-06-27 10:49 ` Li Wang via ltp 0 siblings, 1 reply; 13+ messages in thread From: Cyril Hrubis @ 2025-06-27 10:43 UTC (permalink / raw) To: Li Wang; +Cc: ltp Hi! > > > So, will you send a new patch (or I do that in my next version)? > > > > I will send the patchset. > > > > Thanks! And one more question: > > The tst_checkpoint_init() in tst_checkpoint.c is not used by any test > and library, should we delete it (and declare that the IPC only init/reinit > by the tst_test.c function)? There is actually a define to TST_CHECKPOINT_INIT in the include/old/old_checkpoint.h but it looks like the last parts where this is called are old library tests that should be removed along with that. And the last test that was using it before rewrite was: commit b043751a6984c41db61067eebb0fee6ebf303960 Author: Andrea Cervesato <andrea.cervesato@suse.de> Date: Fri Mar 25 13:54:43 2022 +0100 Rewrite shm_comm.c using new LTP API Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.de> Reviewed-by: Cyril Hrubis <chrubis@suse.cz> So yes please, let's get rid of it. We should have do so actually three years ago. -- Cyril Hrubis chrubis@suse.cz -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [LTP] [PATCH 0/3] checkpoint: Refactor and unify shell/C reinit support 2025-06-27 10:43 ` Cyril Hrubis @ 2025-06-27 10:49 ` Li Wang via ltp 0 siblings, 0 replies; 13+ messages in thread From: Li Wang via ltp @ 2025-06-27 10:49 UTC (permalink / raw) To: Cyril Hrubis; +Cc: ltp On Fri, Jun 27, 2025 at 6:43 PM Cyril Hrubis <chrubis@suse.cz> wrote: > Hi! > > > > So, will you send a new patch (or I do that in my next version)? > > > > > > I will send the patchset. > > > > > > > Thanks! And one more question: > > > > The tst_checkpoint_init() in tst_checkpoint.c is not used by any test > > and library, should we delete it (and declare that the IPC only > init/reinit > > by the tst_test.c function)? > > There is actually a define to TST_CHECKPOINT_INIT in the > include/old/old_checkpoint.h but it looks like the last parts where this > is called are old library tests that should be removed along with that. > > And the last test that was using it before rewrite was: > > commit b043751a6984c41db61067eebb0fee6ebf303960 > Author: Andrea Cervesato <andrea.cervesato@suse.de> > Date: Fri Mar 25 13:54:43 2022 +0100 > > Rewrite shm_comm.c using new LTP API > > Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.de> > Reviewed-by: Cyril Hrubis <chrubis@suse.cz> > > > So yes please, let's get rid of it. We should have do so actually three > years ago. > True, that became a noise factor in reading the checkpoint code, and yes, I will send a patch to clean it up. -- Regards, Li Wang -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2025-06-27 10:49 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-06-16 10:26 [LTP] [PATCH 0/3] checkpoint: Refactor and unify shell/C reinit support Li Wang via ltp 2025-06-16 10:26 ` [LTP] [PATCH 1/3] shell/lib: refactor checkpoint with shared path for exec() support Li Wang via ltp 2025-06-17 12:18 ` Avinesh Kumar 2025-06-16 10:26 ` [LTP] [PATCH 2/3] kernel/pec: switch to new checkpoint wait/wake interface Li Wang via ltp 2025-06-16 10:26 ` [LTP] [PATCH 3/3] tst_checkpoint: Detect and reinit shell or C style checkpoint file Li Wang via ltp 2025-06-26 13:26 ` [LTP] [PATCH 0/3] checkpoint: Refactor and unify shell/C reinit support Cyril Hrubis 2025-06-26 15:09 ` Li Wang via ltp 2025-06-27 7:49 ` Cyril Hrubis 2025-06-27 9:25 ` Li Wang via ltp 2025-06-27 10:20 ` Cyril Hrubis 2025-06-27 10:28 ` Li Wang via ltp 2025-06-27 10:43 ` Cyril Hrubis 2025-06-27 10:49 ` Li Wang via ltp
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox