Thread (31 messages) 31 messages, 6 authors, 2016-11-22

Re: [glibc PATCH] fcntl: put F_OFD_* constants under #ifdef __USE_FILE_OFFSET64

From: Jeff Layton <hidden>
Date: 2016-08-17 20:58:04

On Wed, 2016-08-17 at 13:37 -0700, Mike Frysinger wrote:
On 17 Aug 2016 16:05, Jeff Layton wrote:
quoted
The way it works now is that when you define _FILE_OFFSET_BITS=64 and
call fcntl(fd, F_SETLK, fl) glibc swaps in a struct flock64 for your
struct flock, and F_SETLK64 for the F_SETLK.
does it ?  doesn't seem like it does to me.  here's glibc's fcntl.c:
	io/fcntl.c - generic stub that sets ENOSYS
	sysdeps/unix/sysv/linux/fcntl.c - just calls syscall(fcntl)
	sysdeps/unix/sysv/linux/generic/wordsize-32/fcntl.c - just calls syscall(fcntl64)
	sysdeps/unix/sysv/linux/i386/fcntl.c - same as above
	<all the other 32-bit arches include the i386 file>
Ok, I was being a little cavalier with my description. This is what
really happens (from x86 struct flock definition):

struct flock
  {
    short int l_type;   /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK.  */
    short int l_whence; /* Where `l_start' is relative to (like `lseek').  */
#ifndef __USE_FILE_OFFSET64
    __off_t l_start;    /* Offset where the lock begins.  */
    __off_t l_len;      /* Size of the locked area; zero means until EOF.  */
#else
    __off64_t l_start;  /* Offset where the lock begins.  */
    __off64_t l_len;    /* Size of the locked area; zero means until EOF.  */
#endif
    __pid_t l_pid;      /* Process holding the lock.  */
  };

So, l_start and l_len get redefined into larger sizes when LFS is
enabled. The F_GETLK/F_SETLK/F_SETLKW are also redefined to their *64
equivalents in that case using the preprocessor.
the kernel is where it gets interesting:
Yes indeed. It's quite the twisty maze...
	fs/compat.c:
quoted
		COMPAT_SYSCALL_DEFINE3(fcntl):
			rejects all 64-bit commands w/EINVAL
			passes all other calls to compat_sys_fcntl64
		COMPAT_SYSCALL_DEFINE3(fcntl64):
quoted
			rewrites 32-bit flock struct to 64-bit flock struct
			passes args to sys_fcntl 
	fs/fcntl.c:
quoted
		SYSCALL_DEFINE3(fcntl):
			passes all args to do_fcntl
		SYSCALL_DEFINE3(fcntl64):
quoted
			handles 64-bit flock commands
			passes all others commands to do_fcntl
		do_fcntl:
			handles all commands using native sized flock struct
so for a 32-bit system (e.g. i386), you must match LFS & command usage.
if LFS is turned on, then using 32-bit commands w/struct flock fails.
if LFS is turned off, then using 64-bit commands w/struct flock fails.
-mike
Yes. The command is what tells the kernel the sort of struct flock it
has been given. The problem here is that we assume that it's
sizeof(struct flock64), but it could a non-LFS struct flock.

-- 
Jeff Layton [off-list ref]
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help