Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Jul 2002 13:14:18 -0700 (PDT)
From:      Robert Drehmel <robert@FreeBSD.org>
To:        emulation@FreeBSD.org
Subject:   Linux emulation: fcntl64()
Message-ID:  <200207102014.g6AKEIQB037047@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
Hello emulation folks,

when the Linux system call fcntl64() is called with a F_GETLK,
F_SETLK, and F_SETLKW fcntl() command, we currently handle the
'arg' argument as if it were an Linux 'struct flock64', like
the one passed with the 64 bit lock commands.

Testing on an SuSE 7.3 Linux showed that a 'struct flock64'
is *only* passed as an argument for the 64 bit lock commands,
but not for the commands mentioned above.

There is a comment in that patch that says more.

I would like to commit that in a few days.
Any comments or objections?

ciao,
-robert


Index: linux_file.c
===================================================================
RCS file: /home/ncvs/src/sys/compat/linux/linux_file.c,v
retrieving revision 1.66
diff -u -r1.66 linux_file.c
--- linux_file.c	9 Jul 2002 19:25:43 -0000	1.66
+++ linux_file.c	10 Jul 2002 19:31:32 -0000
@@ -874,7 +874,7 @@
 	linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
 }
 
-#if defined(__i386__)
+#if defined(__i386__) || defined(__powerpc__)
 struct l_flock64 {
 	l_short		l_type;
 	l_short		l_whence;
@@ -925,9 +925,7 @@
 	linux_flock->l_len = (l_loff_t)bsd_flock->l_len;
 	linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid;
 }
-#endif /* __i386__ */
-
-#if defined(__alpha__)
+#elif defined(__alpha__) || defined(__sparc64__) || defined(__ia64__)
 #define	linux_fcntl64_args	linux_fcntl_args
 #endif
 
@@ -1016,14 +1014,70 @@
 	return (EINVAL);
 }
 
+static int
+linux_fcntl_getlk(struct thread *td, int fd, struct flock *bsd_flock,
+    void *arg)
+{
+	struct fcntl_args fcntl_args;
+	struct l_flock linux_flock;
+	int error;
+
+	error = copyin(arg, &linux_flock, sizeof(linux_flock));
+	if (error)
+		return (error);
+	linux_to_bsd_flock(&linux_flock, bsd_flock);
+	fcntl_args.fd = fd;
+	fcntl_args.cmd = F_GETLK;
+	fcntl_args.arg = (long)bsd_flock;
+	error = fcntl(td, &fcntl_args);
+	if (error)
+		return (error);
+	bsd_to_linux_flock(bsd_flock, &linux_flock);
+	return (copyout(&linux_flock, (caddr_t)arg, sizeof(linux_flock)));
+}
+
+static int
+linux_fcntl_setlk(struct thread *td, int fd, struct flock *bsd_flock,
+    void *arg)
+{
+	struct fcntl_args fcntl_args;
+	struct l_flock linux_flock;
+	int error;
+
+	error = copyin((caddr_t)arg, &linux_flock, sizeof(linux_flock));
+	if (error)
+		return (error);
+	linux_to_bsd_flock(&linux_flock, bsd_flock);
+	fcntl_args.fd = fd;
+	fcntl_args.cmd = F_SETLK;
+	fcntl_args.arg = (long)bsd_flock;
+	return (fcntl(td, &fcntl_args));
+
+}
+
+static int
+linux_fcntl_setlkw(struct thread *td, int fd, struct flock *bsd_flock,
+    void *arg)
+{
+	struct fcntl_args fcntl_args;
+	struct l_flock linux_flock;
+	int error;
+
+	error = copyin((caddr_t)arg, &linux_flock, sizeof(linux_flock));
+	if (error)
+		return (error);
+	linux_to_bsd_flock(&linux_flock, bsd_flock);
+	fcntl_args.fd = fd;
+	fcntl_args.cmd = F_SETLKW;
+	fcntl_args.arg = (long)bsd_flock;
+	return (fcntl(td, &fcntl_args));
+}
+
 int
 linux_fcntl(struct thread *td, struct linux_fcntl_args *args)
 {
 	struct linux_fcntl64_args args64;
-	struct fcntl_args fcntl_args;
-	struct l_flock linux_flock;
 	struct flock *bsd_flock;
-	int error;
 	caddr_t sg;
 
 	sg = stackgap_init();
@@ -1036,42 +1090,11 @@
 
 	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);
-		fcntl_args.fd = args->fd;
-		fcntl_args.cmd = F_GETLK;
-		fcntl_args.arg = (long)bsd_flock;
-		error = fcntl(td, &fcntl_args);
-		if (error)
-			return (error);
-		bsd_to_linux_flock(bsd_flock, &linux_flock);
-		return (copyout(&linux_flock, (caddr_t)args->arg,
-		    sizeof(linux_flock)));
-
+		return (linux_fcntl_getlk(td, args->fd, bsd_flock, (void *)args->arg));
 	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);
-		fcntl_args.fd = args->fd;
-		fcntl_args.cmd = F_SETLK;
-		fcntl_args.arg = (long)bsd_flock;
-		return (fcntl(td, &fcntl_args));
-
+		return (linux_fcntl_setlk(td, args->fd, bsd_flock, (void *)args->arg));
 	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);
-		fcntl_args.fd = args->fd;
-		fcntl_args.cmd = F_SETLKW;
-		fcntl_args.arg = (long)bsd_flock;
-		return (fcntl(td, &fcntl_args));
+		return (linux_fcntl_setlkw(td, args->fd, bsd_flock, (void *)args->arg));
 	}
 
 	args64.fd = args->fd;
@@ -1080,13 +1103,14 @@
 	return (fcntl_common(td, &args64));
 }
 
-#if defined(__i386__)
+/* The fcntl64() system call exists only on 32 bit platforms */
+#if defined(__i386__) || defined(__powerpc__)
 int
 linux_fcntl64(struct thread *td, struct linux_fcntl64_args *args)
 {
-	struct fcntl_args fcntl_args;
-	struct l_flock64 linux_flock;
-	struct flock *bsd_flock;
+	struct fcntl_args fcntl_args;		/* FreeBSD fcntl arguments */
+	struct l_flock64 linux_flock64;		/* Linux wide flock struct */
+	struct flock *bsd_flock;		/* FreeBSD flock struct */
 	int error;
 	caddr_t sg;
 
@@ -1099,42 +1123,63 @@
 #endif
 
 	switch (args->cmd) {
+	/*
+	 * Linux environments that have __USE_FILE_OFFSET64 defined use
+	 * a 64 bit wide offset type in 'struct flock' and define all
+	 * locking commands to the values of their 64 bit counterparts.
+	 *
+	 * This removes the need for conditional compilation directives
+	 * to explicitly fill an 'struct flock64' and call fcntl64() for
+	 * 32 bit architectures.
+	 *
+	 * However, the original values of the commands below still
+	 * imply that there is the narrower 'struct flock' passed.
+	 */
 	case LINUX_F_GETLK:
+		return linux_fcntl_getlk(td, args->fd, bsd_flock,
+		    (void *)args->arg);
+
+	case LINUX_F_SETLK:
+		return linux_fcntl_setlk(td, args->fd, bsd_flock,
+		    (void *)args->arg);
+
+	case LINUX_F_SETLKW:
+		return linux_fcntl_setlkw(td, args->fd, bsd_flock,
+		    (void *)args->arg);
+
 	case LINUX_F_GETLK64:
-		error = copyin((caddr_t)args->arg, &linux_flock,
-		    sizeof(linux_flock));
+		error = copyin((caddr_t)args->arg, &linux_flock64,
+		    sizeof(linux_flock64));
 		if (error)
 			return (error);
-		linux_to_bsd_flock64(&linux_flock, bsd_flock);
+		linux_to_bsd_flock64(&linux_flock64, bsd_flock);
 		fcntl_args.fd = args->fd;
 		fcntl_args.cmd = F_GETLK;
 		fcntl_args.arg = (long)bsd_flock;
 		error = fcntl(td, &fcntl_args);
 		if (error)
 			return (error);
-		bsd_to_linux_flock64(bsd_flock, &linux_flock);
-		return (copyout(&linux_flock, (caddr_t)args->arg,
-		    sizeof(linux_flock)));
+		bsd_to_linux_flock64(bsd_flock, &linux_flock64);
+		return (copyout(&linux_flock64, (caddr_t)args->arg,
+		    sizeof(linux_flock64)));
 
-	case LINUX_F_SETLK:
 	case LINUX_F_SETLK64:
-		error = copyin((caddr_t)args->arg, &linux_flock,
-		    sizeof(linux_flock));
+		error = copyin((caddr_t)args->arg, &linux_flock64,
+		    sizeof(linux_flock64));
 		if (error)
 			return (error);
-		linux_to_bsd_flock64(&linux_flock, bsd_flock);
+		linux_to_bsd_flock64(&linux_flock64, bsd_flock);
 		fcntl_args.fd = args->fd;
 		fcntl_args.cmd = F_SETLK;
 		fcntl_args.arg = (long)bsd_flock;
 		return (fcntl(td, &fcntl_args));
 
-	case LINUX_F_SETLKW:
 	case LINUX_F_SETLKW64:
-		error = copyin((caddr_t)args->arg, &linux_flock,
-		    sizeof(linux_flock));
+		error = copyin((caddr_t)args->arg, &linux_flock64,
+		    sizeof(linux_flock64));
 		if (error)
 			return (error);
-		linux_to_bsd_flock64(&linux_flock, bsd_flock);
+		linux_to_bsd_flock64(&linux_flock64, bsd_flock);
 		fcntl_args.fd = args->fd;
 		fcntl_args.cmd = F_SETLKW;
 		fcntl_args.arg = (long)bsd_flock;
@@ -1143,7 +1188,7 @@
 
 	return (fcntl_common(td, args));
 }
-#endif /* __i386__ */
+#endif /* __i386__ || __powerpc__ */
 
 int
 linux_chown(struct thread *td, struct linux_chown_args *args)

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?200207102014.g6AKEIQB037047>