[CRIU] [PATCH 09/12] files: Add get_unused_fd() helper
Kirill Tkhai
ktkhai at virtuozzo.com
Fri Apr 29 07:37:10 PDT 2016
This function helps to find a fd, which is not occupied by restored
task and which won't be need by the task in the future.
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
criu/cr-restore.c | 2 -
criu/files.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++
criu/include/files.h | 2 +
criu/include/pstree.h | 1
4 files changed, 103 insertions(+), 1 deletion(-)
diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index 777c71d..9560254 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -108,7 +108,7 @@
#define arch_export_unmap __export_unmap
#endif
-static struct pstree_item *current;
+struct pstree_item *current;
static int restore_task_with_children(void *);
static int sigreturn_restore(pid_t pid, CoreEntry *core);
diff --git a/criu/files.c b/criu/files.c
index fd5c61d..9ad640b 100644
--- a/criu/files.c
+++ b/criu/files.c
@@ -1149,6 +1149,105 @@ int prepare_fds(struct pstree_item *me)
return ret;
}
+#define fle_entry(list) list_entry(list, struct fdinfo_list_entry, ps_list)
+/*
+ * Returns next range (*l, *r) above initial (*l). The search starts from
+ * fle, which is not necessary the first element.
+ */
+static void next_range(struct fdinfo_list_entry **fle, struct list_head *head, int *l, int *r)
+{
+ bool found = false;
+ int start = *l;
+
+ if (&(*fle)->ps_list != head) {
+ if ((*fle)->ps_list.prev != head)
+ *l = fle_entry((*fle)->ps_list.prev)->fe->fd;
+ else
+ *l = -1;
+
+ while (&(*fle)->ps_list != head) {
+ *r = (*fle)->fe->fd;
+ if (start + 1 < *r && *l + 1 < *r) {
+ found = true;
+ *l = max(start, *l);
+ break;
+ }
+ *l = *r;
+ *fle = fle_entry((*fle)->ps_list.next);
+ }
+ if (!found)
+ *r = INT_MAX;
+ } else if (!list_empty(head)) {
+ *l = fle_entry((*fle)->ps_list.prev)->fe->fd;
+ *l = max(*l, start);
+ *r = INT_MAX;
+ } else {
+ *l = start;
+ *r = INT_MAX;
+ }
+}
+
+int find_unused_fd(void)
+{
+ struct rst_info *ri = rsti(current);
+ struct fdinfo_list_entry *flea, *fleb, *flec, *fled;
+ int la, lb, lc, ld, ra, rb, rc, rd, i, ret = -1;
+
+ la = lb = lc = ld = -1;
+ ra = rb = rc = rd = INT_MAX;
+
+ flea = fle_entry(ri->fds.next);
+ fleb = fle_entry(ri->eventpoll.next);
+ flec = fle_entry(ri->tty_slaves.next);
+ fled = fle_entry(ri->tty_ctty.next);
+nexta:
+ next_range(&flea, &ri->fds, &la, &ra);
+ if (la == INT_MAX)
+ goto out;
+ lb = la;
+nextb:
+ next_range(&fleb, &ri->eventpoll, &lb, &rb);
+ if (lb == INT_MAX || lb >= ra) {
+ fleb = fle_entry(fleb->ps_list.prev);
+ la = ra;
+ goto nexta;
+ }
+
+ lc = lb;
+ rb = min(ra, rb);
+nextc:
+ next_range(&flec, &ri->tty_slaves, &lc, &rc);
+ if (lc == INT_MAX || lc >= rb) {
+ flec = fle_entry(flec->ps_list.prev);
+ lb = rb;
+ goto nextb;
+ }
+
+ ld = lc;
+ rc = min(rb, rc);
+nextd:
+ next_range(&fled, &ri->tty_ctty, &ld, &rd);
+ if (ld == INT_MAX || ld >= rc) {
+ fled = fle_entry(fled->ps_list.prev);
+ lc = rc;
+ goto nextc;
+ }
+
+ rd = min(rc, rd);
+
+ for (i = ld + 1; i < rd; i++) {
+ if (fcntl(i, F_GETFD) == -1 && errno == EBADF) {
+ ret = i;
+ goto out;
+ }
+ }
+
+ ld = rd;
+ goto nextd;
+out:
+ return ret;
+}
+
static int fchroot(int fd)
{
char fd_path[PSFDS];
diff --git a/criu/include/files.h b/criu/include/files.h
index 472cc45..6c5d579 100644
--- a/criu/include/files.h
+++ b/criu/include/files.h
@@ -160,9 +160,11 @@ extern int prepare_fd_pid(struct pstree_item *me);
extern int prepare_ctl_tty(int pid, struct rst_info *rst_info, u32 ctl_tty_id);
extern int prepare_shared_fdinfo(void);
extern int get_filemap_fd(struct vma_area *);
+extern int find_unused_fd(void);
extern int restore_fs(struct pstree_item *);
extern int prepare_fs_pid(struct pstree_item *);
extern int set_fd_flags(int fd, int flags);
+extern int get_unused_fd(void);
extern int close_old_fds(void);
#ifndef AT_EMPTY_PATH
diff --git a/criu/include/pstree.h b/criu/include/pstree.h
index 4bf6db7..f79a2ef 100644
--- a/criu/include/pstree.h
+++ b/criu/include/pstree.h
@@ -29,6 +29,7 @@ struct pstree_item {
TaskKobjIdsEntry *ids;
};
+struct pstree_item *current;
struct rst_info;
/* See alloc_pstree_item() for details */
static inline struct rst_info *rsti(struct pstree_item *i)
More information about the CRIU
mailing list