diff mbox series

[2/3] syscalls/readahead01: Make use of tst_fd_iterate()

Message ID 20231004124712.3833-3-chrubis@suse.cz (mailing list archive)
State New, archived
Headers show
Series Add tst_iterate_fd() | expand

Commit Message

Cyril Hrubis Oct. 4, 2023, 12:47 p.m. UTC
TODO: readahead() on /proc/self/maps seems to succeed is that to be
      expected?

Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
---
 .../kernel/syscalls/readahead/readahead01.c   | 46 ++++++++-----------
 1 file changed, 20 insertions(+), 26 deletions(-)

Comments

Amir Goldstein Oct. 4, 2023, 1:55 p.m. UTC | #1
On Wed, Oct 4, 2023 at 3:46 PM Cyril Hrubis <chrubis@suse.cz> wrote:
>

Hi Cyril,

Thanks for following up on this!

> TODO: readahead() on /proc/self/maps seems to succeed is that to be
>       expected?

Not sure.
How does llseek() work on the same fd?
Matthew suggested that we align the behavior of both readahead(2)
and posix_fadvise(2) to that of llseek(2)

>
> Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
> ---
>  .../kernel/syscalls/readahead/readahead01.c   | 46 ++++++++-----------
>  1 file changed, 20 insertions(+), 26 deletions(-)
>
> diff --git a/testcases/kernel/syscalls/readahead/readahead01.c b/testcases/kernel/syscalls/readahead/readahead01.c
> index bdef7945d..28134d416 100644
> --- a/testcases/kernel/syscalls/readahead/readahead01.c
> +++ b/testcases/kernel/syscalls/readahead/readahead01.c
> @@ -29,44 +29,38 @@
>  #if defined(__NR_readahead)
>
>  static void test_bad_fd(void)
> -{
> -       char tempname[PATH_MAX] = "readahead01_XXXXXX";
> -       int fd;
> -
> -       tst_res(TINFO, "%s -1", __func__);
> -       TST_EXP_FAIL(readahead(-1, 0, getpagesize()), EBADF);
> -
> -       tst_res(TINFO, "%s O_WRONLY", __func__);
> -       fd = mkstemp(tempname);
> -       if (fd == -1)
> -               tst_res(TFAIL | TERRNO, "mkstemp failed");
> -       SAFE_CLOSE(fd);
> -       fd = SAFE_OPEN(tempname, O_WRONLY);
> -       TST_EXP_FAIL(readahead(fd, 0, getpagesize()), EBADF);
> -       SAFE_CLOSE(fd);
> -       unlink(tempname);
> -}
> -
> -static void test_invalid_fd(void)
>  {
>         int fd[2];
>
> -       tst_res(TINFO, "%s pipe", __func__);
> +       TST_EXP_FAIL(readahead(-1, 0, getpagesize()), EBADF,
> +                    "readahead() with fd = -1");
> +

Any reason not to include a bad and a closed fd in the iterator?

>         SAFE_PIPE(fd);
> -       TST_EXP_FAIL(readahead(fd[0], 0, getpagesize()), EINVAL);
>         SAFE_CLOSE(fd[0]);
>         SAFE_CLOSE(fd[1]);
>
> -       tst_res(TINFO, "%s socket", __func__);
> -       fd[0] = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0);
> -       TST_EXP_FAIL(readahead(fd[0], 0, getpagesize()), EINVAL);
> -       SAFE_CLOSE(fd[0]);
> +       TST_EXP_FAIL(readahead(fd[0], 0, getpagesize()), EBADF,
> +                    "readahead() with invalid fd");
> +}
> +
> +static void test_invalid_fd(struct tst_fd *fd)
> +{
> +       switch (fd->type) {
> +       case TST_FD_FILE:
> +       case TST_FD_PIPE_OUT:
> +               return;
> +       default:
> +               break;
> +       }
> +
> +       TST_EXP_FAIL(readahead(fd->fd, 0, getpagesize()), EINVAL,
> +                    "readahead() on %s", tst_fd_desc(fd));

Thinking forward and we would like to change this error code to ESPIPE
is there already a helper to expect one of a few error codes?

Thanks,
Amir.

>  }
>
>  static void test_readahead(void)
>  {
>         test_bad_fd();
> -       test_invalid_fd();
> +       tst_fd_iterate(test_invalid_fd);
>  }
>
>  static void setup(void)
> --
> 2.41.0
>
Cyril Hrubis Oct. 4, 2023, 2:24 p.m. UTC | #2
Hi!
> > TODO: readahead() on /proc/self/maps seems to succeed is that to be
> >       expected?
> 
> Not sure.
> How does llseek() work on the same fd?

Looks like we we can seek in that file as well, accordingly to man pages
we cannot seek in pipe, socket, and fifo, which seems to match the
reality.  We can apparently seek in O_DIRECTORY fd as well, not sure if
that is even useful.

> > -static void test_invalid_fd(void)
> >  {
> >         int fd[2];
> >
> > -       tst_res(TINFO, "%s pipe", __func__);
> > +       TST_EXP_FAIL(readahead(-1, 0, getpagesize()), EBADF,
> > +                    "readahead() with fd = -1");
> > +
> 
> Any reason not to include a bad and a closed fd in the iterator?

I wanted to avoid mixing valid and invalid fds because we tend to get
different errnos for these, since the situation is different between
"this is not a file descriptor" and "this is not supported on this kind
of file descriptor".

> >         SAFE_PIPE(fd);
> > -       TST_EXP_FAIL(readahead(fd[0], 0, getpagesize()), EINVAL);
> >         SAFE_CLOSE(fd[0]);
> >         SAFE_CLOSE(fd[1]);
> >
> > -       tst_res(TINFO, "%s socket", __func__);
> > -       fd[0] = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0);
> > -       TST_EXP_FAIL(readahead(fd[0], 0, getpagesize()), EINVAL);
> > -       SAFE_CLOSE(fd[0]);
> > +       TST_EXP_FAIL(readahead(fd[0], 0, getpagesize()), EBADF,
> > +                    "readahead() with invalid fd");
> > +}
> > +
> > +static void test_invalid_fd(struct tst_fd *fd)
> > +{
> > +       switch (fd->type) {
> > +       case TST_FD_FILE:
> > +       case TST_FD_PIPE_OUT:
> > +               return;
> > +       default:
> > +               break;
> > +       }
> > +
> > +       TST_EXP_FAIL(readahead(fd->fd, 0, getpagesize()), EINVAL,
> > +                    "readahead() on %s", tst_fd_desc(fd));
> 
> Thinking forward and we would like to change this error code to ESPIPE
> is there already a helper to expect one of a few error codes?

Not yet. The hardest part is again figuring out right API. We usually
try to check for the new behavior on newer kernels, which would be
complex to encode into the parameters, so maybe we just need to pass a
callback that would return the right errno. Maybe something as:

static int exp_errno(void)
{
	if (tst_kvercmp(6, 7, 0) >= 0)
		return ESPIPE;

	return EINVAL;
}

...
	TST_EXP_FAIL_CB(readahead(fd->fd, 0, getpagesize()), exp_errno,
		"readahead() on %s", tst_fd_desc(fd));
...
Jan Kara Oct. 4, 2023, 2:52 p.m. UTC | #3
On Wed 04-10-23 16:24:30, Cyril Hrubis wrote:
> Hi!
> > > TODO: readahead() on /proc/self/maps seems to succeed is that to be
> > >       expected?
> > 
> > Not sure.
> > How does llseek() work on the same fd?
> 
> Looks like we we can seek in that file as well, accordingly to man pages
> we cannot seek in pipe, socket, and fifo, which seems to match the
> reality.  We can apparently seek in O_DIRECTORY fd as well, not sure if
> that is even useful.

Seeking on O_DIRECTORY fd is actually well defined by POSIX. You can store
current file position you've got back from lseek and you are guaranteed to
get back at the same position in the directory if you lseek to it (even if
there was a change to the directory, although effects on changed directory
entries is undefined). This is actually pretty tough to implement in
contemporary filesystems with non-trivial directory structure but that is
how POSIX defined it...

								Honza
diff mbox series

Patch

diff --git a/testcases/kernel/syscalls/readahead/readahead01.c b/testcases/kernel/syscalls/readahead/readahead01.c
index bdef7945d..28134d416 100644
--- a/testcases/kernel/syscalls/readahead/readahead01.c
+++ b/testcases/kernel/syscalls/readahead/readahead01.c
@@ -29,44 +29,38 @@ 
 #if defined(__NR_readahead)
 
 static void test_bad_fd(void)
-{
-	char tempname[PATH_MAX] = "readahead01_XXXXXX";
-	int fd;
-
-	tst_res(TINFO, "%s -1", __func__);
-	TST_EXP_FAIL(readahead(-1, 0, getpagesize()), EBADF);
-
-	tst_res(TINFO, "%s O_WRONLY", __func__);
-	fd = mkstemp(tempname);
-	if (fd == -1)
-		tst_res(TFAIL | TERRNO, "mkstemp failed");
-	SAFE_CLOSE(fd);
-	fd = SAFE_OPEN(tempname, O_WRONLY);
-	TST_EXP_FAIL(readahead(fd, 0, getpagesize()), EBADF);
-	SAFE_CLOSE(fd);
-	unlink(tempname);
-}
-
-static void test_invalid_fd(void)
 {
 	int fd[2];
 
-	tst_res(TINFO, "%s pipe", __func__);
+	TST_EXP_FAIL(readahead(-1, 0, getpagesize()), EBADF,
+	             "readahead() with fd = -1");
+
 	SAFE_PIPE(fd);
-	TST_EXP_FAIL(readahead(fd[0], 0, getpagesize()), EINVAL);
 	SAFE_CLOSE(fd[0]);
 	SAFE_CLOSE(fd[1]);
 
-	tst_res(TINFO, "%s socket", __func__);
-	fd[0] = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0);
-	TST_EXP_FAIL(readahead(fd[0], 0, getpagesize()), EINVAL);
-	SAFE_CLOSE(fd[0]);
+	TST_EXP_FAIL(readahead(fd[0], 0, getpagesize()), EBADF,
+	             "readahead() with invalid fd");
+}
+
+static void test_invalid_fd(struct tst_fd *fd)
+{
+	switch (fd->type) {
+	case TST_FD_FILE:
+	case TST_FD_PIPE_OUT:
+		return;
+	default:
+		break;
+	}
+
+	TST_EXP_FAIL(readahead(fd->fd, 0, getpagesize()), EINVAL,
+		     "readahead() on %s", tst_fd_desc(fd));
 }
 
 static void test_readahead(void)
 {
 	test_bad_fd();
-	test_invalid_fd();
+	tst_fd_iterate(test_invalid_fd);
 }
 
 static void setup(void)