[LTP] [PATCH] syscalls/fcntl: make OFD commands use fcntl64() syscall on 32-bit

Jan Stancek jstancek@redhat.com
Wed Oct 17 10:39:50 CEST 2018


ping, any thoughts about this one?


----- Original Message -----
> OFD commands require 64-bit argument (struct flock64). Until
> glibc commit 06ab719d30b0 ("Fix Linux fcntl OFD locks for
> non-LFS architectures (BZ#20251)") we relied on glibc passing
> arg directly to syscall.
> 
> This creates problem for 32-bit version of the test, because old
> glibc is passing arg directly, while new one is casting it to
> struct flock.
> 
> We could add a configure check for glibc version, but that may
> not help with other libc libraries.
> 
> We could do a runtime check that exploits non-zero l_pid returning
> EINVAL. This however complicates SAFE_FCNTL macro substantially.
> 
> This patch changes 32-bit version of test to use syscall directly.
> 
> Signed-off-by: Jan Stancek <jstancek@redhat.com>
> ---
>  testcases/kernel/syscalls/fcntl/fcntl34.c      | 10 ++++++--
>  testcases/kernel/syscalls/fcntl/fcntl36.c      | 19 +++++++++++----
>  testcases/kernel/syscalls/fcntl/fcntl_common.h | 33
>  ++++++++++++++++++++++++++
>  3 files changed, 56 insertions(+), 6 deletions(-)
>  create mode 100644 testcases/kernel/syscalls/fcntl/fcntl_common.h
> 
> diff --git a/testcases/kernel/syscalls/fcntl/fcntl34.c
> b/testcases/kernel/syscalls/fcntl/fcntl34.c
> index aa29cf9ea0d8..90c40f9cf4c6 100644
> --- a/testcases/kernel/syscalls/fcntl/fcntl34.c
> +++ b/testcases/kernel/syscalls/fcntl/fcntl34.c
> @@ -28,6 +28,7 @@
>  #include "lapi/fcntl.h"
>  #include "tst_safe_pthread.h"
>  #include "tst_test.h"
> +#include "fcntl_common.h"
>  
>  static int thread_cnt;
>  static const int max_thread_cnt = 32;
> @@ -68,7 +69,12 @@ void *thread_fn_01(void *arg)
>  
>  	memset(buf, (intptr_t)arg, write_size);
>  
> +/* see explanation in fcntl_common.h */
> +#ifdef USE_STRUCT_FLOCK64
>  	struct flock64 lck = {
> +#else
> +	struct flock lck = {
> +#endif
>  		.l_whence = SEEK_SET,
>  		.l_start  = 0,
>  		.l_len    = 1,
> @@ -76,13 +82,13 @@ void *thread_fn_01(void *arg)
>  
>  	for (i = 0; i < writes_num; ++i) {
>  		lck.l_type = F_WRLCK;
> -		SAFE_FCNTL(fd, F_OFD_SETLKW, &lck);
> +		my_fcntl(fd, F_OFD_SETLKW, &lck);
>  
>  		SAFE_LSEEK(fd, 0, SEEK_END);
>  		SAFE_WRITE(1, fd, buf, write_size);
>  
>  		lck.l_type = F_UNLCK;
> -		SAFE_FCNTL(fd, F_OFD_SETLKW, &lck);
> +		my_fcntl(fd, F_OFD_SETLKW, &lck);
>  
>  		sched_yield();
>  	}
> diff --git a/testcases/kernel/syscalls/fcntl/fcntl36.c
> b/testcases/kernel/syscalls/fcntl/fcntl36.c
> index 81bd5a647e4c..709fcd3a6239 100644
> --- a/testcases/kernel/syscalls/fcntl/fcntl36.c
> +++ b/testcases/kernel/syscalls/fcntl/fcntl36.c
> @@ -57,6 +57,7 @@
>  #include "lapi/fcntl.h"
>  #include "tst_safe_pthread.h"
>  #include "tst_test.h"
> +#include "fcntl_common.h"
>  
>  static int thread_cnt;
>  static int fail_flag = 0;
> @@ -87,7 +88,12 @@ static void *fn_ofd_w(void *arg)
>  	int fd = SAFE_OPEN(fname, O_RDWR);
>  	long wt = pa->cnt;
>  
> +/* see explanation in fcntl_common.h */
> +#ifdef USE_STRUCT_FLOCK64
>  	struct flock64 lck = {
> +#else
> +	struct flock lck = {
> +#endif
>  		.l_whence = SEEK_SET,
>  		.l_start  = pa->offset,
>  		.l_len    = pa->length,
> @@ -99,13 +105,13 @@ static void *fn_ofd_w(void *arg)
>  		memset(buf, wt, pa->length);
>  
>  		lck.l_type = F_WRLCK;
> -		SAFE_FCNTL(fd, F_OFD_SETLKW, &lck);
> +		my_fcntl(fd, F_OFD_SETLKW, &lck);
>  
>  		SAFE_LSEEK(fd, pa->offset, SEEK_SET);
>  		SAFE_WRITE(1, fd, buf, pa->length);
>  
>  		lck.l_type = F_UNLCK;
> -		SAFE_FCNTL(fd, F_OFD_SETLKW, &lck);
> +		my_fcntl(fd, F_OFD_SETLKW, &lck);
>  
>  		wt++;
>  		if (wt >= 255)
> @@ -166,7 +172,12 @@ static void *fn_ofd_r(void *arg)
>  	int i;
>  	int fd = SAFE_OPEN(fname, O_RDWR);
>  
> +/* see explanation in fcntl_common.h */
> +#ifdef USE_STRUCT_FLOCK64
>  	struct flock64 lck = {
> +#else
> +	struct flock lck = {
> +#endif
>  		.l_whence = SEEK_SET,
>  		.l_start  = pa->offset,
>  		.l_len    = pa->length,
> @@ -178,7 +189,7 @@ static void *fn_ofd_r(void *arg)
>  		memset(buf, 0, pa->length);
>  
>  		lck.l_type = F_RDLCK;
> -		SAFE_FCNTL(fd, F_OFD_SETLKW, &lck);
> +		my_fcntl(fd, F_OFD_SETLKW, &lck);
>  
>  		/* rlock acquired */
>  		SAFE_LSEEK(fd, pa->offset, SEEK_SET);
> @@ -209,7 +220,7 @@ static void *fn_ofd_r(void *arg)
>  		}
>  
>  		lck.l_type = F_UNLCK;
> -		SAFE_FCNTL(fd, F_OFD_SETLK, &lck);
> +		my_fcntl(fd, F_OFD_SETLK, &lck);
>  
>  		sched_yield();
>  	}
> diff --git a/testcases/kernel/syscalls/fcntl/fcntl_common.h
> b/testcases/kernel/syscalls/fcntl/fcntl_common.h
> new file mode 100644
> index 000000000000..d73e4624f3f6
> --- /dev/null
> +++ b/testcases/kernel/syscalls/fcntl/fcntl_common.h
> @@ -0,0 +1,33 @@
> +#include "lapi/syscalls.h"
> +
> +/*
> + * glibc commit:
> + *   06ab719d30b0 ("Fix Linux fcntl OFD locks for non-LFS architectures
> (BZ#20251)")
> + * changed behavior of arg parameter for OFD commands. It is no
> + * longer passing arg directly to syscall, but expects it to be
> + * 'struct flock'.
> + *
> + * On 64-bit or _FILE_OFFSET_BITS == 64 we can use fcntl() and
> + * struct flock with any glibc version. struct flock and flock64
> + * should be identical.
> + *
> + * On 32-bit, older glibc would pass arg directly, recent one treats
> + * it as 'struct flock' and converts it to 'struct flock64'.
> + * So, to support both version, on 32-bit we use fcntl64 syscall
> + * directly with struct flock64.
> + */
> +#if __WORDSIZE == 64 || _FILE_OFFSET_BITS == 64
> +static int my_fcntl(int fd, int cmd, void *lck)
> +{
> +	return SAFE_FCNTL(fd, cmd, lck);
> +}
> +#else
> +#define USE_STRUCT_FLOCK64
> +static int my_fcntl(int fd, int cmd, void *lck)
> +{
> +	int ret = tst_syscall(__NR_fcntl64, fd, cmd, lck);
> +	if (ret == -1)
> +		tst_brk(TBROK|TERRNO, "fcntl64");
> +	return ret;
> +}
> +#endif
> --
> 1.8.3.1
> 
> 
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
> 


More information about the ltp mailing list