[CRIU] [PATCH 11/28] rst: new routines for restoring shared files
introduced
Kinsbursky Stanislav
skinsbursky at openvz.org
Thu Mar 22 13:58:45 EDT 2012
From: Stanislav Kinsbursky <skinsbursky at openvz.org>
These are slighlty reqirtten currently existent routines. Old ones will be
removed later (simple replacement leads to unreadable patch).
Refresh of diff-rst-files-undump
---
files.c | 200 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 200 insertions(+), 0 deletions(-)
-------------- next part --------------
diff --git a/files.c b/files.c
index 6c14781..feff47b 100644
--- a/files.c
+++ b/files.c
@@ -59,6 +59,15 @@ static struct fdinfo_desc *find_fd(u64 id)
return NULL;
}
+struct file_recipient {
+ struct list_head list;
+ int pid;
+ int fd;
+ struct sockaddr_un saddr;
+ int sun_len;
+ u32 ready;
+};
+
static int get_file_path(char *path, struct fdinfo_entry *fe, int fd)
{
if (read(fd, path, fe->len) != fe->len) {
@@ -71,6 +80,34 @@ static int get_file_path(char *path, struct fdinfo_entry *fe, int fd)
return 0;
}
+static int collect_fd_pid(int pid, struct fd_entry *fde)
+{
+ struct file_info *fi;
+ struct file_recipient *recipient;
+
+ pr_info("%d: Collect fd=%d type=%d id=%16lx\n",
+ pid, fde->fd, fde->type, fde->id);
+
+ fi = file_search(fde->type, fde->id);
+ if (fi == NULL) {
+ pr_err("Failed to find shared file: type %d, id %ld\n\n", fde->type, fde->id);
+ return -1;
+ }
+
+ recipient = xmalloc_shm(sizeof(*recipient));
+ if (!recipient)
+ return -ENOMEM;
+ recipient->pid = pid;
+ recipient->fd = fde->fd;
+ cr_wait_init(&recipient->ready);
+
+ if (fi->pid < pid)
+ fi->pid = pid;
+
+ list_add_tail(&recipient->list, &fi->recipients);
+ return 0;
+}
+
static int collect_fd(int pid, struct fdinfo_entry *e)
{
int i;
@@ -128,6 +165,17 @@ static int collect_fd(int pid, struct fdinfo_entry *e)
return 0;
}
+static struct file_recipient *get_fd_recipient(struct file_info *fi,
+ int pid, int fd)
+{
+ struct file_recipient *recipient = NULL;
+
+ list_for_each_entry(recipient, &fi->recipients, list)
+ if ((recipient->pid == pid) && (recipient->fd == fd))
+ return recipient;
+ return NULL;
+}
+
static int prepare_reg_files(void)
{
int reg_file_fd, ret = 0;
@@ -270,6 +318,25 @@ static int restore_exe_early(struct fdinfo_entry *fe, int fd)
return 0;
}
+static int receive_shared_fd(int pid, struct file_info *fi, struct fd_entry *fde)
+{
+ int real_fd;
+
+ if (fi->pid == pid)
+ return 0;
+
+ pr_info("\t%d: Receive fd %d\n", pid, fde->fd);
+
+ real_fd = recv_fd(fde->fd);
+ if (real_fd < 0) {
+ pr_err("Can't get fd %d\n", real_fd);
+ return -1;
+ }
+ close(fde->fd);
+
+ return reopen_fd_as(fde->fd, real_fd);
+}
+
struct fdinfo_list_entry *find_fdinfo_list_entry(int pid, int fd, struct fdinfo_desc *fi)
{
struct fdinfo_list_entry *fle;
@@ -330,6 +397,139 @@ static int open_transport_fd(int pid, struct fdinfo_entry *fe,
return 0;
}
+static int open_transport(int pid, int fd, struct file_info *fi)
+{
+ struct file_recipient *recipient;
+ struct sockaddr_un *saddr;
+ int ret;
+ int sock;
+
+ recipient = get_fd_recipient(fi, pid, fd);
+ if (!recipient) {
+ pr_err("Can't find recipient\n");
+ return -1;
+ }
+
+ pr_info("\t%d: Found recipient: %p\n", pid, recipient);
+
+ saddr = &recipient->saddr;
+ saddr->sun_family = AF_UNIX;
+ snprintf(saddr->sun_path, UNIX_PATH_MAX,
+ "X/crtools-%d-fd-%d", pid, fd);
+
+ recipient->sun_len = SUN_LEN(saddr);
+ *saddr->sun_path = '\0';
+
+ sock = socket(PF_UNIX, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ pr_perror("Can't create socket");
+ return -1;
+ }
+
+ ret = bind(sock, saddr, recipient->sun_len);
+ if (ret < 0) {
+ pr_perror("Can't bind unix socket %s", saddr->sun_path + 1);
+ return -1;
+ }
+
+ ret = reopen_fd_as(recipient->fd, sock);
+ if (ret < 0)
+ return -1;
+
+ cr_wait_set(&recipient->ready, pid);
+ pr_info("\t%d: Transport for fd %d ready (fi: %p, recipient: %p)\n",
+ pid, fd, fi, recipient);
+ return 0;
+}
+
+static int send_fd_to_recipients(struct file_info *fi)
+{
+ struct file_recipient *recipient, *tmp;
+ int sock;
+
+ if (list_empty(&fi->recipients))
+ return 0;
+
+ sock = socket(PF_UNIX, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ pr_perror("Can't create socket");
+ return -1;
+ }
+
+ pr_info("\t%d: Send fd %d\n", fi->pid, fi->fd);
+
+ list_for_each_entry_safe(recipient, tmp, &fi->recipients, list) {
+ if (recipient->pid == fi->pid)
+ continue;
+ pr_info("\t%d: Wait pid's %d fd %d ready\n",
+ fi->pid, recipient->pid, recipient->fd);
+ cr_wait_while(&recipient->ready, 0);
+ pr_info("\t%d: Send to %s (fi: %p, recipient: %p)\n",
+ fi->pid, recipient->saddr.sun_path + 1, fi, recipient);
+ if (send_fd(sock, &recipient->saddr, recipient->sun_len, fi->fd) < 0) {
+ pr_perror("Can't send file descriptor");
+ return -1;
+ }
+ }
+ close(sock);
+ return 0;
+}
+
+static int open_reg_file(struct file_info *fi, struct fd_entry *fde)
+{
+ const struct file_entry *rfe = fi->rfe;
+
+ pr_info("\t%d: Open fd %d (%s)\n", fi->pid, fde->fd, (char *)rfe->name);
+
+ if (fi->fd != FD_ID_INVALID) {
+ if (dup2(fi->fd, fde->fd) != fde->fd)
+ return -1;
+ return 0;
+ }
+
+ fi->fd = open((char *)rfe->name, rfe->flags);
+ if (fi->fd < 0) {
+ pr_perror("Can't open file %s", rfe->name);
+ return -1;
+ }
+ lseek(fi->fd, rfe->pos, SEEK_SET);
+
+ if (reopen_fd_as(fde->fd, fi->fd) < 0)
+ return -1;
+
+ fi->fd = fde->fd;
+
+ return send_fd_to_recipients(fi);
+}
+
+static int open_fd_and_send(int pid, struct file_info *fi, struct fd_entry *fde)
+{
+ if (fi->pid != pid)
+ return 0;
+
+ switch (fde->type) {
+ case FDINFO_REG:
+ return open_reg_file(fi, fde);
+ }
+
+ pr_err("Failed to find shared file: type %d is not supported\n\n", fde->type);
+ return -1;
+}
+
+static int open_fd_transport(int pid, struct file_info *fi, struct fd_entry *fde)
+{
+ if (fi->pid == pid)
+ return 0;
+
+ if (fde->type != FDINFO_REG)
+ return 0;
+
+ pr_info("\t%d: Create transport for fd %d type %d id %ld\n", pid,
+ fde->fd, fde->type, fde->id);
+
+ return open_transport(pid, fde->fd, fi);
+}
+
static int open_fd(int pid, struct fdinfo_entry *fe,
struct fdinfo_desc *fi, int fdinfo_fd)
{
More information about the CRIU
mailing list