From patchwork Wed Jul 4 15:51:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [v5,09/19] epoll: Add support for multiple duped fds From: Cyrill Gorcunov X-Patchwork-Id: 8813 Message-Id: <20180704155147.29114-10-gorcunov@gmail.com> To: crml Cc: Andrey Vagin Date: Wed, 4 Jul 2018 18:51:37 +0300 Signed-off-by: Cyrill Gorcunov --- criu/eventpoll.c | 52 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/criu/eventpoll.c b/criu/eventpoll.c index 90fac99488f4..1ac6d5d9aff1 100644 --- a/criu/eventpoll.c +++ b/criu/eventpoll.c @@ -68,17 +68,18 @@ static int tfd_cmp(const void *a, const void *b) * fds in fd_parms are sorted so we can use binary search * for better performance. */ -static int find_tfd(pid_t pid, int efd, int fds[], size_t nr_fds, int tfd) +static int find_tfd(pid_t pid, int efd, int fds[], size_t nr_fds, int tfd, + unsigned int toff) { kcmp_epoll_slot_t slot = { .efd = efd, .tfd = tfd, - .toff = 0, + .toff = toff, }; int *tfd_found; size_t i; - pr_debug("find_tfd: pid %d efd %d tfd %d\n", pid, efd, tfd); + pr_debug("find_tfd: pid %d efd %d tfd %d toff %u\n", pid, efd, tfd, toff); /* * Optimistic case: the target fd belongs to us @@ -88,13 +89,13 @@ static int find_tfd(pid_t pid, int efd, int fds[], size_t nr_fds, int tfd) if (tfd_found) { if (kdat.has_kcmp_epoll_tfd) { if (syscall(SYS_kcmp, pid, pid, KCMP_EPOLL_TFD, tfd, &slot) == 0) { - pr_debug("find_tfd (kcmp-yes): bsearch match pid %d efd %d tfd %d\n", - pid, efd, tfd); + pr_debug("find_tfd (kcmp-yes): bsearch match pid %d efd %d tfd %d toff %u\n", + pid, efd, tfd, toff); return tfd; } } else { - pr_debug("find_tfd (kcmp-no): bsearch match pid %d efd %d tfd %d\n", - pid, efd, tfd); + pr_debug("find_tfd (kcmp-no): bsearch match pid %d efd %d tfd %d toff %u\n", + pid, efd, tfd, toff); return tfd; } } @@ -106,21 +107,21 @@ static int find_tfd(pid_t pid, int efd, int fds[], size_t nr_fds, int tfd) */ if (!kdat.has_kcmp_epoll_tfd) { - pr_debug("find_tfd (kcmp-no): no match pid %d efd %d tfd %d\n", - pid, efd, tfd); + pr_debug("find_tfd (kcmp-no): no match pid %d efd %d tfd %d toff %u\n", + pid, efd, tfd, toff); return -1; } for (i = 0; i < nr_fds; i++) { if (syscall(SYS_kcmp, pid, pid, KCMP_EPOLL_TFD, fds[i], &slot) == 0) { - pr_debug("find_tfd (kcmp-yes): nsearch match pid %d efd %d tfd %d -> %d\n", - pid, efd, tfd, fds[i]); + pr_debug("find_tfd (kcmp-yes): nsearch match pid %d efd %d tfd %d toff %u -> %d\n", + pid, efd, tfd, toff, fds[i]); return fds[i]; } } - pr_debug("find_tfd (kcmp-yes): no match pid %d efd %d tfd %d\n", - pid, efd, tfd); + pr_debug("find_tfd (kcmp-yes): no match pid %d efd %d tfd %d toff %u\n", + pid, efd, tfd, toff); return -1; } @@ -129,7 +130,8 @@ static int dump_one_eventpoll(int lfd, u32 id, const struct fd_parms *p) FileEntry fe = FILE_ENTRY__INIT; EventpollFileEntry e = EVENTPOLL_FILE_ENTRY__INIT; EventpollTfdEntry **tfd_cpy = NULL; - size_t i, j, n_tfd_cpy; + ssize_t i, j, n_tfd_cpy; + uint32_t *toff = NULL; int ret = -1; e.id = id; @@ -148,6 +150,25 @@ static int dump_one_eventpoll(int lfd, u32 id, const struct fd_parms *p) if (!tfd_cpy) goto out; + /* + * In regular case there is no so many dup'ed + * descriptors so instead of complex mappings + * lets rather walk over members with O(n^2) + */ + if (p->dfds) { + toff = xzalloc(sizeof(*toff) * e.n_tfd); + if (!toff) + goto out; + for (i = 1; i < e.n_tfd; i++) { + for (j = i - 1; j < e.n_tfd && j >= 0; j--) { + if (e.tfd[i]->tfd == e.tfd[j]->tfd) { + toff[i] = toff[j] + 1; + break; + } + } + } + } + /* * Handling dup'ed or transferred target * files is tricky: we need to use kcmp @@ -159,7 +180,7 @@ static int dump_one_eventpoll(int lfd, u32 id, const struct fd_parms *p) if (p->dfds) { for (i = j = 0; i < e.n_tfd; i++) { int tfd = find_tfd(p->pid, p->fd, p->dfds->fds, - p->dfds->nr_fds, e.tfd[i]->tfd); + p->dfds->nr_fds, e.tfd[i]->tfd, toff[i]); if (tfd == -1) { pr_warn("Escaped/closed fd descriptor %d on pid %d, ignoring\n", e.tfd[i]->tfd, p->pid); @@ -186,6 +207,7 @@ static int dump_one_eventpoll(int lfd, u32 id, const struct fd_parms *p) eventpoll_tfd_entry__free_unpacked(e.tfd[i], NULL); xfree(tfd_cpy); xfree(e.tfd); + xfree(toff); return ret; }