[CRIU] [PATCH RFC 21/30] unix: Wait a peer using task_st futex
Kirill Tkhai
ktkhai at virtuozzo.com
Tue Nov 1 07:33:49 PDT 2016
Use new task_st futex notifier instead of per-socket.
The step to make open file non-blocking but task_st.
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
criu/sk-unix.c | 38 +++++++++++++++++++++++++++-----------
1 file changed, 27 insertions(+), 11 deletions(-)
diff --git a/criu/sk-unix.c b/criu/sk-unix.c
index a3301fc..49720da 100644
--- a/criu/sk-unix.c
+++ b/criu/sk-unix.c
@@ -785,13 +785,6 @@ struct unix_sk_info {
struct list_head node; /* To link in peer's connected list */
/*
- * Futex to signal when the socket is prepared. In particular, we
- * signal after bind()ing the socket if it is not in TCP_LISTEN, or
- * after listen() if the socket is in TCP_LISTEN.
- */
- futex_t prepared;
-
- /*
* For DGRAM sockets with queues, we should only restore the queue
* once although it may be open by more than one tid. This is the peer
* that should do the queueing.
@@ -814,6 +807,29 @@ static struct unix_sk_info *find_unix_sk_by_ino(int ino)
return NULL;
}
+static int wake_connected_sockets(struct unix_sk_info *ui)
+{
+ struct fdinfo_list_entry *fle;
+ struct unix_sk_info *tmp;
+
+ list_for_each_entry(tmp, &ui->connected, node) {
+ fle = file_master(&tmp->d);
+ set_fds_event(fle->pid);
+ }
+ return 0;
+}
+
+static bool peer_is_not_prepared(struct unix_sk_info *peer)
+{
+ struct fdinfo_list_entry *fle;
+ fle = file_master(&peer->d);
+
+ if (peer->ue->state != TCP_LISTEN)
+ return (fle->stage < FLE_BOUND) ? true : false;
+ else
+ return (fle->stage < FLE_LISTEN) ? true : false;
+}
+
static int shutdown_unix_sk(int sk, struct unix_sk_info *ui)
{
int how;
@@ -886,7 +902,8 @@ static int post_open_unix_sk(struct file_desc *d, int fd)
/* Skip external sockets */
if (!list_empty(&peer->d.fd_info_head))
- futex_wait_while(&peer->prepared, 0);
+ while (peer_is_not_prepared(peer))
+ wait_fds_event();
if (ui->ue->uflags & USK_INHERIT)
return 0;
@@ -1028,9 +1045,9 @@ static int bind_unix_sk(int sk, struct unix_sk_info *ui)
}
if (ui->ue->state != TCP_LISTEN) {
- futex_set_and_wake(&ui->prepared, 1);
fle = file_master(&ui->d);
fle->stage = FLE_BOUND;
+ wake_connected_sockets(ui);
}
ret = 0;
@@ -1240,9 +1257,9 @@ static int open_unixsk_standalone(struct unix_sk_info *ui)
pr_perror("Can't make usk listen");
return -1;
}
- futex_set_and_wake(&ui->prepared, 1);
fle = file_master(&ui->d);
fle->stage = FLE_LISTEN;
+ wake_connected_sockets(ui);
}
out:
if (rst_file_params(sk, ui->ue->fown, ui->ue->flags))
@@ -1347,7 +1364,6 @@ static int collect_one_unixsk(void *o, ProtobufCMessage *base, struct cr_img *i)
} else
ui->name = NULL;
- futex_init(&ui->prepared);
ui->queuer = 0;
ui->peer = NULL;
INIT_LIST_HEAD(&ui->connected);
More information about the CRIU
mailing list