[CRIU] [PATCH v6 04/13] files: Add new_fd parameter to file_desc_ops::open()

Kirill Tkhai ktkhai at virtuozzo.com
Wed Jan 18 03:58:04 PST 2017


Return results of work separate: a new fd is in a parameter,
a status is in return value.

In next patches we will use return value "1" to indicate,
that open callback should be called once again, and restore
for this fle has not finished yet. So, we need to be able
to differ file descriptor with number 1 and "again" request.
We do not use negative value like -2 for this purpose,
because we want to allow fles to be served out before
they are completelly restored. So, if a fle is successefuly open,
but it's need one more call of open to complete its restore,
then we return 1 and populate new_fd in not negative value.
See "files: Kill struct file_desc_ops::post_open" for the details.

Also, export open_pipe()

v5: Use 0 and -1 for successful return and error.
v6: Rebase on new criu

Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
 criu/eventfd.c       |    5 +++--
 criu/eventpoll.c     |    5 +++--
 criu/fifo.c          |    9 +++++++--
 criu/files-ext.c     |    5 +++--
 criu/files-reg.c     |   10 ++++++++--
 criu/files.c         |    3 +--
 criu/fsnotify.c      |   10 ++++++----
 criu/include/files.h |    2 +-
 criu/include/pipes.h |    1 +
 criu/namespaces.c    |    5 +++--
 criu/pipes.c         |   19 +++++++++++--------
 criu/signalfd.c      |    5 +++--
 criu/sk-inet.c       |    7 ++++---
 criu/sk-netlink.c    |    5 +++--
 criu/sk-packet.c     |   12 +++++++-----
 criu/sk-unix.c       |   32 ++++++++++++++++++--------------
 criu/timerfd.c       |    5 +++--
 criu/tty.c           |   18 +++++++++++-------
 criu/tun.c           |    9 +++++----
 19 files changed, 101 insertions(+), 66 deletions(-)

diff --git a/criu/eventfd.c b/criu/eventfd.c
index 0aab4287e..68edb1c56 100644
--- a/criu/eventfd.c
+++ b/criu/eventfd.c
@@ -79,7 +79,7 @@ const struct fdtype_ops eventfd_dump_ops = {
 	.dump		= dump_one_eventfd,
 };
 
-static int eventfd_open(struct file_desc *d)
+static int eventfd_open(struct file_desc *d, int *new_fd)
 {
 	struct eventfd_file_info *info;
 	int tmp;
@@ -99,7 +99,8 @@ static int eventfd_open(struct file_desc *d)
 		goto err_close;
 	}
 
-	return tmp;
+	*new_fd = tmp;
+	return 0;
 
 err_close:
 	close(tmp);
diff --git a/criu/eventpoll.c b/criu/eventpoll.c
index 42a656f31..aaea54a56 100644
--- a/criu/eventpoll.c
+++ b/criu/eventpoll.c
@@ -114,7 +114,7 @@ const struct fdtype_ops eventpoll_dump_ops = {
 	.dump		= dump_one_eventpoll,
 };
 
-static int eventpoll_open(struct file_desc *d)
+static int eventpoll_open(struct file_desc *d, int *new_fd)
 {
 	struct eventpoll_file_info *info;
 	int tmp;
@@ -136,7 +136,8 @@ static int eventpoll_open(struct file_desc *d)
 		goto err_close;
 	}
 
-	return tmp;
+	*new_fd = tmp;
+	return 0;
 err_close:
 	close(tmp);
 	return -1;
diff --git a/criu/fifo.c b/criu/fifo.c
index 68f55b4e5..cb642befc 100644
--- a/criu/fifo.c
+++ b/criu/fifo.c
@@ -106,11 +106,16 @@ static int do_open_fifo(int ns_root_fd, struct reg_file_info *rfi, void *arg)
 	return new_fifo;
 }
 
-static int open_fifo_fd(struct file_desc *d)
+static int open_fifo_fd(struct file_desc *d, int *new_fd)
 {
 	struct fifo_info *info = container_of(d, struct fifo_info, d);
+	int fd;
 
-	return open_path(info->reg_d, do_open_fifo, info);
+	fd = open_path(info->reg_d, do_open_fifo, info);
+	if (fd < 0)
+		return -1;
+	*new_fd = fd;
+	return 0;
 }
 
 static void collect_fifo_fd(struct file_desc *d,
diff --git a/criu/files-ext.c b/criu/files-ext.c
index 4c129fa64..df23ec671 100644
--- a/criu/files-ext.c
+++ b/criu/files-ext.c
@@ -37,7 +37,7 @@ struct ext_file_info {
 	ExtFileEntry		*xfe;
 };
 
-static int open_fd(struct file_desc *d)
+static int open_fd(struct file_desc *d, int *new_fd)
 {
 	struct ext_file_info *xfi;
 	int fd;
@@ -53,7 +53,8 @@ static int open_fd(struct file_desc *d)
 	if (restore_fown(fd, xfi->xfe->fown))
 		return -1;
 
-	return fd;
+	*new_fd = fd;
+	return 0;
 }
 
 static struct file_desc_ops ext_desc_ops = {
diff --git a/criu/files-reg.c b/criu/files-reg.c
index 73a1838c9..6e488e898 100644
--- a/criu/files-reg.c
+++ b/criu/files-reg.c
@@ -1659,9 +1659,15 @@ static void collect_reg_fd(struct file_desc *fdesc,
 	collect_gen_fd(fle, ri);
 }
 
-static int open_fe_fd(struct file_desc *fd)
+static int open_fe_fd(struct file_desc *fd, int *new_fd)
 {
-	return open_path(fd, do_open_reg, NULL);
+	int tmp;
+
+	tmp = open_path(fd, do_open_reg, NULL);
+	if (tmp < 0)
+		return -1;
+	*new_fd = tmp;
+	return 0;
 }
 
 static char *reg_file_path(struct file_desc *d, char *buf, size_t s)
diff --git a/criu/files.c b/criu/files.c
index 944e1477e..342e728eb 100644
--- a/criu/files.c
+++ b/criu/files.c
@@ -1053,8 +1053,7 @@ static int open_fd(int pid, struct fdinfo_list_entry *fle)
 	if (fle != file_master(d))
 		return 0;
 
-	new_fd = d->ops->open(d);
-	if (new_fd < 0)
+	if (d->ops->open(d, &new_fd) < 0)
 		return -1;
 
 	if (reopen_fd_as(fle->fe->fd, new_fd))
diff --git a/criu/fsnotify.c b/criu/fsnotify.c
index 07ccca964..0dcb07c7c 100644
--- a/criu/fsnotify.c
+++ b/criu/fsnotify.c
@@ -674,7 +674,7 @@ static int restore_one_fanotify(int fd, struct fsnotify_mark_info *mark)
 	return ret;
 }
 
-static int open_inotify_fd(struct file_desc *d)
+static int open_inotify_fd(struct file_desc *d, int *new_fd)
 {
 	struct fsnotify_file_info *info;
 	struct fsnotify_mark_info *wd_info;
@@ -699,10 +699,11 @@ static int open_inotify_fd(struct file_desc *d)
 	if (restore_fown(tmp, info->ife->fown))
 		close_safe(&tmp);
 
-	return tmp;
+	*new_fd = tmp;
+	return 0;
 }
 
-static int open_fanotify_fd(struct file_desc *d)
+static int open_fanotify_fd(struct file_desc *d, int *new_fd)
 {
 	struct fsnotify_file_info *info;
 	struct fsnotify_mark_info *mark;
@@ -734,7 +735,8 @@ static int open_fanotify_fd(struct file_desc *d)
 	if (restore_fown(ret, info->ffe->fown))
 		close_safe(&ret);
 
-	return ret;
+	*new_fd = ret;
+	return 0;
 }
 
 static struct file_desc_ops inotify_desc_ops = {
diff --git a/criu/include/files.h b/criu/include/files.h
index 8cc29996f..c3979ff4a 100644
--- a/criu/include/files.h
+++ b/criu/include/files.h
@@ -104,7 +104,7 @@ struct file_desc_ops {
 	 * The returned descriptor may be closed (dup2-ed to another)
 	 * so it shouldn't be saved for any post-actions.
 	 */
-	int			(*open)(struct file_desc *d);
+	int			(*open)(struct file_desc *d, int *new_fd);
 	/*
 	 * Called on a file when all files of that type are opened
 	 * and with the fd being the "restored" one.
diff --git a/criu/include/pipes.h b/criu/include/pipes.h
index a16069bd2..47d98aee7 100644
--- a/criu/include/pipes.h
+++ b/criu/include/pipes.h
@@ -58,5 +58,6 @@ struct pipe_info {
 
 extern int collect_one_pipe_ops(void *o, ProtobufCMessage *base,
 				struct file_desc_ops *ops);
+extern int open_pipe(struct file_desc *d, int *new_fd);
 
 #endif /* __CR_PIPES_H__ */
diff --git a/criu/namespaces.c b/criu/namespaces.c
index 412362976..b954f9796 100644
--- a/criu/namespaces.c
+++ b/criu/namespaces.c
@@ -496,7 +496,7 @@ struct ns_file_info {
 	NsFileEntry		*nfe;
 };
 
-static int open_ns_fd(struct file_desc *d)
+static int open_ns_fd(struct file_desc *d, int *new_fd)
 {
 	struct ns_file_info *nfi = container_of(d, struct ns_file_info, d);
 	struct pstree_item *item, *t;
@@ -558,7 +558,8 @@ static int open_ns_fd(struct file_desc *d)
 		return fd;
 	}
 
-	return fd;
+	*new_fd = fd;
+	return 0;
 }
 
 static struct file_desc_ops ns_desc_ops = {
diff --git a/criu/pipes.c b/criu/pipes.c
index 08dd7d19e..6eaabeb4b 100644
--- a/criu/pipes.c
+++ b/criu/pipes.c
@@ -227,7 +227,7 @@ static int reopen_pipe(int fd, int flags)
 	return ret;
 }
 
-static int recv_pipe_fd(struct pipe_info *pi)
+static int recv_pipe_fd(struct pipe_info *pi, int *new_fd)
 {
 	struct fdinfo_list_entry *fle;
 	int tmp, fd;
@@ -252,9 +252,10 @@ static int recv_pipe_fd(struct pipe_info *pi)
 			close(fd);
 			return -1;
 		}
+		*new_fd = fd;
 	}
 
-	return fd;
+	return fd < 0 ? -1 : 0;
 }
 
 static char *pipe_d_name(struct file_desc *d, char *buf, size_t s)
@@ -271,7 +272,7 @@ static char *pipe_d_name(struct file_desc *d, char *buf, size_t s)
 	return buf;
 }
 
-static int open_pipe(struct file_desc *d)
+int open_pipe(struct file_desc *d, int *new_fd)
 {
 	struct pipe_info *pi, *p;
 	int ret, tmp;
@@ -284,11 +285,11 @@ static int open_pipe(struct file_desc *d)
 			return tmp;
 
 		pi->reopen = 1;
-		goto out;
+		goto reopen;
 	}
 
 	if (!pi->create)
-		return recv_pipe_fd(pi);
+		return recv_pipe_fd(pi, new_fd);
 
 	if (pipe(pfd) < 0) {
 		pr_perror("Can't create pipe");
@@ -316,15 +317,17 @@ static int open_pipe(struct file_desc *d)
 	close(pfd[!(pi->pe->flags & O_WRONLY)]);
 	tmp = pfd[pi->pe->flags & O_WRONLY];
 
-out:
+reopen:
 	if (pi->reopen)
 		tmp = reopen_pipe(tmp, pi->pe->flags);
 
 	if (tmp >= 0)
 		if (rst_file_params(tmp, pi->pe->fown, pi->pe->flags))
 			return -1;
-
-	return tmp;
+	if (tmp < 0)
+		return -1;
+	*new_fd = tmp;
+	return 0;
 }
 
 static struct file_desc_ops pipe_desc_ops = {
diff --git a/criu/signalfd.c b/criu/signalfd.c
index 2f5db5879..7c3ab4f33 100644
--- a/criu/signalfd.c
+++ b/criu/signalfd.c
@@ -72,7 +72,7 @@ static void sigset_fill(sigset_t *to, unsigned long long from)
 		}
 }
 
-static int signalfd_open(struct file_desc *d)
+static int signalfd_open(struct file_desc *d, int *new_fd)
 {
 	struct signalfd_info *info;
 	int tmp;
@@ -94,7 +94,8 @@ static int signalfd_open(struct file_desc *d)
 		goto err_close;
 	}
 
-	return tmp;
+	*new_fd = tmp;
+	return 0;
 
 err_close:
 	close(tmp);
diff --git a/criu/sk-inet.c b/criu/sk-inet.c
index 470baa821..552f8bba3 100644
--- a/criu/sk-inet.c
+++ b/criu/sk-inet.c
@@ -484,7 +484,7 @@ int inet_collect_one(struct nlmsghdr *h, int family, int type)
 	return ret;
 }
 
-static int open_inet_sk(struct file_desc *d);
+static int open_inet_sk(struct file_desc *d, int *new_fd);
 static int post_open_inet_sk(struct file_desc *d, int sk);
 
 static struct file_desc_ops inet_desc_ops = {
@@ -604,7 +604,7 @@ int restore_ip_opts(int sk, IpOptsEntry *ioe)
 
 	return ret;
 }
-static int open_inet_sk(struct file_desc *d)
+static int open_inet_sk(struct file_desc *d, int *new_fd)
 {
 	struct inet_sk_info *ii;
 	InetSkEntry *ie;
@@ -701,7 +701,8 @@ static int open_inet_sk(struct file_desc *d)
 	if (restore_socket_opts(sk, ie->opts))
 		goto err;
 
-	return sk;
+	*new_fd = sk;
+	return 0;
 
 err:
 	close(sk);
diff --git a/criu/sk-netlink.c b/criu/sk-netlink.c
index dc5c4a105..e61aa4455 100644
--- a/criu/sk-netlink.c
+++ b/criu/sk-netlink.c
@@ -155,7 +155,7 @@ struct netlink_sock_info {
 	struct file_desc d;
 };
 
-static int open_netlink_sk(struct file_desc *d)
+static int open_netlink_sk(struct file_desc *d, int *new_fd)
 {
 	struct netlink_sock_info *nsi;
 	NetlinkSkEntry *nse;
@@ -206,7 +206,8 @@ static int open_netlink_sk(struct file_desc *d)
 	if (restore_socket_opts(sk, nse->opts))
 		goto err;
 
-	return sk;
+	*new_fd = sk;
+	return 0;
 err:
 	close(sk);
 	return -1;
diff --git a/criu/sk-packet.c b/criu/sk-packet.c
index a7657bfc3..841a4aae6 100644
--- a/criu/sk-packet.c
+++ b/criu/sk-packet.c
@@ -405,7 +405,7 @@ static int restore_rings(int sk, PacketSockEntry *psk)
 	return 0;
 }
 
-static int open_packet_sk_spkt(PacketSockEntry *pse)
+static int open_packet_sk_spkt(PacketSockEntry *pse, int *new_fd)
 {
 	struct sockaddr addr_spkt;
 	int sk;
@@ -447,14 +447,15 @@ static int open_packet_sk_spkt(PacketSockEntry *pse)
 	if (restore_socket_opts(sk, pse->opts))
 		goto err;
 
-	return sk;
+	*new_fd = sk;
+	return 0;
 
 err:
 	close(sk);
 	return -1;
 }
 
-static int open_packet_sk(struct file_desc *d)
+static int open_packet_sk(struct file_desc *d, int *new_fd)
 {
 	struct packet_sock_info *psi;
 	PacketSockEntry *pse;
@@ -467,7 +468,7 @@ static int open_packet_sk(struct file_desc *d)
 	pr_info("Opening packet socket id %#x\n", pse->id);
 
 	if (pse->type == SOCK_PACKET)
-		return open_packet_sk_spkt(pse);
+		return open_packet_sk_spkt(pse, new_fd);
 
 	sk = socket(PF_PACKET, pse->type, pse->protocol);
 	if (sk < 0) {
@@ -538,7 +539,8 @@ static int open_packet_sk(struct file_desc *d)
 	if (restore_socket_opts(sk, pse->opts))
 		goto err_cl;
 
-	return sk;
+	*new_fd = sk;
+	return 0;
 
 err_cl:
 	close(sk);
diff --git a/criu/sk-unix.c b/criu/sk-unix.c
index cb7a04df5..27badb857 100644
--- a/criu/sk-unix.c
+++ b/criu/sk-unix.c
@@ -1054,7 +1054,7 @@ static int bind_unix_sk(int sk, struct unix_sk_info *ui)
 	return ret;
 }
 
-static int open_unixsk_pair_master(struct unix_sk_info *ui)
+static int open_unixsk_pair_master(struct unix_sk_info *ui, int *new_fd)
 {
 	int sk[2];
 	struct unix_sk_info *peer = ui->peer;
@@ -1093,10 +1093,11 @@ static int open_unixsk_pair_master(struct unix_sk_info *ui)
 
 	close(sk[1]);
 
-	return sk[0];
+	*new_fd = sk[0];
+	return 0;
 }
 
-static int open_unixsk_pair_slave(struct unix_sk_info *ui)
+static int open_unixsk_pair_slave(struct unix_sk_info *ui, int *new_fd)
 {
 	struct fdinfo_list_entry *fle;
 	int sk;
@@ -1124,10 +1125,11 @@ static int open_unixsk_pair_slave(struct unix_sk_info *ui)
 	if (shutdown_unix_sk(sk, ui))
 		return -1;
 
-	return sk;
+	*new_fd = sk;
+	return 0;
 }
 
-static int open_unixsk_standalone(struct unix_sk_info *ui)
+static int open_unixsk_standalone(struct unix_sk_info *ui, int *new_fd)
 {
 	int sk;
 
@@ -1264,26 +1266,28 @@ static int open_unixsk_standalone(struct unix_sk_info *ui)
 	if (restore_socket_opts(sk, ui->ue->opts))
 		return -1;
 
-	return sk;
+	*new_fd = sk;
+	return 0;
 }
 
-static int open_unix_sk(struct file_desc *d)
+static int open_unix_sk(struct file_desc *d, int *new_fd)
 {
 	struct unix_sk_info *ui;
+	int ret;
 
 	ui = container_of(d, struct unix_sk_info, d);
 
-	int unixsk_fd = -1;
-
-	if (inherited_fd(d, &unixsk_fd)) {
+	if (inherited_fd(d, new_fd)) {
 		ui->ue->uflags |= USK_INHERIT;
-		return unixsk_fd;
+		ret = *new_fd >= 0 ? 0 : -1;
 	} else if (ui->flags & USK_PAIR_MASTER)
-		return open_unixsk_pair_master(ui);
+		ret = open_unixsk_pair_master(ui, new_fd);
 	else if (ui->flags & USK_PAIR_SLAVE)
-		return open_unixsk_pair_slave(ui);
+		ret = open_unixsk_pair_slave(ui, new_fd);
 	else
-		return open_unixsk_standalone(ui);
+		ret = open_unixsk_standalone(ui, new_fd);
+
+	return ret;
 }
 
 static char *socket_d_name(struct file_desc *d, char *buf, size_t s)
diff --git a/criu/timerfd.c b/criu/timerfd.c
index a18588c05..476bf602e 100644
--- a/criu/timerfd.c
+++ b/criu/timerfd.c
@@ -122,7 +122,7 @@ int prepare_timerfds(struct task_restore_args *ta)
 	return 0;
 }
 
-static int timerfd_open(struct file_desc *d)
+static int timerfd_open(struct file_desc *d, int *new_fd)
 {
 	struct timerfd_info *info;
 	TimerfdEntry *tfe;
@@ -150,7 +150,8 @@ static int timerfd_open(struct file_desc *d)
 	info->t_fd = file_master(d)->fe->fd;
 	list_add_tail(&info->rlist, &rst_timerfds);
 
-	return tmp;
+	*new_fd = tmp;
+	return 0;
 
 err_close:
 	close_safe(&tmp);
diff --git a/criu/tty.c b/criu/tty.c
index 97443e85e..8b342a95d 100644
--- a/criu/tty.c
+++ b/criu/tty.c
@@ -1093,19 +1093,23 @@ static int open_ext_tty(struct tty_info *info)
 	return fd;
 }
 
-static int tty_open(struct file_desc *d)
+static int tty_open(struct file_desc *d, int *new_fd)
 {
 	struct tty_info *info = container_of(d, struct tty_info, d);
+	int ret;
 
 	tty_show_pty_info("open", info);
 
 	if (!info->create)
-		return receive_tty(info);
-
-	if (is_pty(info->driver) && !tty_is_master(info))
-		return pty_open_unpaired_slave(d, info);
-
-	return info->driver->open(info);
+		ret = receive_tty(info);
+	else if (is_pty(info->driver) && !tty_is_master(info))
+		ret = pty_open_unpaired_slave(d, info);
+	else
+		ret = info->driver->open(info);
+	if (ret < 0)
+		return -1;
+	*new_fd = ret;
+	return 0;
 }
 
 static void tty_collect_fd(struct file_desc *d, struct fdinfo_list_entry *fle,
diff --git a/criu/tun.c b/criu/tun.c
index 391f968bb..6a429b6c2 100644
--- a/criu/tun.c
+++ b/criu/tun.c
@@ -320,7 +320,7 @@ struct tunfile_info {
 	TunfileEntry *tfe;
 };
 
-static int tunfile_open(struct file_desc *d)
+static int tunfile_open(struct file_desc *d, int *new_fd)
 {
 	int fd;
 	struct tunfile_info *ti;
@@ -334,7 +334,7 @@ static int tunfile_open(struct file_desc *d)
 
 	if (!ti->tfe->netdev)
 		/* just-opened tun file */
-		return fd;
+		goto ok;;
 
 	tl = find_tun_link(ti->tfe->netdev);
 	if (!tl) {
@@ -367,8 +367,9 @@ static int tunfile_open(struct file_desc *d)
 			goto err;
 		}
 	}
-
-	return fd;
+ok:
+	*new_fd = fd;
+	return 0;
 
 err:
 	close(fd);



More information about the CRIU mailing list