[CRIU] [PATCH 06/12] parasite: Add interface for file descriptors
draining
Cyrill Gorcunov
gorcunov at openvz.org
Sun Mar 25 17:33:52 EDT 2012
Just implemented but not yet used in dumping procedure,
this will be addressed in further patches.
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
include/parasite-syscall.h | 2 +
include/parasite.h | 14 ++++++++++++
parasite-syscall.c | 51 ++++++++++++++++++++++++++++++++++++++++++++
parasite.c | 20 +++++++++++++++++
4 files changed, 87 insertions(+), 0 deletions(-)
diff --git a/include/parasite-syscall.h b/include/parasite-syscall.h
index 5ae1554..d2b3ec3 100644
--- a/include/parasite-syscall.h
+++ b/include/parasite-syscall.h
@@ -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);
diff --git a/include/parasite.h b/include/parasite.h
index 291e561..3ec010a 100644
--- a/include/parasite.h
+++ b/include/parasite.h
@@ -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
*/
diff --git a/parasite-syscall.c b/parasite-syscall.c
index 969f6ae..35562bb 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -605,6 +605,57 @@ 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 = &args.status;
+ int ret = -1;
+ int sock, i;
+
+ 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");
+ return -1;
+ }
+
+ 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;
+ }
+
+ /* Verify the descriptors do match */
+ for (i = 0; i < nr_fds; i++) {
+ pid_t me = getpid();
+ if (sys_kcmp(me, ctl->pid, KCMP_FILE, fds[i], lfds[i])) {
+ pr_err("File descriptors mismatch: (%d) %d (%d) %d\n",
+ me, ctl->pid, fds[i], lfds[i]);
+ }
+ }
+
+ ret = 0;
+err:
+ close(sock);
+ return ret;
+}
+
int parasite_cure_seized(struct parasite_ctl *ctl)
{
parasite_status_t args = { };
diff --git a/parasite.c b/parasite.c
index 134b068..b080eb1 100644
--- a/parasite.c
+++ b/parasite.c
@@ -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 = -1;
+
+ 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;
--
1.7.7.6
More information about the CRIU
mailing list