Messages in this thread Patch in this message |  | | | Subject | [PATCH 1/2] IPC: message queue receive cleanup | | From | Stanislav Kinsbursky <> | | Date | Wed, 15 Feb 2012 20:54:31 +0400 |
| |
This patch moves all message related manipulation into one function msg_fill(). Actually, two functions because of the compat one.
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
--- arch/tile/kernel/compat.c | 11 +---------- include/linux/compat.h | 2 ++ include/linux/msg.h | 5 +++-- ipc/compat.c | 33 +++++++++++++++++---------------- ipc/msg.c | 44 +++++++++++++++++++++++--------------------- 5 files changed, 46 insertions(+), 49 deletions(-) diff --git a/arch/tile/kernel/compat.c b/arch/tile/kernel/compat.c index bf5e9d7..d963b45 100644 --- a/arch/tile/kernel/compat.c +++ b/arch/tile/kernel/compat.c @@ -121,16 +121,7 @@ long tile_compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp, size_t msgsz, long msgtyp, int msgflg) { - long err, mtype; - - err = do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg); - if (err < 0) - goto out; - - if (put_user(mtype, &msgp->mtype)) - err = -EFAULT; - out: - return err; + return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, compat_do_msg_fill); } /* Provide the compat syscall number to call mapping. */ diff --git a/include/linux/compat.h b/include/linux/compat.h index 41c9f65..7389209 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -224,6 +224,7 @@ struct compat_sysinfo; struct compat_sysctl_args; struct compat_kexec_segment; struct compat_mq_attr; +struct msg_msg; extern void compat_exit_robust_list(struct task_struct *curr); @@ -236,6 +237,7 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr, long compat_sys_semctl(int first, int second, int third, void __user *uptr); long compat_sys_msgsnd(int first, int second, int third, void __user *uptr); +long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz); long compat_sys_msgrcv(int first, int second, int msgtyp, int third, int version, void __user *uptr); long compat_sys_msgctl(int first, int second, void __user *uptr); diff --git a/include/linux/msg.h b/include/linux/msg.h index 6689e73..9411b76 100644 --- a/include/linux/msg.h +++ b/include/linux/msg.h @@ -105,8 +105,9 @@ struct msg_queue { /* Helper routines for sys_msgsnd and sys_msgrcv */ extern long do_msgsnd(int msqid, long mtype, void __user *mtext, size_t msgsz, int msgflg); -extern long do_msgrcv(int msqid, long *pmtype, void __user *mtext, - size_t msgsz, long msgtyp, int msgflg); +extern long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, + int msgflg, + long (*msg_fill)(void __user *, struct msg_msg *, size_t )); #endif /* __KERNEL__ */ diff --git a/ipc/compat.c b/ipc/compat.c index b828244..38c1ee5 100644 --- a/ipc/compat.c +++ b/ipc/compat.c @@ -328,13 +328,23 @@ long compat_sys_msgsnd(int first, int second, int third, void __user *uptr) return do_msgsnd(first, type, up->mtext, second, third); } +long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz) +{ + struct compat_msgbuf __user *msgp; + size_t msgsz; + + if (put_user(msg->m_type, &msgp->mtype)) + return -EFAULT; + + msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz; + if (store_msg(msgp->mtext, msg, msgsz)) + return -EFAULT; + return msgsz; +} + long compat_sys_msgrcv(int first, int second, int msgtyp, int third, int version, void __user *uptr) { - struct compat_msgbuf __user *up; - long type; - int err; - if (first < 0) return -EINVAL; if (second < 0) @@ -342,23 +352,14 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third, if (!version) { struct compat_ipc_kludge ipck; - err = -EINVAL; if (!uptr) - goto out; - err = -EFAULT; + return -EINVAL; if (copy_from_user (&ipck, uptr, sizeof(ipck))) - goto out; + return -EFAULT; uptr = compat_ptr(ipck.msgp); msgtyp = ipck.msgtyp; } - up = uptr; - err = do_msgrcv(first, &type, up->mtext, second, msgtyp, third); - if (err < 0) - goto out; - if (put_user(type, &up->mtype)) - err = -EFAULT; -out: - return err; + return do_msgrcv(first, uptr, second, msgtyp, third, compat_do_msg_fill); } static inline int get_compat_msqid64(struct msqid64_ds *m64, diff --git a/ipc/msg.c b/ipc/msg.c index 303362b..1d34c11 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -762,15 +762,30 @@ static inline int convert_mode(long *msgtyp, int msgflg) return SEARCH_EQUAL; } -long do_msgrcv(int msqid, long *pmtype, void __user *mtext, - size_t msgsz, long msgtyp, int msgflg) +static long do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz) +{ + struct msgbuf __user *msgp = dest; + size_t msgsz; + + if (put_user(msg->m_type, &msgp->mtype)) + return -EFAULT; + + msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz; + if (store_msg(msgp->mtext, msg, msgsz)) + return -EFAULT; + return msgsz; +} + +long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, + int msgflg, + long (*msg_fill)(void __user *, struct msg_msg *, size_t )) { struct msg_queue *msq; struct msg_msg *msg; int mode; struct ipc_namespace *ns; - if (msqid < 0 || (long) msgsz < 0) + if (msqid < 0 || (long) bufsz < 0) return -EINVAL; mode = convert_mode(&msgtyp, msgflg); ns = current->nsproxy->ipc_ns; @@ -814,7 +829,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext, * Found a suitable message. * Unlink it from the queue. */ - if ((msgsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) { + if ((bufsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) { msg = ERR_PTR(-E2BIG); goto out_unlock; } @@ -841,7 +856,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext, if (msgflg & MSG_NOERROR) msr_d.r_maxsize = INT_MAX; else - msr_d.r_maxsize = msgsz; + msr_d.r_maxsize = bufsz; msr_d.r_msg = ERR_PTR(-EAGAIN); current->state = TASK_INTERRUPTIBLE; msg_unlock(msq); @@ -904,29 +919,16 @@ out_unlock: if (IS_ERR(msg)) return PTR_ERR(msg); - msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz; - *pmtype = msg->m_type; - if (store_msg(mtext, msg, msgsz)) - msgsz = -EFAULT; - + bufsz = msg_fill(buf, msg, bufsz); free_msg(msg); - return msgsz; + return bufsz; } SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, long, msgtyp, int, msgflg) { - long err, mtype; - - err = do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg); - if (err < 0) - goto out; - - if (put_user(mtype, &msgp->mtype)) - err = -EFAULT; -out: - return err; + return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill); } #ifdef CONFIG_PROC_FS
|  |