[CRIU] [PATCH 3/4] IPC: restore namespace itself

Kinsbursky Stanislav skinsbursky at openvz.org
Mon Jan 30 12:19:13 EST 2012


From: Stanislav Kinsbursky <skinsbursky at parallels.com>



Signed-off-by: Stanislav Kinsbursky <skinsbursky at parallels.com>

---
 Documentation/crtools.txt |    2 -
 crtools.c                 |    2 -
 ipc_ns.c                  |  136 +++++++++++++++++++++++++++++++++++++++++++++
 namespaces.c              |    2 +
 4 files changed, 140 insertions(+), 2 deletions(-)

diff --git a/Documentation/crtools.txt b/Documentation/crtools.txt
index c7b028d..c1f6bcc 100644
--- a/Documentation/crtools.txt
+++ b/Documentation/crtools.txt
@@ -49,7 +49,7 @@ OPTIONS
 
 -n <ns>::
     Checkpoint namespaces. Namespaces must be separated by comma.
-    Currently supported namespaces: uts.
+    Currently supported namespaces: uts, ipc.
 
 -o <file>::
     Write logging messages to 'file'.
diff --git a/crtools.c b/crtools.c
index baeabed..c1d0d19 100644
--- a/crtools.c
+++ b/crtools.c
@@ -385,7 +385,7 @@ usage:
 	       "                 show contents of pages dumped in hexdump format\n");
 	printk("  -d             detach after restore\n");
 	printk("  -n             checkpoint/restore namespaces - values must be separated by comma\n");
-	printk("                 supported: uts\n");
+	printk("                 supported: uts, ipc\n");
 
 	printk("\nAdditional common parameters:\n");
 	printk("  -D dir         save checkpoint files in specified directory\n");
diff --git a/ipc_ns.c b/ipc_ns.c
index 434501c..37db899 100644
--- a/ipc_ns.c
+++ b/ipc_ns.c
@@ -310,3 +310,139 @@ void show_ipc_ns(int fd)
 	show_ipc_data(fd);
 	pr_img_tail(CR_FD_IPCNS);
 }
+
+static int write_ipc_sysctl(char *name, void *data, size_t size)
+{
+	int fd;
+	int ret;
+	char buf[32];
+
+	fd = open(name, O_WRONLY);
+	if (fd < 0) {
+		pr_err("Can't open %d\n", name);
+		return fd;
+	}
+	if (size > sizeof(int))
+		sprintf(buf, "%ld\n", *(long *)data);
+	else
+		sprintf(buf, "%d\n", *(int *)data);
+
+	ret = write(fd, buf, 32);
+	if (ret < 0) {
+		pr_err("Can't write %s\n", name);
+		ret = -errno;
+	}
+	close(fd);
+	return ret;
+}
+
+static int write_ipc_sem(u32 sem[])
+{
+	int fd;
+	int ret;
+	char buf[128];
+	char *name = "/proc/sys/kernel/sem";
+
+	fd = open(name, O_WRONLY);
+	if (fd < 0) {
+		pr_err("Can't open %d\n", name);
+		return fd;
+	}
+	sprintf(buf, "%d %d %d %d\n", sem[0], sem[1], sem[2], sem[3]);
+	ret = write(fd, buf, 128);
+	if (ret < 0) {
+		pr_err("Can't write %s: %d\n", name, errno);
+		ret = -errno;
+	}
+	close(fd);
+	return ret;
+}
+
+static int prepare_ipc_tun(struct ipc_ns_entry *entry)
+{
+	int ret;
+
+	ret = write_ipc_sem(entry->sem_ctls);
+	if (ret < 0)
+		goto err;
+	ret = write_ipc_sysctl("/proc/sys/kernel/msgmax",
+			  &entry->msg_ctlmax, sizeof(entry->msg_ctlmax));
+	if (ret < 0)
+		goto err;
+	ret = write_ipc_sysctl("/proc/sys/kernel/msgmnb",
+			  &entry->msg_ctlmnb, sizeof(entry->msg_ctlmnb));
+	if (ret < 0)
+		goto err;
+	ret = write_ipc_sysctl("/proc/sys/kernel/msgmni",
+			  &entry->msg_ctlmni, sizeof(entry->msg_ctlmni));
+	if (ret < 0)
+		goto err;
+	ret = write_ipc_sysctl("/proc/sys/kernel/auto_msgmni",
+			  &entry->auto_msgmni, sizeof(entry->auto_msgmni));
+	if (ret < 0)
+		goto err;
+	ret = write_ipc_sysctl("/proc/sys/kernel/shmmax",
+			  &entry->shm_ctlmax, sizeof(entry->shm_ctlmax));
+	if (ret < 0)
+		goto err;
+	ret = write_ipc_sysctl("/proc/sys/kernel/shmall",
+			  &entry->shm_ctlall, sizeof(entry->shm_ctlall));
+	if (ret < 0)
+		goto err;
+	ret = write_ipc_sysctl("/proc/sys/kernel/shmmni",
+			  &entry->shm_ctlmni, sizeof(entry->shm_ctlmni));
+	if (ret < 0)
+		goto err;
+	ret = write_ipc_sysctl("/proc/sys/kernel/shm_rmid_forced",
+			  &entry->shm_rmid_forced, sizeof(entry->shm_rmid_forced));
+	if (ret < 0)
+		goto err;
+
+
+	ret = write_ipc_sysctl("/proc/sys/fs/mqueue/queues_max",
+			  &entry->mq_queues_max, sizeof(entry->mq_queues_max));
+	if (ret < 0)
+		goto err;
+	ret = write_ipc_sysctl("/proc/sys/fs/mqueue/msg_max",
+			  &entry->mq_msg_max, sizeof(entry->mq_msg_max));
+	if (ret < 0)
+		goto err;
+	ret = write_ipc_sysctl("/proc/sys/fs/mqueue/msgsize_max",
+			  &entry->mq_msgsize_max, sizeof(entry->mq_msgsize_max));
+	if (ret < 0)
+		goto err;
+
+	return 0;
+err:
+	pr_err("Failed to restore ipc namespace tunables\n");
+	return ret;
+}
+
+static int prepare_ipc_data(int fd)
+{
+	int ret;
+	struct ipc_ns_data ipc;
+
+	ret = read_img(fd, &ipc);
+	if (ret <= 0)
+		return -EFAULT;
+	ret = prepare_ipc_tun(&ipc.entry);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+int prepare_ipc_ns(int pid)
+{
+	int fd, ret;
+
+	fd = open_image_ro(CR_FD_IPCNS, pid);
+	if (fd < 0)
+		return -1;
+
+	ret = prepare_ipc_data(fd);
+
+	close(fd);
+	return ret;
+}
+
diff --git a/namespaces.c b/namespaces.c
index ea0f6d1..4b65b3d 100644
--- a/namespaces.c
+++ b/namespaces.c
@@ -104,6 +104,8 @@ int prepare_namespace(int pid, unsigned long clone_flags)
 
 	if (clone_flags & CLONE_NEWUTS)
 		ret = prepare_utsns(pid);
+	if (clone_flags & CLONE_NEWIPC)
+		ret = prepare_ipc_ns(pid);
 
 	return ret;
 }



More information about the CRIU mailing list