This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


On Wed, 2016-08-17 at 13:37 -0700, Mike Frysinger wrote:
> On 17 Aug 2016 16:05, Jeff Layton wrote:
> > 
> > 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:
> > 		COMPAT_SYSCALL_DEFINE3(fcntl):
> > 			rejects all 64-bit commands w/EINVAL
> 			passes all other calls to compat_sys_fcntl64
> 		COMPAT_SYSCALL_DEFINE3(fcntl64):
> > 			rewrites 32-bit flock struct to 64-bit flock struct
> 			passes args to sys_fcntl 
> 	fs/fcntl.c:
> > 		SYSCALL_DEFINE3(fcntl):
> 			passes all args to do_fcntl
> 		SYSCALL_DEFINE3(fcntl64):
> > 			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 <jlayton@redhat.com>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]