Date: Sat, 07 Dec 2002 04:38:12 +0000 From: Ian Dowse <iedowse@maths.tcd.ie> To: emulation@freebsd.org Cc: robert@freebsd.org, marcel@freebsd.org Subject: linux_fcntl64() implementation Message-ID: <200212070438.aa65335@salmon.maths.tcd.ie>
next in thread | raw e-mail | index | archive | help
It seems that we do not implement fcntl64() correctly in the Linux
emulation code. I noticed that some programs were complaining about
F_SETLK failing, so I compared what we do with what appears in
bits/fcntl.h and some version of the Linux fcntl() from the web.
Currently we assume that all F_*ETLK* operations in fcntl64() use
the 64-bit arguments, but it appears that in fact only the versions
with the `64' suffix actually do.
The patch below seems to fix the problem I was seeing - does anybody
know the precise details of the fcntl() vs. fcntl64() ABI? This bug
probably is the cause of PR kern/37656.
Ian
Index: linux_file.c
===================================================================
RCS file: /dump/FreeBSD-CVS/src/sys/compat/linux/linux_file.c,v
retrieving revision 1.71
diff -u -r1.71 linux_file.c
--- linux_file.c 2 Sep 2002 22:46:05 -0000 1.71
+++ linux_file.c 7 Dec 2002 03:28:03 -0000
@@ -931,6 +931,8 @@
static int
fcntl_common(struct thread *td, struct linux_fcntl64_args *args)
{
+ struct l_flock linux_flock;
+ struct flock bsd_flock;
struct file *fp;
long arg;
int error, result;
@@ -977,6 +979,37 @@
arg |= O_ASYNC;
return (kern_fcntl(td, args->fd, F_SETFL, arg));
+ case LINUX_F_GETLK:
+ error = copyin((caddr_t)args->arg, &linux_flock,
+ sizeof(linux_flock));
+ if (error)
+ return (error);
+ linux_to_bsd_flock(&linux_flock, &bsd_flock);
+ error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock);
+ if (error)
+ return (error);
+ bsd_to_linux_flock(&bsd_flock, &linux_flock);
+ return (copyout(&linux_flock, (caddr_t)args->arg,
+ sizeof(linux_flock)));
+
+ case LINUX_F_SETLK:
+ error = copyin((caddr_t)args->arg, &linux_flock,
+ sizeof(linux_flock));
+ if (error)
+ return (error);
+ linux_to_bsd_flock(&linux_flock, &bsd_flock);
+ return (kern_fcntl(td, args->fd, F_SETLK,
+ (intptr_t)&bsd_flock));
+
+ case LINUX_F_SETLKW:
+ error = copyin((caddr_t)args->arg, &linux_flock,
+ sizeof(linux_flock));
+ if (error)
+ return (error);
+ linux_to_bsd_flock(&linux_flock, &bsd_flock);
+ return (kern_fcntl(td, args->fd, F_SETLKW,
+ (intptr_t)&bsd_flock));
+
case LINUX_F_GETOWN:
return (kern_fcntl(td, args->fd, F_GETOWN, 0));
@@ -1005,48 +1038,12 @@
linux_fcntl(struct thread *td, struct linux_fcntl_args *args)
{
struct linux_fcntl64_args args64;
- struct l_flock linux_flock;
- struct flock bsd_flock;
- int error;
#ifdef DEBUG
if (ldebug(fcntl))
printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd);
#endif
- switch (args->cmd) {
- case LINUX_F_GETLK:
- error = copyin((caddr_t)args->arg, &linux_flock,
- sizeof(linux_flock));
- if (error)
- return (error);
- linux_to_bsd_flock(&linux_flock, &bsd_flock);
- error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock);
- if (error)
- return (error);
- bsd_to_linux_flock(&bsd_flock, &linux_flock);
- return (copyout(&linux_flock, (caddr_t)args->arg,
- sizeof(linux_flock)));
-
- case LINUX_F_SETLK:
- error = copyin((caddr_t)args->arg, &linux_flock,
- sizeof(linux_flock));
- if (error)
- return (error);
- linux_to_bsd_flock(&linux_flock, &bsd_flock);
- return (kern_fcntl(td, args->fd, F_SETLK,
- (intptr_t)&bsd_flock));
-
- case LINUX_F_SETLKW:
- error = copyin((caddr_t)args->arg, &linux_flock,
- sizeof(linux_flock));
- if (error)
- return (error);
- linux_to_bsd_flock(&linux_flock, &bsd_flock);
- return (kern_fcntl(td, args->fd, F_SETLKW,
- (intptr_t)&bsd_flock));
- }
-
args64.fd = args->fd;
args64.cmd = args->cmd;
args64.arg = args->arg;
@@ -1067,7 +1064,6 @@
#endif
switch (args->cmd) {
- case LINUX_F_GETLK:
case LINUX_F_GETLK64:
error = copyin((caddr_t)args->arg, &linux_flock,
sizeof(linux_flock));
@@ -1081,7 +1077,6 @@
return (copyout(&linux_flock, (caddr_t)args->arg,
sizeof(linux_flock)));
- case LINUX_F_SETLK:
case LINUX_F_SETLK64:
error = copyin((caddr_t)args->arg, &linux_flock,
sizeof(linux_flock));
@@ -1091,7 +1086,6 @@
return (kern_fcntl(td, args->fd, F_SETLK,
(intptr_t)&bsd_flock));
- case LINUX_F_SETLKW:
case LINUX_F_SETLKW64:
error = copyin((caddr_t)args->arg, &linux_flock,
sizeof(linux_flock));
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-emulation" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200212070438.aa65335>
