[CRIU] [crtools-bot] Add sysctl handling engine

Cyrill Gorcunov gorcunov at openvz.org
Thu Feb 2 12:22:20 EST 2012


The commit is pushed to "master" and will appear on git://github.com/cyrillos/crtools.git
------>
commit 405985e9647c025d7ab7fee38d9647da80ad0e93
Author: Cyrill Gorcunov <gorcunov at openvz.org>
Date:   Thu Feb 2 19:55:48 2012 +0400

    Add sysctl handling engine
    
    Since we need to operate with sysctls pretty heavy,
    better to add some common engine for all handlers.
    
    Based-on-patch-from: Pavel Emelyanov <xemul at parallels.com>
    Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
    Acked-by: Pavel Emelyanov <xemul at parallels.com>
---
 Makefile         |    1 +
 include/image.h  |    4 +-
 include/sysctl.h |   33 ++++++
 ipc_ns.c         |  303 +++++-------------------------------------------------
 sysctl.c         |  216 ++++++++++++++++++++++++++++++++++++++
 uts_ns.c         |   66 ++++++-------
 6 files changed, 310 insertions(+), 313 deletions(-)

diff --git a/Makefile b/Makefile
index 2c552fc..113012c 100644
--- a/Makefile
+++ b/Makefile
@@ -34,6 +34,7 @@ OBJS		+= cr-dump.o
 OBJS		+= cr-show.o
 OBJS		+= util.o
 OBJS		+= util-net.o
+OBJS		+= sysctl.o
 OBJS		+= ptrace.o
 OBJS		+= log.o
 OBJS		+= libnetlink.o
diff --git a/include/image.h b/include/image.h
index 59e91a6..8e6a000 100644
--- a/include/image.h
+++ b/include/image.h
@@ -111,8 +111,8 @@ struct ipc_ns_entry {
 	u32	msg_ctlmnb;
 	u32	msg_ctlmni;
 	u32	auto_msgmni;
-	u32	shm_ctlmax[2];
-	u64	shm_ctlall[2];
+	u64	shm_ctlmax;
+	u64	shm_ctlall;
 	u32	shm_ctlmni;
 	u32	shm_rmid_forced;
 	u32	mq_queues_max;
diff --git a/include/sysctl.h b/include/sysctl.h
new file mode 100644
index 0000000..0d67b21
--- /dev/null
+++ b/include/sysctl.h
@@ -0,0 +1,33 @@
+#ifndef CR_SYSCTL_H_
+#define CR_SYSCTL_H_
+
+struct sysctl_req {
+	char	*name;
+	void	*arg;
+	int	type;
+};
+
+extern int sysctl_op(struct sysctl_req *req, int op);
+
+enum {
+	CTL_READ,
+	CTL_WRITE,
+	CTL_PRINT,
+};
+
+#define CTL_SHIFT	4	/* Up to 16 types */
+
+#define CTL_U32		1	/* Single u32 */
+#define CTL_U64		2	/* Single u64 */
+#define __CTL_U32A	3	/* Array of u32 */
+#define __CTL_U64A	4	/* Array of u64 */
+#define __CTL_STR	5	/* String */
+
+#define CTL_U32A(n)	(__CTL_U32A | ((n)   << CTL_SHIFT))
+#define CTL_U64A(n)	(__CTL_U64A | ((n)   << CTL_SHIFT))
+#define CTL_STR(len)	(__CTL_STR  | ((len) << CTL_SHIFT))
+
+#define CTL_LEN(t)	((t) >> CTL_SHIFT)
+#define CTL_TYPE(t)	((t) & ((1 << CTL_SHIFT) - 1))
+
+#endif /* CR_SYSCTL_H_ */
diff --git a/ipc_ns.c b/ipc_ns.c
index 88c6b06..a54d6ec 100644
--- a/ipc_ns.c
+++ b/ipc_ns.c
@@ -6,10 +6,12 @@
 #include <sys/msg.h>
 #include <sys/sem.h>
 #include <sys/shm.h>
+
 #include "util.h"
 #include "crtools.h"
 #include "syscall.h"
 #include "namespaces.h"
+#include "sysctl.h"
 
 struct ipc_ns_data {
 	struct ipc_ns_entry entry;
@@ -19,6 +21,27 @@ struct ipc_ns_data {
 #define IPC_MSG_IDS		1
 #define IPC_SHM_IDS		2
 
+static int ipc_sysctl_req(struct ipc_ns_entry *e, int op)
+{
+	struct sysctl_req req[] = {
+		{ "kernel/sem",			e->sem_ctls,		CTL_U32A(4) },
+		{ "kernel/msgmax",		&e->msg_ctlmax,		CTL_U32 },
+		{ "kernel/msgmnb",		&e->msg_ctlmnb,		CTL_U32 },
+		{ "kernel/msgmni",		&e->msg_ctlmni,		CTL_U32 },
+		{ "kernel/auto_msgmni",		&e->auto_msgmni,	CTL_U32 },
+		{ "kernel/shmmax",		&e->shm_ctlmax,		CTL_U64 },
+		{ "kernel/shmall",		&e->shm_ctlall,		CTL_U64 },
+		{ "kernel/shmmni",		&e->shm_ctlmni,		CTL_U32 },
+		{ "kernel/shm_rmid_forced",	&e->shm_rmid_forced,	CTL_U32 },
+		{ "fs/mqueue/queues_max",	&e->mq_queues_max,	CTL_U32 },
+		{ "fs/mqueue/msg_max",		&e->mq_msg_max,		CTL_U32 },
+		{ "fs/mqueue/msgsize_max",	&e->mq_msgsize_max,	CTL_U32 },
+		{ },
+	};
+
+	return sysctl_op(req, op);
+}
+
 static int collect_ipc_msg(void *data)
 {
 	struct msginfo info;
@@ -74,149 +97,9 @@ static int collect_ipc_shm(void *data)
 	return 0;
 }
 
-#ifdef CONFIG_X86_64
-static int read_ipc_sysctl_long(char *name, u64 *data, size_t size)
-{
-	int fd;
-	int ret;
-	char buf[32];
-
-	fd = open(name, O_RDONLY);
-	if (fd < 0) {
-		pr_perror("Can't open %s", name);
-		return fd;
-	}
-	ret = read(fd, buf, sizeof(buf));
-	if (ret < 0) {
-		pr_perror("Can't read %s", name);
-		ret = -errno;
-		goto err;
-	}
-	*data = strtoull(buf, NULL, 10);
-err:
-	close(fd);
-	return ret;
-}
-#endif
-
-static int read_ipc_sysctl(char *name, u32 *data, size_t size)
-{
-	int fd;
-	int ret;
-	char buf[32];
-
-	fd = open(name, O_RDONLY);
-	if (fd < 0) {
-		pr_perror("Can't open %s", name);
-		return fd;
-	}
-	ret = read(fd, buf, sizeof(buf));
-	if (ret < 0) {
-		pr_perror("Can't read %s", name);
-		ret = -errno;
-		goto err;
-	}
-	*data = (u32)strtoul(buf, NULL, 10);
-err:
-	close(fd);
-	return ret;
-}
-
-static int read_ipc_sem(u32 sem[])
+static int collect_ipc_tun(struct ipc_ns_entry *e)
 {
-	int fd;
-	int ret;
-	char buf[128], *ptr = buf;
-	char *name = "/proc/sys/kernel/sem";
-	int i;
-
-	fd = open(name, O_RDONLY);
-	if (fd < 0) {
-		pr_perror("Can't open %s", name);
-		return fd;
-	}
-	ret = read(fd, buf, sizeof(buf));
-	if (ret < 0) {
-		pr_perror("Can't read %s", name);
-		ret = -errno;
-		goto err;
-	}
-	sem[0] = (u32)strtoul(ptr, &ptr, 10); ptr++;
-	sem[1] = (u32)strtoul(ptr, &ptr, 10); ptr++;
-	sem[2] = (u32)strtoul(ptr, &ptr, 10); ptr++;
-	sem[3] = (u32)strtoul(ptr, &ptr, 10); ptr++;
-err:
-	close(fd);
-	return ret;
-}
-
-static int collect_ipc_tun(struct ipc_ns_entry *entry)
-{
-	int ret;
-
-	ret = read_ipc_sem(entry->sem_ctls);
-	if (ret < 0)
-		goto err;
-	ret = read_ipc_sysctl("/proc/sys/kernel/msgmax",
-			  &entry->msg_ctlmax, sizeof(entry->msg_ctlmax));
-	if (ret < 0)
-		goto err;
-	ret = read_ipc_sysctl("/proc/sys/kernel/msgmnb",
-			  &entry->msg_ctlmnb, sizeof(entry->msg_ctlmnb));
-	if (ret < 0)
-		goto err;
-	ret = read_ipc_sysctl("/proc/sys/kernel/msgmni",
-			  &entry->msg_ctlmni, sizeof(entry->msg_ctlmni));
-	if (ret < 0)
-		goto err;
-	ret = read_ipc_sysctl("/proc/sys/kernel/auto_msgmni",
-			  &entry->auto_msgmni, sizeof(entry->auto_msgmni));
-	if (ret < 0)
-		goto err;
-#ifdef CONFIG_X86_64
-	ret = read_ipc_sysctl_long("/proc/sys/kernel/shmmax",
-			  (u64 *)entry->shm_ctlmax, sizeof(entry->shm_ctlmax));
-	if (ret < 0)
-		goto err;
-	ret = read_ipc_sysctl_long("/proc/sys/kernel/shmall",
-			  (u64 *)entry->shm_ctlall, sizeof(entry->shm_ctlall));
-#else
-	ret = read_ipc_sysctl("/proc/sys/kernel/shmmax",
-			  entry->shm_ctlmax, sizeof(entry->shm_ctlmax));
-	if (ret < 0)
-		goto err;
-	ret = read_ipc_sysctl("/proc/sys/kernel/shmall",
-			  entry->shm_ctlall, sizeof(entry->shm_ctlall));
-#endif
-	if (ret < 0)
-		goto err;
-	ret = read_ipc_sysctl("/proc/sys/kernel/shmmni",
-			  &entry->shm_ctlmni, sizeof(entry->shm_ctlmni));
-	if (ret < 0)
-		goto err;
-	ret = read_ipc_sysctl("/proc/sys/kernel/shm_rmid_forced",
-			  &entry->shm_rmid_forced, sizeof(entry->shm_rmid_forced));
-	if (ret < 0)
-		goto err;
-
-
-	ret = read_ipc_sysctl("/proc/sys/fs/mqueue/queues_max",
-			  &entry->mq_queues_max, sizeof(entry->mq_queues_max));
-	if (ret < 0)
-		goto err;
-	ret = read_ipc_sysctl("/proc/sys/fs/mqueue/msg_max",
-			  &entry->mq_msg_max, sizeof(entry->mq_msg_max));
-	if (ret < 0)
-		goto err;
-	ret = read_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 dump ipc namespace tunables\n");
-	return ret;
+	return ipc_sysctl_req(e, CTL_READ);
 }
 
 static int collect_ipc_data(int ns_pid, struct ipc_ns_data *ipc)
@@ -277,20 +160,7 @@ int dump_ipc_ns(int ns_pid, struct cr_fdset *fdset)
 
 static void show_ipc_entry(struct ipc_ns_entry *entry)
 {
-	pr_info("/proc/sys/kernel/sem             : %d\t%d\t%d\t%d\n",
-				entry->sem_ctls[0], entry->sem_ctls[1],
-				entry->sem_ctls[2], entry->sem_ctls[3]);
-	pr_info("/proc/sys/kernel/msgmax          : %d\n", entry->msg_ctlmax);
-	pr_info("/proc/sys/kernel/msgmnb          : %d\n", entry->msg_ctlmnb);
-	pr_info("/proc/sys/kernel/msgmni          : %d\n", entry->msg_ctlmni);
-	pr_info("/proc/sys/kernel/auto_msgmni     : %d\n", entry->auto_msgmni);
-	pr_info("/proc/sys/kernel/shmmax          : %ld\n", *(u64 *)entry->shm_ctlmax);
-	pr_info("/proc/sys/kernel/shmall          : %ld\n", *(u64 *)entry->shm_ctlall);
-	pr_info("/proc/sys/kernel/shmmni          : %d\n", entry->shm_ctlmni);
-	pr_info("/proc/sys/kernel/shm_rmid_forced : %d\n", entry->shm_rmid_forced);
-	pr_info("/proc/sys/fs/mqueue/queues_max   : %d\n", entry->mq_queues_max);
-	pr_info("/proc/sys/fs/mqueue/msg_max      : %d\n", entry->mq_msg_max);
-	pr_info("/proc/sys/fs/mqueue/msgsize_max  : %d\n", entry->mq_msgsize_max);
+	ipc_sysctl_req(entry, CTL_PRINT);
 }
 
 static void show_ipc_data(int fd)
@@ -311,126 +181,9 @@ void show_ipc_ns(int 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_perror("Can't open %s", name);
-		return fd;
-	}
-	sprintf(buf, "%ld\n", *(long *)data);
-	ret = write(fd, buf, 32);
-	if (ret < 0) {
-		pr_perror("Can't write %s", 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_perror("Can't open %s", name);
-		return fd;
-	}
-	sprintf(buf, "%d\n", *(int *)data);
-	ret = write(fd, buf, 32);
-	if (ret < 0) {
-		pr_perror("Can't write %s", name);
-		ret = -errno;
-	}
-	close(fd);
-	return ret;
-}
-
-static int write_ipc_sem(u32 sem[])
+static int prepare_ipc_tun(struct ipc_ns_entry *e)
 {
-	int fd;
-	int ret;
-	char buf[128];
-	char *name = "/proc/sys/kernel/sem";
-
-	fd = open(name, O_WRONLY);
-	if (fd < 0) {
-		pr_perror("Can't open %s", 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_perror("Can't write %s", name);
-		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;
+	return ipc_sysctl_req(e, CTL_WRITE);
 }
 
 static int prepare_ipc_data(int fd)
diff --git a/sysctl.c b/sysctl.c
new file mode 100644
index 0000000..6d0f8bd
--- /dev/null
+++ b/sysctl.c
@@ -0,0 +1,216 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+
+#include "types.h"
+#include "sysctl.h"
+#include "util.h"
+
+#define __SYSCTL_OP(__ret, __fd, __req, __type, __nr, __op)		\
+do {									\
+	if (__op == CTL_READ)						\
+		__ret = sysctl_read_##__type(__fd, __req,		\
+					     (__type *)(__req)->arg,	\
+					     __nr);			\
+	else if (__op == CTL_WRITE)					\
+		__ret = sysctl_write_##__type(__fd, __req,		\
+					      (__type *)(__req)->arg,	\
+					      __nr);			\
+	else if (__op == CTL_PRINT)					\
+		__ret = sysctl_print_##__type(__fd, __req,		\
+					      (__type *)(__req)->arg,	\
+					      __nr);			\
+	else								\
+		__ret = -1;						\
+} while (0)
+
+#define GEN_SYSCTL_READ_FUNC(__type, __conv)				\
+static int sysctl_read_##__type(int fd,					\
+				struct sysctl_req *req,			\
+				__type *arg,				\
+				int nr)					\
+{									\
+	char buf[1024] = {0};						\
+	int i, ret = -1;						\
+	char *p = buf;							\
+									\
+	ret = read(fd, buf, sizeof(buf));				\
+	if (ret < 0) {							\
+		pr_perror("Can't read %s", req->name);			\
+		ret = -1;						\
+		goto err;						\
+	}								\
+									\
+	for (i = 0; i < nr && p < buf + sizeof(buf); p++, i++)		\
+		((__type *)arg)[i] = __conv(p, &p, 10);			\
+									\
+	if (i != nr) {							\
+		pr_err("Not enough params for %s (%d != %d)\n",		\
+			req->name, i, nr);				\
+		goto err;						\
+	}								\
+									\
+	ret = 0;							\
+									\
+err:									\
+	return ret;							\
+}
+
+#define GEN_SYSCTL_WRITE_FUNC(__type, __fmt)				\
+static int sysctl_write_##__type(int fd,				\
+				 struct sysctl_req *req,		\
+				 __type *arg,				\
+				 int nr)				\
+{									\
+	char buf[1024];							\
+	int i, ret = -1;						\
+	int off = 0;							\
+									\
+	for (i = 0; i < nr && off < sizeof(buf) - 2; i++) {		\
+		snprintf(&buf[off], sizeof(buf) - off, __fmt, arg[i]);	\
+		off += strlen(&buf[off]);				\
+	}								\
+									\
+	if (i != nr) {							\
+		pr_err("Not enough space for %s (%d != %d)\n",		\
+			req->name, i, nr);				\
+		goto err;						\
+	}								\
+									\
+	/* trailing spaces in format */					\
+	while (off > 0 && isspace(buf[off - 1]))			\
+		off--;							\
+	buf[off + 0] = '\n';						\
+	buf[off + 1] = '\0';						\
+	ret = write(fd, buf, off + 2);					\
+	if (ret < 0) {							\
+		pr_perror("Can't write %s", req->name);			\
+		ret = -1;						\
+		goto err;						\
+	}								\
+									\
+	ret = 0;							\
+err:									\
+	return ret;							\
+}
+
+#define GEN_SYSCTL_PRINT_FUNC(__type, __fmt)				\
+static int sysctl_print_##__type(int fd,				\
+				 struct sysctl_req *req,		\
+				 __type *arg,				\
+				 int nr)				\
+{									\
+	int i;								\
+	pr_info("sysctl: <%s> = <", req->name);				\
+	for (i = 0; i < nr; i++)					\
+		pr_info(__fmt, arg[i]);					\
+	pr_info(">\n");							\
+									\
+	return 0;							\
+}
+
+GEN_SYSCTL_READ_FUNC(u32, strtoul);
+GEN_SYSCTL_READ_FUNC(u64, strtoull);
+
+GEN_SYSCTL_WRITE_FUNC(u32, "%u ");
+GEN_SYSCTL_WRITE_FUNC(u64, "%lu ");
+
+GEN_SYSCTL_PRINT_FUNC(u32, "%u ");
+GEN_SYSCTL_PRINT_FUNC(u64, "%lu ");
+GEN_SYSCTL_PRINT_FUNC(char, "%c");
+
+static int
+sysctl_write_char(int fd, struct sysctl_req *req, char *arg, int nr)
+{
+	pr_debug("%s nr %d\n", req->name, nr);
+	if (dprintf(fd, "%s\n", arg) < 0)
+		return -1;
+
+	return 0;
+}
+
+static int
+sysctl_read_char(int fd, struct sysctl_req *req, char *arg, int nr)
+{
+	int ret = -1;
+
+	pr_debug("%s nr %d\n", req->name, nr);
+	ret = read(fd, arg, nr);
+	if (ret < 0) {
+		pr_perror("Can't read %s", req->name);
+		goto err;
+	}
+	ret = 0;
+
+err:
+	return ret;
+}
+
+static int __sysctl_op(int dir, struct sysctl_req *req, int op)
+{
+	int fd = -1;
+	int ret = -1;
+	int nr = 1;
+
+	if (dir > 0) {
+		int flags;
+
+		if (op == CTL_READ)
+			flags = O_RDONLY;
+		else
+			flags = O_WRONLY;
+
+		fd = openat(dir, req->name, flags);
+		if (fd < 0) {
+			pr_perror("Can't open sysctl %s", req->name);
+			return -1;
+		}
+	}
+
+	switch (CTL_TYPE(req->type)) {
+	case __CTL_U32A:
+		nr = CTL_LEN(req->type);
+	case CTL_U32:
+		__SYSCTL_OP(ret, fd, req, u32, nr, op);
+		break;
+	case __CTL_U64A:
+		nr = CTL_LEN(req->type);
+	case CTL_U64:
+		__SYSCTL_OP(ret, fd, req, u64, nr, op);
+		break;
+	case __CTL_STR:
+		nr = CTL_LEN(req->type);
+		__SYSCTL_OP(ret, fd, req, char, nr, op);
+		break;
+	}
+
+	if (fd > 0)
+		close(fd);
+
+	return ret;
+}
+
+int sysctl_op(struct sysctl_req *req, int op)
+{
+	int ret = 0;
+	int dir = -1;
+
+	if (op != CTL_PRINT) {
+		dir = open("/proc/sys", O_RDONLY);
+		if (dir < 0) {
+			pr_perror("Can't open sysctl dir");
+			return -1;
+		}
+	}
+
+	while (req->name) {
+		ret = __sysctl_op(dir, req, op);
+		if (ret < 0)
+			break;
+		req++;
+	}
+
+	if (dir > 0)
+		close(dir);
+	return ret;
+}
diff --git a/uts_ns.c b/uts_ns.c
index 306aca3..32f9d25 100644
--- a/uts_ns.c
+++ b/uts_ns.c
@@ -6,6 +6,7 @@
 #include "crtools.h"
 #include "syscall.h"
 #include "namespaces.h"
+#include "sysctl.h"
 
 static int dump_uts_string(int fd, char *str)
 {
@@ -44,62 +45,55 @@ int dump_uts_ns(int ns_pid, struct cr_fdset *fdset)
 	return ret;
 }
 
-static int prepare_uts_str(int fd, char *n)
+static int read_uts_str(int fd, char *n, int size)
 {
 	int ret;
 	u32 len;
-	char str[65], path[128];
 
 	ret = read_img(fd, &len);
-	if (ret > 0) {
-		if (len >= sizeof(str)) {
-			pr_err("Corrupted %s\n", n);
-			return -1;
-		}
-
-		ret = read_img_buf(fd, str, len);
-		if (ret < 0)
-			return -1;
-
-		str[len] = '\0';
-
-		snprintf(path, sizeof(path),
-				"/proc/sys/kernel/%s", n);
-		fd = open(path, O_WRONLY);
-		if (fd < 0) {
-			pr_perror("Can't open %s", path);
-			return -1;
-		}
-
-		pr_info("Restoring %s to [%s]\n", n, str);
-
-		ret = write(fd, str, len);
-		close(fd);
-		if (ret != len) {
-			pr_perror("Can't write %s to %s",
-					str, path);
-			return -1;
-		}
+	if (ret < 0)
+		return -1;
 
-		ret = 0;
+	if (len >= size) {
+		pr_err("Corrupted %s\n", n);
+		return -1;
 	}
 
-	return ret;
+	ret = read_img_buf(fd, n, len);
+	if (ret < 0)
+		return -1;
+
+	n[len] = '\0';
+	return 0;
 }
 
 int prepare_utsns(int pid)
 {
 	int fd, ret;
 	u32 len;
+	char hostname[65];
+	char domainname[65];
+
+	struct sysctl_req req[] = {
+		{ "kernel/hostname",	hostname,	CTL_STR(sizeof(hostname)) },
+		{ "kernel/domainname",	domainname,	CTL_STR(sizeof(hostname)) },
+		{ },
+	};
 
 	fd = open_image_ro(CR_FD_UTSNS, pid);
 	if (fd < 0)
 		return -1;
 
-	ret = prepare_uts_str(fd, "hostname");
-	if (!ret)
-		ret = prepare_uts_str(fd, "domainname");
+	ret = read_uts_str(fd, hostname, sizeof(hostname));
+	if (ret < 0)
+		goto out;
+
+	ret = read_uts_str(fd, domainname, sizeof(domainname));
+	if (ret < 0)
+		goto out;
 
+	ret = sysctl_op(req, CTL_WRITE);
+out:
 	close(fd);
 	return ret;
 }


More information about the CRIU mailing list