aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/msgutil.c
diff options
context:
space:
mode:
authorStanislav Kinsbursky <skinsbursky@parallels.com>2013-01-04 18:34:55 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-01-04 19:11:45 -0500
commit4a674f34ba04a002244edaf891b5da7fc1473ae8 (patch)
tree14544a5d49b4a218bac3f5995503c8e208735cef /ipc/msgutil.c
parentf9dd87f4738c7555aca2cdf8cb2b2326cafb0cad (diff)
ipc: introduce message queue copy feature
This patch is required for checkpoint/restore in userspace. c/r requires some way to get all pending IPC messages without deleting them from 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_COPY for sys_msgrcv() system call was introduced. If this flag was specified, then mtype is interpreted as number of the message to copy. If MSG_COPY is set, then kernel will allocate dummy message with passed size, and then use new copy_msg() helper function to copy desired message (instead of unlinking it from the queue). Notes: 1) Return -ENOSYS if MSG_COPY is specified, but CONFIG_CHECKPOINT_RESTORE is not set. Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com> Cc: Serge Hallyn <serge.hallyn@canonical.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Pavel Emelyanov <xemul@parallels.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Michael Kerrisk <mtk.manpages@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc/msgutil.c')
-rw-r--r--ipc/msgutil.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/ipc/msgutil.c b/ipc/msgutil.c
index 6471f1bdae96..7eecdad40efc 100644
--- a/ipc/msgutil.c
+++ b/ipc/msgutil.c
@@ -102,7 +102,45 @@ out_err:
102 free_msg(msg); 102 free_msg(msg);
103 return ERR_PTR(err); 103 return ERR_PTR(err);
104} 104}
105#ifdef CONFIG_CHECKPOINT_RESTORE
106struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
107{
108 struct msg_msgseg *dst_pseg, *src_pseg;
109 int len = src->m_ts;
110 int alen;
111
112 BUG_ON(dst == NULL);
113 if (src->m_ts > dst->m_ts)
114 return ERR_PTR(-EINVAL);
115
116 alen = len;
117 if (alen > DATALEN_MSG)
118 alen = DATALEN_MSG;
119
120 dst->next = NULL;
121 dst->security = NULL;
105 122
123 memcpy(dst + 1, src + 1, alen);
124
125 len -= alen;
126 dst_pseg = dst->next;
127 src_pseg = src->next;
128 while (len > 0) {
129 alen = len;
130 if (alen > DATALEN_SEG)
131 alen = DATALEN_SEG;
132 memcpy(dst_pseg + 1, src_pseg + 1, alen);
133 dst_pseg = dst_pseg->next;
134 len -= alen;
135 src_pseg = src_pseg->next;
136 }
137
138 dst->m_type = src->m_type;
139 dst->m_ts = src->m_ts;
140
141 return dst;
142}
143#endif
106int store_msg(void __user *dest, struct msg_msg *msg, int len) 144int store_msg(void __user *dest, struct msg_msg *msg, int len)
107{ 145{
108 int alen; 146 int alen;