Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 10 Apr 2012 18:56:43 -0400
From:      Jung-uk Kim <jkim@FreeBSD.org>
To:        freebsd-emulation@FreeBSD.org
Subject:   [PATCH] pipe2 for Linuxulator
Message-ID:  <201204101856.46591.jkim@FreeBSD.org>

next in thread | raw e-mail | index | archive | help

--Boundary-00=_uqLhPoic5tB/c6n
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Th attached patch implements pipe2 syscall for Linuxulator, which is 
quite trivial.  Although it was added in Linux 2.6.27 (thanks, 
netchild!), it is often used by popular Linux applications, e.g., 
Adobe Flash plugin.  Please note linux_pipe() was moved from MD files 
to sys/compat/linux/linux_file.c because both amd64 and i386 versions 
looked the same and I failed to see any reason.  I also changed file 
descriptor argument from l_ulong * to l_int *, which seemed more 
appropriate.  Any objections?

Thanks!

Jung-uk Kim

* PS: This patch is also available from here:

http://people.freebsd.org/~jkim/linux_pipe2.diff

--Boundary-00=_uqLhPoic5tB/c6n
Content-Type: text/plain;
  charset="iso-8859-1";
  name="linux_pipe2.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="linux_pipe2.diff"

Index: sys/amd64/linux32/linux32_machdep.c
===================================================================
--- sys/amd64/linux32/linux32_machdep.c	(revision 234112)
+++ sys/amd64/linux32/linux32_machdep.c	(working copy)
@@ -698,25 +698,6 @@ linux_iopl(struct thread *td, struct linux_iopl_ar
 }
 
 int
-linux_pipe(struct thread *td, struct linux_pipe_args *args)
-{
-	int error;
-	int fildes[2];
-
-#ifdef DEBUG
-	if (ldebug(pipe))
-		printf(ARGS(pipe, "*"));
-#endif
-
-	error = kern_pipe(td, fildes);
-	if (error)
-		return (error);
-
-	/* XXX: Close descriptors on error. */
-	return (copyout(fildes, args->pipefds, sizeof fildes));
-}
-
-int
 linux_sigaction(struct thread *td, struct linux_sigaction_args *args)
 {
 	l_osigaction_t osa;
Index: sys/amd64/linux32/linux32_systrace_args.c
===================================================================
--- sys/amd64/linux32/linux32_systrace_args.c	(revision 234112)
+++ sys/amd64/linux32/linux32_systrace_args.c	(working copy)
@@ -287,7 +287,7 @@ systrace_args(int sysnum, void *params, uint64_t *
 	/* linux_pipe */
 	case 42: {
 		struct linux_pipe_args *p = params;
-		uarg[0] = (intptr_t) p->pipefds; /* l_ulong * */
+		uarg[0] = (intptr_t) p->pipefds; /* l_int * */
 		*n_args = 1;
 		break;
 	}
@@ -2172,7 +2172,10 @@ systrace_args(int sysnum, void *params, uint64_t *
 	}
 	/* linux_pipe2 */
 	case 331: {
-		*n_args = 0;
+		struct linux_pipe2_args *p = params;
+		uarg[0] = (intptr_t) p->pipefds; /* l_int * */
+		iarg[1] = p->flags; /* l_int */
+		*n_args = 2;
 		break;
 	}
 	/* linux_inotify_init1 */
@@ -2689,7 +2692,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, cha
 	case 42:
 		switch(ndx) {
 		case 0:
-			p = "l_ulong *";
+			p = "l_int *";
 			break;
 		default:
 			break;
@@ -5368,6 +5371,16 @@ systrace_entry_setargdesc(int sysnum, int ndx, cha
 		break;
 	/* linux_pipe2 */
 	case 331:
+		switch(ndx) {
+		case 0:
+			p = "l_int *";
+			break;
+		case 1:
+			p = "l_int";
+			break;
+		default:
+			break;
+		};
 		break;
 	/* linux_inotify_init1 */
 	case 332:
@@ -6621,6 +6634,9 @@ systrace_return_setargdesc(int sysnum, int ndx, ch
 	case 330:
 	/* linux_pipe2 */
 	case 331:
+		if (ndx == 0 || ndx == 1)
+			p = "int";
+		break;
 	/* linux_inotify_init1 */
 	case 332:
 	/* linux_preadv */
Index: sys/amd64/linux32/syscalls.master
===================================================================
--- sys/amd64/linux32/syscalls.master	(revision 234112)
+++ sys/amd64/linux32/syscalls.master	(working copy)
@@ -95,7 +95,7 @@
 39	AUE_MKDIR	STD	{ int linux_mkdir(char *path, l_int mode); }
 40	AUE_RMDIR	STD	{ int linux_rmdir(char *path); }
 41	AUE_DUP		NOPROTO	{ int dup(u_int fd); }
-42	AUE_PIPE	STD	{ int linux_pipe(l_ulong *pipefds); }
+42	AUE_PIPE	STD	{ int linux_pipe(l_int *pipefds); }
 43	AUE_NULL	STD	{ int linux_times(struct l_times_argv *buf); }
 44	AUE_NULL	UNIMPL	prof
 45	AUE_NULL	STD	{ int linux_brk(l_ulong dsend); }
@@ -536,7 +536,7 @@
 328	AUE_NULL	STD	{ int linux_eventfd2(void); }
 329	AUE_NULL	STD	{ int linux_epoll_create1(void); }
 330	AUE_NULL	STD	{ int linux_dup3(void); }
-331	AUE_NULL	STD	{ int linux_pipe2(void); }
+331	AUE_NULL	STD	{ int linux_pipe2(l_int *pipefds, l_int flags); }
 332	AUE_NULL	STD	{ int linux_inotify_init1(void); }
 ; linux 2.6.30:
 333	AUE_NULL	STD	{ int linux_preadv(void); }
Index: sys/amd64/linux32/linux32_sysent.c
===================================================================
--- sys/amd64/linux32/linux32_sysent.c	(revision 234112)
+++ sys/amd64/linux32/linux32_sysent.c	(working copy)
@@ -350,7 +350,7 @@ struct sysent linux_sysent[] = {
 	{ 0, (sy_call_t *)linux_eventfd2, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 328 = linux_eventfd2 */
 	{ 0, (sy_call_t *)linux_epoll_create1, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 329 = linux_epoll_create1 */
 	{ 0, (sy_call_t *)linux_dup3, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 330 = linux_dup3 */
-	{ 0, (sy_call_t *)linux_pipe2, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 331 = linux_pipe2 */
+	{ AS(linux_pipe2_args), (sy_call_t *)linux_pipe2, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 331 = linux_pipe2 */
 	{ 0, (sy_call_t *)linux_inotify_init1, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 332 = linux_inotify_init1 */
 	{ 0, (sy_call_t *)linux_preadv, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 333 = linux_preadv */
 	{ 0, (sy_call_t *)linux_pwritev, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 334 = linux_pwritev */
Index: sys/amd64/linux32/linux32_dummy.c
===================================================================
--- sys/amd64/linux32/linux32_dummy.c	(revision 234112)
+++ sys/amd64/linux32/linux32_dummy.c	(working copy)
@@ -122,7 +122,6 @@ DUMMY(signalfd4);
 DUMMY(eventfd2);
 DUMMY(epoll_create1);
 DUMMY(dup3);
-DUMMY(pipe2);
 DUMMY(inotify_init1);
 /* linux 2.6.30: */
 DUMMY(preadv);
Index: sys/amd64/linux32/linux32_proto.h
===================================================================
--- sys/amd64/linux32/linux32_proto.h	(revision 234112)
+++ sys/amd64/linux32/linux32_proto.h	(working copy)
@@ -153,7 +153,7 @@ struct linux_rmdir_args {
 	char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
 };
 struct linux_pipe_args {
-	char pipefds_l_[PADL_(l_ulong *)]; l_ulong * pipefds; char pipefds_r_[PADR_(l_ulong *)];
+	char pipefds_l_[PADL_(l_int *)]; l_int * pipefds; char pipefds_r_[PADR_(l_int *)];
 };
 struct linux_times_args {
 	char buf_l_[PADL_(struct l_times_argv *)]; struct l_times_argv * buf; char buf_r_[PADR_(struct l_times_argv *)];
@@ -1046,7 +1046,8 @@ struct linux_dup3_args {
 	register_t dummy;
 };
 struct linux_pipe2_args {
-	register_t dummy;
+	char pipefds_l_[PADL_(l_int *)]; l_int * pipefds; char pipefds_r_[PADR_(l_int *)];
+	char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)];
 };
 struct linux_inotify_init1_args {
 	register_t dummy;
Index: sys/compat/linux/linux_file.c
===================================================================
--- sys/compat/linux/linux_file.c	(revision 234112)
+++ sys/compat/linux/linux_file.c	(working copy)
@@ -69,6 +69,8 @@ __FBSDID("$FreeBSD$");
 #include <compat/linux/linux_util.h>
 #include <compat/linux/linux_file.h>
 
+extern int do_pipe(struct thread *td, int fildes[2], int flags);
+
 int
 linux_creat(struct thread *td, struct linux_creat_args *args)
 {
@@ -1575,3 +1577,49 @@ linux_fadvise64_64(struct thread *td, struct linux
 	return (kern_posix_fadvise(td, args->fd, args->offset, args->len,
 	    advice));
 }
+
+int
+linux_pipe(struct thread *td, struct linux_pipe_args *args)
+{
+	int fildes[2];
+	int error;
+
+#ifdef DEBUG
+	if (ldebug(pipe))
+		printf(ARGS(pipe, "*"));
+#endif
+
+	error = kern_pipe(td, fildes);
+	if (error)
+		return (error);
+
+	/* XXX: Close descriptors on error. */
+	return (copyout(fildes, args->pipefds, sizeof(fildes)));
+}
+
+int
+linux_pipe2(struct thread *td, struct linux_pipe2_args *args)
+{
+	int fildes[2];
+	int error, flags;
+
+#ifdef DEBUG
+	if (ldebug(pipe2))
+		printf(ARGS(pipe2, "*, %d"), args->flags);
+#endif
+
+	if ((args->flags & ~(LINUX_O_NONBLOCK | LINUX_O_CLOEXEC)) != 0)
+		return (EINVAL);
+
+	flags = 0;
+	if ((args->flags & LINUX_O_NONBLOCK) != 0)
+		flags |= O_NONBLOCK;
+	if ((args->flags & LINUX_O_CLOEXEC) != 0)
+		flags |= O_CLOEXEC;
+	error = do_pipe(td, fildes, flags);
+	if (error)
+		return (error);
+
+	/* XXX: Close descriptors on error. */
+	return (copyout(fildes, args->pipefds, sizeof(fildes)));
+}
Index: sys/i386/linux/linux_sysent.c
===================================================================
--- sys/i386/linux/linux_sysent.c	(revision 234112)
+++ sys/i386/linux/linux_sysent.c	(working copy)
@@ -349,7 +349,7 @@ struct sysent linux_sysent[] = {
 	{ 0, (sy_call_t *)linux_eventfd2, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 328 = linux_eventfd2 */
 	{ 0, (sy_call_t *)linux_epoll_create1, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 329 = linux_epoll_create1 */
 	{ 0, (sy_call_t *)linux_dup3, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 330 = linux_dup3 */
-	{ 0, (sy_call_t *)linux_pipe2, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 331 = linux_pipe2 */
+	{ AS(linux_pipe2_args), (sy_call_t *)linux_pipe2, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 331 = linux_pipe2 */
 	{ 0, (sy_call_t *)linux_inotify_init1, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 332 = linux_inotify_init1 */
 	{ 0, (sy_call_t *)linux_preadv, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 333 = linux_preadv */
 	{ 0, (sy_call_t *)linux_pwritev, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC },	/* 334 = linux_pwritev */
Index: sys/i386/linux/linux_machdep.c
===================================================================
--- sys/i386/linux/linux_machdep.c	(revision 234112)
+++ sys/i386/linux/linux_machdep.c	(working copy)
@@ -587,25 +587,6 @@ linux_mprotect(struct thread *td, struct linux_mpr
 }
 
 int
-linux_pipe(struct thread *td, struct linux_pipe_args *args)
-{
-	int error;
-	int fildes[2];
-
-#ifdef DEBUG
-	if (ldebug(pipe))
-		printf(ARGS(pipe, "*"));
-#endif
-
-	error = kern_pipe(td, fildes);
-	if (error)
-		return (error);
-
-	/* XXX: Close descriptors on error. */
-	return (copyout(fildes, args->pipefds, sizeof fildes));
-}
-
-int
 linux_ioperm(struct thread *td, struct linux_ioperm_args *args)
 {
 	int error;
Index: sys/i386/linux/linux_systrace_args.c
===================================================================
--- sys/i386/linux/linux_systrace_args.c	(revision 234112)
+++ sys/i386/linux/linux_systrace_args.c	(working copy)
@@ -295,7 +295,7 @@ systrace_args(int sysnum, void *params, uint64_t *
 	/* linux_pipe */
 	case 42: {
 		struct linux_pipe_args *p = params;
-		uarg[0] = (intptr_t) p->pipefds; /* l_ulong * */
+		uarg[0] = (intptr_t) p->pipefds; /* l_int * */
 		*n_args = 1;
 		break;
 	}
@@ -2263,7 +2263,10 @@ systrace_args(int sysnum, void *params, uint64_t *
 	}
 	/* linux_pipe2 */
 	case 331: {
-		*n_args = 0;
+		struct linux_pipe2_args *p = params;
+		uarg[0] = (intptr_t) p->pipefds; /* l_int * */
+		iarg[1] = p->flags; /* l_int */
+		*n_args = 2;
 		break;
 	}
 	/* linux_inotify_init1 */
@@ -2793,7 +2796,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, cha
 	case 42:
 		switch(ndx) {
 		case 0:
-			p = "l_ulong *";
+			p = "l_int *";
 			break;
 		default:
 			break;
@@ -5664,6 +5667,16 @@ systrace_entry_setargdesc(int sysnum, int ndx, cha
 		break;
 	/* linux_pipe2 */
 	case 331:
+		switch(ndx) {
+		case 0:
+			p = "l_int *";
+			break;
+		case 1:
+			p = "l_int";
+			break;
+		default:
+			break;
+		};
 		break;
 	/* linux_inotify_init1 */
 	case 332:
@@ -6979,6 +6992,9 @@ systrace_return_setargdesc(int sysnum, int ndx, ch
 	case 330:
 	/* linux_pipe2 */
 	case 331:
+		if (ndx == 0 || ndx == 1)
+			p = "int";
+		break;
 	/* linux_inotify_init1 */
 	case 332:
 	/* linux_preadv */
Index: sys/i386/linux/syscalls.master
===================================================================
--- sys/i386/linux/syscalls.master	(revision 234112)
+++ sys/i386/linux/syscalls.master	(working copy)
@@ -95,7 +95,7 @@
 39	AUE_MKDIR	STD	{ int linux_mkdir(char *path, l_int mode); }
 40	AUE_RMDIR	STD	{ int linux_rmdir(char *path); }
 41	AUE_DUP		NOPROTO	{ int dup(u_int fd); }
-42	AUE_PIPE	STD	{ int linux_pipe(l_ulong *pipefds); }
+42	AUE_PIPE	STD	{ int linux_pipe(l_int *pipefds); }
 43	AUE_NULL	STD	{ int linux_times(struct l_times_argv *buf); }
 44	AUE_NULL	UNIMPL	prof
 45	AUE_NULL	STD	{ int linux_brk(l_ulong dsend); }
@@ -546,7 +546,7 @@
 328	AUE_NULL	STD	{ int linux_eventfd2(void); }
 329	AUE_NULL	STD	{ int linux_epoll_create1(void); }
 330	AUE_NULL	STD	{ int linux_dup3(void); }
-331	AUE_NULL	STD	{ int linux_pipe2(void); }
+331	AUE_NULL	STD	{ int linux_pipe2(l_int *pipefds, l_int flags); }
 332	AUE_NULL	STD	{ int linux_inotify_init1(void); }
 ; linux 2.6.30:
 333	AUE_NULL	STD	{ int linux_preadv(void); }
Index: sys/i386/linux/linux_dummy.c
===================================================================
--- sys/i386/linux/linux_dummy.c	(revision 234112)
+++ sys/i386/linux/linux_dummy.c	(working copy)
@@ -113,7 +113,6 @@ DUMMY(signalfd4);
 DUMMY(eventfd2);
 DUMMY(epoll_create1);
 DUMMY(dup3);
-DUMMY(pipe2);
 DUMMY(inotify_init1);
 /* linux 2.6.30: */
 DUMMY(preadv);
Index: sys/i386/linux/linux_proto.h
===================================================================
--- sys/i386/linux/linux_proto.h	(revision 234112)
+++ sys/i386/linux/linux_proto.h	(working copy)
@@ -157,7 +157,7 @@ struct linux_rmdir_args {
 	char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
 };
 struct linux_pipe_args {
-	char pipefds_l_[PADL_(l_ulong *)]; l_ulong * pipefds; char pipefds_r_[PADR_(l_ulong *)];
+	char pipefds_l_[PADL_(l_int *)]; l_int * pipefds; char pipefds_r_[PADR_(l_int *)];
 };
 struct linux_times_args {
 	char buf_l_[PADL_(struct l_times_argv *)]; struct l_times_argv * buf; char buf_r_[PADR_(struct l_times_argv *)];
@@ -1065,7 +1065,8 @@ struct linux_dup3_args {
 	register_t dummy;
 };
 struct linux_pipe2_args {
-	register_t dummy;
+	char pipefds_l_[PADL_(l_int *)]; l_int * pipefds; char pipefds_r_[PADR_(l_int *)];
+	char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)];
 };
 struct linux_inotify_init1_args {
 	register_t dummy;
Index: sys/kern/sys_pipe.c
===================================================================
--- sys/kern/sys_pipe.c	(revision 234112)
+++ sys/kern/sys_pipe.c	(working copy)
@@ -129,6 +129,8 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm_page.h>
 #include <vm/uma.h>
 
+int	do_pipe(struct thread *td, int fildes[2], int flags);
+
 /*
  * Use this define if you want to disable *fancy* VM things.  Expect an
  * approx 30% decrease in transfer rate.  This could be useful for
@@ -405,6 +407,13 @@ pipe_dtor(struct pipe *dpipe)
 int
 kern_pipe(struct thread *td, int fildes[2])
 {
+
+	return (do_pipe(td, fildes, 0));
+}
+
+int
+do_pipe(struct thread *td, int fildes[2], int flags)
+{
 	struct filedesc *fdp; 
 	struct file *rf, *wf;
 	struct pipe *rpipe, *wpipe;
@@ -417,7 +426,7 @@ kern_pipe(struct thread *td, int fildes[2])
 		return (error);
 	rpipe = &pp->pp_rpipe;
 	wpipe = &pp->pp_wpipe;
-	error = falloc(td, &rf, &fd, 0);
+	error = falloc(td, &rf, &fd, flags);
 	if (error) {
 		pipeclose(rpipe);
 		pipeclose(wpipe);
@@ -433,7 +442,7 @@ kern_pipe(struct thread *td, int fildes[2])
 	 * side while we are blocked trying to allocate the write side.
 	 */
 	finit(rf, FREAD | FWRITE, DTYPE_PIPE, rpipe, &pipeops);
-	error = falloc(td, &wf, &fd, 0);
+	error = falloc(td, &wf, &fd, flags);
 	if (error) {
 		fdclose(fdp, rf, fildes[0], td);
 		fdrop(rf, td);

--Boundary-00=_uqLhPoic5tB/c6n--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201204101856.46591.jkim>