Tests to ensure namespace cases are working correctly. Ensures that namespaces work as before for status/write cases and validates removing a namespace with open files, tracing enabled, etc. Signed-off-by: Beau Belgrave <beaub@xxxxxxxxxxxxxxxxxxx> --- .../selftests/user_events/ftrace_test.c | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/tools/testing/selftests/user_events/ftrace_test.c b/tools/testing/selftests/user_events/ftrace_test.c index 404a2713dcae..5d384c1b31c4 100644 --- a/tools/testing/selftests/user_events/ftrace_test.c +++ b/tools/testing/selftests/user_events/ftrace_test.c @@ -22,6 +22,16 @@ const char *enable_file = "/sys/kernel/debug/tracing/events/user_events/__test_e const char *trace_file = "/sys/kernel/debug/tracing/trace"; const char *fmt_file = "/sys/kernel/debug/tracing/events/user_events/__test_event/format"; +const char *namespace_dir = "/sys/kernel/debug/tracing/namespaces/self_test"; +const char *ns_data_file = "/sys/kernel/debug/tracing/namespaces/self_test/" + "root/user_events_data"; +const char *ns_status_file = "/sys/kernel/debug/tracing/namespaces/self_test/" + "root/user_events_status"; +const char *ns_enable_file = "/sys/kernel/debug/tracing/events/" + "user_events.self_test/__test_event/enable"; +const char *ns_options_file = "/sys/kernel/debug/tracing/namespaces/self_test/" + "options"; + static inline int status_check(char *status_page, int status_bit) { return status_page[status_bit >> 3] & (1 << (status_bit & 7)); @@ -160,6 +170,53 @@ static int check_print_fmt(const char *event, const char *expected) return strcmp(print_fmt, expected); } +FIXTURE(ns) { + int status_fd; + int data_fd; + int enable_fd; + int options_fd; +}; + +FIXTURE_SETUP(ns) { + if (mkdir(namespace_dir, 770)) { + ASSERT_EQ(EEXIST, errno); + } + + self->status_fd = open(ns_status_file, O_RDONLY); + ASSERT_NE(-1, self->status_fd); + + self->data_fd = open(ns_data_file, O_RDWR); + ASSERT_NE(-1, self->data_fd); + + self->options_fd = open(ns_options_file, O_RDWR); + ASSERT_NE(-1, self->options_fd); + + self->enable_fd = -1; +} + +FIXTURE_TEARDOWN(ns) { + if (self->status_fd != -1) + close(self->status_fd); + + if (self->data_fd != -1) + close(self->data_fd); + + if (self->options_fd != -1) + close(self->options_fd); + + if (self->enable_fd != -1) { + write(self->enable_fd, "0", sizeof("0")); + close(self->enable_fd); + self->enable_fd = -1; + } + + ASSERT_EQ(0, clear()); + + if (rmdir(namespace_dir)) { + ASSERT_EQ(ENOENT, errno); + } +} + FIXTURE(user) { int status_fd; int data_fd; @@ -477,6 +534,99 @@ TEST_F(user, print_fmt) { ASSERT_EQ(0, ret); } +TEST_F(ns, namespaces) { + struct user_reg reg = {0}; + struct iovec io[3]; + __u32 field1, field2; + int before = 0, after = 0; + int page_size = sysconf(_SC_PAGESIZE); + char *status_page; + + reg.size = sizeof(reg); + reg.name_args = (__u64)"__test_event u32 field1; u32 field2"; + + field1 = 1; + field2 = 2; + + io[0].iov_base = ®.write_index; + io[0].iov_len = sizeof(reg.write_index); + io[1].iov_base = &field1; + io[1].iov_len = sizeof(field1); + io[2].iov_base = &field2; + io[2].iov_len = sizeof(field2); + + /* Limit to 1 event */ + ASSERT_NE(-1, write(self->options_fd, + "user_events_limit=1\n", + sizeof("user_events_limit=1\n") - 1)); + + /* Register should work */ + ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSREG, ®)); + ASSERT_EQ(0, reg.write_index); + ASSERT_NE(0, reg.status_bit); + + status_page = mmap(NULL, page_size, PROT_READ, MAP_SHARED, + self->status_fd, 0); + + /* MMAP should work and be zero'd */ + ASSERT_NE(MAP_FAILED, status_page); + ASSERT_NE(NULL, status_page); + ASSERT_EQ(0, status_check(status_page, reg.status_bit)); + + /* Enable event (start tracing) */ + self->enable_fd = open(ns_enable_file, O_RDWR); + ASSERT_NE(-1, write(self->enable_fd, "1", sizeof("1"))) + + /* Event should now be enabled */ + ASSERT_NE(0, status_check(status_page, reg.status_bit)); + + /* Write should make it out to ftrace buffers */ + before = trace_bytes(); + ASSERT_NE(-1, writev(self->data_fd, (const struct iovec *)io, 3)); + after = trace_bytes(); + ASSERT_GT(after, before); + + /* Register above limit should fail */ + reg.name_args = (__u64)"__test_event_nope u32 field1; u32 field2"; + ASSERT_EQ(-1, ioctl(self->data_fd, DIAG_IOCSREG, ®)); + ASSERT_EQ(EMFILE, errno); + + /* Removing namespace while files open should fail */ + ASSERT_EQ(-1, rmdir(namespace_dir)); + + close(self->options_fd); + self->options_fd = -1; + + /* Removing namespace while files open should fail */ + ASSERT_EQ(-1, rmdir(namespace_dir)); + + close(self->status_fd); + self->status_fd = -1; + + /* Removing namespace while files open should fail */ + ASSERT_EQ(-1, rmdir(namespace_dir)); + + close(self->data_fd); + self->data_fd = -1; + + /* Removing namespace while mmaps are open should fail */ + ASSERT_EQ(-1, rmdir(namespace_dir)); + + /* Unmap */ + ASSERT_EQ(0, munmap(status_page, page_size)); + + /* Removing namespace with no files but tracing should fail */ + ASSERT_EQ(-1, rmdir(namespace_dir)); + + /* Disable event (stop tracing) */ + ASSERT_NE(-1, write(self->enable_fd, "0", sizeof("0"))) + close(self->enable_fd); + self->enable_fd = -1; + + /* Removing namespace should now work */ + ASSERT_EQ(0, rmdir(namespace_dir)); +} + int main(int argc, char **argv) { return test_harness_run(argc, argv); -- 2.25.1