MFC r205325:

Implement compat32 shims for mqueuefs.
This commit is contained in:
Konstantin Belousov 2010-04-07 14:49:35 +00:00
parent 0aab10e1a8
commit 048575ee75
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/stable/8/; revision=206351
3 changed files with 328 additions and 68 deletions

View File

@ -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_ */

View File

@ -798,12 +798,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, \

View File

@ -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>
@ -1616,7 +1618,7 @@ mqueue_send(struct mqueue *mq, const char *msg_ptr,
const struct timespec *abs_timeout)
{
struct mqueue_msg *msg;
struct timespec ets, ts, ts2;
struct timespec ts, ts2;
struct timeval tv;
int error;
@ -1652,15 +1654,12 @@ mqueue_send(struct mqueue *mq, const char *msg_ptr,
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)) {
@ -1767,7 +1766,7 @@ mqueue_receive(struct mqueue *mq, char *msg_ptr,
const struct timespec *abs_timeout)
{
struct mqueue_msg *msg;
struct timespec ets, ts, ts2;
struct timespec ts, ts2;
struct timeval tv;
int error;
@ -1798,16 +1797,13 @@ mqueue_receive(struct mqueue *mq, char *msg_ptr,
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)) {
@ -1928,40 +1924,28 @@ notifier_remove(struct proc *p, struct mqueue *mq, int fd)
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);
@ -1984,7 +1968,7 @@ kmq_open(struct thread *td, struct kmq_open_args *uap)
if (!(flags & O_CREAT)) {
error = ENOENT;
} else {
mq = mqueue_alloc(pattr);
mq = mqueue_alloc(attr);
if (mq == NULL) {
error = ENFILE;
} else {
@ -2038,6 +2022,27 @@ kmq_open(struct thread *td, struct kmq_open_args *uap)
return (0);
}
/*
* 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.
*/
@ -2114,39 +2119,52 @@ getmq_write(struct thread *td, int fd, struct file **fpp,
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);
}
@ -2156,15 +2174,23 @@ kmq_timedreceive(struct thread *td, struct kmq_timedreceive_args *uap)
{
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);
}
@ -2174,14 +2200,22 @@ kmq_timedsend(struct thread *td, struct kmq_timedsend_args *uap)
{
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);
}
@ -2505,12 +2539,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
};
VFS_SET(mqfs_vfsops, mqueuefs, 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);
}
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);