[CRIU] [PATCH v8 06/15] files: new "used" files list introduced

Stanislav Kinsburskiy skinsbursky at virtuozzo.com
Wed Mar 16 06:17:27 PDT 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 a couple of simple helpers to find unused file
descriptor:
1) fd_is_used() does exactly what it is named
2) find_unused_fd() returns "hint_fd" if unused or last used descriptor plus
one.

Signed-off-by: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>
---
 criu/files.c            |    3 +++
 criu/include/files.h    |   33 +++++++++++++++++++++++++++++++++
 criu/include/rst_info.h |    1 +
 3 files changed, 37 insertions(+)

diff --git a/criu/files.c b/criu/files.c
index 8a7d85f..40bb13a 100644
--- a/criu/files.c
+++ b/criu/files.c
@@ -646,6 +646,8 @@ static int collect_fd(int pid, FdinfoEntry *e, struct rst_info *rst_info)
 	else
 		collect_gen_fd(new_le, rst_info);
 
+	collect_used_fd(new_le, rst_info);
+
 	list_add_tail(&new_le->desc_list, &le->desc_list);
 	new_le->desc = fdesc;
 
@@ -686,6 +688,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/criu/include/files.h b/criu/include/files.h
index 5db6ab1..d38dbfd 100644
--- a/criu/include/files.h
+++ b/criu/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,11 +109,43 @@ 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);
 }
 
+static inline bool fd_is_used(struct list_head *head, int fd)
+{
+	struct fdinfo_list_entry *fle;
+
+	list_for_each_entry(fle, head, used_list) {
+		if (fle->fe->fd == fd)
+			return true;
+	}
+
+	return false;
+}
+
+static inline unsigned int find_unused_fd(struct list_head *head, int hint_fd)
+{
+	if ((hint_fd >= 0) && (!fd_is_used(head, hint_fd)))
+		return hint_fd;
+	/* Return last used fd +1 */
+	return list_entry(head->prev, typeof(struct fdinfo_list_entry), used_list)->fe->fd + 1;
+}
+
 struct file_desc {
 	u32			id;		/* File id, unique */
 	struct hlist_node	hash;		/* Descriptor hashing and lookup */
diff --git a/criu/include/rst_info.h b/criu/include/rst_info.h
index b6d378e..562e2f0 100644
--- a/criu/include/rst_info.h
+++ b/criu/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;



More information about the CRIU mailing list