[CRIU] Re: [PATCH RFC] IPC: message queue stealing feature
introduced
Pavel Emelyanov
xemul at parallels.com
Mon Feb 13 02:58:16 EST 2012
On 02/10/2012 09:33 PM, Stanislav Kinsbursky wrote:
> This patch is required for checkpoint/restart ins userspace.
> IOW, c/r reuqires some way to get IPC messages without deleting them for the
> queue (checkpoint can fail and in this case tasks will be resumed, so queue
> have to be valid).
> To achive this, new operation flag MSG_STEAL for sys_msgrcv() system call
> introduced.
> If this flag is set, then passed struct msgbuf pointer will be used for storing
> array of structures:
>
> struct msgbuf_a {
> long mtype; /* type of message */
> size_t msize; /* size of message */
> char mtext[0]; /* message text */
> };
>
> where each of them is followed by respective message array.
>
> Signed-off-by: Stanislav Kinsbursky <skinsbursky at parallels.com>
Ack. Cyrill, plz, put to our tree.
> ---
> include/linux/msg.h | 8 ++++++++
> ipc/msg.c | 43 ++++++++++++++++++++++++++++++++++++++-----
> 2 files changed, 46 insertions(+), 5 deletions(-)
>
> diff --git a/include/linux/msg.h b/include/linux/msg.h
> index 6689e73..2bace1a 100644
> --- a/include/linux/msg.h
> +++ b/include/linux/msg.h
> @@ -11,6 +11,7 @@
> /* msgrcv options */
> #define MSG_NOERROR 010000 /* no error if message is too big */
> #define MSG_EXCEPT 020000 /* recv any msg except of specified type.*/
> +#define MSG_STEAL 040000 /* copy (not remove) all queue messages */
>
> /* Obsolete, used only for backwards compatibility and libc5 compiles */
> struct msqid_ds {
> @@ -38,6 +39,13 @@ struct msgbuf {
> char mtext[1]; /* message text */
> };
>
> +/* message buffer for msgrcv in case of array calls */
> +struct msgbuf_a {
> + long mtype; /* type of message */
> + size_t msize; /* size of message */
> + char mtext[0]; /* message text */
> +};
> +
> /* buffer for msgctl calls IPC_INFO, MSG_INFO */
> struct msginfo {
> int msgpool;
> diff --git a/ipc/msg.c b/ipc/msg.c
> index 303362b..d024cdc 100644
> --- a/ipc/msg.c
> +++ b/ipc/msg.c
> @@ -762,6 +762,23 @@ static inline int convert_mode(long *msgtyp, int msgflg)
> return SEARCH_EQUAL;
> }
>
> +static int do_store_msg(void __user *mtext, size_t msgsz, struct msg_msg *msg)
> +{
> + msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz;
> + if (store_msg(mtext, msg, msgsz))
> + return -EFAULT;
> + return msgsz;
> +}
> +
> +static int do_steal_msg(struct msgbuf_a __user *msgp, size_t msgsz, struct msg_msg *msg)
> +{
> + if (put_user(msg->m_type, &msgp->mtype))
> + return -EFAULT;
> + if (put_user(msg->m_ts, &msgp->msize))
> + return -EFAULT;
> + return do_store_msg(msgp->mtext, msgsz, msg);
> +}
> +
> long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
> size_t msgsz, long msgtyp, int msgflg)
> {
> @@ -769,6 +786,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
> struct msg_msg *msg;
> int mode;
> struct ipc_namespace *ns;
> + size_t arrsz = msgsz;
>
> if (msqid < 0 || (long) msgsz < 0)
> return -EINVAL;
> @@ -802,6 +820,16 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
> walk_msg->m_type != 1) {
> msg = walk_msg;
> msgtyp = walk_msg->m_type - 1;
> + } else if (msgflg & MSG_STEAL) {
> + int ret;
> +
> + ret = do_steal_msg(mtext, arrsz, msg);
> + if (ret < 0) {
> + msg = ERR_PTR(ret);
> + goto out_unlock;
> + }
> + mtext += ret + sizeof(struct msgbuf_a);
> + arrsz -= ret + sizeof(struct msgbuf_a);
> } else {
> msg = walk_msg;
> break;
> @@ -810,6 +838,8 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
> tmp = tmp->next;
> }
> if (!IS_ERR(msg)) {
> + if (msgflg & MSG_STEAL)
> + goto out_unlock;
> /*
> * Found a suitable message.
> * Unlink it from the queue.
> @@ -904,10 +934,11 @@ out_unlock:
> if (IS_ERR(msg))
> return PTR_ERR(msg);
>
> - msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz;
> + if (msgflg & MSG_STEAL)
> + return msgsz;
> +
> *pmtype = msg->m_type;
> - if (store_msg(mtext, msg, msgsz))
> - msgsz = -EFAULT;
> + msgsz = do_store_msg(mtext, msgsz, msg);
>
> free_msg(msg);
>
> @@ -919,8 +950,10 @@ SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
> {
> long err, mtype;
>
> - err = do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg);
> - if (err < 0)
> + err = do_msgrcv(msqid, &mtype,
> + (msgflg & MSG_STEAL) ? (void *)msgp : msgp->mtext,
> + msgsz, msgtyp, msgflg);
> + if (err < 0 || msgflg & MSG_STEAL)
> goto out;
>
> if (put_user(mtype, &msgp->mtype))
>
More information about the CRIU
mailing list