Message ID | 551441b4bce2d9dfd1567ffcd536f50f14a049d0.1599041148.git.viresh.kumar@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | [V10,1/2] syscalls/semtimedop: Add support for semtimedop and its time64 version | expand |
Hi! > Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> > --- > V10: > - Update comment in semop02.c. > - Let callers call tst_ts_get() on the timeout. > > testcases/kernel/syscalls/ipc/semop/semop.h | 55 +++++++++++++++++++ > testcases/kernel/syscalls/ipc/semop/semop01.c | 26 ++++++++- > testcases/kernel/syscalls/ipc/semop/semop02.c | 44 +++++++++++---- > testcases/kernel/syscalls/ipc/semop/semop03.c | 15 ++++- > 4 files changed, 125 insertions(+), 15 deletions(-) > create mode 100644 testcases/kernel/syscalls/ipc/semop/semop.h > > diff --git a/testcases/kernel/syscalls/ipc/semop/semop.h b/testcases/kernel/syscalls/ipc/semop/semop.h > new file mode 100644 > index 000000000000..1fac31818108 > --- /dev/null > +++ b/testcases/kernel/syscalls/ipc/semop/semop.h > @@ -0,0 +1,55 @@ > +// SPDX-License-Identifier: GPL-2.0-or-later > + > +#ifndef SEMOP_VAR__ > +#define SEMOP_VAR__ > + > +#include <sys/sem.h> > +#include "tst_timer.h" > + > +static inline int sys_semtimedop(int semid, struct sembuf *sops, size_t nsops, > + void *timeout) > +{ > + return tst_syscall(__NR_semtimedop, semid, sops, nsops, timeout); > +} > + > +static inline int sys_semtimedop_time64(int semid, struct sembuf *sops, > + size_t nsops, void *timeout) > +{ > + return tst_syscall(__NR_semtimedop_time64, semid, sops, nsops, timeout); > +} > + > +struct test_variants { > + int (*semop)(int semid, struct sembuf *sops, size_t nsops); > + int (*semtimedop)(int semid, struct sembuf *sops, size_t nsops, void *timeout); > + enum tst_ts_type type; > + char *desc; > +} variants[] = { > + { .semop = semop, .type = TST_LIBC_TIMESPEC, .desc = "semop: syscall"}, > + > +#if (__NR_semtimedop != __LTP__NR_INVALID_SYSCALL) > + { .semtimedop = sys_semtimedop, .type = TST_KERN_OLD_TIMESPEC, .desc = "semtimedop: syscall with old kernel spec"}, > +#endif > + > +#if (__NR_semtimedop_time64 != __LTP__NR_INVALID_SYSCALL) > + { .semtimedop = sys_semtimedop_time64, .type = TST_KERN_TIMESPEC, .desc = "semtimedop: syscall time64 with kernel spec"}, > +#endif > +}; > + > +static inline int call_semop(struct test_variants *tv, int semid, > + struct sembuf *sops, size_t nsops, void *timeout) > +{ > + if (tv->semop) > + return tv->semop(semid, sops, nsops); > + > + return tv->semtimedop(semid, sops, nsops, timeout); > +} > + > +static inline void semop_supported_by_kernel(struct test_variants *tv) > +{ > + /* Check if the syscall is implemented on the platform */ > + TEST(call_semop(tv, 0, NULL, 0, NULL)); > + if (TST_RET == -1 && TST_ERR == ENOSYS) > + tst_brk(TCONF, "Test not supported on kernel/platform"); > +} > + > +#endif /* SEMOP_VAR__ */ > diff --git a/testcases/kernel/syscalls/ipc/semop/semop01.c b/testcases/kernel/syscalls/ipc/semop/semop01.c > index 2daf6bbc5c4e..0524a8098e23 100644 > --- a/testcases/kernel/syscalls/ipc/semop/semop01.c > +++ b/testcases/kernel/syscalls/ipc/semop/semop01.c > @@ -12,6 +12,7 @@ > #include "tst_test.h" > #include "libnewipc.h" > #include "lapi/semun.h" > +#include "semop.h" > > #define NSEMS 4 > > @@ -21,14 +22,23 @@ static key_t semkey; > static unsigned short int sarr[PSEMS]; > static union semun get_arr = {.array = sarr}; > static struct sembuf sops[PSEMS]; > +static struct tst_ts timeout; > > -static void run(void) > +static struct test_case_t { > + struct tst_ts *to; > +} tc[] = { > + {NULL}, > + {&timeout} > +}; > + > +static void run(unsigned int n) > { > + struct test_variants *tv = &variants[tst_variant]; > union semun arr = { .val = 0 }; > int fail = 0; > int i; > > - TEST(semop(sem_id, sops, NSEMS)); > + TEST(call_semop(tv, sem_id, sops, NSEMS, tst_ts_get(tc[n].to))); > if (TST_RET == -1) { > tst_res(TFAIL | TTERRNO, "semop() failed"); > return; > @@ -56,8 +66,16 @@ static void run(void) > > static void setup(void) > { > + struct test_variants *tv = &variants[tst_variant]; > int i; > > + tst_res(TINFO, "Testing variant: %s", tv->desc); > + semop_supported_by_kernel(tv); > + > + timeout.type = tv->type; > + tst_ts_set_sec(&timeout, 1); > + tst_ts_set_nsec(&timeout, 10000); > + > semkey = GETIPCKEY(); > > sem_id = semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA); > @@ -80,7 +98,9 @@ static void cleanup(void) > } > > static struct tst_test test = { > - .test_all = run, > + .test = run, > + .tcnt = ARRAY_SIZE(tc), > + .test_variants = ARRAY_SIZE(variants), > .setup = setup, > .cleanup = cleanup, > .needs_tmpdir = 1, > diff --git a/testcases/kernel/syscalls/ipc/semop/semop02.c b/testcases/kernel/syscalls/ipc/semop/semop02.c > index 0dff8e537719..22fdb5cbef4c 100644 > --- a/testcases/kernel/syscalls/ipc/semop/semop02.c > +++ b/testcases/kernel/syscalls/ipc/semop/semop02.c > @@ -10,6 +10,8 @@ > * EFBIG - sem_num > number of semaphores in a set > * EAGAIN - semop = 0 for non-zero semaphore and IPC_NOWAIT passed in flags > * EAGAIN - semop = -1 for zero semaphore and IPC_NOWAIT passed in flags > + * EAGAIN - semop = 0 and timeout happens > + * EAGAIN - semop = -1 and timeout happens > * > * Copyright (c) International Business Machines Corp., 2001 > * 03/2001 - Written by Wayne Boyer > @@ -23,17 +25,20 @@ > #include "tst_test.h" > #include "libnewipc.h" > #include "lapi/semun.h" > +#include "semop.h" > > static int valid_sem_id = -1; > static int noperm_sem_id = -1; > static int bad_sem_id = -1; > static short sem_op_max, sem_op_1 = 1, sem_op_negative = -1, sem_op_zero = 0; > static struct sembuf *faulty_buf; > +static struct tst_ts timeout; > > #define NSOPS 1 > #define BIGOPS 1024 > > static struct test_case_t { > + int all_variants; Something as needs_timeout, or semtimedop_only would be a bit more descriptive. > int *semid; > struct sembuf **buf; > short *sem_op; > @@ -44,25 +49,35 @@ static struct test_case_t { > int arr_val; > int error; > } tc[] = { > - {&valid_sem_id, NULL, &sem_op_1, 0, 0, 0, BIGOPS, 1, E2BIG}, > - {&noperm_sem_id, NULL, &sem_op_1, 0, 0, 0, NSOPS, 1, EACCES}, > - {&valid_sem_id, &faulty_buf, &sem_op_1, 0, 0, 0, NSOPS, 1, EFAULT}, > - {&valid_sem_id, NULL, &sem_op_1, 0, 0, 0, 0, 1, EINVAL}, > - {&bad_sem_id, NULL, &sem_op_1, 0, 0, 0, NSOPS, 1, EINVAL}, > - {&valid_sem_id, NULL, &sem_op_max, 0, 0, 0, 1, 1, ERANGE}, > - {&valid_sem_id, NULL, &sem_op_1, 0, -1, SEM_UNDO, 1, 1, EFBIG}, > - {&valid_sem_id, NULL, &sem_op_1, 0, PSEMS + 1, SEM_UNDO, 1, 1, EFBIG}, > - {&valid_sem_id, NULL, &sem_op_zero, 2, 2, IPC_NOWAIT, 1, 1, EAGAIN}, > - {&valid_sem_id, NULL, &sem_op_negative, 2, 2, IPC_NOWAIT, 1, 0, EAGAIN} > + {1, &valid_sem_id, NULL, &sem_op_1, 0, 0, 0, BIGOPS, 1, E2BIG}, > + {1, &noperm_sem_id, NULL, &sem_op_1, 0, 0, 0, NSOPS, 1, EACCES}, > + {1, &valid_sem_id, &faulty_buf, &sem_op_1, 0, 0, 0, NSOPS, 1, EFAULT}, > + {1, &valid_sem_id, NULL, &sem_op_1, 0, 0, 0, 0, 1, EINVAL}, > + {1, &bad_sem_id, NULL, &sem_op_1, 0, 0, 0, NSOPS, 1, EINVAL}, > + {1, &valid_sem_id, NULL, &sem_op_max, 0, 0, 0, 1, 1, ERANGE}, > + {1, &valid_sem_id, NULL, &sem_op_1, 0, -1, SEM_UNDO, 1, 1, EFBIG}, > + {1, &valid_sem_id, NULL, &sem_op_1, 0, PSEMS + 1, SEM_UNDO, 1, 1, EFBIG}, > + {1, &valid_sem_id, NULL, &sem_op_zero, 2, 2, IPC_NOWAIT, 1, 1, EAGAIN}, > + {1, &valid_sem_id, NULL, &sem_op_negative, 2, 2, IPC_NOWAIT, 1, 0, EAGAIN}, > + {0, &valid_sem_id, NULL, &sem_op_zero, 0, 0, SEM_UNDO, 1, 1, EAGAIN}, > + {0, &valid_sem_id, NULL, &sem_op_negative, 0, 0, SEM_UNDO, 1, 0, EAGAIN}, > }; > > static void setup(void) > { > + struct test_variants *tv = &variants[tst_variant]; > struct passwd *ltpuser; > key_t semkey; > union semun arr; > struct seminfo ipc_buf; > > + tst_res(TINFO, "Testing variant: %s", tv->desc); > + semop_supported_by_kernel(tv); > + > + timeout.type = tv->type; > + tst_ts_set_sec(&timeout, 1); > + tst_ts_set_nsec(&timeout, 10000); One second is way too much, can we please make it just 10000ns ? LTP runs on many automated labs, adding a useless second to a test adds up to years of wasted runtime.
diff --git a/testcases/kernel/syscalls/ipc/semop/semop.h b/testcases/kernel/syscalls/ipc/semop/semop.h new file mode 100644 index 000000000000..1fac31818108 --- /dev/null +++ b/testcases/kernel/syscalls/ipc/semop/semop.h @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#ifndef SEMOP_VAR__ +#define SEMOP_VAR__ + +#include <sys/sem.h> +#include "tst_timer.h" + +static inline int sys_semtimedop(int semid, struct sembuf *sops, size_t nsops, + void *timeout) +{ + return tst_syscall(__NR_semtimedop, semid, sops, nsops, timeout); +} + +static inline int sys_semtimedop_time64(int semid, struct sembuf *sops, + size_t nsops, void *timeout) +{ + return tst_syscall(__NR_semtimedop_time64, semid, sops, nsops, timeout); +} + +struct test_variants { + int (*semop)(int semid, struct sembuf *sops, size_t nsops); + int (*semtimedop)(int semid, struct sembuf *sops, size_t nsops, void *timeout); + enum tst_ts_type type; + char *desc; +} variants[] = { + { .semop = semop, .type = TST_LIBC_TIMESPEC, .desc = "semop: syscall"}, + +#if (__NR_semtimedop != __LTP__NR_INVALID_SYSCALL) + { .semtimedop = sys_semtimedop, .type = TST_KERN_OLD_TIMESPEC, .desc = "semtimedop: syscall with old kernel spec"}, +#endif + +#if (__NR_semtimedop_time64 != __LTP__NR_INVALID_SYSCALL) + { .semtimedop = sys_semtimedop_time64, .type = TST_KERN_TIMESPEC, .desc = "semtimedop: syscall time64 with kernel spec"}, +#endif +}; + +static inline int call_semop(struct test_variants *tv, int semid, + struct sembuf *sops, size_t nsops, void *timeout) +{ + if (tv->semop) + return tv->semop(semid, sops, nsops); + + return tv->semtimedop(semid, sops, nsops, timeout); +} + +static inline void semop_supported_by_kernel(struct test_variants *tv) +{ + /* Check if the syscall is implemented on the platform */ + TEST(call_semop(tv, 0, NULL, 0, NULL)); + if (TST_RET == -1 && TST_ERR == ENOSYS) + tst_brk(TCONF, "Test not supported on kernel/platform"); +} + +#endif /* SEMOP_VAR__ */ diff --git a/testcases/kernel/syscalls/ipc/semop/semop01.c b/testcases/kernel/syscalls/ipc/semop/semop01.c index 2daf6bbc5c4e..0524a8098e23 100644 --- a/testcases/kernel/syscalls/ipc/semop/semop01.c +++ b/testcases/kernel/syscalls/ipc/semop/semop01.c @@ -12,6 +12,7 @@ #include "tst_test.h" #include "libnewipc.h" #include "lapi/semun.h" +#include "semop.h" #define NSEMS 4 @@ -21,14 +22,23 @@ static key_t semkey; static unsigned short int sarr[PSEMS]; static union semun get_arr = {.array = sarr}; static struct sembuf sops[PSEMS]; +static struct tst_ts timeout; -static void run(void) +static struct test_case_t { + struct tst_ts *to; +} tc[] = { + {NULL}, + {&timeout} +}; + +static void run(unsigned int n) { + struct test_variants *tv = &variants[tst_variant]; union semun arr = { .val = 0 }; int fail = 0; int i; - TEST(semop(sem_id, sops, NSEMS)); + TEST(call_semop(tv, sem_id, sops, NSEMS, tst_ts_get(tc[n].to))); if (TST_RET == -1) { tst_res(TFAIL | TTERRNO, "semop() failed"); return; @@ -56,8 +66,16 @@ static void run(void) static void setup(void) { + struct test_variants *tv = &variants[tst_variant]; int i; + tst_res(TINFO, "Testing variant: %s", tv->desc); + semop_supported_by_kernel(tv); + + timeout.type = tv->type; + tst_ts_set_sec(&timeout, 1); + tst_ts_set_nsec(&timeout, 10000); + semkey = GETIPCKEY(); sem_id = semget(semkey, PSEMS, IPC_CREAT | IPC_EXCL | SEM_RA); @@ -80,7 +98,9 @@ static void cleanup(void) } static struct tst_test test = { - .test_all = run, + .test = run, + .tcnt = ARRAY_SIZE(tc), + .test_variants = ARRAY_SIZE(variants), .setup = setup, .cleanup = cleanup, .needs_tmpdir = 1, diff --git a/testcases/kernel/syscalls/ipc/semop/semop02.c b/testcases/kernel/syscalls/ipc/semop/semop02.c index 0dff8e537719..22fdb5cbef4c 100644 --- a/testcases/kernel/syscalls/ipc/semop/semop02.c +++ b/testcases/kernel/syscalls/ipc/semop/semop02.c @@ -10,6 +10,8 @@ * EFBIG - sem_num > number of semaphores in a set * EAGAIN - semop = 0 for non-zero semaphore and IPC_NOWAIT passed in flags * EAGAIN - semop = -1 for zero semaphore and IPC_NOWAIT passed in flags + * EAGAIN - semop = 0 and timeout happens + * EAGAIN - semop = -1 and timeout happens * * Copyright (c) International Business Machines Corp., 2001 * 03/2001 - Written by Wayne Boyer @@ -23,17 +25,20 @@ #include "tst_test.h" #include "libnewipc.h" #include "lapi/semun.h" +#include "semop.h" static int valid_sem_id = -1; static int noperm_sem_id = -1; static int bad_sem_id = -1; static short sem_op_max, sem_op_1 = 1, sem_op_negative = -1, sem_op_zero = 0; static struct sembuf *faulty_buf; +static struct tst_ts timeout; #define NSOPS 1 #define BIGOPS 1024 static struct test_case_t { + int all_variants; int *semid; struct sembuf **buf; short *sem_op; @@ -44,25 +49,35 @@ static struct test_case_t { int arr_val; int error; } tc[] = { - {&valid_sem_id, NULL, &sem_op_1, 0, 0, 0, BIGOPS, 1, E2BIG}, - {&noperm_sem_id, NULL, &sem_op_1, 0, 0, 0, NSOPS, 1, EACCES}, - {&valid_sem_id, &faulty_buf, &sem_op_1, 0, 0, 0, NSOPS, 1, EFAULT}, - {&valid_sem_id, NULL, &sem_op_1, 0, 0, 0, 0, 1, EINVAL}, - {&bad_sem_id, NULL, &sem_op_1, 0, 0, 0, NSOPS, 1, EINVAL}, - {&valid_sem_id, NULL, &sem_op_max, 0, 0, 0, 1, 1, ERANGE}, - {&valid_sem_id, NULL, &sem_op_1, 0, -1, SEM_UNDO, 1, 1, EFBIG}, - {&valid_sem_id, NULL, &sem_op_1, 0, PSEMS + 1, SEM_UNDO, 1, 1, EFBIG}, - {&valid_sem_id, NULL, &sem_op_zero, 2, 2, IPC_NOWAIT, 1, 1, EAGAIN}, - {&valid_sem_id, NULL, &sem_op_negative, 2, 2, IPC_NOWAIT, 1, 0, EAGAIN} + {1, &valid_sem_id, NULL, &sem_op_1, 0, 0, 0, BIGOPS, 1, E2BIG}, + {1, &noperm_sem_id, NULL, &sem_op_1, 0, 0, 0, NSOPS, 1, EACCES}, + {1, &valid_sem_id, &faulty_buf, &sem_op_1, 0, 0, 0, NSOPS, 1, EFAULT}, + {1, &valid_sem_id, NULL, &sem_op_1, 0, 0, 0, 0, 1, EINVAL}, + {1, &bad_sem_id, NULL, &sem_op_1, 0, 0, 0, NSOPS, 1, EINVAL}, + {1, &valid_sem_id, NULL, &sem_op_max, 0, 0, 0, 1, 1, ERANGE}, + {1, &valid_sem_id, NULL, &sem_op_1, 0, -1, SEM_UNDO, 1, 1, EFBIG}, + {1, &valid_sem_id, NULL, &sem_op_1, 0, PSEMS + 1, SEM_UNDO, 1, 1, EFBIG}, + {1, &valid_sem_id, NULL, &sem_op_zero, 2, 2, IPC_NOWAIT, 1, 1, EAGAIN}, + {1, &valid_sem_id, NULL, &sem_op_negative, 2, 2, IPC_NOWAIT, 1, 0, EAGAIN}, + {0, &valid_sem_id, NULL, &sem_op_zero, 0, 0, SEM_UNDO, 1, 1, EAGAIN}, + {0, &valid_sem_id, NULL, &sem_op_negative, 0, 0, SEM_UNDO, 1, 0, EAGAIN}, }; static void setup(void) { + struct test_variants *tv = &variants[tst_variant]; struct passwd *ltpuser; key_t semkey; union semun arr; struct seminfo ipc_buf; + tst_res(TINFO, "Testing variant: %s", tv->desc); + semop_supported_by_kernel(tv); + + timeout.type = tv->type; + tst_ts_set_sec(&timeout, 1); + tst_ts_set_nsec(&timeout, 10000); + ltpuser = SAFE_GETPWNAM("nobody"); SAFE_SETUID(ltpuser->pw_uid); @@ -88,6 +103,7 @@ static void setup(void) static void run(unsigned int i) { + struct test_variants *tv = &variants[tst_variant]; union semun arr = {.val = tc[i].arr_val}; struct sembuf buf = { .sem_op = *tc[i].sem_op, @@ -96,6 +112,11 @@ static void run(unsigned int i) }; struct sembuf *ptr = &buf; + if (!tc[i].all_variants && tv->semop == semop) { + tst_res(TCONF, "Test not supported for variant"); + return; + } + if (*tc[i].semid == valid_sem_id) { if (semctl(valid_sem_id, tc[i].ctl_sem_num, SETVAL, arr) == -1) tst_brk(TBROK | TERRNO, "semctl() SETVAL failed"); @@ -104,7 +125,7 @@ static void run(unsigned int i) if (tc[i].buf) ptr = *tc[i].buf; - TEST(semop(*(tc[i].semid), ptr, tc[i].t_ops)); + TEST(call_semop(tv, *(tc[i].semid), ptr, tc[i].t_ops, tst_ts_get(&timeout))); if (TST_RET != -1) { tst_res(TFAIL | TTERRNO, "call succeeded unexpectedly"); @@ -136,6 +157,7 @@ static void cleanup(void) static struct tst_test test = { .test = run, .tcnt = ARRAY_SIZE(tc), + .test_variants = ARRAY_SIZE(variants), .setup = setup, .cleanup = cleanup, .needs_tmpdir = 1, diff --git a/testcases/kernel/syscalls/ipc/semop/semop03.c b/testcases/kernel/syscalls/ipc/semop/semop03.c index 25123f08c239..19f3d7fb1499 100644 --- a/testcases/kernel/syscalls/ipc/semop/semop03.c +++ b/testcases/kernel/syscalls/ipc/semop/semop03.c @@ -15,9 +15,11 @@ #include "tst_test.h" #include "libnewipc.h" #include "lapi/semun.h" +#include "semop.h" static key_t semkey; static int sem_id = -1; +static struct tst_ts timeout; struct test_case_t { union semun semunptr; @@ -34,13 +36,14 @@ struct test_case_t { static void do_child(int i) { + struct test_variants *tv = &variants[tst_variant]; struct sembuf s_buf = { .sem_op = tc[i].op, .sem_flg = tc[i].flg, .sem_num = tc[i].num, }; - TEST(semop(sem_id, &s_buf, 1)); + TEST(call_semop(tv, sem_id, &s_buf, 1, tst_ts_get(&timeout))); if (TST_RET != -1) { tst_res(TFAIL, "call succeeded when error expected"); exit(0); @@ -62,6 +65,15 @@ static void sighandler(int sig) static void setup(void) { + struct test_variants *tv = &variants[tst_variant]; + + tst_res(TINFO, "Testing variant: %s", tv->desc); + semop_supported_by_kernel(tv); + + timeout.type = tv->type; + tst_ts_set_sec(&timeout, 1); + tst_ts_set_nsec(&timeout, 10000); + SAFE_SIGNAL(SIGHUP, sighandler); semkey = GETIPCKEY(); @@ -119,6 +131,7 @@ static void run(unsigned int i) static struct tst_test test = { .test = run, .tcnt = ARRAY_SIZE(tc), + .test_variants = ARRAY_SIZE(variants), .setup = setup, .cleanup = cleanup, .needs_tmpdir = 1,
This adds support for semtimedop() and its time64 variant to the existing semop() syscall tests. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> --- V10: - Update comment in semop02.c. - Let callers call tst_ts_get() on the timeout. testcases/kernel/syscalls/ipc/semop/semop.h | 55 +++++++++++++++++++ testcases/kernel/syscalls/ipc/semop/semop01.c | 26 ++++++++- testcases/kernel/syscalls/ipc/semop/semop02.c | 44 +++++++++++---- testcases/kernel/syscalls/ipc/semop/semop03.c | 15 ++++- 4 files changed, 125 insertions(+), 15 deletions(-) create mode 100644 testcases/kernel/syscalls/ipc/semop/semop.h