ipc: implement MSG_COPY as a new receive mode
[platform/adaptation/renesas_rcar/renesas_kernel.git] / ipc / msg.c
index fede1d0..7c209b4 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -66,6 +66,7 @@ struct msg_sender {
 #define SEARCH_EQUAL           2
 #define SEARCH_NOTEQUAL                3
 #define SEARCH_LESSEQUAL       4
+#define SEARCH_NUMBER          5
 
 #define msg_ids(ns)    ((ns)->ids[IPC_MSG_IDS])
 
@@ -583,6 +584,7 @@ static int testmsg(struct msg_msg *msg, long type, int mode)
        switch(mode)
        {
                case SEARCH_ANY:
+               case SEARCH_NUMBER:
                        return 1;
                case SEARCH_LESSEQUAL:
                        if (msg->m_type <=type)
@@ -738,6 +740,8 @@ SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
 
 static inline int convert_mode(long *msgtyp, int msgflg)
 {
+       if (msgflg & MSG_COPY)
+               return SEARCH_NUMBER;
        /*
         *  find message of correct type.
         *  msgtyp = 0 => get first.
@@ -774,14 +778,10 @@ static long do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
  * This function creates new kernel message structure, large enough to store
  * bufsz message bytes.
  */
-static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz,
-                                          int msgflg, long *msgtyp,
-                                          unsigned long *copy_number)
+static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz)
 {
        struct msg_msg *copy;
 
-       *copy_number = *msgtyp;
-       *msgtyp = 0;
        /*
         * Create dummy message to copy real message to.
         */
@@ -797,9 +797,7 @@ static inline void free_copy(struct msg_msg *copy)
                free_msg(copy);
 }
 #else
-static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz,
-                                          int msgflg, long *msgtyp,
-                                          unsigned long *copy_number)
+static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz)
 {
        return ERR_PTR(-ENOSYS);
 }
@@ -818,15 +816,13 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
        int mode;
        struct ipc_namespace *ns;
        struct msg_msg *copy = NULL;
-       unsigned long copy_number = 0;
 
        ns = current->nsproxy->ipc_ns;
 
        if (msqid < 0 || (long) bufsz < 0)
                return -EINVAL;
        if (msgflg & MSG_COPY) {
-               copy = prepare_copy(buf, min_t(size_t, bufsz, ns->msg_ctlmax),
-                                   msgflg, &msgtyp, &copy_number);
+               copy = prepare_copy(buf, min_t(size_t, bufsz, ns->msg_ctlmax));
                if (IS_ERR(copy))
                        return PTR_ERR(copy);
        }
@@ -861,17 +857,9 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
                                if (mode == SEARCH_LESSEQUAL &&
                                                walk_msg->m_type != 1) {
                                        msgtyp = walk_msg->m_type - 1;
-                               } else if (msgflg & MSG_COPY) {
-                                       if (copy_number == msg_counter) {
-                                               /*
-                                                * Found requested message.
-                                                * Copy it.
-                                                */
-                                               msg = copy_msg(msg, copy);
-                                               if (IS_ERR(msg))
-                                                       goto out_unlock;
+                               } else if (mode == SEARCH_NUMBER) {
+                                       if (msgtyp == msg_counter)
                                                break;
-                                       }
                                        msg = ERR_PTR(-EAGAIN);
                                } else
                                        break;
@@ -892,8 +880,10 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
                         * If we are copying, then do not unlink message and do
                         * not update queue parameters.
                         */
-                       if (msgflg & MSG_COPY)
+                       if (msgflg & MSG_COPY) {
+                               msg = copy_msg(msg, copy);
                                goto out_unlock;
+                       }
                        list_del(&msg->m_list);
                        msq->q_qnum--;
                        msq->q_rtime = get_seconds();