[CRIU] [PATCH] util: use F_DUPFD when we don't want to overwrite an existing descriptor
Andrei Vagin
avagin at gmail.com
Tue May 21 10:13:27 MSK 2019
Right now we use fcntl(F_GETFD) to check whether a target descriptor
is used and then we call dup2(). Actually, we can do this for one system
call.
Cc: Cyrill Gorcunov <gorcunov at openvz.org>
Signed-off-by: Andrei Vagin <avagin at gmail.com>
---
criu/include/servicefd.h | 11 -----------
criu/servicefd.c | 37 +++++++++++++++++++++++--------------
criu/util.c | 18 +++++++++---------
3 files changed, 32 insertions(+), 34 deletions(-)
diff --git a/criu/include/servicefd.h b/criu/include/servicefd.h
index 7be472cf4..986c46af5 100644
--- a/criu/include/servicefd.h
+++ b/criu/include/servicefd.h
@@ -35,17 +35,6 @@ struct pstree_item;
extern bool sfds_protected;
-#define sfd_verify_target(_type, _old_fd, _new_fd) \
- ({ \
- int __ret = 0; \
- if (fcntl(_new_fd, F_GETFD) != -1 && errno != EBADF) { \
- pr_err("%s busy target %d -> %d\n", \
- sfd_type_name(_type), _old_fd, _new_fd); \
- __ret = -1; \
- } \
- __ret; \
- })
-
extern const char *sfd_type_name(enum sfd_type type);
extern int init_service_fd(void);
extern int get_service_fd(enum sfd_type type);
diff --git a/criu/servicefd.c b/criu/servicefd.c
index 82147921c..dc423895b 100644
--- a/criu/servicefd.c
+++ b/criu/servicefd.c
@@ -153,6 +153,7 @@ static void sfds_protection_bug(enum sfd_type type)
int install_service_fd(enum sfd_type type, int fd)
{
int sfd = __get_service_fd(type, service_fd_id);
+ int tmp;
BUG_ON((int)type <= SERVICE_FD_MIN || (int)type >= SERVICE_FD_MAX);
if (sfds_protected && !test_bit(type, sfd_map))
@@ -166,16 +167,19 @@ int install_service_fd(enum sfd_type type, int fd)
return fd;
}
- if (!test_bit(type, sfd_map)) {
- if (sfd_verify_target(type, fd, sfd))
- return -1;
- }
-
- if (dup3(fd, sfd, O_CLOEXEC) != sfd) {
+ if (!test_bit(type, sfd_map))
+ tmp = fcntl(fd, F_DUPFD, sfd);
+ else
+ tmp = dup3(fd, sfd, O_CLOEXEC);
+ if (tmp < 0) {
pr_perror("%s dup %d -> %d failed",
sfd_type_name(type), fd, sfd);
close(fd);
return -1;
+ } else if (tmp != sfd) {
+ pr_err("%s busy target %d -> %d\n", sfd_type_name(type), fd, sfd);
+ close(fd);
+ return -1;
}
set_bit(type, sfd_map);
@@ -201,25 +205,30 @@ int close_service_fd(enum sfd_type type)
return 0;
}
-static void move_service_fd(struct pstree_item *me, int type, int new_id, int new_base)
+static int move_service_fd(struct pstree_item *me, int type, int new_id, int new_base)
{
int old = get_service_fd(type);
int new = new_base - type - SERVICE_FD_MAX * new_id;
int ret;
if (old < 0)
- return;
+ return 0;
if (!test_bit(type, sfd_map))
- sfd_verify_target(type, old, new);
-
- ret = dup2(old, new);
+ ret = fcntl(old, F_DUPFD, new);
+ else
+ ret = dup2(old, new);
if (ret == -1) {
- if (errno != EBADF)
- pr_perror("%s unable to clone %d->%d",
- sfd_type_name(type), old, new);
+ pr_perror("%s unable to clone %d->%d",
+ sfd_type_name(type), old, new);
+ return -1;
+ } else if (ret != new) {
+ pr_err("%s busy target %d -> %d\n", sfd_type_name(type), old, new);
+ return -1;
} else if (!(rsti(me)->clone_flags & CLONE_FILES))
close(old);
+
+ return 0;
}
static int choose_service_fd_base(struct pstree_item *me)
diff --git a/criu/util.c b/criu/util.c
index 41b6915b7..8faffb859 100644
--- a/criu/util.c
+++ b/criu/util.c
@@ -229,19 +229,19 @@ int reopen_fd_as_safe(char *file, int line, int new_fd, int old_fd, bool allow_r
int tmp;
if (old_fd != new_fd) {
- if (!allow_reuse_fd) {
- if (fcntl(new_fd, F_GETFD) != -1 || errno != EBADF) {
- pr_err("fd %d already in use (called at %s:%d)\n",
- new_fd, file, line);
- return -1;
- }
- }
-
- tmp = dup2(old_fd, new_fd);
+ if (!allow_reuse_fd)
+ tmp = fcntl(old_fd, F_DUPFD, new_fd);
+ else
+ tmp = dup2(old_fd, new_fd);
if (tmp < 0) {
pr_perror("Dup %d -> %d failed (called at %s:%d)",
old_fd, new_fd, file, line);
return tmp;
+ } else if (tmp != new_fd) {
+ close(tmp);
+ pr_err("fd %d already in use (called at %s:%d)\n",
+ new_fd, file, line);
+ return -1;
}
/* Just to have error message if failed */
--
2.20.1
More information about the CRIU
mailing list