[CRIU] [PATCH cr 4/6] util: clone service descriptors, if fd tables are shared for tasks

Andrey Vagin avagin at openvz.org
Tue Oct 2 10:07:20 EDT 2012


It looks like a namespace for service descriptors.
It will be used for restoring tasks with shared fd tables.
Service descriptors should be its for each process.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 image.c           |   22 ++++++++++++++++
 include/crtools.h |    3 ++
 include/log.h     |    1 +
 log.c             |   13 +++++++++
 util.c            |   73 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 111 insertions(+), 1 deletions(-)

diff --git a/image.c b/image.c
index f1f93a0..70ababe 100644
--- a/image.c
+++ b/image.c
@@ -276,6 +276,28 @@ err:
 	return -1;
 }
 
+int clone_image_dir(void)
+{
+	int fd;
+
+	if (image_dir_fd < 0)
+		return 0;
+
+	fd = get_service_fd(IMG_FD_OFF);
+	if (fd < 0) {
+		pr_perror("Can't get image fd");
+		return -1;
+	}
+
+	image_dir_fd = dup2(image_dir_fd, fd);
+	if (image_dir_fd < 0) {
+		pr_perror("Unable to duplicate an image directory descriptor");
+		return -1;
+	}
+
+	return 0;
+}
+
 int open_image_dir(void)
 {
 	int fd;
diff --git a/include/crtools.h b/include/crtools.h
index 3c31b88..c72c0b0 100644
--- a/include/crtools.h
+++ b/include/crtools.h
@@ -8,6 +8,7 @@
 #include "list.h"
 #include "util.h"
 #include "image.h"
+#include "lock.h"
 
 #include "../protobuf/vma.pb-c.h"
 
@@ -120,6 +121,7 @@ enum sfd_type {
 	SERVICE_FD_MAX
 };
 
+extern int clone_service_fd(bool to_init);
 extern int init_service_fd(void);
 extern int get_service_fd(enum sfd_type type);
 extern bool is_service_fd(int fd, enum sfd_type type);
@@ -162,6 +164,7 @@ extern void print_image_data(int fd, unsigned int length);
 extern struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX];
 
 extern int open_image_dir(void);
+extern int clone_image_dir(void);
 extern void close_image_dir(void);
 
 int open_image(int type, unsigned long flags, ...);
diff --git a/include/log.h b/include/log.h
index 24d69dd..a5fdc9c 100644
--- a/include/log.h
+++ b/include/log.h
@@ -9,6 +9,7 @@ extern int log_init_by_pid(void);
 extern void log_closedir(void);
 
 extern int log_get_fd(void);
+extern int log_clone_fd(void);
 
 extern void log_set_loglevel(unsigned int loglevel);
 extern unsigned int log_get_loglevel(void);
diff --git a/log.c b/log.c
index d9a36f1..124ed85 100644
--- a/log.c
+++ b/log.c
@@ -27,6 +27,19 @@ static int logdir = -1;
 static char buffer[PAGE_SIZE];
 static char buf_off = 0;
 
+int log_clone_fd(void)
+{
+	current_logfd = dup2(current_logfd, get_service_fd(LOG_FD_OFF));
+	if (current_logfd < 0)
+		return -1;
+
+	logdir = dup2(logdir, get_service_fd(LOG_DIR_FD_OFF));
+	if (logdir < 0)
+		return -1;
+
+	return 0;
+}
+
 int log_get_fd(void)
 {
 	return current_logfd;
diff --git a/util.c b/util.c
index f1f0155..1e107c4 100644
--- a/util.c
+++ b/util.c
@@ -168,6 +168,22 @@ int close_pid_proc(void)
 	return ret;
 }
 
+static int clone_proc(void)
+{
+	close_pid_proc();
+
+	if (proc_dir_fd <= 0)
+		return 0;
+
+	proc_dir_fd = dup2(proc_dir_fd, get_service_fd(PROC_FD_OFF));
+	if (proc_dir_fd < 0) {
+		pr_perror("Unable to duplicate a proc descriptor");
+		return -1;
+	}
+
+	return 0;
+}
+
 void close_proc()
 {
 	close_pid_proc();
@@ -260,6 +276,8 @@ int do_open_proc(pid_t pid, int flags, const char *fmt, ...)
 }
 
 static int service_fd_rlim_cur;
+static int service_fd_id = 0;
+static mutex_t *service_fd_lock;
 
 int init_service_fd(void)
 {
@@ -278,12 +296,65 @@ int init_service_fd(void)
 	service_fd_rlim_cur = (int)rlimit.rlim_cur;
 	BUG_ON(service_fd_rlim_cur < SERVICE_FD_MAX);
 
+	service_fd_lock = shmalloc(sizeof(mutex_t));
+	if (service_fd_lock == NULL)
+		return -1;
+
+	mutex_init(service_fd_lock);
+
 	return 0;
 }
 
+int clone_service_fd(bool to_init)
+{
+	int ret = -1;
+
+	if (to_init && service_fd_id == 0)
+		return 0;
+
+	mutex_lock(service_fd_lock);
+
+	if (to_init)
+		service_fd_id = 0;
+	else {
+		/*
+		 * Find a free service fd namespace. We suppose,
+		 * that LOG_FD_OFF should be opened all time, so
+		 * if LOG_FD_OFF isn't busy, a service fd namespace is free.
+		 */
+		while (1) {
+			service_fd_id++;
+
+			if (fcntl(get_service_fd(LOG_FD_OFF), F_GETFD) != -1)
+				continue;
+
+			if (errno == EBADF)
+				break;
+
+			pr_perror("fcntl failed\n");
+			goto out;
+		}
+	}
+
+	if (log_clone_fd())
+		goto out;
+
+	if (clone_proc())
+		goto out;
+
+	if (clone_image_dir())
+		goto out;
+
+	ret = 0;
+out:
+	mutex_unlock(service_fd_lock);
+
+	return ret;
+}
+
 static int __get_service_fd(enum sfd_type type)
 {
-	return service_fd_rlim_cur - type;
+	return service_fd_rlim_cur - type - SERVICE_FD_MAX * service_fd_id;
 }
 
 int get_service_fd(enum sfd_type type)
-- 
1.7.1



More information about the CRIU mailing list