Commit 0ddcfbf2 authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Pavel Emelyanov

parasite: Add interface for file descriptors draining

Just implemented but not yet used in dumping procedure,
this will be addressed in further patches.

Note the space for file descriptors is statically allocated
in 8K arguments area, not on stack.
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent d360133f
......@@ -42,6 +42,8 @@ struct parasite_dump_tid_addr;
extern int parasite_dump_tid_addr_seized(struct parasite_ctl *ctl,
pid_t pid, unsigned int **tid_add);
extern int parasite_drain_fds_seized(struct parasite_ctl *ctl, int *fds, int *lfds, int nr_fds);
extern int parasite_cure_seized(struct parasite_ctl *ctl);
extern struct parasite_ctl *parasite_infect_seized(pid_t pid,
struct list_head *vma_area_list);
......
......@@ -9,6 +9,8 @@
#include "image.h"
#include "sockets.h"
#include "util-net.h"
#define __parasite_head __used __section(.parasite.head.text)
#define PARASITE_STACK_SIZE 2048
......@@ -30,6 +32,7 @@ enum {
PARASITE_CMD_DUMP_MISC,
PARASITE_CMD_DUMP_TID_ADDR,
PARASITE_CMD_DUMP_SK_QUEUES,
PARASITE_CMD_DRAIN_FDS,
PARASITE_CMD_MAX,
};
......@@ -84,6 +87,17 @@ struct parasite_dump_sk_queues {
struct sk_queue_item items[0];
};
#define PARASITE_MAX_FDS (PAGE_SIZE / sizeof(int))
struct parasite_drain_fd {
parasite_status_t status;
struct sockaddr_un saddr;
int sun_len;
int fds[PARASITE_MAX_FDS];
int nr_fds;
};
/*
* Some useful offsets
*/
......
......@@ -605,6 +605,55 @@ out:
return ret;
}
int parasite_drain_fds_seized(struct parasite_ctl *ctl, int *fds, int *lfds, int nr_fds)
{
struct parasite_drain_fd *args;
parasite_status_t *st;
int ret = -1;
int sock;
args = xmalloc(sizeof(*args));
if (!args)
return -ENOMEM;
st = &args->status;
args->sun_len = gen_parasite_saddr(&args->saddr, (int)-2u);
args->nr_fds = nr_fds;
sock = socket(PF_UNIX, SOCK_DGRAM, 0);
if (sock < 0) {
pr_perror("Can't create socket");
ret = sock;
goto out;
}
ret = bind(sock, (struct sockaddr *)&args->saddr, args->sun_len);
if (ret < 0) {
pr_perror("Can't bind socket");
goto err;
}
memcpy(&args->fds, fds, sizeof(int) * nr_fds);
ret = parasite_execute(PARASITE_CMD_DRAIN_FDS, ctl, st, sizeof(*args));
if (ret) {
pr_err("Parasite failed to drain descriptors\n");
goto err;
}
ret = recv_fds(sock, lfds, nr_fds);
if (ret) {
pr_err("Can't retrieve FDs from socket\n");
goto err;
}
err:
close(sock);
out:
xfree(args);
return ret;
}
int parasite_cure_seized(struct parasite_ctl *ctl)
{
parasite_status_t args = { };
......
......@@ -494,6 +494,23 @@ err_dmp:
return ret;
}
static int drain_fds(struct parasite_drain_fd *args)
{
parasite_status_t *st = &args->status;
int ret;
ret = send_fds(tsock, &args->saddr, args->sun_len,
args->fds, args->nr_fds);
if (ret) {
sys_write_msg("send_fds failed\n");
SET_PARASITE_RET(st, ret);
goto err;
}
err:
return ret;
}
static int init(struct parasite_init_args *args)
{
parasite_status_t *st = &args->status;
......@@ -561,6 +578,7 @@ static int __used parasite_service(unsigned long cmd, void *args)
BUILD_BUG_ON(sizeof(struct parasite_dump_misc) > PARASITE_ARG_SIZE);
BUILD_BUG_ON(sizeof(struct parasite_dump_tid_addr) > PARASITE_ARG_SIZE);
BUILD_BUG_ON(sizeof(struct parasite_dump_sk_queues) > PARASITE_ARG_SIZE);
BUILD_BUG_ON(sizeof(struct parasite_drain_fd) > PARASITE_ARG_SIZE);
switch (cmd) {
case PARASITE_CMD_INIT:
......@@ -585,6 +603,8 @@ static int __used parasite_service(unsigned long cmd, void *args)
return dump_tid_addr((struct parasite_dump_tid_addr *)args);
case PARASITE_CMD_DUMP_SK_QUEUES:
return dump_skqueues((struct parasite_dump_sk_queues *)args);
case PARASITE_CMD_DRAIN_FDS:
return drain_fds((struct parasite_drain_fd *)args);
default:
{
parasite_status_t *st = (parasite_status_t *)args;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment