mirror of
https://github.com/checkpoint-restore/criu
synced 2025-09-04 16:25:31 +00:00
remote: Minor improvements on img-remote.c
This commit is contained in:
committed by
Andrei Vagin
parent
cb5f93675a
commit
cc4cc0750c
@@ -44,14 +44,26 @@ LIST_HEAD(rop_forwarding);
|
|||||||
// List of snapshots (useful when doing incremental restores/dumps
|
// List of snapshots (useful when doing incremental restores/dumps
|
||||||
LIST_HEAD(snapshot_head);
|
LIST_HEAD(snapshot_head);
|
||||||
|
|
||||||
|
// Snapshot id (setup at launch time by dump or restore).
|
||||||
static char *snapshot_id;
|
static char *snapshot_id;
|
||||||
bool restoring = true; // TODO - check where this is used!
|
|
||||||
// TODO - split this into two vars, recv_from_proxy, send_to_cache
|
// True if restoring (cache := true; proxy := false).
|
||||||
bool forwarding = false; // TODO - true if proxy_to_cache_fd is being used.
|
bool restoring = true;
|
||||||
|
|
||||||
|
// True if the proxy to cache socket is being used (receiving or sending).
|
||||||
|
bool forwarding = false;
|
||||||
|
|
||||||
|
// True if the local dump or restore is finished.
|
||||||
bool finished_local = false;
|
bool finished_local = false;
|
||||||
|
|
||||||
|
// True if the communication between the proxy and cache can be closed.
|
||||||
bool finished_remote = false;
|
bool finished_remote = false;
|
||||||
|
|
||||||
|
// Proxy to cache socket fd; Local dump or restore servicing fd.
|
||||||
int proxy_to_cache_fd;
|
int proxy_to_cache_fd;
|
||||||
int local_req_fd;
|
int local_req_fd;
|
||||||
|
|
||||||
|
// Epoll fd and event array.
|
||||||
int epoll_fd;
|
int epoll_fd;
|
||||||
struct epoll_event *events;
|
struct epoll_event *events;
|
||||||
|
|
||||||
@@ -457,7 +469,7 @@ static struct rimage *clear_remote_image(struct rimage *rimg)
|
|||||||
return rimg;
|
return rimg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_accept_write(
|
struct roperation* handle_accept_write(
|
||||||
int cli_fd, char* snapshot_id, char* path, int flags, bool close_fd, uint64_t size)
|
int cli_fd, char* snapshot_id, char* path, int flags, bool close_fd, uint64_t size)
|
||||||
{
|
{
|
||||||
struct roperation *rop = NULL;
|
struct roperation *rop = NULL;
|
||||||
@@ -484,25 +496,24 @@ void handle_accept_write(
|
|||||||
|
|
||||||
rop_set_rimg(rop, rimg);
|
rop_set_rimg(rop, rimg);
|
||||||
rop->size = size;
|
rop->size = size;
|
||||||
list_add_tail(&(rop->l), &rop_inprogress);
|
return rop;
|
||||||
event_set(epoll_fd, EPOLL_CTL_ADD, rop->fd, EPOLLIN, rop);
|
|
||||||
return;
|
|
||||||
err:
|
err:
|
||||||
free(rimg);
|
free(rimg);
|
||||||
free(rop);
|
free(rop);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_accept_proxy_write(
|
struct roperation* handle_accept_proxy_write(
|
||||||
int cli_fd, char* snapshot_id, char* path, int flags)
|
int cli_fd, char* snapshot_id, char* path, int flags)
|
||||||
{
|
{
|
||||||
handle_accept_write(cli_fd, snapshot_id, path, flags, true, 0);
|
return handle_accept_write(cli_fd, snapshot_id, path, flags, true, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_accept_proxy_read(
|
struct roperation* handle_accept_proxy_read(
|
||||||
int cli_fd, char* snapshot_id, char* path, int flags)
|
int cli_fd, char* snapshot_id, char* path, int flags)
|
||||||
{
|
{
|
||||||
struct roperation *rop = NULL;
|
struct roperation *rop = NULL;
|
||||||
struct rimage *rimg = NULL;
|
struct rimage *rimg = NULL;
|
||||||
|
|
||||||
rimg = get_rimg_by_name(snapshot_id, path);
|
rimg = get_rimg_by_name(snapshot_id, path);
|
||||||
|
|
||||||
@@ -513,40 +524,40 @@ void handle_accept_proxy_read(
|
|||||||
pr_perror("Error writing reply header for unexisting image");
|
pr_perror("Error writing reply header for unexisting image");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
close(cli_fd);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if (write_reply_header(cli_fd, 0) < 0) {
|
|
||||||
pr_perror("Error writing reply header for %s:%s",
|
|
||||||
path, snapshot_id);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
rop = new_remote_operation(path, snapshot_id, cli_fd, flags, true);
|
if (write_reply_header(cli_fd, 0) < 0) {
|
||||||
if (rop == NULL) {
|
pr_perror("Error writing reply header for %s:%s",
|
||||||
pr_perror("Error preparing remote operation");
|
path, snapshot_id);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
|
||||||
rop_set_rimg(rop, rimg);
|
|
||||||
list_add_tail(&(rop->l), &rop_inprogress);
|
|
||||||
event_set(epoll_fd, EPOLL_CTL_ADD, rop->fd, EPOLLOUT, rop);
|
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
|
rop = new_remote_operation(path, snapshot_id, cli_fd, flags, true);
|
||||||
|
if (rop == NULL) {
|
||||||
|
pr_perror("Error preparing remote operation");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
rop_set_rimg(rop, rimg);
|
||||||
|
return rop;
|
||||||
err:
|
err:
|
||||||
close(cli_fd);
|
close(cli_fd);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void finish_local()
|
void finish_local()
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
finished_local = true;
|
finished_local = true;
|
||||||
//shutdown(local_req_fd, SHUT_RD); //TODO - should this be removed?
|
|
||||||
ret = event_set(epoll_fd, EPOLL_CTL_DEL, local_req_fd, 0, 0);
|
ret = event_set(epoll_fd, EPOLL_CTL_DEL, local_req_fd, 0, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_perror("Failed to del local fd from epoll");
|
pr_perror("Failed to del local fd from epoll");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_accept_cache_read(
|
struct roperation* handle_accept_cache_read(
|
||||||
int cli_fd, char* snapshot_id, char* path, int flags)
|
int cli_fd, char* snapshot_id, char* path, int flags)
|
||||||
{
|
{
|
||||||
struct rimage *rimg = NULL;
|
struct rimage *rimg = NULL;
|
||||||
@@ -556,14 +567,14 @@ void handle_accept_cache_read(
|
|||||||
if (!strncmp(path, RESTORE_FINISH, sizeof(RESTORE_FINISH))) {
|
if (!strncmp(path, RESTORE_FINISH, sizeof(RESTORE_FINISH))) {
|
||||||
close(cli_fd);
|
close(cli_fd);
|
||||||
finish_local();
|
finish_local();
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rop = new_remote_operation(path, snapshot_id, cli_fd, flags, true);
|
rop = new_remote_operation(path, snapshot_id, cli_fd, flags, true);
|
||||||
if (rop == NULL) {
|
if (rop == NULL) {
|
||||||
pr_perror("Error preparing remote operation");
|
pr_perror("Error preparing remote operation");
|
||||||
close(cli_fd);
|
close(cli_fd);
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we already have the image.
|
// Check if we already have the image.
|
||||||
@@ -576,28 +587,25 @@ void handle_accept_cache_read(
|
|||||||
close(rop->fd);
|
close(rop->fd);
|
||||||
}
|
}
|
||||||
rop_set_rimg(rop, rimg);
|
rop_set_rimg(rop, rimg);
|
||||||
list_add_tail(&(rop->l), &rop_inprogress);
|
return rop;
|
||||||
event_set(epoll_fd, EPOLL_CTL_ADD, rop->fd, EPOLLOUT, rop);
|
|
||||||
}
|
|
||||||
// The file may exist in future.
|
|
||||||
else if (!finished_remote){
|
|
||||||
list_add_tail(&(rop->l), &rop_pending);
|
|
||||||
}
|
}
|
||||||
// The file does not exist.
|
// The file does not exist.
|
||||||
else {
|
else if (finished_remote) {
|
||||||
pr_info("No image %s:%s.\n", path, snapshot_id);
|
pr_info("No image %s:%s.\n", path, snapshot_id);
|
||||||
if (write_reply_header(cli_fd, ENOENT) < 0)
|
if (write_reply_header(cli_fd, ENOENT) < 0)
|
||||||
pr_perror("Error writing reply header for unexisting image");
|
pr_perror("Error writing reply header for unexisting image");
|
||||||
free(rop);
|
free(rop);
|
||||||
close(cli_fd);
|
close(cli_fd);
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void forward_remote_image(struct roperation* rop)
|
void forward_remote_image(struct roperation* rop)
|
||||||
{
|
{
|
||||||
uint64_t ret = 0;
|
uint64_t ret = 0;
|
||||||
|
|
||||||
// Set blocking during the setup.
|
// Set blocking during the setup.
|
||||||
// socket_set_blocking(rop->fd); // TODO - test
|
socket_set_blocking(rop->fd);
|
||||||
|
|
||||||
ret = write_remote_header(
|
ret = write_remote_header(
|
||||||
rop->fd, rop->snapshot_id, rop->path, rop->flags, rop->size);
|
rop->fd, rop->snapshot_id, rop->path, rop->flags, rop->size);
|
||||||
@@ -616,7 +624,7 @@ void forward_remote_image(struct roperation* rop)
|
|||||||
|
|
||||||
|
|
||||||
// Go back to non-blocking
|
// Go back to non-blocking
|
||||||
// socket_set_non_blocking(rop->fd); // TODO - test
|
socket_set_non_blocking(rop->fd);
|
||||||
|
|
||||||
forwarding = true;
|
forwarding = true;
|
||||||
event_set(epoll_fd, EPOLL_CTL_ADD, rop->fd, EPOLLOUT, rop);
|
event_set(epoll_fd, EPOLL_CTL_ADD, rop->fd, EPOLLOUT, rop);
|
||||||
@@ -629,9 +637,10 @@ void handle_remote_accept(int fd)
|
|||||||
int flags;
|
int flags;
|
||||||
uint64_t size = 0;
|
uint64_t size = 0;
|
||||||
uint64_t ret;
|
uint64_t ret;
|
||||||
|
struct roperation* rop = NULL;
|
||||||
|
|
||||||
// Set blocking during the setup.
|
// Set blocking during the setup.
|
||||||
// socket_set_blocking(fd); // TODO - test!
|
socket_set_blocking(fd);
|
||||||
|
|
||||||
ret = read_remote_header(fd, snapshot_id, path, &flags, &size);
|
ret = read_remote_header(fd, snapshot_id, path, &flags, &size);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -646,7 +655,7 @@ void handle_remote_accept(int fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Go back to non-blocking
|
// Go back to non-blocking
|
||||||
// socket_set_non_blocking(fd); // TODO - test!
|
socket_set_non_blocking(fd);
|
||||||
|
|
||||||
pr_info("[fd=%d] Received %s request for %s:%s with %lu bytes\n",
|
pr_info("[fd=%d] Received %s request for %s:%s with %lu bytes\n",
|
||||||
fd,
|
fd,
|
||||||
@@ -656,8 +665,13 @@ void handle_remote_accept(int fd)
|
|||||||
|
|
||||||
|
|
||||||
forwarding = true;
|
forwarding = true;
|
||||||
handle_accept_write(fd, snapshot_id, path, flags, false, size);
|
rop = handle_accept_write(fd, snapshot_id, path, flags, false, size);
|
||||||
return;
|
|
||||||
|
if (rop != NULL) {
|
||||||
|
list_add_tail(&(rop->l), &rop_inprogress);
|
||||||
|
event_set(epoll_fd, EPOLL_CTL_ADD, rop->fd, EPOLLIN, rop);
|
||||||
|
}
|
||||||
|
return;
|
||||||
err:
|
err:
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
@@ -670,6 +684,7 @@ void handle_local_accept(int fd)
|
|||||||
int flags = 0;
|
int flags = 0;
|
||||||
struct sockaddr_in cli_addr;
|
struct sockaddr_in cli_addr;
|
||||||
socklen_t clilen = sizeof(cli_addr);
|
socklen_t clilen = sizeof(cli_addr);
|
||||||
|
struct roperation *rop = NULL;
|
||||||
|
|
||||||
cli_fd = accept(fd, (struct sockaddr *) &cli_addr, &clilen);
|
cli_fd = accept(fd, (struct sockaddr *) &cli_addr, &clilen);
|
||||||
if (cli_fd < 0) {
|
if (cli_fd < 0) {
|
||||||
@@ -690,19 +705,32 @@ void handle_local_accept(int fd)
|
|||||||
|
|
||||||
// Write/Append case (only possible in img-proxy).
|
// Write/Append case (only possible in img-proxy).
|
||||||
if (flags != O_RDONLY) {
|
if (flags != O_RDONLY) {
|
||||||
handle_accept_proxy_write(cli_fd, snapshot_id, path, flags);
|
rop = handle_accept_proxy_write(cli_fd, snapshot_id, path, flags);
|
||||||
}
|
}
|
||||||
// Read case while restoring (img-cache).
|
// Read case while restoring (img-cache).
|
||||||
else if (restoring) {
|
else if (restoring) {
|
||||||
handle_accept_cache_read(cli_fd, snapshot_id, path, flags);
|
rop = handle_accept_cache_read(cli_fd, snapshot_id, path, flags);
|
||||||
}
|
}
|
||||||
// Read case while dumping (img-proxy).
|
// Read case while dumping (img-proxy).
|
||||||
else {
|
else {
|
||||||
handle_accept_proxy_read(cli_fd, snapshot_id, path, flags);
|
rop = handle_accept_proxy_read(cli_fd, snapshot_id, path, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set socket non-blocking.
|
// If we have an operation. Check if we are ready to start or not.
|
||||||
socket_set_non_blocking(cli_fd);
|
if (rop != NULL) {
|
||||||
|
if (rop->rimg != NULL) {
|
||||||
|
list_add_tail(&(rop->l), &rop_inprogress);
|
||||||
|
event_set(
|
||||||
|
epoll_fd,
|
||||||
|
EPOLL_CTL_ADD,
|
||||||
|
rop->fd,
|
||||||
|
rop->flags == O_RDONLY ? EPOLLOUT : EPOLLIN,
|
||||||
|
rop);
|
||||||
|
} else {
|
||||||
|
list_add_tail(&(rop->l), &rop_pending);
|
||||||
|
}
|
||||||
|
socket_set_non_blocking(rop->fd);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
err:
|
err:
|
||||||
@@ -760,7 +788,6 @@ void finish_cache_write(struct roperation* rop)
|
|||||||
// Add image to list of images.
|
// Add image to list of images.
|
||||||
list_add_tail(&(rop->rimg->l), &rimg_head);
|
list_add_tail(&(rop->rimg->l), &rimg_head);
|
||||||
|
|
||||||
// TODO - what if we have multiple requests for the same name?
|
|
||||||
if (prop != NULL) {
|
if (prop != NULL) {
|
||||||
pr_info("\t[fd=%d] Resuming pending %s for %s:%s\n",
|
pr_info("\t[fd=%d] Resuming pending %s for %s:%s\n",
|
||||||
prop->fd,
|
prop->fd,
|
||||||
@@ -949,31 +976,17 @@ void accept_image_connections() {
|
|||||||
|
|
||||||
// If both local and remote sockets are closed, leave.
|
// If both local and remote sockets are closed, leave.
|
||||||
if (finished_local && finished_remote) {
|
if (finished_local && finished_remote) {
|
||||||
pr_info("\tFinished both local and remote, exiting\n");
|
pr_info("Finished both local and remote, exiting\n");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
// TODO - release pending when no receiving and finished.
|
|
||||||
close(epoll_fd);
|
close(epoll_fd);
|
||||||
close(local_req_fd);
|
close(local_req_fd);
|
||||||
free(events);
|
free(events);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int64_t recv_image(int fd, struct rimage *rimg, uint64_t size, int flags, bool close_fd)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
struct roperation *op = new_remote_operation(
|
|
||||||
rimg->path, rimg->snapshot_id, fd, flags, close_fd);
|
|
||||||
rop_set_rimg(op, rimg);
|
|
||||||
while ((ret = recv_image_async(op)) < 0)
|
|
||||||
if (ret != EAGAIN && ret != EWOULDBLOCK)
|
|
||||||
return -1;
|
|
||||||
free(op);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note: size is a limit on how much we want to read from the socket. Zero means
|
/* Note: size is a limit on how much we want to read from the socket. Zero means
|
||||||
* read until the socket is closed.
|
* read until the socket is closed.
|
||||||
*/
|
*/
|
||||||
@@ -1028,18 +1041,6 @@ int64_t recv_image_async(struct roperation *op)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t send_image(int fd, struct rimage *rimg, int flags, bool close_fd)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
struct roperation *op = new_remote_operation(
|
|
||||||
rimg->path, rimg->snapshot_id, fd, flags, close_fd);
|
|
||||||
rop_set_rimg(op, rimg);
|
|
||||||
while ((ret = send_image_async(op)) < 0)
|
|
||||||
if (ret != EAGAIN && ret != EWOULDBLOCK)
|
|
||||||
return -1;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t send_image_async(struct roperation *op)
|
int64_t send_image_async(struct roperation *op)
|
||||||
{
|
{
|
||||||
int fd = op->fd;
|
int fd = op->fd;
|
||||||
@@ -1060,7 +1061,6 @@ int64_t send_image_async(struct roperation *op)
|
|||||||
op->curr_sent_bytes = 0;
|
op->curr_sent_bytes = 0;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
// TODO - cloudn't we just compare to the img size?
|
|
||||||
else if (op->curr_sent_bytes == op->curr_sent_buf->nbytes) {
|
else if (op->curr_sent_bytes == op->curr_sent_buf->nbytes) {
|
||||||
if (close_fd)
|
if (close_fd)
|
||||||
close(fd);
|
close(fd);
|
||||||
@@ -1068,7 +1068,6 @@ int64_t send_image_async(struct roperation *op)
|
|||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
// TODO - clouldn't these checks be made upstream?
|
|
||||||
else if (errno == EPIPE || errno == ECONNRESET) {
|
else if (errno == EPIPE || errno == ECONNRESET) {
|
||||||
pr_warn("Connection for %s:%s was closed early than expected\n",
|
pr_warn("Connection for %s:%s was closed early than expected\n",
|
||||||
rimg->path, rimg->snapshot_id);
|
rimg->path, rimg->snapshot_id);
|
||||||
|
Reference in New Issue
Block a user