[CRIU] [PATCH 2/5] Unix socket for local connections is async.
rodrigo-bruno
rbruno at gsd.inesc-id.pt
Mon May 14 03:29:48 MSK 2018
From: Rodrigo Bruno <rbruno at gsd.inesc-id.pt>
---
criu/img-cache.c | 2 +
criu/img-proxy.c | 2 +
criu/img-remote.c | 158 ++++++++++++++++++++++++++++----------
criu/include/img-remote.h | 1 +
4 files changed, 124 insertions(+), 39 deletions(-)
diff --git a/criu/img-cache.c b/criu/img-cache.c
index 7020a30f..7b828b9b 100644
--- a/criu/img-cache.c
+++ b/criu/img-cache.c
@@ -125,6 +125,8 @@ int image_cache(bool background, char *local_cache_path, unsigned short cache_wr
return -1;
}
+ socket_set_non_blocking(local_req_fd);
+
if (init_daemon(background, wait_for_image)) {
pr_perror("Unable to initialize daemon");
return -1;
diff --git a/criu/img-proxy.c b/criu/img-proxy.c
index f56073b4..b63d69a0 100644
--- a/criu/img-proxy.c
+++ b/criu/img-proxy.c
@@ -60,6 +60,8 @@ int image_proxy(bool background, char *local_proxy_path, char *fwd_host, unsigne
return -1;
}
+ socket_set_non_blocking(local_req_fd);
+
if (opts.ps_socket != -1) {
proxy_to_cache_fd = opts.ps_socket;
pr_info("Re-using ps socket %d\n", proxy_to_cache_fd);
diff --git a/criu/img-remote.c b/criu/img-remote.c
index 70db71e2..4c566450 100644
--- a/criu/img-remote.c
+++ b/criu/img-remote.c
@@ -3,6 +3,7 @@
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/epoll.h>
#include <netinet/in.h>
#include <netdb.h>
#include "xmalloc.h"
@@ -24,6 +25,7 @@
#include "image.h"
#define PB_LOCAL_IMAGE_SIZE PATHLEN
+#define EPOLL_MAX_EVENTS 50
static char *snapshot_id;
bool restoring = true;
@@ -236,6 +238,8 @@ err:
return -1;
}
+
+
int setup_TCP_client_socket(char *hostname, int port)
{
int sockfd;
@@ -272,10 +276,33 @@ err:
return -1;
}
+int event_set(int epoll_fd, int op, int fd, uint32_t events, void *data)
+{
+ struct epoll_event event;
+ event.events = events;
+ event.data.ptr = data;
+ // TODO - check if this is okay to send a stack allocated object!
+ return epoll_ctl(epoll_fd, op, fd, &event);
+}
+
+void socket_set_non_blocking(int fd)
+{
+ int flags = fcntl(fd, F_GETFL, NULL);
+
+ if (flags < 0) {
+ pr_perror("Failed to obtain flags from fd %d", fd);
+ return;
+ }
+ flags |= O_NONBLOCK;
+
+ if (fcntl(fd, F_SETFL, flags) < 0)
+ pr_perror("Failed to set flags for fd %d", fd);
+}
+
int setup_UNIX_server_socket(char *path)
{
struct sockaddr_un addr;
- int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+ int sockfd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
if (sockfd < 0) {
pr_perror("Unable to open image socket");
@@ -609,59 +636,111 @@ static void *process_local_image_connection(void *ptr)
return NULL;
}
-
-void *accept_local_image_connections(void *port)
+void handle_local_accept(int fd)
{
- int fd = *((int *) port);
+ struct wthread *wt = NULL;
int cli_fd;
+ pthread_t tid;
struct sockaddr_in cli_addr;
-
socklen_t clilen = sizeof(cli_addr);
- pthread_t tid;
- struct wthread *wt;
- while (1) {
- cli_fd = accept(fd, (struct sockaddr *) &cli_addr, &clilen);
- if (cli_fd < 0) {
- if (!finished)
- pr_perror("Unable to accept local image connection");
- close(cli_fd);
- return NULL;
- }
+ cli_fd = accept(fd, (struct sockaddr *) &cli_addr, &clilen);
+ if (cli_fd < 0) {
+ pr_perror("Unable to accept local image connection");
+ goto err;
+ }
- wt = new_worker();
- wt->fd = cli_fd;
+ wt = new_worker();
+ wt->fd = cli_fd;
- if (read_header(wt->fd, wt->snapshot_id, wt->path, &(wt->flags)) < 0) {
- pr_err("Error reading local image header\n");
- goto err;
- }
+ if (read_header(wt->fd, wt->snapshot_id, wt->path, &(wt->flags)) < 0) {
+ pr_err("Error reading local image header\n");
+ goto err;
+ }
+
+ /* These function calls are used to avoid other threads from
+ * thinking that there are no more images are coming.
+ */
+ if (wt->flags != O_RDONLY) {
+ prepare_recv_rimg();
+ prepare_fwd_rimg();
+ }
- pr_info("Received %s request for %s:%s\n",
- wt->flags == O_RDONLY ? "read" :
+ pr_info("Received %s request for %s:%s\n",
+ wt->flags == O_RDONLY ? "read" :
wt->flags == O_APPEND ? "append" : "write",
- wt->path, wt->snapshot_id);
-
- /* These function calls are used to avoid other threads from
- * thinking that there are no more images are coming.
- */
- if (wt->flags != O_RDONLY) {
- prepare_recv_rimg();
- prepare_fwd_rimg();
- }
+ wt->path, wt->snapshot_id);
- if (pthread_create(
- &tid, NULL, process_local_image_connection, (void *) wt)) {
- pr_perror("Unable to create worker thread");
- goto err;
- }
- wt->tid = tid;
- add_worker(wt);
+ if (pthread_create(
+ &tid, NULL, process_local_image_connection, (void *) wt)) {
+ pr_perror("Unable to create worker thread");
+ goto err;
}
+ wt->tid = tid;
+ add_worker(wt);
+ return;
err:
close(cli_fd);
free(wt);
+}
+
+
+void *accept_local_image_connections(void *port)
+{
+ int fd = *((int *) port);
+ int epoll_fd;
+ struct epoll_event *events;
+ int ret;
+
+ epoll_fd = epoll_create(EPOLL_MAX_EVENTS);
+ if (epoll_fd < 0) {
+ pr_perror("Unable to open epoll");
+ return NULL;
+ }
+
+ events = calloc(EPOLL_MAX_EVENTS, sizeof(struct epoll_event));
+ if (events == NULL) {
+ pr_perror("Failed to allocated epoll events");
+ goto end;
+ }
+
+ ret = event_set(epoll_fd, EPOLL_CTL_ADD, fd, EPOLLIN, &fd);
+ if (ret) {
+ pr_perror("Failed to set event for epoll");
+ goto end;
+ }
+
+ while (1) {
+ int n_events = epoll_wait(epoll_fd, events, EPOLL_MAX_EVENTS, -1);
+ if (n_events < 0) {
+ pr_perror("Failed to epoll wait");
+ goto end;
+ }
+
+ for (int i = 0; i < n_events; i++) {
+ if (events[i].data.ptr == &fd) {
+ if ( events[i].events & EPOLLHUP ||
+ events[i].events & EPOLLERR) {
+ if (!finished)
+ pr_perror("Unable to accept more local image connections");
+ goto end;
+ }
+ // accept
+ pr_perror("Calling accept %d", i);
+ handle_local_accept(fd);
+ }
+ else {
+ // TODO - handle write/read
+ pr_perror("Event on unexpected file descripor");
+ goto end;
+ }
+ }
+ }
+end:
+ close(epoll_fd);
+ close(fd);
+ free(events);
return NULL;
}
@@ -680,6 +759,7 @@ int64_t recv_image(int fd, struct rimage *rimg, uint64_t size, int flags, bool c
while ((ret = recv_image_async(op)) < 0)
if (ret != EAGAIN && ret != EWOULDBLOCK)
return -1;
+ free(op);
return ret;
}
diff --git a/criu/include/img-remote.h b/criu/include/img-remote.h
index 0947e7f0..779a137f 100644
--- a/criu/include/img-remote.h
+++ b/criu/include/img-remote.h
@@ -108,6 +108,7 @@ int64_t write_remote_header(int fd, char *snapshot_id, char *path, int open_mode
int setup_TCP_server_socket(int port);
int setup_TCP_client_socket(char *hostname, int port);
int setup_UNIX_server_socket(char *path);
+void socket_set_non_blocking(int fd);
/* Called by restore to get the fd correspondent to a particular path. This call
* will block until the connection is received.
--
2.17.0
More information about the CRIU
mailing list