svn commit: r205325 - in head/sys: compat/freebsd32 kern

Konstantin Belousov kib at FreeBSD.org
Fri Mar 19 11:10:24 UTC 2010


Author: kib
Date: Fri Mar 19 11:10:24 2010
New Revision: 205325
URL: http://svn.freebsd.org/changeset/base/205325

Log:
  Implement compat32 shims for mqueuefs.
  
  Reviewed by:	jhb
  MFC after:	2 weeks

Modified:
  head/sys/compat/freebsd32/freebsd32.h
  head/sys/compat/freebsd32/syscalls.master
  head/sys/kern/uipc_mqueue.c

Modified: head/sys/compat/freebsd32/freebsd32.h
==============================================================================
--- head/sys/compat/freebsd32/freebsd32.h	Fri Mar 19 11:08:43 2010	(r205324)
+++ head/sys/compat/freebsd32/freebsd32.h	Fri Mar 19 11:10:24 2010	(r205325)
@@ -221,4 +221,12 @@ struct prpsinfo32 {
         char    pr_psargs[PRARGSZ+1];
 };
 
+struct mq_attr32 {
+	int	mq_flags;
+	int	mq_maxmsg;
+	int	mq_msgsize;
+	int	mq_curmsgs;
+	int	__reserved[4];
+};
+
 #endif /* !_COMPAT_FREEBSD32_FREEBSD32_H_ */

Modified: head/sys/compat/freebsd32/syscalls.master
==============================================================================
--- head/sys/compat/freebsd32/syscalls.master	Fri Mar 19 11:08:43 2010	(r205324)
+++ head/sys/compat/freebsd32/syscalls.master	Fri Mar 19 11:10:24 2010	(r205325)
@@ -797,12 +797,23 @@
 				    int param_size); }
 456	AUE_NULL	NOPROTO	{ int sigqueue(pid_t pid, int signum, \
 				    void *value); }
-457	AUE_NULL	UNIMPL	kmq_open
-458	AUE_NULL	UNIMPL	kmq_setattr
-459	AUE_NULL	UNIMPL	kmq_timedreceive
-460	AUE_NULL	UNIMPL  kmq_timedsend
-461	AUE_NULL	UNIMPL	kmq_notify
-462	AUE_NULL	UNIMPL	kmq_unlink
+457	AUE_NULL	NOSTD	{ int freebsd32_kmq_open( \
+				    const char *path, int flags, mode_t mode, \
+				    const struct mq_attr32 *attr); }
+458	AUE_NULL	NOSTD	{ int freebsd32_kmq_setattr(int mqd, \
+				    const struct mq_attr32 *attr,	\
+				    struct mq_attr32 *oattr); }
+459	AUE_NULL	NOSTD	{ int freebsd32_kmq_timedreceive(int mqd, \
+				    char *msg_ptr, size_t msg_len,	\
+				    unsigned *msg_prio,			\
+				    const struct timespec32 *abs_timeout); }
+460	AUE_NULL	NOSTD	{ int freebsd32_kmq_timedsend(int mqd,	\
+				    const char *msg_ptr, size_t msg_len,\
+				    unsigned msg_prio,			\
+				    const struct timespec32 *abs_timeout);}
+461	AUE_NULL	NOPROTO|NOSTD	{ int kmq_notify(int mqd,	\
+				    const struct sigevent *sigev); }
+462	AUE_NULL	NOPROTO|NOSTD	{ int kmq_unlink(const char *path); }
 463	AUE_NULL	NOPROTO	{ int abort2(const char *why, int nargs, void **args); }
 464	AUE_NULL 	NOPROTO	{ int thr_set_name(long id, const char *name); }
 465	AUE_NULL	NOSTD	{ int freebsd32_aio_fsync(int op, \

Modified: head/sys/kern/uipc_mqueue.c
==============================================================================
--- head/sys/kern/uipc_mqueue.c	Fri Mar 19 11:08:43 2010	(r205324)
+++ head/sys/kern/uipc_mqueue.c	Fri Mar 19 11:10:24 2010	(r205325)
@@ -45,6 +45,8 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_compat.h"
+
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/systm.h>
@@ -1622,7 +1624,7 @@ mqueue_send(struct mqueue *mq, const cha
 	const struct timespec *abs_timeout)
 {
 	struct mqueue_msg *msg;
-	struct timespec ets, ts, ts2;
+	struct timespec ts, ts2;
 	struct timeval tv;
 	int error;
 
@@ -1658,15 +1660,12 @@ mqueue_send(struct mqueue *mq, const cha
 	if (error != EAGAIN)
 		goto bad;
 
-	error = copyin(abs_timeout, &ets, sizeof(ets));
-	if (error != 0)
-		goto bad;
-	if (ets.tv_nsec >= 1000000000 || ets.tv_nsec < 0) {
+	if (abs_timeout->tv_nsec >= 1000000000 || abs_timeout->tv_nsec < 0) {
 		error = EINVAL;
 		goto bad;
 	}
 	for (;;) {
-		ts2 = ets;
+		ts2 = *abs_timeout;
 		getnanotime(&ts);
 		timespecsub(&ts2, &ts);
 		if (ts2.tv_sec < 0 || (ts2.tv_sec == 0 && ts2.tv_nsec <= 0)) {
@@ -1773,7 +1772,7 @@ mqueue_receive(struct mqueue *mq, char *
 	const struct timespec *abs_timeout)
 {
 	struct mqueue_msg *msg;
-	struct timespec ets, ts, ts2;
+	struct timespec ts, ts2;
 	struct timeval tv;
 	int error;
 
@@ -1804,16 +1803,13 @@ mqueue_receive(struct mqueue *mq, char *
 	if (error != EAGAIN)
 		return (error);
 
-	error = copyin(abs_timeout, &ets, sizeof(ets));
-	if (error != 0)
-		return (error);
-	if (ets.tv_nsec >= 1000000000 || ets.tv_nsec < 0) {
+	if (abs_timeout->tv_nsec >= 1000000000 || abs_timeout->tv_nsec < 0) {
 		error = EINVAL;
 		return (error);
 	}
 
 	for (;;) {
-		ts2 = ets;
+		ts2 = *abs_timeout;
 		getnanotime(&ts);
 		timespecsub(&ts2, &ts);
 		if (ts2.tv_sec < 0 || (ts2.tv_sec == 0 && ts2.tv_nsec <= 0)) {
@@ -1934,40 +1930,28 @@ notifier_remove(struct proc *p, struct m
 	PROC_UNLOCK(p);
 }
 
-/*
- * Syscall to open a message queue.
- */
-int
-kmq_open(struct thread *td, struct kmq_open_args *uap)
+static int
+kern_kmq_open(struct thread *td, const char *upath, int flags, mode_t mode,
+    const struct mq_attr *attr)
 {
 	char path[MQFS_NAMELEN + 1];
-	struct mq_attr attr, *pattr;
 	struct mqfs_node *pn;
 	struct filedesc *fdp;
 	struct file *fp;
 	struct mqueue *mq;
-	int fd, error, len, flags, cmode;
-
-	if ((uap->flags & O_ACCMODE) == O_ACCMODE)
-		return (EINVAL);
+	int fd, error, len, cmode;
 
 	fdp = td->td_proc->p_fd;
-	flags = FFLAGS(uap->flags);
-	cmode = (((uap->mode & ~fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT);
+	cmode = (((mode & ~fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT);
 	mq = NULL;
-	if ((flags & O_CREAT) && (uap->attr != NULL)) {
-		error = copyin(uap->attr, &attr, sizeof(attr));
-		if (error)
-			return (error);
-		if (attr.mq_maxmsg <= 0 || attr.mq_maxmsg > maxmsg)
+	if ((flags & O_CREAT) != 0 && attr != NULL) {
+		if (attr->mq_maxmsg <= 0 || attr->mq_maxmsg > maxmsg)
 			return (EINVAL);
-		if (attr.mq_msgsize <= 0 || attr.mq_msgsize > maxmsgsize)
+		if (attr->mq_msgsize <= 0 || attr->mq_msgsize > maxmsgsize)
 			return (EINVAL);
-		pattr = &attr;
-	} else
-		pattr = NULL;
+	}
 
-	error = copyinstr(uap->path, path, MQFS_NAMELEN + 1, NULL);
+	error = copyinstr(upath, path, MQFS_NAMELEN + 1, NULL);
         if (error)
 		return (error);
 
@@ -1990,7 +1974,7 @@ kmq_open(struct thread *td, struct kmq_o
 		if (!(flags & O_CREAT)) {
 			error = ENOENT;
 		} else {
-			mq = mqueue_alloc(pattr);
+			mq = mqueue_alloc(attr);
 			if (mq == NULL) {
 				error = ENFILE;
 			} else {
@@ -2045,6 +2029,27 @@ kmq_open(struct thread *td, struct kmq_o
 }
 
 /*
+ * Syscall to open a message queue.
+ */
+int
+kmq_open(struct thread *td, struct kmq_open_args *uap)
+{
+	struct mq_attr attr;
+	int flags, error;
+
+	if ((uap->flags & O_ACCMODE) == O_ACCMODE)
+		return (EINVAL);
+	flags = FFLAGS(uap->flags);
+	if ((flags & O_CREAT) != 0 && uap->attr != NULL) {
+		error = copyin(uap->attr, &attr, sizeof(attr));
+		if (error)
+			return (error);
+	}
+	return (kern_kmq_open(td, uap->path, flags, uap->mode,
+	    uap->attr != NULL ? &attr : NULL));
+}
+
+/*
  * Syscall to unlink a message queue.
  */
 int
@@ -2120,39 +2125,52 @@ getmq_write(struct thread *td, int fd, s
 	return _getmq(td, fd, fget_write, fpp, ppn, pmq);
 }
 
-int
-kmq_setattr(struct thread *td, struct kmq_setattr_args *uap)
+static int
+kern_kmq_setattr(struct thread *td, int mqd, const struct mq_attr *attr,
+    struct mq_attr *oattr)
 {
 	struct mqueue *mq;
 	struct file *fp;
-	struct mq_attr attr, oattr;
 	u_int oflag, flag;
 	int error;
 
-	if (uap->attr) {
-		error = copyin(uap->attr, &attr, sizeof(attr));
-		if (error)
-			return (error);
-		if (attr.mq_flags & ~O_NONBLOCK)
-			return (EINVAL);
-	}
-	error = getmq(td, uap->mqd, &fp, NULL, &mq);
+	if (attr != NULL && (attr->mq_flags & ~O_NONBLOCK) != 0)
+		return (EINVAL);
+	error = getmq(td, mqd, &fp, NULL, &mq);
 	if (error)
 		return (error);
-	oattr.mq_maxmsg  = mq->mq_maxmsg;
-	oattr.mq_msgsize = mq->mq_msgsize;
-	oattr.mq_curmsgs = mq->mq_curmsgs;
-	if (uap->attr) {
+	oattr->mq_maxmsg  = mq->mq_maxmsg;
+	oattr->mq_msgsize = mq->mq_msgsize;
+	oattr->mq_curmsgs = mq->mq_curmsgs;
+	if (attr != NULL) {
 		do {
 			oflag = flag = fp->f_flag;
 			flag &= ~O_NONBLOCK;
-			flag |= (attr.mq_flags & O_NONBLOCK);
+			flag |= (attr->mq_flags & O_NONBLOCK);
 		} while (atomic_cmpset_int(&fp->f_flag, oflag, flag) == 0);
 	} else
 		oflag = fp->f_flag;
-	oattr.mq_flags = (O_NONBLOCK & oflag);
+	oattr->mq_flags = (O_NONBLOCK & oflag);
 	fdrop(fp, td);
-	if (uap->oattr)
+	return (error);
+}
+
+int
+kmq_setattr(struct thread *td, struct kmq_setattr_args *uap)
+{
+	struct mq_attr attr, oattr;
+	int error;
+
+	if (uap->attr != NULL) {
+		error = copyin(uap->attr, &attr, sizeof(attr));
+		if (error != 0)
+			return (error);
+	}
+	error = kern_kmq_setattr(td, uap->mqd, uap->attr != NULL ? &attr : NULL,
+	    &oattr);
+	if (error != 0)
+		return (error);
+	if (uap->oattr != NULL)
 		error = copyout(&oattr, uap->oattr, sizeof(oattr));
 	return (error);
 }
@@ -2162,15 +2180,23 @@ kmq_timedreceive(struct thread *td, stru
 {
 	struct mqueue *mq;
 	struct file *fp;
+	struct timespec *abs_timeout, ets;
 	int error;
 	int waitok;
 
 	error = getmq_read(td, uap->mqd, &fp, NULL, &mq);
 	if (error)
 		return (error);
+	if (uap->abs_timeout != NULL) {
+		error = copyin(uap->abs_timeout, &ets, sizeof(ets));
+		if (error != 0)
+			return (error);
+		abs_timeout = &ets;
+	} else
+		abs_timeout = NULL;
 	waitok = !(fp->f_flag & O_NONBLOCK);
 	error = mqueue_receive(mq, uap->msg_ptr, uap->msg_len,
-		uap->msg_prio, waitok, uap->abs_timeout);
+		uap->msg_prio, waitok, abs_timeout);
 	fdrop(fp, td);
 	return (error);
 }
@@ -2180,14 +2206,22 @@ kmq_timedsend(struct thread *td, struct 
 {
 	struct mqueue *mq;
 	struct file *fp;
+	struct timespec *abs_timeout, ets;
 	int error, waitok;
 
 	error = getmq_write(td, uap->mqd, &fp, NULL, &mq);
 	if (error)
 		return (error);
+	if (uap->abs_timeout != NULL) {
+		error = copyin(uap->abs_timeout, &ets, sizeof(ets));
+		if (error != 0)
+			return (error);
+		abs_timeout = &ets;
+	} else
+		abs_timeout = NULL;
 	waitok = !(fp->f_flag & O_NONBLOCK);
 	error = mqueue_send(mq, uap->msg_ptr, uap->msg_len,
-		uap->msg_prio, waitok, uap->abs_timeout);
+		uap->msg_prio, waitok, abs_timeout);
 	fdrop(fp, td);
 	return (error);
 }
@@ -2511,12 +2545,219 @@ static struct vfsops mqfs_vfsops = {
 	.vfs_statfs		= mqfs_statfs,
 };
 
-SYSCALL_MODULE_HELPER(kmq_open);
-SYSCALL_MODULE_HELPER(kmq_setattr);
-SYSCALL_MODULE_HELPER(kmq_timedsend);
-SYSCALL_MODULE_HELPER(kmq_timedreceive);
-SYSCALL_MODULE_HELPER(kmq_notify);
-SYSCALL_MODULE_HELPER(kmq_unlink);
+static struct vfsconf mqueuefs_vfsconf = {
+	.vfc_version = VFS_VERSION,
+	.vfc_name = "mqueuefs",
+	.vfc_vfsops = &mqfs_vfsops,
+	.vfc_typenum = -1,
+	.vfc_flags = VFCF_SYNTHETIC
+};
+
+static struct syscall_helper_data mq_syscalls[] = {
+	SYSCALL_INIT_HELPER(kmq_open),
+	SYSCALL_INIT_HELPER(kmq_setattr),
+	SYSCALL_INIT_HELPER(kmq_timedsend),
+	SYSCALL_INIT_HELPER(kmq_timedreceive),
+	SYSCALL_INIT_HELPER(kmq_notify),
+	SYSCALL_INIT_HELPER(kmq_unlink),
+	SYSCALL_INIT_LAST
+};
+
+#ifdef COMPAT_FREEBSD32
+#include <compat/freebsd32/freebsd32.h>
+#include <compat/freebsd32/freebsd32_proto.h>
+#include <compat/freebsd32/freebsd32_syscall.h>
+#include <compat/freebsd32/freebsd32_util.h>
+
+static void
+mq_attr_from32(const struct mq_attr32 *from, struct mq_attr *to)
+{
+
+	to->mq_flags = from->mq_flags;
+	to->mq_maxmsg = from->mq_maxmsg;
+	to->mq_msgsize = from->mq_msgsize;
+	to->mq_curmsgs = from->mq_curmsgs;
+}
+
+static void
+mq_attr_to32(const struct mq_attr *from, struct mq_attr32 *to)
+{
+
+	to->mq_flags = from->mq_flags;
+	to->mq_maxmsg = from->mq_maxmsg;
+	to->mq_msgsize = from->mq_msgsize;
+	to->mq_curmsgs = from->mq_curmsgs;
+}
+
+int
+freebsd32_kmq_open(struct thread *td, struct freebsd32_kmq_open_args *uap)
+{
+	struct mq_attr attr;
+	struct mq_attr32 attr32;
+	int flags, error;
+
+	if ((uap->flags & O_ACCMODE) == O_ACCMODE)
+		return (EINVAL);
+	flags = FFLAGS(uap->flags);
+	if ((flags & O_CREAT) != 0 && uap->attr != NULL) {
+		error = copyin(uap->attr, &attr32, sizeof(attr32));
+		if (error)
+			return (error);
+		mq_attr_from32(&attr32, &attr);
+	}
+	return (kern_kmq_open(td, uap->path, flags, uap->mode,
+	    uap->attr != NULL ? &attr : NULL));
+}
+
+int
+freebsd32_kmq_setattr(struct thread *td, struct freebsd32_kmq_setattr_args *uap)
+{
+	struct mq_attr attr, oattr;
+	struct mq_attr32 attr32, oattr32;
+	int error;
+
+	if (uap->attr != NULL) {
+		error = copyin(uap->attr, &attr32, sizeof(attr32));
+		if (error != 0)
+			return (error);
+		mq_attr_from32(&attr32, &attr);
+	}
+	error = kern_kmq_setattr(td, uap->mqd, uap->attr != NULL ? &attr : NULL,
+	    &oattr);
+	if (error != 0)
+		return (error);
+	if (uap->oattr != NULL) {
+		mq_attr_to32(&oattr, &oattr32);
+		error = copyout(&oattr32, uap->oattr, sizeof(oattr32));
+	}
+	return (error);
+}
+
+int
+freebsd32_kmq_timedsend(struct thread *td,
+    struct freebsd32_kmq_timedsend_args *uap)
+{
+	struct mqueue *mq;
+	struct file *fp;
+	struct timespec32 ets32;
+	struct timespec *abs_timeout, ets;
+	int error;
+	int waitok;
+
+	error = getmq_read(td, uap->mqd, &fp, NULL, &mq);
+	if (error)
+		return (error);
+	if (uap->abs_timeout != NULL) {
+		error = copyin(uap->abs_timeout, &ets32, sizeof(ets32));
+		if (error != 0)
+			return (error);
+		CP(ets32, ets, tv_sec);
+		CP(ets32, ets, tv_nsec);
+		abs_timeout = &ets;
+	} else
+		abs_timeout = NULL;
+	waitok = !(fp->f_flag & O_NONBLOCK);
+	error = mqueue_send(mq, uap->msg_ptr, uap->msg_len,
+		uap->msg_prio, waitok, abs_timeout);
+	fdrop(fp, td);
+	return (error);
+}
+
+int
+freebsd32_kmq_timedreceive(struct thread *td,
+    struct freebsd32_kmq_timedreceive_args *uap)
+{
+	struct mqueue *mq;
+	struct file *fp;
+	struct timespec32 ets32;
+	struct timespec *abs_timeout, ets;
+	int error, waitok;
+
+	error = getmq_write(td, uap->mqd, &fp, NULL, &mq);
+	if (error)
+		return (error);
+	if (uap->abs_timeout != NULL) {
+		error = copyin(uap->abs_timeout, &ets32, sizeof(ets32));
+		if (error != 0)
+			return (error);
+		CP(ets32, ets, tv_sec);
+		CP(ets32, ets, tv_nsec);
+		abs_timeout = &ets;
+	} else
+		abs_timeout = NULL;
+	waitok = !(fp->f_flag & O_NONBLOCK);
+	error = mqueue_receive(mq, uap->msg_ptr, uap->msg_len,
+		uap->msg_prio, waitok, abs_timeout);
+	fdrop(fp, td);
+	return (error);
+}
+
+static struct syscall_helper_data mq32_syscalls[] = {
+	SYSCALL32_INIT_HELPER(freebsd32_kmq_open),
+	SYSCALL32_INIT_HELPER(freebsd32_kmq_setattr),
+	SYSCALL32_INIT_HELPER(freebsd32_kmq_timedsend),
+	SYSCALL32_INIT_HELPER(freebsd32_kmq_timedreceive),
+	SYSCALL32_INIT_HELPER(kmq_notify),
+	SYSCALL32_INIT_HELPER(kmq_unlink),
+	SYSCALL_INIT_LAST
+};
+#endif
+
+static int
+mqinit(void)
+{
+	int error;
+
+	error = syscall_helper_register(mq_syscalls);
+	if (error != 0)
+		return (error);
+#ifdef COMPAT_FREEBSD32
+	error = syscall32_helper_register(mq32_syscalls);
+	if (error != 0)
+		return (error);
+#endif
+	return (0);
+}
 
-VFS_SET(mqfs_vfsops, mqueuefs, VFCF_SYNTHETIC);
+static int
+mqunload(void)
+{
+
+#ifdef COMPAT_FREEBSD32
+	syscall32_helper_unregister(mq32_syscalls);
+#endif
+	syscall_helper_unregister(mq_syscalls);
+	return (0);
+}
+
+static int
+mq_modload(struct module *module, int cmd, void *arg)
+{
+	int error = 0;
+
+	error = vfs_modevent(module, cmd, arg);
+	if (error != 0)
+		return (error);
+
+	switch (cmd) {
+	case MOD_LOAD:
+		error = mqinit();
+		if (error != 0)
+			mqunload();
+		break;
+	case MOD_UNLOAD:
+		error = mqunload();
+		break;
+	default:
+		break;
+	}
+	return (error);
+}
+
+static moduledata_t mqueuefs_mod = {
+	"mqueuefs",
+	mq_modload,
+	&mqueuefs_vfsconf
+};
+DECLARE_MODULE(mqueuefs, mqueuefs_mod, SI_SUB_VFS, SI_ORDER_MIDDLE);
 MODULE_VERSION(mqueuefs, 1);


More information about the svn-src-head mailing list