mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
selftests: ntsync: test absolute MONOTONIC waits under time namespaces
Cover the timens conversion in ntsync_schedule(): with a negative CLOCK_MONOTONIC offset, a 100 ms absolute wait must not return immediately against the host clock. Suggested-by: Maoyi Xie <maoyixie.tju@gmail.com> Signed-off-by: Iván Ezequiel Rodriguez <ivanrwcm25@gmail.com> Reviewed-by: Elizabeth Figura <zfigura@codeweavers.com> Signed-off-by: Elizabeth Figura <zfigura@codeweavers.com> Link: https://patch.msgid.link/20260723201301.11826-6-zfigura@codeweavers.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
2fded3140d
commit
facd8463a5
|
|
@ -8,12 +8,18 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
#include <sched.h>
|
||||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
#include <linux/ntsync.h>
|
||||
#include "kselftest_harness.h"
|
||||
|
||||
#ifndef CLONE_NEWTIME
|
||||
#define CLONE_NEWTIME 0x00000080
|
||||
#endif
|
||||
|
||||
static int read_sem_state(int sem, __u32 *count, __u32 *max)
|
||||
{
|
||||
struct ntsync_sem_args args;
|
||||
|
|
@ -1384,4 +1390,85 @@ TEST(wait_args_validation)
|
|||
close(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Absolute MONOTONIC timeouts must honour the caller's time namespace.
|
||||
* With a negative monotonic offset, a 100 ms wait must still take ~100 ms
|
||||
* of namespace time (not return immediately against the host clock).
|
||||
*/
|
||||
TEST(wait_any_monotonic_timens)
|
||||
{
|
||||
struct ntsync_sem_args sem_args = {0};
|
||||
struct ntsync_wait_args wait_args = {0};
|
||||
struct timespec start, end;
|
||||
char buf[64];
|
||||
__u64 elapsed_ns;
|
||||
int fd, offset_fd, sem, ret, status, len;
|
||||
pid_t pid;
|
||||
|
||||
if (access("/proc/self/ns/time", F_OK))
|
||||
SKIP(return, "Time namespaces are not supported");
|
||||
|
||||
fd = open("/dev/ntsync", O_CLOEXEC | O_RDONLY);
|
||||
if (fd < 0)
|
||||
SKIP(return, "/dev/ntsync is not available");
|
||||
|
||||
ret = unshare(CLONE_NEWTIME);
|
||||
if (ret) {
|
||||
close(fd);
|
||||
if (errno == EPERM)
|
||||
SKIP(return, "need CAP_SYS_ADMIN for CLONE_NEWTIME");
|
||||
ASSERT_EQ(0, ret);
|
||||
}
|
||||
|
||||
len = snprintf(buf, sizeof(buf), "%d %d 0", CLOCK_MONOTONIC, -10);
|
||||
offset_fd = open("/proc/self/timens_offsets", O_WRONLY);
|
||||
ASSERT_LE(0, offset_fd);
|
||||
ASSERT_EQ(len, write(offset_fd, buf, len));
|
||||
close(offset_fd);
|
||||
|
||||
pid = fork();
|
||||
ASSERT_LE(0, pid);
|
||||
if (!pid) {
|
||||
int obj;
|
||||
|
||||
sem_args.count = 0;
|
||||
sem_args.max = 1;
|
||||
sem = ioctl(fd, NTSYNC_IOC_CREATE_SEM, &sem_args);
|
||||
if (sem < 0)
|
||||
_exit(1);
|
||||
|
||||
obj = sem;
|
||||
wait_args.timeout = get_abs_timeout(100);
|
||||
wait_args.objs = (uintptr_t)&obj;
|
||||
wait_args.count = 1;
|
||||
wait_args.owner = 123;
|
||||
wait_args.index = 0xdeadbeef;
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &start))
|
||||
_exit(2);
|
||||
ret = ioctl(fd, NTSYNC_IOC_WAIT_ANY, &wait_args);
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &end))
|
||||
_exit(2);
|
||||
|
||||
if (ret != -1 || errno != ETIMEDOUT)
|
||||
_exit(3);
|
||||
|
||||
elapsed_ns = (end.tv_sec - start.tv_sec) * 1000000000ULL +
|
||||
(end.tv_nsec - start.tv_nsec);
|
||||
/* Without timens conversion this returns in ~0 ms. */
|
||||
if (elapsed_ns < 50 * 1000000ULL)
|
||||
_exit(4);
|
||||
if (elapsed_ns > 1000 * 1000000ULL)
|
||||
_exit(5);
|
||||
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
ASSERT_EQ(pid, waitpid(pid, &status, 0));
|
||||
EXPECT_TRUE(WIFEXITED(status));
|
||||
EXPECT_EQ(0, WEXITSTATUS(status));
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
TEST_HARNESS_MAIN
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user