Skip site navigation (1)Skip section navigation (2)
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>