git: 97add684f530 - main - linux: Support POSIX message queues

From: Warner Losh <imp_at_FreeBSD.org>
Date: Thu, 23 May 2024 19:42:15 UTC
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=97add684f5306ebf93be238a0340597ba1898d0e

commit 97add684f5306ebf93be238a0340597ba1898d0e
Author:     Ricardo Branco <rbranco@suse.de>
AuthorDate: 2024-05-17 20:31:49 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2024-05-23 19:40:46 +0000

    linux: Support POSIX message queues
    
    Reviewed by: imp, kib
    Pull Request: https://github.com/freebsd/freebsd-src/pull/1248
---
 sys/amd64/linux/linux_dummy_machdep.c     |   6 --
 sys/amd64/linux32/linux32_dummy_machdep.c |   6 --
 sys/arm64/linux/linux_dummy_machdep.c     |   6 --
 sys/compat/linux/linux_misc.c             | 124 ++++++++++++++++++++++++++++++
 sys/i386/linux/linux_machdep.c            |  61 ---------------
 5 files changed, 124 insertions(+), 79 deletions(-)

diff --git a/sys/amd64/linux/linux_dummy_machdep.c b/sys/amd64/linux/linux_dummy_machdep.c
index 759586d9f1fc..53bdb8099578 100644
--- a/sys/amd64/linux/linux_dummy_machdep.c
+++ b/sys/amd64/linux/linux_dummy_machdep.c
@@ -56,12 +56,6 @@ DUMMY(io_destroy);
 DUMMY(io_getevents);
 DUMMY(io_submit);
 DUMMY(io_cancel);
-DUMMY(mq_open);
-DUMMY(mq_unlink);
-DUMMY(mq_timedsend);
-DUMMY(mq_timedreceive);
-DUMMY(mq_notify);
-DUMMY(mq_getsetattr);
 DUMMY(readahead);
 DUMMY(restart_syscall);
 /* Linux 3.15: */
diff --git a/sys/amd64/linux32/linux32_dummy_machdep.c b/sys/amd64/linux32/linux32_dummy_machdep.c
index c2206c81c528..1476d39b9c35 100644
--- a/sys/amd64/linux32/linux32_dummy_machdep.c
+++ b/sys/amd64/linux32/linux32_dummy_machdep.c
@@ -55,12 +55,6 @@ DUMMY(olduname);
 DUMMY(uname);
 DUMMY(bdflush);
 DUMMY(ptrace);
-DUMMY(mq_open);
-DUMMY(mq_unlink);
-DUMMY(mq_timedsend);
-DUMMY(mq_timedreceive);
-DUMMY(mq_notify);
-DUMMY(mq_getsetattr);
 /* Linux 4.11: */
 DUMMY(arch_prctl);
 /* Linux 5.0: */
diff --git a/sys/arm64/linux/linux_dummy_machdep.c b/sys/arm64/linux/linux_dummy_machdep.c
index a7a7795f573d..5ff6bfafe2d6 100644
--- a/sys/arm64/linux/linux_dummy_machdep.c
+++ b/sys/arm64/linux/linux_dummy_machdep.c
@@ -42,10 +42,4 @@ LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
  * Before adding new stubs to this file, please check if a stub can be added to
  * the machine-independent code in sys/compat/linux/linux_dummy.c.
  */
-DUMMY(mq_open);
-DUMMY(mq_unlink);
-DUMMY(mq_timedsend);
-DUMMY(mq_timedreceive);
-DUMMY(mq_notify);
-DUMMY(mq_getsetattr);
 DUMMY(kexec_file_load);
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index 9b8ab193f2bd..14c36669efc8 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -29,6 +29,8 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "opt_posix.h"
+
 #include <sys/param.h>
 #include <sys/fcntl.h>
 #include <sys/jail.h>
@@ -36,6 +38,7 @@
 #include <sys/limits.h>
 #include <sys/lock.h>
 #include <sys/msgbuf.h>
+#include <sys/mqueue.h>
 #include <sys/mutex.h>
 #include <sys/poll.h>
 #include <sys/priv.h>
@@ -2963,3 +2966,124 @@ linux_ioprio_set(struct thread *td, struct linux_ioprio_set_args *args)
 	}
 	return (error);
 }
+
+/* The only flag is O_NONBLOCK */
+#define B2L_MQ_FLAGS(bflags)	((bflags) != 0 ? LINUX_O_NONBLOCK : 0)
+#define L2B_MQ_FLAGS(lflags)	((lflags) != 0 ? O_NONBLOCK : 0)
+
+int
+linux_mq_open(struct thread *td, struct linux_mq_open_args *args)
+{
+	struct mq_attr attr;
+	int error, flags;
+
+	flags = linux_common_openflags(args->oflag);
+	if ((flags & O_ACCMODE) == O_ACCMODE || (flags & O_EXEC) != 0)
+		return (EINVAL);
+	flags = FFLAGS(flags);
+	if ((flags & O_CREAT) != 0 && args->attr != NULL) {
+		error = copyin(args->attr, &attr, sizeof(attr));
+		if (error != 0)
+			return (error);
+		attr.mq_flags = L2B_MQ_FLAGS(attr.mq_flags);
+	}
+
+	return (kern_kmq_open(td, args->name, flags, args->mode,
+	    args->attr != NULL ? &attr : NULL));
+}
+
+int
+linux_mq_unlink(struct thread *td, struct linux_mq_unlink_args *args)
+{
+	struct kmq_unlink_args bsd_args = {
+		.path = PTRIN(args->name)
+	};
+
+	return (sys_kmq_unlink(td, &bsd_args));
+}
+
+int
+linux_mq_timedsend(struct thread *td, struct linux_mq_timedsend_args *args)
+{
+	struct timespec ts, *abs_timeout;
+	int error;
+
+	if (args->abs_timeout == NULL)
+		abs_timeout = NULL;
+	else {
+		error = linux_get_timespec(&ts, args->abs_timeout);
+		if (error != 0)
+			return (error);
+		abs_timeout = &ts;
+	}
+
+	return (kern_kmq_timedsend(td, args->mqd, PTRIN(args->msg_ptr),
+		args->msg_len, args->msg_prio, abs_timeout));
+}
+
+int
+linux_mq_timedreceive(struct thread *td, struct linux_mq_timedreceive_args *args)
+{
+	struct timespec ts, *abs_timeout;
+	int error;
+
+	if (args->abs_timeout == NULL)
+		abs_timeout = NULL;
+	else {
+		error = linux_get_timespec(&ts, args->abs_timeout);
+		if (error != 0)
+			return (error);
+		abs_timeout = &ts;
+	}
+
+	return (kern_kmq_timedreceive(td, args->mqd, PTRIN(args->msg_ptr),
+		args->msg_len, args->msg_prio, abs_timeout));
+}
+
+int
+linux_mq_notify(struct thread *td, struct linux_mq_notify_args *args)
+{
+	struct sigevent ev, *evp;
+	struct l_sigevent l_ev;
+	int error;
+
+	if (args->sevp == NULL)
+		evp = NULL;
+	else {
+		error = copyin(args->sevp, &l_ev, sizeof(l_ev));
+		if (error != 0)
+			return (error);
+		error = linux_convert_l_sigevent(&l_ev, &ev);
+		if (error != 0)
+			return (error);
+		evp = &ev;
+	}
+
+	return (kern_kmq_notify(td, args->mqd, evp));
+}
+
+int
+linux_mq_getsetattr(struct thread *td, struct linux_mq_getsetattr_args *args)
+{
+	struct mq_attr attr, oattr;
+	int error;
+
+	if (args->attr != NULL) {
+		error = copyin(args->attr, &attr, sizeof(attr));
+		if (error != 0)
+			return (error);
+		attr.mq_flags = L2B_MQ_FLAGS(attr.mq_flags);
+	}
+
+	error = kern_kmq_setattr(td, args->mqd, args->attr != NULL ? &attr : NULL,
+	    &oattr);
+	if (error == 0 && args->oattr != NULL) {
+		oattr.mq_flags = B2L_MQ_FLAGS(oattr.mq_flags);
+		bzero(oattr.__reserved, sizeof(oattr.__reserved));
+		error = copyout(&oattr, args->oattr, sizeof(oattr));
+	}
+
+	return (error);
+}
+
+MODULE_DEPEND(linux, mqueuefs, 1, 1, 1);
diff --git a/sys/i386/linux/linux_machdep.c b/sys/i386/linux/linux_machdep.c
index b5d42dc22162..0e056aadb4b5 100644
--- a/sys/i386/linux/linux_machdep.c
+++ b/sys/i386/linux/linux_machdep.c
@@ -592,67 +592,6 @@ linux_get_thread_area(struct thread *td, struct linux_get_thread_area_args *args
 	return (0);
 }
 
-/* XXX: this wont work with module - convert it */
-int
-linux_mq_open(struct thread *td, struct linux_mq_open_args *args)
-{
-#ifdef P1003_1B_MQUEUE
-	return (sys_kmq_open(td, (struct kmq_open_args *)args));
-#else
-	return (ENOSYS);
-#endif
-}
-
-int
-linux_mq_unlink(struct thread *td, struct linux_mq_unlink_args *args)
-{
-#ifdef P1003_1B_MQUEUE
-	return (sys_kmq_unlink(td, (struct kmq_unlink_args *)args));
-#else
-	return (ENOSYS);
-#endif
-}
-
-int
-linux_mq_timedsend(struct thread *td, struct linux_mq_timedsend_args *args)
-{
-#ifdef P1003_1B_MQUEUE
-	return (sys_kmq_timedsend(td, (struct kmq_timedsend_args *)args));
-#else
-	return (ENOSYS);
-#endif
-}
-
-int
-linux_mq_timedreceive(struct thread *td, struct linux_mq_timedreceive_args *args)
-{
-#ifdef P1003_1B_MQUEUE
-	return (sys_kmq_timedreceive(td, (struct kmq_timedreceive_args *)args));
-#else
-	return (ENOSYS);
-#endif
-}
-
-int
-linux_mq_notify(struct thread *td, struct linux_mq_notify_args *args)
-{
-#ifdef P1003_1B_MQUEUE
-	return (sys_kmq_notify(td, (struct kmq_notify_args *)args));
-#else
-	return (ENOSYS);
-#endif
-}
-
-int
-linux_mq_getsetattr(struct thread *td, struct linux_mq_getsetattr_args *args)
-{
-#ifdef P1003_1B_MQUEUE
-	return (sys_kmq_setattr(td, (struct kmq_setattr_args *)args));
-#else
-	return (ENOSYS);
-#endif
-}
-
 void
 bsd_to_linux_regset(const struct reg *b_reg,
     struct linux_pt_regset *l_regset)