[CRIU] [PATCH v5 07/15] files: new "used" files list introduced

Stanislav Kinsburskiy skinsbursky at virtuozzo.com
Wed Jan 27 04:04:18 PST 2016


This list contains all per-process used file fdinfo's, sorted by fd number.
Will be used to safely create new artificial file descriptors and also allow
to recreate temporary descriptors with original number, if possible, like
AutoFS tries to preserve original pipe write end descriptor, when it was
closed.
This patch also adds simple helper to find unused file descriptor.
Return "hint" if unused or last used descriptor plus one.

Signed-off-by: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>
---
 eventpoll.c        |    1 +
 files.c            |    1 +
 include/files.h    |   30 ++++++++++++++++++++++++++++++
 include/rst_info.h |    1 +
 tty.c              |    1 +
 5 files changed, 34 insertions(+)

diff --git a/eventpoll.c b/eventpoll.c
index c414c35..8d3a001 100644
--- a/eventpoll.c
+++ b/eventpoll.c
@@ -185,6 +185,7 @@ static void eventpoll_collect_fd(struct file_desc *d,
 		struct fdinfo_list_entry *fle, struct rst_info *ri)
 {
 	list_add_tail(&fle->ps_list, &ri->eventpoll);
+	collect_used_fd(fle, ri);
 }
 
 static struct file_desc_ops desc_ops = {
diff --git a/files.c b/files.c
index aa23303..0928649 100644
--- a/files.c
+++ b/files.c
@@ -686,6 +686,7 @@ int prepare_fd_pid(struct pstree_item *item)
 	pid_t pid = item->pid.virt;
 	struct rst_info *rst_info = rsti(item);
 
+	INIT_LIST_HEAD(&rst_info->used);
 	INIT_LIST_HEAD(&rst_info->fds);
 	INIT_LIST_HEAD(&rst_info->eventpoll);
 	INIT_LIST_HEAD(&rst_info->tty_slaves);
diff --git a/include/files.h b/include/files.h
index 9ea2344..da38d88 100644
--- a/include/files.h
+++ b/include/files.h
@@ -67,6 +67,7 @@ struct fdinfo_list_entry {
 	struct list_head	desc_list;	/* To chain on  @fd_info_head */
 	struct file_desc	*desc;		/* Associated file descriptor */
 	struct list_head	ps_list;	/* To chain  per-task files */
+	struct list_head	used_list;	/* To chain per-task used fds */
 	int			pid;
 	futex_t			real_pid;
 	FdinfoEntry		*fe;
@@ -108,9 +109,38 @@ struct file_desc_ops {
 	char *			(*name)(struct file_desc *, char *b, size_t s);
 };
 
+static inline void collect_used_fd(struct fdinfo_list_entry *new_fle, struct rst_info *ri)
+{
+	struct fdinfo_list_entry *fle;
+
+	list_for_each_entry(fle, &ri->used, used_list) {
+		if (new_fle->fe->fd < fle->fe->fd)
+			break;
+	}
+
+	list_add_tail(&new_fle->used_list, &fle->used_list);
+}
+
 static inline void collect_gen_fd(struct fdinfo_list_entry *fle, struct rst_info *ri)
 {
 	list_add_tail(&fle->ps_list, &ri->fds);
+	collect_used_fd(fle, ri);
+}
+
+static inline unsigned int find_unused_fd(struct list_head *head, int hint_fd)
+{
+	struct fdinfo_list_entry *fle;
+	bool hint_fd_used = false;
+	int last_used_fd = 0;
+
+	list_for_each_entry(fle, head, used_list) {
+		if (fle->fe->fd == hint_fd)
+			hint_fd_used = true;
+		last_used_fd = fle->fe->fd;
+	}
+	if (hint_fd_used || (hint_fd < 0))
+		return last_used_fd + 1;
+	return hint_fd;
 }
 
 struct file_desc {
diff --git a/include/rst_info.h b/include/rst_info.h
index b72e5d0..ef3a33a 100644
--- a/include/rst_info.h
+++ b/include/rst_info.h
@@ -27,6 +27,7 @@ struct fdt {
 struct _MmEntry;
 
 struct rst_info {
+	struct list_head	used;
 	struct list_head	fds;
 	struct list_head	eventpoll;
 	struct list_head	tty_slaves;
diff --git a/tty.c b/tty.c
index 1643ef0..0533310 100644
--- a/tty.c
+++ b/tty.c
@@ -1048,6 +1048,7 @@ static void tty_collect_fd(struct file_desc *d, struct fdinfo_list_entry *fle,
 		tgt = &ri->tty_slaves;
 
 	list_add_tail(&fle->ps_list, tgt);
+	collect_used_fd(fle, ri);
 }
 
 static char *tty_d_name(struct file_desc *d, char *buf, size_t s)



More information about the CRIU mailing list