[LTP] [PATCH 2/2] fcntl{34, 36}: Always use 64-bit flock struct to avoid EINVAL

Richard Palethorpe rpalethorpe@suse.de
Thu Jan 12 09:54:19 CET 2023


Hello,

Petr Vorel <pvorel@suse.cz> writes:

> Hi Richie,
>
> [ Cc Khem Raj ]
>
>> Recently we switched to using struct fcntl with _FILE_OFFSET_BITS
>> instead of the transitional type fcntl64 which has been removed from
>> some libcs.
>
> Do you mean b0320456cd ("testcases: Fix largefile support") ?
> Because this commit really broke both 32 bit emulation
> + (obviously) LTP on native 32bit.
>
> Please add before merge:
>
> Fixes: b0320456c ("testcases: Fix largefile support")

I suppose, thanks. I'm not sure how much fixes tags help in LTP? In
kernel they are used in automatic backporting and such.

>
> (although this needs also previous fix)
>
>> This broke testing with 32-bit executables on a 64bit kernel when
>> FILE_OFFSET_BITS was not set to 64. Because the fcntl64 syscall does
>> not exist on 64 bit kernels.
>
>> The reason we are making the syscall directly is because of old
>> glibc's which don't do any conversion.
>
>> So we now do a conversion unconditionally and call fcntl64 if the
>> kernel is 32-bit.
> +1.
>
>> When we no longer support old glibcs we can drop this compat function
>> altogether.
> I wonder which glibc these are. And how about musl?

I find it difficult to tell honestly. Pre 2.28 perhaps which is just
what "git describe --contains" suggests.

Muslc appears to always use 64-bit fcntl.

>
> Anyway, thanks!
>
> Reviewed-by: Petr Vorel <pvorel@suse.cz>
> Tested-by: Petr Vorel <pvorel@suse.cz>

Will merge, thanks!

>
> Few unimportant notes below.
> ...
>
>> +++ b/testcases/kernel/syscalls/fcntl/fcntl_common.h
>> @@ -1,38 +1,71 @@
>>  #ifndef FCNTL_COMMON_H__
>>  #define FCNTL_COMMON_H__
>
>> +#include <inttypes.h>
>> +
>> +#include "tst_test.h"
>> +#include "tst_kernel.h"
>> +
>>  #include "lapi/syscalls.h"
>>  #include "lapi/abisize.h"
>> +#include "lapi/fcntl.h"
>> +
>> +struct my_flock64 {
>> +	int16_t l_type;
>> +	int16_t l_whence;
>> +	int64_t l_start;
>> +	int64_t l_len;
>> +	int32_t l_pid;
>> +#if defined(__sparc__)
> nit: #ifdef __sparc__
>
> Well, we still support 32bit sparc (you did support for atomic in
> include/tst_atomic.h), but IMHO it's dead (I might ask if John Paul Adrian
> Glaubitz knows about anybody using LTP for testing on sparc).  But as this is in
> kernel struct, there is no harm to keep it for LTP as well.

Yes, my main thinking was that it is easy to include and I'm not sure if
__sparc__ also gets set on sparc64 or whatever is actually in use.

>
>> +	int16_t padding;
>> +#endif
>> +};
>
> ...
>
>> +static inline int fcntl_compat(const char *file, const int line, const char *cmd_name,
>> +			       int fd, int cmd, struct flock *lck)
>>  {
>> -	int ret = tst_syscall(__NR_fcntl64, fd, cmd, lck);
>> -	if (ret == -1)
>> -		tst_brk(TBROK|TERRNO, "fcntl64");
>> +	struct my_flock64 l64 = {
>> +		.l_type = lck->l_type,
>> +		.l_whence = lck->l_whence,
>> +		.l_start = lck->l_start,
>> +		.l_len = lck->l_len,
>> +		.l_pid = lck->l_pid,
>> +	};
>> +	const long sysno = tst_kernel_bits() > 32 ? __NR_fcntl : __NR_fcntl64;
>> +	const int ret = tst_syscall(sysno, fd, cmd, &l64);
>> +
>> +	lck->l_type = l64.l_type;
>> +	lck->l_whence = l64.l_whence;
>> +	lck->l_start = l64.l_start;
>> +	lck->l_len = l64.l_len;
>> +	lck->l_pid = l64.l_pid;
>> +
>> +	if (ret != -1)
>> +		return ret;
>> +
>> +	tst_brk_(file, line, TBROK | TERRNO,
>> +		 "%s(%d, %s, { %d, %d, %"PRId64", %"PRId64", %d })",
>> +		 tst_kernel_bits() > 32 ? "fcntl" : "fcntl64",
> nit: maybe cache tst_kernel_bits() to variable?

The function already does it.

>
> Kind regards,
> Petr
>
>> +		 fd,
>> +		 cmd_name,
>> +		 l64.l_type, l64.l_whence, l64.l_start, l64.l_len, l64.l_pid);
>> +
>>  	return ret;
>>  }
>> -#endif
>> +
>> +#define FCNTL_COMPAT(fd, cmd, flock) \
>> +	fcntl_compat(__FILE__, __LINE__, #cmd, fd, cmd, flock)
>
>>  #endif /* FCNTL_COMMON_H__ */


-- 
Thank you,
Richard.


More information about the ltp mailing list