From: Petr Vorel <pvorel@suse.cz>
To: Amir Goldstein <amir73il@gmail.com>
Cc: "Ahelenia Ziemiańska" <nabijaczleweli@nabijaczleweli.xyz>,
"Alexander Viro" <viro@zeniv.linux.org.uk>,
"Christian Brauner" <brauner@kernel.org>,
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
"Jan Kara" <jack@suse.cz>,
"Chung-Chiang Cheng" <cccheng@synology.com>,
ltp@vger.kernel.org
Subject: Re: [LTP PATCH] inotify13: new test for fs/splice.c functions vs pipes vs inotify
Date: Wed, 28 Jun 2023 00:57:25 +0200 [thread overview]
Message-ID: <20230627225725.GB93981@pevik> (raw)
In-Reply-To: <CAOQ4uxifYoKdup6gzyW0iV=KFBzTWu5T8=zq8s8pFw2X3+5xRg@mail.gmail.com>
> On Tue, Jun 27, 2023 at 7:57 PM Ahelenia Ziemiańska
> <nabijaczleweli@nabijaczleweli.xyz> wrote:
> > The only one that passes on 6.1.27-1 is sendfile_file_to_pipe.
> > Link: https://lore.kernel.org/linux-fsdevel/jbyihkyk5dtaohdwjyivambb2gffyjs3dodpofafnkkunxq7bu@jngkdxx65pux/t/#u
> > Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
> > ---
> > Formatted to clang-format defaults. Put the original Fixes:ed SHA in the
> > metadata, that's probably fine, right?
> No. The git commit is for the commits that fix the problem.
> This can only be added after your fixes are merged.
> I will let the LPT developers comment about style,
> but I think LTP project wants tab indents.
> I am personally unable to read this patch with so little indentation
> and so much macroing.
Yes, it's hard to read. Style formatting it would improve it little bit
(make check-inotify13 is your friend, it complains a lot, also some spaces above
if () would make it more readable), but there are other things, e.g. macros
F2P(splice) and P2P(splice) should be functions (readability). Please have look
at other inotify tests, they are fairly simple and easy to read.
Also, this is a patch for LTP, you're supposed to post it also to LTP mailing
list (ltp@lists.linux.it, you need to register to
https://lists.linux.it/listinfo/ltp first).
> > testcases/kernel/syscalls/inotify/.gitignore | 1 +
> > testcases/kernel/syscalls/inotify/inotify13.c | 246 ++++++++++++++++++
> > 2 files changed, 247 insertions(+)
> > create mode 100644 testcases/kernel/syscalls/inotify/inotify13.c
> > diff --git a/testcases/kernel/syscalls/inotify/.gitignore b/testcases/kernel/syscalls/inotify/.gitignore
> > index f6e5c546a..b597ea63f 100644
> > --- a/testcases/kernel/syscalls/inotify/.gitignore
> > +++ b/testcases/kernel/syscalls/inotify/.gitignore
> > @@ -10,3 +10,4 @@
> > /inotify10
> > /inotify11
> > /inotify12
> > +/inotify13
> > diff --git a/testcases/kernel/syscalls/inotify/inotify13.c b/testcases/kernel/syscalls/inotify/inotify13.c
> > new file mode 100644
> > index 000000000..c34f1dc9f
> > --- /dev/null
> > +++ b/testcases/kernel/syscalls/inotify/inotify13.c
> > @@ -0,0 +1,246 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +/*\
You need to add here:
* [Description]
> > + * Verify splice-family functions (and sendfile) generate IN_ACCESS
> > + * for what they read and IN_MODIFY for what they write.
> > + *
> > + * Regression test for 983652c69199 and
I guess there would be only 983652c69199 ("splice: report related fsnotify
events").
> > + * https://lore.kernel.org/linux-fsdevel/jbyihkyk5dtaohdwjyivambb2gffyjs3dodpofafnkkunxq7bu@jngkdxx65pux/t/#u
This is some discussion, not a real patch. Not sure how much useful it is, until
it results to fix accepted in the mainline kernel.
> > + */
> > +
> > +#define _GNU_SOURCE
> > +#include "config.h"
> > +
> > +#include <stdio.h>
> > +#include <unistd.h>
> > +#include <stdlib.h>
> > +#include <fcntl.h>
> > +#include <stdbool.h>
> > +#include <inttypes.h>
> > +#include <signal.h>
> > +#include <sys/mman.h>
> > +#include <sys/sendfile.h>
> > +
> > +#include "tst_test.h"
> > +#include "tst_safe_macros.h"
> > +#include "inotify.h"
> > +
> > +#if defined(HAVE_SYS_INOTIFY_H)
> > +#include <sys/inotify.h>
> > +
> > +
> > +static int pipes[2] = {-1, -1};
> > +static int inotify = -1;
> > +static int memfd = -1;
> > +static int data_pipes[2] = {-1, -1};
> > +
> > +static void watch_rw(int fd) {
> > + char buf[64];
> > + sprintf(buf, "/proc/self/fd/%d", fd);
> > + SAFE_MYINOTIFY_ADD_WATCH(inotify, buf, IN_ACCESS | IN_MODIFY);
> > +}
> > +
> > +static int compar(const void *l, const void *r) {
> > + const struct inotify_event *lie = l;
> > + const struct inotify_event *rie = r;
> > + return lie->wd - rie->wd;
> > +}
> > +
> > +static void get_events(size_t evcnt, struct inotify_event evs[static evcnt]) {
> > + struct inotify_event tail, *itr = evs;
> > + for (size_t left = evcnt; left; --left)
> > + SAFE_READ(true, inotify, itr++, sizeof(struct inotify_event));
> > +
> > + TEST(read(inotify, &tail, sizeof(struct inotify_event)));
> > + if (TST_RET != -1)
> > + tst_brk(TFAIL, "expect %zu events", evcnt);
> > + if (TST_ERR != EAGAIN)
> > + tst_brk(TFAIL | TTERRNO, "expected EAGAIN");
> > +
> > + qsort(evs, evcnt, sizeof(struct inotify_event), compar);
> > +}
> > +
> > +static void expect_event(struct inotify_event *ev, int wd, uint32_t mask) {
> > + if (ev->wd != wd)
> > + tst_brk(TFAIL, "expect event for wd %d got %d", wd, ev->wd);
> > + if (ev->mask != mask)
> > + tst_brk(TFAIL, "expect event with mask %" PRIu32 " got %" PRIu32 "", mask,
> > + ev->mask);
> > +}
> > +
> > +#define F2P(splice) \
> > + SAFE_WRITE(SAFE_WRITE_RETRY, memfd, __func__, sizeof(__func__)); \
> > + SAFE_LSEEK(memfd, 0, SEEK_SET); \
> > + watch_rw(memfd); \
> > + watch_rw(pipes[0]); \
> > + TEST(splice); \
> > + if (TST_RET == -1) \
> > + tst_brk(TBROK | TERRNO, #splice); \
> > + if (TST_RET != sizeof(__func__)) \
> > + tst_brk(TBROK, #splice ": %" PRId64 "", TST_RET); \
> > + \
> > + /*expecting: IN_ACCESS memfd, IN_MODIFY pipes[0]*/ \
> > + struct inotify_event events[2]; \
> > + get_events(ARRAY_SIZE(events), events); \
> > + expect_event(events + 0, 1, IN_ACCESS); \
> > + expect_event(events + 1, 2, IN_MODIFY); \
> > + \
> > + char buf[sizeof(__func__)]; \
> > + SAFE_READ(true, pipes[0], buf, sizeof(__func__)); \
> > + if (memcmp(buf, __func__, sizeof(__func__))) \
> > + tst_brk(TFAIL, "buf contents bad");
> > +static void splice_file_to_pipe(void) {
> > + F2P(splice(memfd, NULL, pipes[1], NULL, 128 * 1024 * 1024, 0));
> > +}
> > +static void sendfile_file_to_pipe(void) {
> > + F2P(sendfile(pipes[1], memfd, NULL, 128 * 1024 * 1024));
> > +}
> > +
> > +static void splice_pipe_to_file(void) {
> > + SAFE_WRITE(SAFE_WRITE_RETRY, pipes[1], __func__, sizeof(__func__));
> > + watch_rw(pipes[0]);
> > + watch_rw(memfd);
> > + TEST(splice(pipes[0], NULL, memfd, NULL, 128 * 1024 * 1024, 0));
> > + if(TST_RET == -1)
> > + tst_brk(TBROK | TERRNO, "splice");
> > + if(TST_RET != sizeof(__func__))
> > + tst_brk(TBROK, "splice: %" PRId64 "", TST_RET);
> > +
> > + // expecting: IN_ACCESS pipes[0], IN_MODIFY memfd
> > + struct inotify_event events[2];
> > + get_events(ARRAY_SIZE(events), events);
> > + expect_event(events + 0, 1, IN_ACCESS);
> > + expect_event(events + 1, 2, IN_MODIFY);
> > +
> > + char buf[sizeof(__func__)];
> > + SAFE_LSEEK(memfd, 0, SEEK_SET);
> > + SAFE_READ(true, memfd, buf, sizeof(__func__));
> > + if (memcmp(buf, __func__, sizeof(__func__)))
> > + tst_brk(TFAIL, "buf contents bad");
> > +}
> > +
> > +#define P2P(splice) \
> > + SAFE_WRITE(SAFE_WRITE_RETRY, data_pipes[1], __func__, sizeof(__func__)); \
> > + watch_rw(data_pipes[0]); \
> > + watch_rw(pipes[1]); \
> > + TEST(splice); \
> > + if (TST_RET == -1) \
> > + tst_brk(TBROK | TERRNO, #splice); \
> > + if (TST_RET != sizeof(__func__)) \
> > + tst_brk(TBROK, #splice ": %" PRId64 "", TST_RET); \
> > + \
> > + /* expecting: IN_ACCESS data_pipes[0], IN_MODIFY pipes[1] */ \
> > + struct inotify_event events[2]; \
> > + get_events(ARRAY_SIZE(events), events); \
> > + expect_event(events + 0, 1, IN_ACCESS); \
> > + expect_event(events + 1, 2, IN_MODIFY); \
> > + \
> > + char buf[sizeof(__func__)]; \
> > + SAFE_READ(true, pipes[0], buf, sizeof(__func__)); \
> > + if (memcmp(buf, __func__, sizeof(__func__))) \
> > + tst_brk(TFAIL, "buf contents bad");
> > +static void splice_pipe_to_pipe(void) {
> > + P2P(splice(data_pipes[0], NULL, pipes[1], NULL, 128 * 1024 * 1024, 0));
> > +}
> > +static void tee_pipe_to_pipe(void) {
> > + P2P(tee(data_pipes[0], pipes[1], 128 * 1024 * 1024, 0));
> > +}
> > +
> > +static char vmsplice_pipe_to_mem_dt[32 * 1024];
> > +static void vmsplice_pipe_to_mem(void) {
> > + memcpy(vmsplice_pipe_to_mem_dt, __func__, sizeof(__func__));
> > + watch_rw(pipes[0]);
> > + TEST(vmsplice(pipes[1],
> > + &(struct iovec){.iov_base = vmsplice_pipe_to_mem_dt,
> > + .iov_len = sizeof(vmsplice_pipe_to_mem_dt)},
> > + 1, SPLICE_F_GIFT));
> > + if (TST_RET == -1)
> > + tst_brk(TBROK | TERRNO, "vmsplice");
> > + if (TST_RET != sizeof(vmsplice_pipe_to_mem_dt))
> > + tst_brk(TBROK, "vmsplice: %" PRId64 "", TST_RET);
> > +
> > + // expecting: IN_MODIFY pipes[0]
> > + struct inotify_event event;
> > + get_events(1, &event);
> > + expect_event(&event, 1, IN_MODIFY);
> > +
> > + char buf[sizeof(__func__)];
> > + SAFE_READ(true, pipes[0], buf, sizeof(__func__));
> > + if (memcmp(buf, __func__, sizeof(__func__)))
> > + tst_brk(TFAIL, "buf contents bad");
> > +}
> > +
> > +static void vmsplice_mem_to_pipe(void) {
> > + char buf[sizeof(__func__)];
> > + SAFE_WRITE(SAFE_WRITE_RETRY, pipes[1], __func__, sizeof(__func__));
> > + watch_rw(pipes[1]);
> > + TEST(vmsplice(pipes[0],
> > + &(struct iovec){.iov_base = buf, .iov_len = sizeof(buf)}, 1,
> > + 0));
> > + if (TST_RET == -1)
> > + tst_brk(TBROK | TERRNO, "vmsplice");
> > + if (TST_RET != sizeof(buf))
> > + tst_brk(TBROK, "vmsplice: %" PRId64 "", TST_RET);
> > +
> > + // expecting: IN_ACCESS pipes[1]
> > + struct inotify_event event;
> > + get_events(1, &event);
> > + expect_event(&event, 1, IN_ACCESS);
> > + if (memcmp(buf, __func__, sizeof(__func__)))
> > + tst_brk(TFAIL, "buf contents bad");
> > +}
> > +
> > +typedef void (*tests_f)(void);
> > +#define TEST_F(f) { f, #f }
> > +static const struct {
> > + tests_f f;
> > + const char *n;
> > +} tests[] = {
> > + TEST_F(splice_file_to_pipe), TEST_F(sendfile_file_to_pipe),
> > + TEST_F(splice_pipe_to_file), TEST_F(splice_pipe_to_pipe),
> > + TEST_F(tee_pipe_to_pipe), TEST_F(vmsplice_pipe_to_mem),
> > + TEST_F(vmsplice_mem_to_pipe),
> > +};
> > +
> > +static void run_test(unsigned int n)
> > +{
> > + tst_res(TINFO, "%s", tests[n].n);
> > +
> > + SAFE_PIPE2(pipes, O_CLOEXEC);
> > + SAFE_PIPE2(data_pipes, O_CLOEXEC);
> > + inotify = SAFE_MYINOTIFY_INIT1(IN_NONBLOCK | IN_CLOEXEC);
> > + if((memfd = memfd_create(__func__, MFD_CLOEXEC)) == -1)
> > + tst_brk(TCONF | TERRNO, "memfd");
> > + tests[n].f();
> Normally, a test cases table would encode things like
> the number of expected events and type of events.
> The idea is that the test template has parametrized code
> and not just a loop for test cases subroutines, but there
> are many ways to write tests, so as long as it gets the job
> done and is readable to humans, I don't mind.
> Right now this test may do the job, but it is not readable
> for this human ;-)
> mostly because of the huge macros -
> LTP is known for pretty large macros, but those are
> for generic utilities and you have complete test cases
> written as macros (templates).
+100. We strive for simple readable code, which is not this one.
Kind regards,
Petr
> > + tst_res(TPASS, "ок");
> > +}
> > +
> > +static void cleanup(void)
> > +{
> > + if (memfd != -1)
> > + SAFE_CLOSE(memfd);
> > + if (inotify != -1)
> > + SAFE_CLOSE(inotify);
> > + if (pipes[0] != -1)
> > + SAFE_CLOSE(pipes[0]);
> > + if (pipes[1] != -1)
> > + SAFE_CLOSE(pipes[1]);
> > + if (data_pipes[0] != -1)
> > + SAFE_CLOSE(data_pipes[0]);
> > + if (data_pipes[1] != -1)
> > + SAFE_CLOSE(data_pipes[1]);
> > +}
> > +
> This cleanup does not happen for every test case -
> it happens only at the end of all the tests IIRC.
> > +static struct tst_test test = {
> > + .max_runtime = 10,
> > + .cleanup = cleanup,
> > + .test = run_test,
> > + .tcnt = ARRAY_SIZE(tests),
> > + .tags = (const struct tst_tag[]) {
> > + {"linux-git", "983652c69199"},
> Leave this out for now.
> Thanks,
> Amir.
next prev parent reply other threads:[~2023-06-27 22:57 UTC|newest]
Thread overview: 55+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-26 3:04 splice(-> FIFO) never wakes up inotify IN_MODIFY? Ahelenia Ziemiańska
2023-06-26 6:11 ` Amir Goldstein
2023-06-26 12:19 ` Ahelenia Ziemiańska
2023-06-26 12:57 ` Ahelenia Ziemiańska
2023-06-26 13:51 ` Jan Kara
2023-06-26 14:25 ` Ahelenia Ziemiańska
2023-06-26 15:00 ` Jan Kara
2023-06-26 15:15 ` Ahelenia Ziemiańska
2023-06-26 16:52 ` Jan Kara
2023-06-26 14:53 ` Amir Goldstein
2023-06-26 15:12 ` Ahelenia Ziemiańska
2023-06-26 16:21 ` Amir Goldstein
2023-06-26 17:14 ` Ahelenia Ziemiańska
2023-06-26 18:57 ` Amir Goldstein
2023-06-26 23:08 ` [PATCH v2 0/3] fanotify accounting for fs/splice.c наб
2023-06-27 6:14 ` Amir Goldstein
2023-06-27 16:55 ` [PATCH v3 0/3+1] " Ahelenia Ziemiańska
2023-06-27 16:55 ` [PATCH v3 1/3] splice: always fsnotify_access(in), fsnotify_modify(out) on success Ahelenia Ziemiańska
2023-06-27 18:10 ` Amir Goldstein
2023-06-27 20:13 ` Ahelenia Ziemiańska
2023-06-27 16:55 ` [PATCH v3 2/3] splice: fsnotify_access(fd)/fsnotify_modify(fd) in vmsplice Ahelenia Ziemiańska
2023-06-27 18:11 ` Amir Goldstein
2023-06-27 16:55 ` [PATCH v3 3/3] splice: fsnotify_access(in), fsnotify_modify(out) on success in tee Ahelenia Ziemiańska
2023-06-27 16:57 ` [LTP PATCH] inotify13: new test for fs/splice.c functions vs pipes vs inotify Ahelenia Ziemiańska
2023-06-27 18:31 ` Amir Goldstein
2023-06-27 20:59 ` [LTP RFC PATCH v2] " Ahelenia Ziemiańska
2023-06-28 0:21 ` [LTP RFC PATCH v3] " Ahelenia Ziemiańska
2023-06-28 5:30 ` Amir Goldstein
2023-06-28 16:03 ` Ahelenia Ziemiańska
2023-06-27 22:57 ` Petr Vorel [this message]
2023-06-27 18:03 ` [PATCH v3 0/3+1] fanotify accounting for fs/splice.c Amir Goldstein
2023-06-27 20:34 ` Ahelenia Ziemiańska
2023-06-27 20:50 ` [PATCH v4 0/3] " Ahelenia Ziemiańska
2023-06-27 20:50 ` [PATCH v4 1/3] splice: always fsnotify_access(in), fsnotify_modify(out) on success Ahelenia Ziemiańska
2023-06-28 6:33 ` Amir Goldstein
2023-06-28 10:11 ` Jan Kara
2023-06-28 17:09 ` Ahelenia Ziemiańska
2023-06-28 18:38 ` Amir Goldstein
2023-06-28 20:18 ` Ahelenia Ziemiańska
2023-06-30 11:03 ` Amir Goldstein
2023-06-27 20:50 ` [PATCH v4 2/3] splice: fsnotify_access(fd)/fsnotify_modify(fd) in vmsplice Ahelenia Ziemiańska
2023-06-27 20:51 ` [PATCH v4 3/3] splice: fsnotify_access(in), fsnotify_modify(out) on success in tee Ahelenia Ziemiańska
2023-06-28 6:02 ` [PATCH v4 0/3] fanotify accounting for fs/splice.c Amir Goldstein
2023-06-28 11:38 ` Jan Kara
2023-06-28 13:41 ` Amir Goldstein
2023-06-28 18:54 ` Ahelenia Ziemiańska
2023-06-29 8:45 ` Jan Kara
2023-06-28 4:51 ` [PATCH v3 0/3+1] " Christoph Hellwig
2023-06-28 10:38 ` Jan Kara
2023-06-26 23:09 ` [PATCH v2 1/3] splice: always fsnotify_access(in), fsnotify_modify(out) on success Ahelenia Ziemiańska
2023-06-27 6:02 ` Amir Goldstein
2023-06-26 23:09 ` [PATCH v2 2/3] splice: fsnotify_modify(fd) in vmsplice Ahelenia Ziemiańska
2023-06-27 6:27 ` Amir Goldstein
2023-06-26 23:09 ` [PATCH v2 3/3] splice: fsnotify_access(in), fsnotify_modify(out) on success in tee Ahelenia Ziemiańska
2023-06-27 6:20 ` Amir Goldstein
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230627225725.GB93981@pevik \
--to=pvorel@suse.cz \
--cc=amir73il@gmail.com \
--cc=brauner@kernel.org \
--cc=cccheng@synology.com \
--cc=jack@suse.cz \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ltp@vger.kernel.org \
--cc=nabijaczleweli@nabijaczleweli.xyz \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).