[CRIU] [PATCH 04/11] crtools: add ability to create and close a service fd (v3)

Andrey Vagin avagin at openvz.org
Fri Jan 11 09:16:20 EST 2013


A service fd should be created, otherwise get_service_fd returns -1.

This patch removes this functionality from other subsystems and
allows to clone service descriptors.

v2: rename open_service_fd to install_service_fd
v3: two patches were merged for bisecting

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 image.c           | 24 +++++++----------
 include/crtools.h |  2 ++
 log.c             | 59 +++++++++++++----------------------------
 tty.c             |  8 ++----
 util.c            | 78 +++++++++++++++++++++++++++++++++++--------------------
 5 files changed, 81 insertions(+), 90 deletions(-)

diff --git a/image.c b/image.c
index 2d13b1a..626aa83 100644
--- a/image.c
+++ b/image.c
@@ -228,10 +228,9 @@ struct cr_fdset *cr_glob_fdset_open(int mode)
 	return cr_fdset_open(-1 /* ignored */, _CR_FD_GLOB_FROM, _CR_FD_GLOB_TO, mode);
 }
 
-static int image_dir_fd = -1;
-
 int open_image(int type, unsigned long flags, ...)
 {
+	int dfd = get_service_fd(IMG_FD_OFF);
 	char path[PATH_MAX];
 	va_list args;
 	int ret;
@@ -241,14 +240,14 @@ int open_image(int type, unsigned long flags, ...)
 	va_end(args);
 
 	if (flags & O_EXCL) {
-		ret = unlinkat(image_dir_fd, path, 0);
+		ret = unlinkat(dfd, path, 0);
 		if (ret && errno != ENOENT) {
 			pr_perror("Unable to unlink %s", path);
 			goto err;
 		}
 	}
 
-	ret = openat(image_dir_fd, path, flags, CR_FD_PERM);
+	ret = openat(dfd, path, flags, CR_FD_PERM);
 	if (ret < 0) {
 		pr_perror("Unable to open %s", path);
 		goto err;
@@ -279,13 +278,7 @@ err:
 
 int open_image_dir(void)
 {
-	int fd;
-
-	image_dir_fd = get_service_fd(IMG_FD_OFF);
-	if (image_dir_fd < 0) {
-		pr_perror("Can't get image fd");
-		return -1;
-	}
+	int fd, ret;
 
 	fd = open(".", O_RDONLY);
 	if (fd < 0) {
@@ -293,13 +286,14 @@ int open_image_dir(void)
 		return -1;
 	}
 
-	pr_info("Image dir fd is %d\n", image_dir_fd);
+	ret = install_service_fd(IMG_FD_OFF, fd);
+
+	close(fd);
 
-	return reopen_fd_as(image_dir_fd, fd);
+	return ret;
 }
 
 void close_image_dir(void)
 {
-	close(image_dir_fd);
-	image_dir_fd = -1;
+	close_service_fd(IMG_FD_OFF);
 }
diff --git a/include/crtools.h b/include/crtools.h
index 72b7699..3300542 100644
--- a/include/crtools.h
+++ b/include/crtools.h
@@ -125,6 +125,8 @@ enum sfd_type {
 extern int clone_service_fd(int id);
 extern int init_service_fd(void);
 extern int get_service_fd(enum sfd_type type);
+extern int install_service_fd(enum sfd_type type, int fd);
+extern int close_service_fd(enum sfd_type type);
 extern bool is_service_fd(int fd, enum sfd_type type);
 extern bool is_any_service_fd(int fd);
 
diff --git a/log.c b/log.c
index c02dff2..5882e9c 100644
--- a/log.c
+++ b/log.c
@@ -20,8 +20,6 @@
 #define DEFAULT_LOGFD		STDERR_FILENO
 
 static unsigned int current_loglevel = DEFAULT_LOGLEVEL;
-static int current_logfd = DEFAULT_LOGFD;
-static int logdir = -1;
 
 static char buffer[PAGE_SIZE];
 static char buf_off = 0;
@@ -55,27 +53,22 @@ static void print_ts(void)
 	buffer[TS_BUF_OFF - 1] = ' '; /* kill the '\0' produced by snprintf */
 }
 
-
-
 int log_get_fd(void)
 {
-	return current_logfd;
+	int fd = get_service_fd(LOG_FD_OFF);
+
+	return fd < 0 ? DEFAULT_LOGFD : fd;
 }
 
 int log_init(const char *output)
 {
-	int new_logfd, sfd, dfd;
+	int new_logfd, dfd, fd;
 
 	gettimeofday(&start, NULL);
 	buf_off = TS_BUF_OFF;
 
 	dfd = get_service_fd(LOG_DIR_FD_OFF);
 	if (dfd < 0) {
-		pr_msg("Can't obtain logfd");
-		goto err;
-	}
-
-	if (logdir < 0) {
 		int tmp;
 		tmp = open(".", O_RDONLY);
 		if (tmp == -1) {
@@ -83,40 +76,26 @@ int log_init(const char *output)
 			return -1;
 		}
 
-		if (reopen_fd_as(dfd, tmp) < 0)
+		dfd = install_service_fd(LOG_DIR_FD_OFF, tmp);
+		close(tmp);
+		if (dfd < 0)
 			return -1;
-
-		logdir = dfd;
-	}
-
-	sfd = get_service_fd(LOG_FD_OFF);
-	if (sfd < 0) {
-		pr_msg("Can't obtain logfd");
-		goto err;
 	}
 
 	if (output) {
-		new_logfd = openat(logdir, output,
+		new_logfd = openat(dfd, output,
 					O_CREAT | O_TRUNC | O_WRONLY | O_APPEND, 0600);
 		if (new_logfd < 0) {
 			pr_perror("Can't create log file %s", output);
 			return -1;
 		}
+	} else
+		new_logfd = dup(DEFAULT_LOGFD);
 
-		if (sfd == current_logfd)
-			close(sfd);
-
-		if (reopen_fd_as(sfd, new_logfd) < 0)
-			goto err;
-	} else {
-		new_logfd = dup2(DEFAULT_LOGFD, sfd);
-		if (new_logfd < 0) {
-			pr_perror("Dup %d -> %d failed", DEFAULT_LOGFD, sfd);
-			goto err;
-		}
-	}
-
-	current_logfd = sfd;
+	fd = install_service_fd(LOG_FD_OFF, new_logfd);
+	close(new_logfd);
+	if (fd < 0)
+		goto err;
 
 	return 0;
 
@@ -151,15 +130,13 @@ int log_init_by_pid(void)
 
 void log_fini(void)
 {
-	if (current_logfd > 2)
-		close_safe(&current_logfd);
-
-	current_logfd = DEFAULT_LOGFD;
+	close_service_fd(LOG_FD_OFF);
+	log_closedir();
 }
 
 void log_closedir(void)
 {
-	close_safe(&logdir);
+	close_service_fd(LOG_DIR_FD_OFF);
 }
 
 void log_set_loglevel(unsigned int level)
@@ -186,7 +163,7 @@ void print_on_level(unsigned int loglevel, const char *format, ...)
 	} else {
 		if (loglevel > current_loglevel)
 			return;
-		fd = current_logfd;
+		fd = log_get_fd();
 		print_ts();
 		off = 0;
 	}
diff --git a/tty.c b/tty.c
index 0f7c87a..5a78a0f 100644
--- a/tty.c
+++ b/tty.c
@@ -94,7 +94,6 @@ struct tty_dump_info {
 
 static LIST_HEAD(all_tty_info_entries);
 static LIST_HEAD(all_ttys);
-static int self_stdin = -1;
 
 #define INHERIT_SID			(-1)
 
@@ -1196,15 +1195,12 @@ int dump_tty(struct fd_parms *p, int lfd, const int fdinfo)
 
 int tty_prep_fds(void)
 {
-	self_stdin = get_service_fd(SELF_STDIN_OFF);
-
 	if (!isatty(STDIN_FILENO)) {
 		pr_err("Standart stream is not a terminal, aborting\n");
 		return -1;
 	}
 
-	if (dup2(STDIN_FILENO, self_stdin) < 0) {
-		self_stdin = -1;
+	if (install_service_fd(SELF_STDIN_OFF, STDIN_FILENO) < 0) {
 		pr_perror("Can't dup stdin to SELF_STDIN_OFF");
 		return -1;
 	}
@@ -1214,5 +1210,5 @@ int tty_prep_fds(void)
 
 void tty_fini_fds(void)
 {
-	close_safe(&self_stdin);
+	close_service_fd(SELF_STDIN_OFF);
 }
diff --git a/util.c b/util.c
index e230f2d..82220ff 100644
--- a/util.c
+++ b/util.c
@@ -173,7 +173,6 @@ int move_img_fd(int *img_fd, int want_fd)
 
 static pid_t open_proc_pid = 0;
 static int open_proc_fd = -1;
-static int proc_dir_fd = -1;
 
 int close_pid_proc(void)
 {
@@ -191,30 +190,18 @@ int close_pid_proc(void)
 void close_proc()
 {
 	close_pid_proc();
-	if (proc_dir_fd > 0)
-		close(proc_dir_fd);
-	proc_dir_fd = -1;
+
+	close_service_fd(PROC_FD_OFF);
 }
 
 int set_proc_fd(int fd)
 {
-	int sfd = get_service_fd(PROC_FD_OFF);
-
-	sfd = dup2(fd, sfd);
-	if (sfd < 0) {
-		pr_perror("Can't set proc fd\n");
-		return -1;
-	}
-
-	proc_dir_fd = sfd;
-
-	return 0;
+	return install_service_fd(PROC_FD_OFF, fd);
 }
 
 int set_proc_mountpoint(char *path)
 {
-	int sfd = get_service_fd(PROC_FD_OFF), fd;
-
+	int fd, ret;
 	close_proc();
 
 	fd = open(path, O_DIRECTORY | O_RDONLY);
@@ -223,14 +210,10 @@ int set_proc_mountpoint(char *path)
 		return -1;
 	}
 
-	sfd = dup2(fd, sfd);
+	ret = install_service_fd(PROC_FD_OFF, fd);
 	close(fd);
-	if (sfd < 0) {
-		pr_err("Can't set proc fd\n");
+	if (ret < 0)
 		return -1;
-	}
-
-	proc_dir_fd = sfd;
 
 	return 0;
 }
@@ -239,20 +222,23 @@ inline int open_pid_proc(pid_t pid)
 {
 	char path[18];
 	int fd;
+	int dfd;
 
 	if (pid == open_proc_pid)
 		return open_proc_fd;
 
 	close_pid_proc();
 
-	if (proc_dir_fd == -1) {
-		fd = set_proc_mountpoint("/proc");
-		if (fd < 0)
-			return fd;
+	dfd = get_service_fd(PROC_FD_OFF);
+	if (dfd < 0) {
+		if (set_proc_mountpoint("/proc") < 0)
+			return -1;
+
+		dfd = get_service_fd(PROC_FD_OFF);
 	}
 
 	snprintf(path, sizeof(path), "%d", pid);
-	fd = openat(proc_dir_fd, path, O_RDONLY);
+	fd = openat(dfd, path, O_RDONLY);
 	if (fd < 0)
 		pr_perror("Can't open %s", path);
 	else {
@@ -307,12 +293,48 @@ static int __get_service_fd(enum sfd_type type, int service_fd_id)
 	return service_fd_rlim_cur - type - SERVICE_FD_MAX * service_fd_id;
 }
 
+static DECLARE_BITMAP(sfd_map, SERVICE_FD_MAX);
+
+int install_service_fd(enum sfd_type type, int fd)
+{
+	int sfd = __get_service_fd(type, service_fd_id);
+
+	BUG_ON((int)type <= SERVICE_FD_MIN || (int)type >= SERVICE_FD_MAX);
+
+	if (dup2(fd, sfd) != sfd) {
+		pr_perror("Dup %d -> %d failed", fd, sfd);
+		return -1;
+	}
+
+	set_bit(type, sfd_map);
+	return sfd;
+}
+
 int get_service_fd(enum sfd_type type)
 {
 	BUG_ON((int)type <= SERVICE_FD_MIN || (int)type >= SERVICE_FD_MAX);
+
+	if (!test_bit(type, sfd_map))
+		return -1;
+
 	return __get_service_fd(type, service_fd_id);
 }
 
+int close_service_fd(enum sfd_type type)
+{
+	int fd;
+
+	fd = get_service_fd(type);
+	if (fd < 0)
+		return 0;
+
+	if (close_safe(&fd))
+		return -1;
+
+	clear_bit(type, sfd_map);
+	return 0;
+}
+
 int clone_service_fd(int id)
 {
 	int ret = -1, i;
-- 
1.7.11.7



More information about the CRIU mailing list