diff mbox series

[v4] syscalls/newmount: new test case for new mount API

Message ID 20200116075633.29752-1-zlang@redhat.com
State Changes Requested
Delegated to: Petr Vorel
Headers show
Series [v4] syscalls/newmount: new test case for new mount API | expand

Commit Message

Zorro Lang Jan. 16, 2020, 7:56 a.m. UTC
Linux supports new mount syscalls from 5.2, so add new test cases
to cover these new API. This newmount01 case make sure new API -
fsopen(), fsconfig(), fsmount() and move_mount() can mount a
filesystem, then can be unmounted.

Signed-off-by: Zorro Lang <zlang@redhat.com>
---

Hi,

V4 made a few changes as https://patchwork.ozlabs.org/patch/1206389/#2341154

And as I said in https://patchwork.ozlabs.org/comment/2342190, the
TST_FS_SKIP_FUSE flag won't help to skip linux kernel internal ntfs and
vfat test for this case.

Thanks,
Zorro

 configure.ac                                  |   1 +
 include/lapi/newmount.h                       |  95 +++++++++++++++
 include/lapi/syscalls/aarch64.in              |   4 +
 include/lapi/syscalls/powerpc64.in            |   4 +
 include/lapi/syscalls/s390x.in                |   4 +
 include/lapi/syscalls/x86_64.in               |   4 +
 m4/ltp-newmount.m4                            |  10 ++
 runtest/syscalls                              |   2 +
 testcases/kernel/syscalls/newmount/.gitignore |   1 +
 testcases/kernel/syscalls/newmount/Makefile   |   9 ++
 .../kernel/syscalls/newmount/newmount01.c     | 112 ++++++++++++++++++
 11 files changed, 246 insertions(+)
 create mode 100644 include/lapi/newmount.h
 create mode 100644 m4/ltp-newmount.m4
 create mode 100644 testcases/kernel/syscalls/newmount/.gitignore
 create mode 100644 testcases/kernel/syscalls/newmount/Makefile
 create mode 100644 testcases/kernel/syscalls/newmount/newmount01.c

Comments

Cyril Hrubis Jan. 16, 2020, 11:49 a.m. UTC | #1
Hi!
>  configure.ac                                  |   1 +
>  include/lapi/newmount.h                       |  95 +++++++++++++++
>  include/lapi/syscalls/aarch64.in              |   4 +
>  include/lapi/syscalls/powerpc64.in            |   4 +
>  include/lapi/syscalls/s390x.in                |   4 +
>  include/lapi/syscalls/x86_64.in               |   4 +
>  m4/ltp-newmount.m4                            |  10 ++
>  runtest/syscalls                              |   2 +
>  testcases/kernel/syscalls/newmount/.gitignore |   1 +
>  testcases/kernel/syscalls/newmount/Makefile   |   9 ++
>  .../kernel/syscalls/newmount/newmount01.c     | 112 ++++++++++++++++++
>  11 files changed, 246 insertions(+)
>  create mode 100644 include/lapi/newmount.h
>  create mode 100644 m4/ltp-newmount.m4
>  create mode 100644 testcases/kernel/syscalls/newmount/.gitignore
>  create mode 100644 testcases/kernel/syscalls/newmount/Makefile
>  create mode 100644 testcases/kernel/syscalls/newmount/newmount01.c
> 
> diff --git a/configure.ac b/configure.ac
> index 50d14967d..28f840c51 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -229,6 +229,7 @@ LTP_CHECK_MADVISE
>  LTP_CHECK_MKDTEMP
>  LTP_CHECK_MMSGHDR
>  LTP_CHECK_MREMAP_FIXED
> +LTP_CHECK_NEWMOUNT
>  LTP_CHECK_NOMMU_LINUX
>  LTP_CHECK_PERF_EVENT
>  LTP_CHECK_PRCTL_SUPPORT
> diff --git a/include/lapi/newmount.h b/include/lapi/newmount.h
> new file mode 100644
> index 000000000..13f9fbb9c
> --- /dev/null
> +++ b/include/lapi/newmount.h
> @@ -0,0 +1,95 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2019 Red Hat, Inc.  All rights reserved.
> + * Author: Zorro Lang <zlang@redhat.com>
> + */
> +
> +#ifndef NEWMOUNT_H__
> +#define NEWMOUNT_H__
> +
> +#include <stdint.h>
> +#include <unistd.h>
> +#include "config.h"
> +#include "lapi/syscalls.h"
> +
> +#if !defined(HAVE_FSOPEN)
> +static inline int fsopen(const char *fs_name, unsigned int flags)
> +{
> +	return tst_syscall(__NR_fsopen, fs_name, flags);
> +}
> +
> +/*
> + * fsopen() flags.
> + */
> +#define FSOPEN_CLOEXEC		0x00000001
> +#endif	/* HAVE_FSOPEN */
> +
> +#if !defined(HAVE_FSCONFIG)
> +static inline int fsconfig(int fsfd, unsigned int cmd,
> +                           const char *key, const void *val, int aux)
> +{
> +	return tst_syscall(__NR_fsconfig, fsfd, cmd, key, val, aux);
> +}
> +
> +/*
> + * The type of fsconfig() call made.
> + */
> +enum fsconfig_command {
> +	FSCONFIG_SET_FLAG	= 0,    /* Set parameter, supplying no value */
> +	FSCONFIG_SET_STRING	= 1,    /* Set parameter, supplying a string value */
> +	FSCONFIG_SET_BINARY	= 2,    /* Set parameter, supplying a binary blob value */
> +	FSCONFIG_SET_PATH	= 3,    /* Set parameter, supplying an object by path */
> +	FSCONFIG_SET_PATH_EMPTY	= 4,    /* Set parameter, supplying an object by (empty) path */
> +	FSCONFIG_SET_FD		= 5,    /* Set parameter, supplying an object by fd */
> +	FSCONFIG_CMD_CREATE	= 6,    /* Invoke superblock creation */
> +	FSCONFIG_CMD_RECONFIGURE = 7,   /* Invoke superblock reconfiguration */
> +};
> +#endif	/* HAVE_FSCONFIG */
> +
> +#if !defined(HAVE_FSMOUNT)
> +static inline int fsmount(int fsfd, unsigned int flags, unsigned int ms_flags)
> +{
> +	return tst_syscall(__NR_fsmount, fsfd, flags, ms_flags);
> +}
> +
> +/*
> + * fsmount() flags.
> + */
> +#define FSMOUNT_CLOEXEC		0x00000001
> +
> +/*
> + * Mount attributes.
> + */
> +#define MOUNT_ATTR_RDONLY	0x00000001 /* Mount read-only */
> +#define MOUNT_ATTR_NOSUID	0x00000002 /* Ignore suid and sgid bits */
> +#define MOUNT_ATTR_NODEV	0x00000004 /* Disallow access to device special files */
> +#define MOUNT_ATTR_NOEXEC	0x00000008 /* Disallow program execution */
> +#define MOUNT_ATTR__ATIME	0x00000070 /* Setting on how atime should be updated */
> +#define MOUNT_ATTR_RELATIME	0x00000000 /* - Update atime relative to mtime/ctime. */
> +#define MOUNT_ATTR_NOATIME	0x00000010 /* - Do not update access times. */
> +#define MOUNT_ATTR_STRICTATIME	0x00000020 /* - Always perform atime updates */
> +#define MOUNT_ATTR_NODIRATIME	0x00000080 /* Do not update directory access times */
> +#endif	/* HAVE_FSMOUNT */
> +
> +#if !defined(HAVE_MOVE_MOUNT)
> +static inline int move_mount(int from_dfd, const char *from_pathname,
> +                             int to_dfd, const char *to_pathname,
> +                             unsigned int flags)
> +{
> +	return tst_syscall(__NR_move_mount, from_dfd, from_pathname, to_dfd,
> +	                   to_pathname, flags);
> +}
> +
> +/*
> + * move_mount() flags.
> + */
> +#define MOVE_MOUNT_F_SYMLINKS		0x00000001 /* Follow symlinks on from path */
> +#define MOVE_MOUNT_F_AUTOMOUNTS		0x00000002 /* Follow automounts on from path */
> +#define MOVE_MOUNT_F_EMPTY_PATH		0x00000004 /* Empty from path permitted */
> +#define MOVE_MOUNT_T_SYMLINKS		0x00000010 /* Follow symlinks on to path */
> +#define MOVE_MOUNT_T_AUTOMOUNTS		0x00000020 /* Follow automounts on to path */
> +#define MOVE_MOUNT_T_EMPTY_PATH		0x00000040 /* Empty to path permitted */
> +#define MOVE_MOUNT__MASK		0x00000077
> +#endif	/* HAVE_MOVE_MOUNT */
> +
> +#endif /* NEWMOUNT_H__ */
> diff --git a/include/lapi/syscalls/aarch64.in b/include/lapi/syscalls/aarch64.in
> index 0e00641bc..5b9e1d9a4 100644
> --- a/include/lapi/syscalls/aarch64.in
> +++ b/include/lapi/syscalls/aarch64.in
> @@ -270,4 +270,8 @@ pkey_mprotect 288
>  pkey_alloc 289
>  pkey_free 290
>  pidfd_send_signal 424
> +move_mount 429
> +fsopen 430
> +fsconfig 431
> +fsmount 432
>  _sysctl 1078
> diff --git a/include/lapi/syscalls/powerpc64.in b/include/lapi/syscalls/powerpc64.in
> index 660165d7a..3aaed64e0 100644
> --- a/include/lapi/syscalls/powerpc64.in
> +++ b/include/lapi/syscalls/powerpc64.in
> @@ -359,3 +359,7 @@ pidfd_send_signal 424
>  pkey_mprotect 386
>  pkey_alloc 384
>  pkey_free 385
> +move_mount 429
> +fsopen 430
> +fsconfig 431
> +fsmount 432
> diff --git a/include/lapi/syscalls/s390x.in b/include/lapi/syscalls/s390x.in
> index 7d632d1dc..bd427555a 100644
> --- a/include/lapi/syscalls/s390x.in
> +++ b/include/lapi/syscalls/s390x.in
> @@ -341,3 +341,7 @@ pkey_mprotect 384
>  pkey_alloc 385
>  pkey_free 386
>  pidfd_send_signal 424
> +move_mount 429
> +fsopen 430
> +fsconfig 431
> +fsmount 432
> diff --git a/include/lapi/syscalls/x86_64.in b/include/lapi/syscalls/x86_64.in
> index b1cbd4f2f..94f0b562e 100644
> --- a/include/lapi/syscalls/x86_64.in
> +++ b/include/lapi/syscalls/x86_64.in
> @@ -320,3 +320,7 @@ pkey_alloc 330
>  pkey_free 331
>  statx 332
>  pidfd_send_signal 424
> +move_mount 429
> +fsopen 430
> +fsconfig 431
> +fsmount 432
> diff --git a/m4/ltp-newmount.m4 b/m4/ltp-newmount.m4
> new file mode 100644
> index 000000000..e13a6f0b1
> --- /dev/null
> +++ b/m4/ltp-newmount.m4
> @@ -0,0 +1,10 @@
> +dnl SPDX-License-Identifier: GPL-2.0-or-later
> +dnl Copyright (C) 2019 Red Hat, Inc. All Rights Reserved.
> +
> +AC_DEFUN([LTP_CHECK_NEWMOUNT],[
> +AC_CHECK_FUNCS(fsopen,,)
> +AC_CHECK_FUNCS(fsconfig,,)
> +AC_CHECK_FUNCS(fsmount,,)
> +AC_CHECK_FUNCS(move_mount,,)
> +AC_CHECK_HEADER(sys/mount.h,,,)

There is no point in checking if the sys/mount.h exits, it has been
there for years. You are not using the HAVE_SYS_MOUNT_H macro anywhere in
the code either.

> +])
> diff --git a/runtest/syscalls b/runtest/syscalls
> index fa87ef63f..bd0725977 100644
> --- a/runtest/syscalls
> +++ b/runtest/syscalls
> @@ -794,6 +794,8 @@ nanosleep01 nanosleep01
>  nanosleep02 nanosleep02
>  nanosleep04 nanosleep04
>  
> +newmount01 newmount01

I'm not sure if we shouldn't call the test fsmount01.c since the main
syscall we are testing here is fsmount().

>  nftw01 nftw01
>  nftw6401 nftw6401
>  
> diff --git a/testcases/kernel/syscalls/newmount/.gitignore b/testcases/kernel/syscalls/newmount/.gitignore
> new file mode 100644
> index 000000000..dc78edd5b
> --- /dev/null
> +++ b/testcases/kernel/syscalls/newmount/.gitignore
> @@ -0,0 +1 @@
> +/newmount01
> diff --git a/testcases/kernel/syscalls/newmount/Makefile b/testcases/kernel/syscalls/newmount/Makefile
> new file mode 100644
> index 000000000..7d0920df6
> --- /dev/null
> +++ b/testcases/kernel/syscalls/newmount/Makefile
> @@ -0,0 +1,9 @@
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +#
> +# Copyright (C) 2019 Red Hat, Inc.  All rights reserved.
> +
> +top_srcdir		?= ../../../..
> +
> +include $(top_srcdir)/include/mk/testcases.mk
> +
> +include $(top_srcdir)/include/mk/generic_leaf_target.mk
> diff --git a/testcases/kernel/syscalls/newmount/newmount01.c b/testcases/kernel/syscalls/newmount/newmount01.c
> new file mode 100644
> index 000000000..1e1ff4a78
> --- /dev/null
> +++ b/testcases/kernel/syscalls/newmount/newmount01.c
> @@ -0,0 +1,112 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2019 Red Hat, Inc.  All rights reserved.
> + * Author: Zorro Lang <zlang@redhat.com>
> + *
> + * Use new mount API (fsopen, fsconfig, fsmount, move_mount) to mount
> + * a filesystem without any specified mount options.
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +#include <errno.h>
> +#include <sys/mount.h>
> +
> +#include "tst_test.h"
> +#include "lapi/newmount.h"
> +
> +#define LINELENGTH 256
> +#define MNTPOINT "newmount_point"
> +static int sfd, mfd, is_mounted;
> +
> +static int ismount(char *mntpoint)
> +{
> +	int ret = 0;
> +	FILE *file;
> +	char line[LINELENGTH];
> +
> +	file = fopen("/proc/mounts", "r");
> +	if (file == NULL)
> +		tst_brk(TFAIL | TTERRNO, "Open /proc/mounts failed");
> +
> +	while (fgets(line, LINELENGTH, file) != NULL) {
> +		if (strstr(line, mntpoint) != NULL) {
> +			ret = 1;
> +			break;
> +		}
> +	}
> +	fclose(file);
> +	return ret;
> +}
> +
> +static void cleanup(void)
> +{
> +	if (is_mounted) {
> +		TEST(tst_umount(MNTPOINT));
> +		if (TST_RET != 0)
> +			tst_brk(TFAIL | TTERRNO, "umount failed in cleanup");
> +	}
> +}
> +
> +static void test_newmount(void)
> +{
> +	TEST(fsopen(tst_device->fs_type, FSOPEN_CLOEXEC));
> +	if (TST_RET < 0) {
> +		tst_brk(TFAIL | TTERRNO,
> +		        "fsopen %s", tst_device->fs_type);

You can't use tst_brk() with TFAIL at the moment. You should either do
tst_res() followed by return or change the TFAIL to TBROK.

See:

https://github.com/linux-test-project/ltp/issues/462

Also this will likely fail on older kernels that does not support the
syscall. I guess that you will get einval here if the fsopen() is not
implemented in kernel. You have to at least set the min_kver in the
tst_test structure so that the test is skipped on older kernels.

> +	}
> +	sfd = TST_RET;
> +	tst_res(TPASS, "fsopen %s", tst_device->fs_type);
> +
> +	TEST(fsconfig(sfd, FSCONFIG_SET_STRING, "source", tst_device->dev, 0));
> +	if (TST_RET < 0) {
> +		tst_brk(TFAIL | TTERRNO,
> +		        "fsconfig set source to %s", tst_device->dev);

Here as well.

> +	}
> +	tst_res(TPASS, "fsconfig set source to %s", tst_device->dev);
> +
> +
> +	TEST(fsconfig(sfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0));
> +	if (TST_RET < 0) {
> +		tst_brk(TFAIL | TTERRNO,
> +		        "fsconfig create superblock");

And here as well.

> +	}
> +	tst_res(TPASS, "fsconfig create superblock");
> +
> +	TEST(fsmount(sfd, FSMOUNT_CLOEXEC, 0));
> +	if (TST_RET < 0) {
> +		tst_brk(TFAIL | TTERRNO, "fsmount");
> +	}

And here as well.

Also LKML prefers not to have curly braces around single line blocks.

See:
https://www.kernel.org/doc/html/v4.10/process/coding-style.html#placing-braces-and-spaces

> +	mfd = TST_RET;
> +	tst_res(TPASS, "fsmount");
> +	SAFE_CLOSE(sfd);
> +
> +	TEST(move_mount(mfd, "", AT_FDCWD, MNTPOINT, MOVE_MOUNT_F_EMPTY_PATH));
> +	if (TST_RET < 0) {
> +		tst_brk(TFAIL | TTERRNO, "move_mount attach to mount point");
> +	}

Here as well.

> +	is_mounted = 1;
> +	tst_res(TPASS, "move_mount attach to mount point");
> +	SAFE_CLOSE(mfd);
> +
> +	if (ismount(MNTPOINT)) {
> +		tst_res(TPASS, "new mount works");
> +		TEST(tst_umount(MNTPOINT));
> +		if (TST_RET != 0)
> +			tst_brk(TFAIL | TTERRNO, "umount failed");

Here as well.

> +		is_mounted = 0;
> +	} else {
> +		tst_res(TFAIL, "new mount fails");
> +	}
> +}
> +
> +static struct tst_test test = {
> +	.test_all	= test_newmount,
> +	.cleanup	= cleanup,
> +	.needs_root	= 1,
> +	.mntpoint	= MNTPOINT,
> +	.format_device	= 1,
> +	.all_filesystems = 1,
> +	.dev_fs_flags	= TST_FS_SKIP_FUSE,
> +};
Petr Vorel Jan. 16, 2020, 11:52 a.m. UTC | #2
Hi Zorro,

> Linux supports new mount syscalls from 5.2, so add new test cases
> to cover these new API. This newmount01 case make sure new API -
> fsopen(), fsconfig(), fsmount() and move_mount() can mount a
> filesystem, then can be unmounted.

Reviewed-by: Petr Vorel <pvorel@suse.cz>

> Hi,

> V4 made a few changes as https://patchwork.ozlabs.org/patch/1206389/#2341154

> And as I said in https://patchwork.ozlabs.org/comment/2342190, the
> TST_FS_SKIP_FUSE flag won't help to skip linux kernel internal ntfs and
> vfat test for this case.
+1

...
> --- /dev/null
> +++ b/m4/ltp-newmount.m4
> @@ -0,0 +1,10 @@
> +dnl SPDX-License-Identifier: GPL-2.0-or-later
> +dnl Copyright (C) 2019 Red Hat, Inc. All Rights Reserved.
> +
> +AC_DEFUN([LTP_CHECK_NEWMOUNT],[
> +AC_CHECK_FUNCS(fsopen,,)
> +AC_CHECK_FUNCS(fsconfig,,)
> +AC_CHECK_FUNCS(fsmount,,)
> +AC_CHECK_FUNCS(move_mount,,)
> +AC_CHECK_HEADER(sys/mount.h,,,)
> +])
This should have been in configure.ac as I reported, but that's ok
(can be fixed by person who merges this).

...
> +static struct tst_test test = {
> +	.test_all	= test_newmount,
> +	.cleanup	= cleanup,
> +	.needs_root	= 1,
> +	.mntpoint	= MNTPOINT,
> +	.format_device	= 1,
> +	.all_filesystems = 1,
> +	.dev_fs_flags	= TST_FS_SKIP_FUSE,
OK, I was wrong, as you found in [1], test shouldn't have .dev_fs_flags   = TST_FS_SKIP_FUSE
(again, can be removed during merge).

I'm just trying to find whether failure caused by CONFIG_NTFS_FS not set,
but mkfs.ntfs installed is a LTP issue or mkfs.ntfs or a kernel issue.

tst_supported_fs_types.c:60: INFO: Kernel supports vfat
tst_supported_fs_types.c:44: INFO: mkfs.vfat does exist
tst_supported_fs_types.c:85: INFO: Filesystem exfat is not supported
tst_supported_fs_types.c:95: INFO: FUSE does support ntfs
tst_supported_fs_types.c:44: INFO: mkfs.ntfs does exist
...
newmount01.c:60: PASS: fsopen vfat
newmount01.c:67: PASS: fsconfig set source to /dev/loop0
newmount01.c:75: PASS: fsconfig create superblock
newmount01.c:82: PASS: fsmount
newmount01.c:90: PASS: move_mount attach to mount point
newmount01.c:94: PASS: new mount works
tst_test.c:1278: INFO: Testing on ntfs
tst_mkfs.c:90: INFO: Formatting /dev/loop0 with ntfs opts='' extra opts=''
The partition start sector was not specified for /dev/loop0 and it could not be obtained automatically.  It has been set to 0.
The number of sectors per track was not specified for /dev/loop0 and it could not be obtained automatically.  It has been set to 0.
The number of heads was not specified for /dev/loop0 and it could not be obtained automatically.  It has been set to 0.
To boot from a device, Windows needs the 'partition start sector', the 'sectors per track' and the 'number of heads' to be set.
Windows will not be able to boot from this device.
tst_test.c:1215: INFO: Timeout per run is 0h 05m 00s
newmount01.c:56: FAIL: fsopen ntfs: ENODEV (19)

Kind regards,
Petr

[1] https://lists.linux.it/pipermail/ltp/2020-January/015046.html
Zorro Lang Jan. 16, 2020, 3:08 p.m. UTC | #3
On Thu, Jan 16, 2020 at 12:49:00PM +0100, Cyril Hrubis wrote:
> Hi!
> >  configure.ac                                  |   1 +
> >  include/lapi/newmount.h                       |  95 +++++++++++++++
> >  include/lapi/syscalls/aarch64.in              |   4 +
> >  include/lapi/syscalls/powerpc64.in            |   4 +
> >  include/lapi/syscalls/s390x.in                |   4 +
> >  include/lapi/syscalls/x86_64.in               |   4 +
> >  m4/ltp-newmount.m4                            |  10 ++
> >  runtest/syscalls                              |   2 +
> >  testcases/kernel/syscalls/newmount/.gitignore |   1 +
> >  testcases/kernel/syscalls/newmount/Makefile   |   9 ++
> >  .../kernel/syscalls/newmount/newmount01.c     | 112 ++++++++++++++++++
> >  11 files changed, 246 insertions(+)
> >  create mode 100644 include/lapi/newmount.h
> >  create mode 100644 m4/ltp-newmount.m4
> >  create mode 100644 testcases/kernel/syscalls/newmount/.gitignore
> >  create mode 100644 testcases/kernel/syscalls/newmount/Makefile
> >  create mode 100644 testcases/kernel/syscalls/newmount/newmount01.c

[snip]

> > diff --git a/m4/ltp-newmount.m4 b/m4/ltp-newmount.m4
> > new file mode 100644
> > index 000000000..e13a6f0b1
> > --- /dev/null
> > +++ b/m4/ltp-newmount.m4
> > @@ -0,0 +1,10 @@
> > +dnl SPDX-License-Identifier: GPL-2.0-or-later
> > +dnl Copyright (C) 2019 Red Hat, Inc. All Rights Reserved.
> > +
> > +AC_DEFUN([LTP_CHECK_NEWMOUNT],[
> > +AC_CHECK_FUNCS(fsopen,,)
> > +AC_CHECK_FUNCS(fsconfig,,)
> > +AC_CHECK_FUNCS(fsmount,,)
> > +AC_CHECK_FUNCS(move_mount,,)
> > +AC_CHECK_HEADER(sys/mount.h,,,)
> 
> There is no point in checking if the sys/mount.h exits, it has been
> there for years. You are not using the HAVE_SYS_MOUNT_H macro anywhere in
> the code either.

Hi,

Thanks so much for your review:)

Sure. I don't include <sys/mount.h> in case, due to I don't know how
glibc will deal with these new syscalls, glibc isn't working on that
yet. I'd like to add includes file in the future after we see the glibc
update:)

> 
> > +])
> > diff --git a/runtest/syscalls b/runtest/syscalls
> > index fa87ef63f..bd0725977 100644
> > --- a/runtest/syscalls
> > +++ b/runtest/syscalls
> > @@ -794,6 +794,8 @@ nanosleep01 nanosleep01
> >  nanosleep02 nanosleep02
> >  nanosleep04 nanosleep04
> >  
> > +newmount01 newmount01
> 
> I'm not sure if we shouldn't call the test fsmount01.c since the main
> syscall we are testing here is fsmount().

Yeah.. Although this case uses fsmount(), my later cases about new mount API
might not use it. I don't like the name "newmount0*" either, but I don't have
a better one for now. If anyone has a better name, please feel free to tell
me :)

> 
> >  nftw01 nftw01
> >  nftw6401 nftw6401
> >  
> > diff --git a/testcases/kernel/syscalls/newmount/.gitignore b/testcases/kernel/syscalls/newmount/.gitignore
> > new file mode 100644
> > index 000000000..dc78edd5b
> > --- /dev/null

[snip]

> > +static void cleanup(void)
> > +{
> > +	if (is_mounted) {
> > +		TEST(tst_umount(MNTPOINT));
> > +		if (TST_RET != 0)
> > +			tst_brk(TFAIL | TTERRNO, "umount failed in cleanup");
> > +	}
> > +}
> > +
> > +static void test_newmount(void)
> > +{
> > +	TEST(fsopen(tst_device->fs_type, FSOPEN_CLOEXEC));
> > +	if (TST_RET < 0) {
> > +		tst_brk(TFAIL | TTERRNO,
> > +		        "fsopen %s", tst_device->fs_type);
> 
> You can't use tst_brk() with TFAIL at the moment. You should either do
> tst_res() followed by return or change the TFAIL to TBROK.

OK, I'll use tst_brk(TBROK | TTERRNO, ...), and change all "tst_brk(TFAIL ...".

> 
> See:
> 
> https://github.com/linux-test-project/ltp/issues/462
> 
> Also this will likely fail on older kernels that does not support the
> syscall. I guess that you will get einval here if the fsopen() is not
> implemented in kernel. You have to at least set the min_kver in the
> tst_test structure so that the test is skipped on older kernels.

If an older downstream kernel (e.g. rhel8/centos kernel-4.18.0-xxx.el8)
merges new mount API features, this case will think the kernel version
is too low to do this test.

I just tested on an old kernel which doesn't support new mount feature.
Then I get this:

  ...
  ...
  tst_test.c:1278: INFO: Testing on xfs
  tst_mkfs.c:90: INFO: Formatting /dev/loop1 with xfs opts='' extra opts=''
  tst_test.c:1217: INFO: Timeout per run is 0h 05m 00s
  ../../../../include/lapi/newmount.h:18: CONF: syscall(430) __NR_fsopen not supported

I think it's fine, due to generally we ignore CONF. What do you think?

Thanks,
Zorro

> 
> > +	}
> > +	sfd = TST_RET;
> > +	tst_res(TPASS, "fsopen %s", tst_device->fs_type);
> > +
> > +	TEST(fsconfig(sfd, FSCONFIG_SET_STRING, "source", tst_device->dev, 0));
> > +	if (TST_RET < 0) {
> > +		tst_brk(TFAIL | TTERRNO,
> > +		        "fsconfig set source to %s", tst_device->dev);
> 
> Here as well.
> 
> > +	}
> > +	tst_res(TPASS, "fsconfig set source to %s", tst_device->dev);
> > +
> > +
> > +	TEST(fsconfig(sfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0));
> > +	if (TST_RET < 0) {
> > +		tst_brk(TFAIL | TTERRNO,
> > +		        "fsconfig create superblock");
> 
> And here as well.
> 
> > +	}
> > +	tst_res(TPASS, "fsconfig create superblock");
> > +
> > +	TEST(fsmount(sfd, FSMOUNT_CLOEXEC, 0));
> > +	if (TST_RET < 0) {
> > +		tst_brk(TFAIL | TTERRNO, "fsmount");
> > +	}
> 
> And here as well.
> 
> Also LKML prefers not to have curly braces around single line blocks.
> 
> See:
> https://www.kernel.org/doc/html/v4.10/process/coding-style.html#placing-braces-and-spaces
> 
> > +	mfd = TST_RET;
> > +	tst_res(TPASS, "fsmount");
> > +	SAFE_CLOSE(sfd);
> > +
> > +	TEST(move_mount(mfd, "", AT_FDCWD, MNTPOINT, MOVE_MOUNT_F_EMPTY_PATH));
> > +	if (TST_RET < 0) {
> > +		tst_brk(TFAIL | TTERRNO, "move_mount attach to mount point");
> > +	}
> 
> Here as well.
> 
> > +	is_mounted = 1;
> > +	tst_res(TPASS, "move_mount attach to mount point");
> > +	SAFE_CLOSE(mfd);
> > +
> > +	if (ismount(MNTPOINT)) {
> > +		tst_res(TPASS, "new mount works");
> > +		TEST(tst_umount(MNTPOINT));
> > +		if (TST_RET != 0)
> > +			tst_brk(TFAIL | TTERRNO, "umount failed");
> 
> Here as well.
> 
> > +		is_mounted = 0;
> > +	} else {
> > +		tst_res(TFAIL, "new mount fails");
> > +	}
> > +}
> > +
> > +static struct tst_test test = {
> > +	.test_all	= test_newmount,
> > +	.cleanup	= cleanup,
> > +	.needs_root	= 1,
> > +	.mntpoint	= MNTPOINT,
> > +	.format_device	= 1,
> > +	.all_filesystems = 1,
> > +	.dev_fs_flags	= TST_FS_SKIP_FUSE,
> > +};
> 
> -- 
> Cyril Hrubis
> chrubis@suse.cz
>
Petr Vorel Jan. 17, 2020, 7:48 a.m. UTC | #4
Hi,

...
> Yeah.. Although this case uses fsmount(), my later cases about new mount API
> might not use it. I don't like the name "newmount0*" either, but I don't have
> a better one for now. If anyone has a better name, please feel free to tell
> me :)
I slightly prefer fsmount01.c as it's based on real name, but no strong opinion.

> > Also this will likely fail on older kernels that does not support the
> > syscall. I guess that you will get einval here if the fsopen() is not
> > implemented in kernel. You have to at least set the min_kver in the
> > tst_test structure so that the test is skipped on older kernels.

> If an older downstream kernel (e.g. rhel8/centos kernel-4.18.0-xxx.el8)
> merges new mount API features, this case will think the kernel version
> is too low to do this test.

> I just tested on an old kernel which doesn't support new mount feature.
> Then I get this:

>   ...
>   ...
>   tst_test.c:1278: INFO: Testing on xfs
>   tst_mkfs.c:90: INFO: Formatting /dev/loop1 with xfs opts='' extra opts=''
>   tst_test.c:1217: INFO: Timeout per run is 0h 05m 00s
>   ../../../../include/lapi/newmount.h:18: CONF: syscall(430) __NR_fsopen not supported

> I think it's fine, due to generally we ignore CONF. What do you think?

I tested it on several distros (old and new kernels) with fixed issues (all but
rename, see following diff) and confirm it TCONF on older kernels
../../../../include/lapi/newmount.h:18: CONF: syscall(430) __NR_fsopen not supported

The only thing with bothers me is is that NTFS related failure
on CONFIG_NTFS_FS is not set and mkfs.ntfs installed.
I'd prefer at least to have a warning, but but better to fix it.
I guess it's LTP problem, see code at safe_mount() in lib/safe_macros.c

	/*
	 * Don't try using the kernel's NTFS driver when mounting NTFS, since
	 * the kernel's NTFS driver doesn't have proper write support.
	 */
	if (!filesystemtype || strcmp(filesystemtype, "ntfs")) {
		rval = mount(source, target, filesystemtype, mountflags, data);
		if (!rval)
			return 0;
	}

But obviously we don't use it as we do mount in the test, not in the library.
So I propose (and can implement) to add flag TST_FS_SKIP_NTFS 0x02 into include/tst_fs.h
and use it in test.

Kind regards,
Petr

diff --git configure.ac configure.ac
index 28f840c51..02d5b8c87 100644
--- configure.ac
+++ configure.ac
@@ -71,12 +71,16 @@ AC_CHECK_FUNCS([ \
     execveat \
     fallocate \
     fchownat \
+    fsconfig \
+    fsmount \
+    fsopen \
     fstatat \
     getdents \
     getdents64 \
     kcmp \
     mkdirat \
     mknodat \
+    move_mount \
     name_to_handle_at \
     openat \
     pidfd_send_signal \
@@ -229,7 +233,6 @@ LTP_CHECK_MADVISE
 LTP_CHECK_MKDTEMP
 LTP_CHECK_MMSGHDR
 LTP_CHECK_MREMAP_FIXED
-LTP_CHECK_NEWMOUNT
 LTP_CHECK_NOMMU_LINUX
 LTP_CHECK_PERF_EVENT
 LTP_CHECK_PRCTL_SUPPORT
diff --git m4/ltp-newmount.m4 m4/ltp-newmount.m4
deleted file mode 100644
index e13a6f0b1..000000000
--- m4/ltp-newmount.m4
+++ /dev/null
@@ -1,10 +0,0 @@
-dnl SPDX-License-Identifier: GPL-2.0-or-later
-dnl Copyright (C) 2019 Red Hat, Inc. All Rights Reserved.
-
-AC_DEFUN([LTP_CHECK_NEWMOUNT],[
-AC_CHECK_FUNCS(fsopen,,)
-AC_CHECK_FUNCS(fsconfig,,)
-AC_CHECK_FUNCS(fsmount,,)
-AC_CHECK_FUNCS(move_mount,,)
-AC_CHECK_HEADER(sys/mount.h,,,)
-])
diff --git testcases/kernel/syscalls/newmount/newmount01.c testcases/kernel/syscalls/newmount/newmount01.c
index 1e1ff4a78..4fe6b350c 100644
--- testcases/kernel/syscalls/newmount/newmount01.c
+++ testcases/kernel/syscalls/newmount/newmount01.c
@@ -28,7 +28,7 @@ static int ismount(char *mntpoint)
 
 	file = fopen("/proc/mounts", "r");
 	if (file == NULL)
-		tst_brk(TFAIL | TTERRNO, "Open /proc/mounts failed");
+		tst_brk(TBROK | TTERRNO, "Open /proc/mounts failed");
 
 	while (fgets(line, LINELENGTH, file) != NULL) {
 		if (strstr(line, mntpoint) != NULL) {
@@ -45,7 +45,7 @@ static void cleanup(void)
 	if (is_mounted) {
 		TEST(tst_umount(MNTPOINT));
 		if (TST_RET != 0)
-			tst_brk(TFAIL | TTERRNO, "umount failed in cleanup");
+			tst_brk(TBROK | TTERRNO, "umount failed in cleanup");
 	}
 }
 
@@ -53,7 +53,7 @@ static void test_newmount(void)
 {
 	TEST(fsopen(tst_device->fs_type, FSOPEN_CLOEXEC));
 	if (TST_RET < 0) {
-		tst_brk(TFAIL | TTERRNO,
+		tst_brk(TBROK | TTERRNO,
 		        "fsopen %s", tst_device->fs_type);
 	}
 	sfd = TST_RET;
@@ -61,7 +61,7 @@ static void test_newmount(void)
 
 	TEST(fsconfig(sfd, FSCONFIG_SET_STRING, "source", tst_device->dev, 0));
 	if (TST_RET < 0) {
-		tst_brk(TFAIL | TTERRNO,
+		tst_brk(TBROK | TTERRNO,
 		        "fsconfig set source to %s", tst_device->dev);
 	}
 	tst_res(TPASS, "fsconfig set source to %s", tst_device->dev);
@@ -69,14 +69,14 @@ static void test_newmount(void)
 
 	TEST(fsconfig(sfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0));
 	if (TST_RET < 0) {
-		tst_brk(TFAIL | TTERRNO,
+		tst_brk(TBROK | TTERRNO,
 		        "fsconfig create superblock");
 	}
 	tst_res(TPASS, "fsconfig create superblock");
 
 	TEST(fsmount(sfd, FSMOUNT_CLOEXEC, 0));
 	if (TST_RET < 0) {
-		tst_brk(TFAIL | TTERRNO, "fsmount");
+		tst_brk(TBROK | TTERRNO, "fsmount");
 	}
 	mfd = TST_RET;
 	tst_res(TPASS, "fsmount");
@@ -84,7 +84,7 @@ static void test_newmount(void)
 
 	TEST(move_mount(mfd, "", AT_FDCWD, MNTPOINT, MOVE_MOUNT_F_EMPTY_PATH));
 	if (TST_RET < 0) {
-		tst_brk(TFAIL | TTERRNO, "move_mount attach to mount point");
+		tst_brk(TBROK | TTERRNO, "move_mount attach to mount point");
 	}
 	is_mounted = 1;
 	tst_res(TPASS, "move_mount attach to mount point");
@@ -94,7 +94,7 @@ static void test_newmount(void)
 		tst_res(TPASS, "new mount works");
 		TEST(tst_umount(MNTPOINT));
 		if (TST_RET != 0)
-			tst_brk(TFAIL | TTERRNO, "umount failed");
+			tst_brk(TBROK | TTERRNO, "umount failed");
 		is_mounted = 0;
 	} else {
 		tst_res(TFAIL, "new mount fails");
@@ -108,5 +108,4 @@ static struct tst_test test = {
 	.mntpoint	= MNTPOINT,
 	.format_device	= 1,
 	.all_filesystems = 1,
-	.dev_fs_flags	= TST_FS_SKIP_FUSE,
 };
Zorro Lang Jan. 17, 2020, 11:05 a.m. UTC | #5
On Fri, Jan 17, 2020 at 08:48:28AM +0100, Petr Vorel wrote:
> Hi,
> 
> ...
> > Yeah.. Although this case uses fsmount(), my later cases about new mount API
> > might not use it. I don't like the name "newmount0*" either, but I don't have
> > a better one for now. If anyone has a better name, please feel free to tell
> > me :)
> I slightly prefer fsmount01.c as it's based on real name, but no strong opinion.

I'd like to follow the choice of LTP maintainers on this kind of problem :)

> 
> > > Also this will likely fail on older kernels that does not support the
> > > syscall. I guess that you will get einval here if the fsopen() is not
> > > implemented in kernel. You have to at least set the min_kver in the
> > > tst_test structure so that the test is skipped on older kernels.
> 
> > If an older downstream kernel (e.g. rhel8/centos kernel-4.18.0-xxx.el8)
> > merges new mount API features, this case will think the kernel version
> > is too low to do this test.
> 
> > I just tested on an old kernel which doesn't support new mount feature.
> > Then I get this:
> 
> >   ...
> >   ...
> >   tst_test.c:1278: INFO: Testing on xfs
> >   tst_mkfs.c:90: INFO: Formatting /dev/loop1 with xfs opts='' extra opts=''
> >   tst_test.c:1217: INFO: Timeout per run is 0h 05m 00s
> >   ../../../../include/lapi/newmount.h:18: CONF: syscall(430) __NR_fsopen not supported
> 
> > I think it's fine, due to generally we ignore CONF. What do you think?
> 
> I tested it on several distros (old and new kernels) with fixed issues (all but
> rename, see following diff) and confirm it TCONF on older kernels
> ../../../../include/lapi/newmount.h:18: CONF: syscall(430) __NR_fsopen not supported

Actually I'm not so familiar with the automake things of LTP, just tried to
follow how other patches deal with that, and try my best to make it work. So
I'd like to agree the opinions from expert(like you) on this part :)

> 
> The only thing with bothers me is is that NTFS related failure
> on CONFIG_NTFS_FS is not set and mkfs.ntfs installed.
> I'd prefer at least to have a warning, but but better to fix it.
> I guess it's LTP problem, see code at safe_mount() in lib/safe_macros.c
> 
> 	/*
> 	 * Don't try using the kernel's NTFS driver when mounting NTFS, since
> 	 * the kernel's NTFS driver doesn't have proper write support.
> 	 */
> 	if (!filesystemtype || strcmp(filesystemtype, "ntfs")) {
> 		rval = mount(source, target, filesystemtype, mountflags, data);
> 		if (!rval)
> 			return 0;
> 	}
> 
> But obviously we don't use it as we do mount in the test, not in the library.
> So I propose (and can implement) to add flag TST_FS_SKIP_NTFS 0x02 into include/tst_fs.h
> and use it in test.

Maybe LTP should do more check to decide a fs list will be tested, not only check
mkfs.$FSTPE tools. For example, check:
1) mkfs.$FSTYPE is exist
2) ${FSTYPE}.ko is loaded, or can be loaded.

Or check:
1) mkfs.$FSTYPE $tmpdev run passed
2) mount $tmpdev $tmpmnt passed
3) umount $tmpdev
4) remove $tmpdev and $tmpmnt

For FUSE, I think we'd better to not test FUSE by default. Then let the case decide if
it would like to support a FUSE fs test. Change the TST_FS_SKIP_FUSE to TST_FS_SUP_FUSE,
if someone case wants to test a FUSE fs (likes ntfs), it should do special steps to mount
it, or it'll test linux internal ntfs.ko.

Due to LTP doesn't like fstests, LTP always tests the syscall itself. If we use bash
command, we can run `mount -t $FSTYPE ....`, don't need to care which program helps
to mount the fs. But if we use old/new mount API, that might totally different to mount
different filesystems. So let's only support those fs which can be mounted generally,
if someone want to write a case to test a special one fs, let the case author write
special steps in the case, and add TST_FS_SUP_*. That's only my tentative opinion :)

Do you need to I send a V5 patch?

Thanks,
Zorro

> 
> Kind regards,
> Petr
> 
> diff --git configure.ac configure.ac
> index 28f840c51..02d5b8c87 100644
> --- configure.ac
> +++ configure.ac
> @@ -71,12 +71,16 @@ AC_CHECK_FUNCS([ \
>      execveat \
>      fallocate \
>      fchownat \
> +    fsconfig \
> +    fsmount \
> +    fsopen \
>      fstatat \
>      getdents \
>      getdents64 \
>      kcmp \
>      mkdirat \
>      mknodat \
> +    move_mount \
>      name_to_handle_at \
>      openat \
>      pidfd_send_signal \
> @@ -229,7 +233,6 @@ LTP_CHECK_MADVISE
>  LTP_CHECK_MKDTEMP
>  LTP_CHECK_MMSGHDR
>  LTP_CHECK_MREMAP_FIXED
> -LTP_CHECK_NEWMOUNT
>  LTP_CHECK_NOMMU_LINUX
>  LTP_CHECK_PERF_EVENT
>  LTP_CHECK_PRCTL_SUPPORT
> diff --git m4/ltp-newmount.m4 m4/ltp-newmount.m4
> deleted file mode 100644
> index e13a6f0b1..000000000
> --- m4/ltp-newmount.m4
> +++ /dev/null
> @@ -1,10 +0,0 @@
> -dnl SPDX-License-Identifier: GPL-2.0-or-later
> -dnl Copyright (C) 2019 Red Hat, Inc. All Rights Reserved.
> -
> -AC_DEFUN([LTP_CHECK_NEWMOUNT],[
> -AC_CHECK_FUNCS(fsopen,,)
> -AC_CHECK_FUNCS(fsconfig,,)
> -AC_CHECK_FUNCS(fsmount,,)
> -AC_CHECK_FUNCS(move_mount,,)
> -AC_CHECK_HEADER(sys/mount.h,,,)
> -])
> diff --git testcases/kernel/syscalls/newmount/newmount01.c testcases/kernel/syscalls/newmount/newmount01.c
> index 1e1ff4a78..4fe6b350c 100644
> --- testcases/kernel/syscalls/newmount/newmount01.c
> +++ testcases/kernel/syscalls/newmount/newmount01.c
> @@ -28,7 +28,7 @@ static int ismount(char *mntpoint)
>  
>  	file = fopen("/proc/mounts", "r");
>  	if (file == NULL)
> -		tst_brk(TFAIL | TTERRNO, "Open /proc/mounts failed");
> +		tst_brk(TBROK | TTERRNO, "Open /proc/mounts failed");
>  
>  	while (fgets(line, LINELENGTH, file) != NULL) {
>  		if (strstr(line, mntpoint) != NULL) {
> @@ -45,7 +45,7 @@ static void cleanup(void)
>  	if (is_mounted) {
>  		TEST(tst_umount(MNTPOINT));
>  		if (TST_RET != 0)
> -			tst_brk(TFAIL | TTERRNO, "umount failed in cleanup");
> +			tst_brk(TBROK | TTERRNO, "umount failed in cleanup");
>  	}
>  }
>  
> @@ -53,7 +53,7 @@ static void test_newmount(void)
>  {
>  	TEST(fsopen(tst_device->fs_type, FSOPEN_CLOEXEC));
>  	if (TST_RET < 0) {
> -		tst_brk(TFAIL | TTERRNO,
> +		tst_brk(TBROK | TTERRNO,
>  		        "fsopen %s", tst_device->fs_type);
>  	}
>  	sfd = TST_RET;
> @@ -61,7 +61,7 @@ static void test_newmount(void)
>  
>  	TEST(fsconfig(sfd, FSCONFIG_SET_STRING, "source", tst_device->dev, 0));
>  	if (TST_RET < 0) {
> -		tst_brk(TFAIL | TTERRNO,
> +		tst_brk(TBROK | TTERRNO,
>  		        "fsconfig set source to %s", tst_device->dev);
>  	}
>  	tst_res(TPASS, "fsconfig set source to %s", tst_device->dev);
> @@ -69,14 +69,14 @@ static void test_newmount(void)
>  
>  	TEST(fsconfig(sfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0));
>  	if (TST_RET < 0) {
> -		tst_brk(TFAIL | TTERRNO,
> +		tst_brk(TBROK | TTERRNO,
>  		        "fsconfig create superblock");
>  	}
>  	tst_res(TPASS, "fsconfig create superblock");
>  
>  	TEST(fsmount(sfd, FSMOUNT_CLOEXEC, 0));
>  	if (TST_RET < 0) {
> -		tst_brk(TFAIL | TTERRNO, "fsmount");
> +		tst_brk(TBROK | TTERRNO, "fsmount");
>  	}
>  	mfd = TST_RET;
>  	tst_res(TPASS, "fsmount");
> @@ -84,7 +84,7 @@ static void test_newmount(void)
>  
>  	TEST(move_mount(mfd, "", AT_FDCWD, MNTPOINT, MOVE_MOUNT_F_EMPTY_PATH));
>  	if (TST_RET < 0) {
> -		tst_brk(TFAIL | TTERRNO, "move_mount attach to mount point");
> +		tst_brk(TBROK | TTERRNO, "move_mount attach to mount point");
>  	}
>  	is_mounted = 1;
>  	tst_res(TPASS, "move_mount attach to mount point");
> @@ -94,7 +94,7 @@ static void test_newmount(void)
>  		tst_res(TPASS, "new mount works");
>  		TEST(tst_umount(MNTPOINT));
>  		if (TST_RET != 0)
> -			tst_brk(TFAIL | TTERRNO, "umount failed");
> +			tst_brk(TBROK | TTERRNO, "umount failed");
>  		is_mounted = 0;
>  	} else {
>  		tst_res(TFAIL, "new mount fails");
> @@ -108,5 +108,4 @@ static struct tst_test test = {
>  	.mntpoint	= MNTPOINT,
>  	.format_device	= 1,
>  	.all_filesystems = 1,
> -	.dev_fs_flags	= TST_FS_SKIP_FUSE,
>  };
>
Cyril Hrubis Jan. 23, 2020, 10:41 a.m. UTC | #6
Hi!
> > The only thing with bothers me is is that NTFS related failure
> > on CONFIG_NTFS_FS is not set and mkfs.ntfs installed.
> > I'd prefer at least to have a warning, but but better to fix it.
> > I guess it's LTP problem, see code at safe_mount() in lib/safe_macros.c
> > 
> > 	/*
> > 	 * Don't try using the kernel's NTFS driver when mounting NTFS, since
> > 	 * the kernel's NTFS driver doesn't have proper write support.
> > 	 */
> > 	if (!filesystemtype || strcmp(filesystemtype, "ntfs")) {
> > 		rval = mount(source, target, filesystemtype, mountflags, data);
> > 		if (!rval)
> > 			return 0;
> > 	}
> > 
> > But obviously we don't use it as we do mount in the test, not in the library.
> > So I propose (and can implement) to add flag TST_FS_SKIP_NTFS 0x02 into include/tst_fs.h
> > and use it in test.
> 
> Maybe LTP should do more check to decide a fs list will be tested, not only check
> mkfs.$FSTPE tools. For example, check:
> 1) mkfs.$FSTYPE is exist
> 2) ${FSTYPE}.ko is loaded, or can be loaded.

That obivously does not work for filesystems build into the kernel.

> Or check:
> 1) mkfs.$FSTYPE $tmpdev run passed
> 2) mount $tmpdev $tmpmnt passed
> 3) umount $tmpdev
> 4) remove $tmpdev and $tmpmnt

If you have a look at the lib/tst_supported_fs_types.c we actually do
this for filesystems implemented in the kernel. For FUSE we only check
that FUSE is enabled in the kernel and that mount.$fs_type is present,
which should be enough to tell if the filesystem is supported.

> For FUSE, I think we'd better to not test FUSE by default. Then let the case decide if
> it would like to support a FUSE fs test. Change the TST_FS_SKIP_FUSE to TST_FS_SUP_FUSE,
> if someone case wants to test a FUSE fs (likes ntfs), it should do special steps to mount
> it, or it'll test linux internal ntfs.ko.

It works fine for majority of testcases, the mount() and fsmount()
syscalls are kind of special here. I guess that all we need to do here
is to skip the fuse here.
Petr Vorel Jan. 23, 2020, 1:15 p.m. UTC | #7
Hi,

Cyril, thanks for review.

> > For FUSE, I think we'd better to not test FUSE by default. Then let the case decide if
> > it would like to support a FUSE fs test. Change the TST_FS_SKIP_FUSE to TST_FS_SUP_FUSE,
> > if someone case wants to test a FUSE fs (likes ntfs), it should do special steps to mount
> > it, or it'll test linux internal ntfs.ko.

> It works fine for majority of testcases, the mount() and fsmount()
> syscalls are kind of special here. I guess that all we need to do here
> is to skip the fuse here.
Great, we get back to the original suggestion, which is in v4:
.dev_fs_flags	= TST_FS_SKIP_FUSE,

Kind regards,
Petr
diff mbox series

Patch

diff --git a/configure.ac b/configure.ac
index 50d14967d..28f840c51 100644
--- a/configure.ac
+++ b/configure.ac
@@ -229,6 +229,7 @@  LTP_CHECK_MADVISE
 LTP_CHECK_MKDTEMP
 LTP_CHECK_MMSGHDR
 LTP_CHECK_MREMAP_FIXED
+LTP_CHECK_NEWMOUNT
 LTP_CHECK_NOMMU_LINUX
 LTP_CHECK_PERF_EVENT
 LTP_CHECK_PRCTL_SUPPORT
diff --git a/include/lapi/newmount.h b/include/lapi/newmount.h
new file mode 100644
index 000000000..13f9fbb9c
--- /dev/null
+++ b/include/lapi/newmount.h
@@ -0,0 +1,95 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2019 Red Hat, Inc.  All rights reserved.
+ * Author: Zorro Lang <zlang@redhat.com>
+ */
+
+#ifndef NEWMOUNT_H__
+#define NEWMOUNT_H__
+
+#include <stdint.h>
+#include <unistd.h>
+#include "config.h"
+#include "lapi/syscalls.h"
+
+#if !defined(HAVE_FSOPEN)
+static inline int fsopen(const char *fs_name, unsigned int flags)
+{
+	return tst_syscall(__NR_fsopen, fs_name, flags);
+}
+
+/*
+ * fsopen() flags.
+ */
+#define FSOPEN_CLOEXEC		0x00000001
+#endif	/* HAVE_FSOPEN */
+
+#if !defined(HAVE_FSCONFIG)
+static inline int fsconfig(int fsfd, unsigned int cmd,
+                           const char *key, const void *val, int aux)
+{
+	return tst_syscall(__NR_fsconfig, fsfd, cmd, key, val, aux);
+}
+
+/*
+ * The type of fsconfig() call made.
+ */
+enum fsconfig_command {
+	FSCONFIG_SET_FLAG	= 0,    /* Set parameter, supplying no value */
+	FSCONFIG_SET_STRING	= 1,    /* Set parameter, supplying a string value */
+	FSCONFIG_SET_BINARY	= 2,    /* Set parameter, supplying a binary blob value */
+	FSCONFIG_SET_PATH	= 3,    /* Set parameter, supplying an object by path */
+	FSCONFIG_SET_PATH_EMPTY	= 4,    /* Set parameter, supplying an object by (empty) path */
+	FSCONFIG_SET_FD		= 5,    /* Set parameter, supplying an object by fd */
+	FSCONFIG_CMD_CREATE	= 6,    /* Invoke superblock creation */
+	FSCONFIG_CMD_RECONFIGURE = 7,   /* Invoke superblock reconfiguration */
+};
+#endif	/* HAVE_FSCONFIG */
+
+#if !defined(HAVE_FSMOUNT)
+static inline int fsmount(int fsfd, unsigned int flags, unsigned int ms_flags)
+{
+	return tst_syscall(__NR_fsmount, fsfd, flags, ms_flags);
+}
+
+/*
+ * fsmount() flags.
+ */
+#define FSMOUNT_CLOEXEC		0x00000001
+
+/*
+ * Mount attributes.
+ */
+#define MOUNT_ATTR_RDONLY	0x00000001 /* Mount read-only */
+#define MOUNT_ATTR_NOSUID	0x00000002 /* Ignore suid and sgid bits */
+#define MOUNT_ATTR_NODEV	0x00000004 /* Disallow access to device special files */
+#define MOUNT_ATTR_NOEXEC	0x00000008 /* Disallow program execution */
+#define MOUNT_ATTR__ATIME	0x00000070 /* Setting on how atime should be updated */
+#define MOUNT_ATTR_RELATIME	0x00000000 /* - Update atime relative to mtime/ctime. */
+#define MOUNT_ATTR_NOATIME	0x00000010 /* - Do not update access times. */
+#define MOUNT_ATTR_STRICTATIME	0x00000020 /* - Always perform atime updates */
+#define MOUNT_ATTR_NODIRATIME	0x00000080 /* Do not update directory access times */
+#endif	/* HAVE_FSMOUNT */
+
+#if !defined(HAVE_MOVE_MOUNT)
+static inline int move_mount(int from_dfd, const char *from_pathname,
+                             int to_dfd, const char *to_pathname,
+                             unsigned int flags)
+{
+	return tst_syscall(__NR_move_mount, from_dfd, from_pathname, to_dfd,
+	                   to_pathname, flags);
+}
+
+/*
+ * move_mount() flags.
+ */
+#define MOVE_MOUNT_F_SYMLINKS		0x00000001 /* Follow symlinks on from path */
+#define MOVE_MOUNT_F_AUTOMOUNTS		0x00000002 /* Follow automounts on from path */
+#define MOVE_MOUNT_F_EMPTY_PATH		0x00000004 /* Empty from path permitted */
+#define MOVE_MOUNT_T_SYMLINKS		0x00000010 /* Follow symlinks on to path */
+#define MOVE_MOUNT_T_AUTOMOUNTS		0x00000020 /* Follow automounts on to path */
+#define MOVE_MOUNT_T_EMPTY_PATH		0x00000040 /* Empty to path permitted */
+#define MOVE_MOUNT__MASK		0x00000077
+#endif	/* HAVE_MOVE_MOUNT */
+
+#endif /* NEWMOUNT_H__ */
diff --git a/include/lapi/syscalls/aarch64.in b/include/lapi/syscalls/aarch64.in
index 0e00641bc..5b9e1d9a4 100644
--- a/include/lapi/syscalls/aarch64.in
+++ b/include/lapi/syscalls/aarch64.in
@@ -270,4 +270,8 @@  pkey_mprotect 288
 pkey_alloc 289
 pkey_free 290
 pidfd_send_signal 424
+move_mount 429
+fsopen 430
+fsconfig 431
+fsmount 432
 _sysctl 1078
diff --git a/include/lapi/syscalls/powerpc64.in b/include/lapi/syscalls/powerpc64.in
index 660165d7a..3aaed64e0 100644
--- a/include/lapi/syscalls/powerpc64.in
+++ b/include/lapi/syscalls/powerpc64.in
@@ -359,3 +359,7 @@  pidfd_send_signal 424
 pkey_mprotect 386
 pkey_alloc 384
 pkey_free 385
+move_mount 429
+fsopen 430
+fsconfig 431
+fsmount 432
diff --git a/include/lapi/syscalls/s390x.in b/include/lapi/syscalls/s390x.in
index 7d632d1dc..bd427555a 100644
--- a/include/lapi/syscalls/s390x.in
+++ b/include/lapi/syscalls/s390x.in
@@ -341,3 +341,7 @@  pkey_mprotect 384
 pkey_alloc 385
 pkey_free 386
 pidfd_send_signal 424
+move_mount 429
+fsopen 430
+fsconfig 431
+fsmount 432
diff --git a/include/lapi/syscalls/x86_64.in b/include/lapi/syscalls/x86_64.in
index b1cbd4f2f..94f0b562e 100644
--- a/include/lapi/syscalls/x86_64.in
+++ b/include/lapi/syscalls/x86_64.in
@@ -320,3 +320,7 @@  pkey_alloc 330
 pkey_free 331
 statx 332
 pidfd_send_signal 424
+move_mount 429
+fsopen 430
+fsconfig 431
+fsmount 432
diff --git a/m4/ltp-newmount.m4 b/m4/ltp-newmount.m4
new file mode 100644
index 000000000..e13a6f0b1
--- /dev/null
+++ b/m4/ltp-newmount.m4
@@ -0,0 +1,10 @@ 
+dnl SPDX-License-Identifier: GPL-2.0-or-later
+dnl Copyright (C) 2019 Red Hat, Inc. All Rights Reserved.
+
+AC_DEFUN([LTP_CHECK_NEWMOUNT],[
+AC_CHECK_FUNCS(fsopen,,)
+AC_CHECK_FUNCS(fsconfig,,)
+AC_CHECK_FUNCS(fsmount,,)
+AC_CHECK_FUNCS(move_mount,,)
+AC_CHECK_HEADER(sys/mount.h,,,)
+])
diff --git a/runtest/syscalls b/runtest/syscalls
index fa87ef63f..bd0725977 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -794,6 +794,8 @@  nanosleep01 nanosleep01
 nanosleep02 nanosleep02
 nanosleep04 nanosleep04
 
+newmount01 newmount01
+
 nftw01 nftw01
 nftw6401 nftw6401
 
diff --git a/testcases/kernel/syscalls/newmount/.gitignore b/testcases/kernel/syscalls/newmount/.gitignore
new file mode 100644
index 000000000..dc78edd5b
--- /dev/null
+++ b/testcases/kernel/syscalls/newmount/.gitignore
@@ -0,0 +1 @@ 
+/newmount01
diff --git a/testcases/kernel/syscalls/newmount/Makefile b/testcases/kernel/syscalls/newmount/Makefile
new file mode 100644
index 000000000..7d0920df6
--- /dev/null
+++ b/testcases/kernel/syscalls/newmount/Makefile
@@ -0,0 +1,9 @@ 
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2019 Red Hat, Inc.  All rights reserved.
+
+top_srcdir		?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/newmount/newmount01.c b/testcases/kernel/syscalls/newmount/newmount01.c
new file mode 100644
index 000000000..1e1ff4a78
--- /dev/null
+++ b/testcases/kernel/syscalls/newmount/newmount01.c
@@ -0,0 +1,112 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2019 Red Hat, Inc.  All rights reserved.
+ * Author: Zorro Lang <zlang@redhat.com>
+ *
+ * Use new mount API (fsopen, fsconfig, fsmount, move_mount) to mount
+ * a filesystem without any specified mount options.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/mount.h>
+
+#include "tst_test.h"
+#include "lapi/newmount.h"
+
+#define LINELENGTH 256
+#define MNTPOINT "newmount_point"
+static int sfd, mfd, is_mounted;
+
+static int ismount(char *mntpoint)
+{
+	int ret = 0;
+	FILE *file;
+	char line[LINELENGTH];
+
+	file = fopen("/proc/mounts", "r");
+	if (file == NULL)
+		tst_brk(TFAIL | TTERRNO, "Open /proc/mounts failed");
+
+	while (fgets(line, LINELENGTH, file) != NULL) {
+		if (strstr(line, mntpoint) != NULL) {
+			ret = 1;
+			break;
+		}
+	}
+	fclose(file);
+	return ret;
+}
+
+static void cleanup(void)
+{
+	if (is_mounted) {
+		TEST(tst_umount(MNTPOINT));
+		if (TST_RET != 0)
+			tst_brk(TFAIL | TTERRNO, "umount failed in cleanup");
+	}
+}
+
+static void test_newmount(void)
+{
+	TEST(fsopen(tst_device->fs_type, FSOPEN_CLOEXEC));
+	if (TST_RET < 0) {
+		tst_brk(TFAIL | TTERRNO,
+		        "fsopen %s", tst_device->fs_type);
+	}
+	sfd = TST_RET;
+	tst_res(TPASS, "fsopen %s", tst_device->fs_type);
+
+	TEST(fsconfig(sfd, FSCONFIG_SET_STRING, "source", tst_device->dev, 0));
+	if (TST_RET < 0) {
+		tst_brk(TFAIL | TTERRNO,
+		        "fsconfig set source to %s", tst_device->dev);
+	}
+	tst_res(TPASS, "fsconfig set source to %s", tst_device->dev);
+
+
+	TEST(fsconfig(sfd, FSCONFIG_CMD_CREATE, NULL, NULL, 0));
+	if (TST_RET < 0) {
+		tst_brk(TFAIL | TTERRNO,
+		        "fsconfig create superblock");
+	}
+	tst_res(TPASS, "fsconfig create superblock");
+
+	TEST(fsmount(sfd, FSMOUNT_CLOEXEC, 0));
+	if (TST_RET < 0) {
+		tst_brk(TFAIL | TTERRNO, "fsmount");
+	}
+	mfd = TST_RET;
+	tst_res(TPASS, "fsmount");
+	SAFE_CLOSE(sfd);
+
+	TEST(move_mount(mfd, "", AT_FDCWD, MNTPOINT, MOVE_MOUNT_F_EMPTY_PATH));
+	if (TST_RET < 0) {
+		tst_brk(TFAIL | TTERRNO, "move_mount attach to mount point");
+	}
+	is_mounted = 1;
+	tst_res(TPASS, "move_mount attach to mount point");
+	SAFE_CLOSE(mfd);
+
+	if (ismount(MNTPOINT)) {
+		tst_res(TPASS, "new mount works");
+		TEST(tst_umount(MNTPOINT));
+		if (TST_RET != 0)
+			tst_brk(TFAIL | TTERRNO, "umount failed");
+		is_mounted = 0;
+	} else {
+		tst_res(TFAIL, "new mount fails");
+	}
+}
+
+static struct tst_test test = {
+	.test_all	= test_newmount,
+	.cleanup	= cleanup,
+	.needs_root	= 1,
+	.mntpoint	= MNTPOINT,
+	.format_device	= 1,
+	.all_filesystems = 1,
+	.dev_fs_flags	= TST_FS_SKIP_FUSE,
+};