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

Kinsbursky Stanislav skinsbursky at openvz.org
Tue Jan 31 06:53:36 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                  |  151 +++++++++++++++++++++++++++++++++++++++++++++
 namespaces.c              |    2 +
 4 files changed, 155 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 ad71441..3b57cce 100644
--- a/crtools.c
+++ b/crtools.c
@@ -383,7 +383,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 e20a01a..5e3b30d 100644
--- a/ipc_ns.c
+++ b/ipc_ns.c
@@ -310,3 +310,154 @@ void show_ipc_ns(int fd)
 	show_ipc_data(fd);
 	pr_img_tail(CR_FD_IPCNS);
 }
+
+#ifdef CONFIG_X86_64
+static int write_ipc_sysctl_long(char *name, u64 *data)
+{
+	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;
+	}
+	sprintf(buf, "%ld\n", *(long *)data);
+	ret = write(fd, buf, 32);
+	if (ret < 0) {
+		pr_err("Can't write %s\n", name);
+		ret = -errno;
+	}
+	close(fd);
+	return ret;
+}
+#endif
+
+static int write_ipc_sysctl(char *name, u32 *data)
+{
+	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;
+	}
+	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);
+	if (ret < 0)
+		goto err;
+	ret = write_ipc_sysctl("/proc/sys/kernel/msgmnb", &entry->msg_ctlmnb);
+	if (ret < 0)
+		goto err;
+	ret = write_ipc_sysctl("/proc/sys/kernel/msgmni", &entry->msg_ctlmni);
+	if (ret < 0)
+		goto err;
+	ret = write_ipc_sysctl("/proc/sys/kernel/auto_msgmni", &entry->auto_msgmni);
+	if (ret < 0)
+		goto err;
+#ifdef CONFIG_X86_64
+	ret = write_ipc_sysctl_long("/proc/sys/kernel/shmmax", (u64 *)entry->shm_ctlmax);
+	if (ret < 0)
+		goto err;
+	ret = write_ipc_sysctl_long("/proc/sys/kernel/shmall", (u64 *)entry->shm_ctlall);
+#else
+	ret = write_ipc_sysctl("/proc/sys/kernel/shmmax", entry->shm_ctlmax);
+	if (ret < 0)
+		goto err;
+	ret = write_ipc_sysctl("/proc/sys/kernel/shmall", entry->shm_ctlall);
+#endif
+	if (ret < 0)
+		goto err;
+	ret = write_ipc_sysctl("/proc/sys/kernel/shmmni", &entry->shm_ctlmni);
+	if (ret < 0)
+		goto err;
+	ret = write_ipc_sysctl("/proc/sys/kernel/shm_rmid_forced", &entry->shm_rmid_forced);
+	if (ret < 0)
+		goto err;
+
+
+	ret = write_ipc_sysctl("/proc/sys/fs/mqueue/queues_max", &entry->mq_queues_max);
+	if (ret < 0)
+		goto err;
+	ret = write_ipc_sysctl("/proc/sys/fs/mqueue/msg_max", &entry->mq_msg_max);
+	if (ret < 0)
+		goto err;
+	ret = write_ipc_sysctl("/proc/sys/fs/mqueue/msgsize_max", &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