[CRIU] [PATCH 16/17] unix: Add support of ghost sockets
Andrei Vagin
avagin at virtuozzo.com
Wed Apr 4 10:00:30 MSK 2018
On Tue, Apr 03, 2018 at 12:18:33PM -0700, Andrei Vagin wrote:
> On Sun, Apr 01, 2018 at 11:07:42PM +0300, Cyrill Gorcunov wrote:
> > @@ -1826,6 +1906,127 @@ static int init_unix_sk_info(struct unix_sk_info *ui, UnixSkEntry *ue)
> > INIT_LIST_HEAD(&ui->connected);
> > INIT_LIST_HEAD(&ui->node);
> > INIT_LIST_HEAD(&ui->scm_fles);
> > + INIT_LIST_HEAD(&ui->ghost_node);
> > + INIT_LIST_HEAD(&ui->ghost_wait_head);
> > + INIT_LIST_HEAD(&ui->ghost_waiter);
> > +
> > + return 0;
> > +}
> > +
> > +#define GHOST_NAME_FMT "~criu-%u"
> > +#define GHOST_NAME_FMT_PREFIX 6 /* num of chars before counter */
> > +
> > +static int ghost_new_name(char *name, size_t namelen,
> > + char **name_new, size_t *namelen_new)
>
> I think we don't need to generate a new unique name for deleted sockets.
>
> We can use the old scheme, but before deleting a file, we need to open
> it with O_PATH and save a file descriptor in fdstore, then we can use it
> to connect peer sockets.
>
Pls take a look at the attached patch.
-------------- next part --------------
diff --git a/criu/sk-unix.c b/criu/sk-unix.c
index 0b0fa699c..3bf1f4592 100644
--- a/criu/sk-unix.c
+++ b/criu/sk-unix.c
@@ -905,6 +905,8 @@ struct unix_sk_info {
u8 listen:1;
u8 is_connected:1;
u8 peer_queue_restored:1; /* Set in 1 after we restore peer's queue */
+
+ int fdstore_id;
};
struct scm_fle {
@@ -1237,6 +1239,77 @@ err:
return -1;
}
+static int connect_by_fd(int sk, int fdstore_id)
+{
+ struct sockaddr_un addr;
+ int fd, cwd = -1, root = -1, fd_dir;
+ int exit_code = -1, len;
+
+ fd = fdstore_get(fdstore_id);
+ if (fd < 0)
+ return -1;
+
+ cwd = open(".", O_PATH);
+ if (cwd < 0) {
+ pr_perror("Unable to open .");
+ goto out;
+ }
+ root = open("/", O_PATH);
+ if (cwd < 0) {
+ pr_perror("Unable to open /");
+ goto out;
+ }
+
+ fd_dir = open_proc(PROC_SELF, "fd");
+ if (fd_dir < 0)
+ goto out;
+ if (fchdir(fd_dir)) {
+ pr_perror("change working directory");
+ close(fd_dir);
+ goto out;
+ }
+ close(fd_dir);
+ if (chroot(".")) {
+ pr_perror("Unable to change root directory");
+ goto out;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ len = snprintf(addr.sun_path, UNIX_PATH_MAX, "%d", fd);
+ if (connect(sk, (struct sockaddr *)&addr,
+ sizeof(addr.sun_family) +
+ len) < 0) {
+ pr_perror("Unable to connect\n");
+ return -1;
+ }
+
+ exit_code = 0;
+out:
+ if (root >= 0) {
+ if (fchdir(root)) {
+ exit_code = -1;
+ pr_perror("Unable to change working directory");
+ }
+ if (chroot(".")) {
+ exit_code = -1;
+ pr_perror("Unable to change root directory");
+ }
+ close(root);
+ }
+ if (cwd >= 0) {
+ if (fchdir(cwd)) {
+ exit_code = -1;
+ pr_perror("Unable to change working directory");
+ }
+ close(cwd);
+ }
+ set_proc_self_fd(-1);
+ close(fd);
+
+ return exit_code;
+}
+
static int post_open_standalone(struct file_desc *d, int fd)
{
struct unix_sk_info *ui;
@@ -1271,6 +1344,12 @@ static int post_open_standalone(struct file_desc *d, int fd)
pr_info("\tConnect %#x to %#x\n", ui->ue->ino, peer->ue->ino);
+ if (peer->fdstore_id >=0) {
+ if (connect_by_fd(fd, peer->fdstore_id) < 0)
+ return -1;
+ goto restore_queue;
+ }
+
if (prep_unix_sk_cwd(peer, &cwd_fd, NULL, &ns_fd))
return -1;
@@ -1300,7 +1379,7 @@ static int bind_deleted_unix_sk(int sk, struct unix_sk_info *ui,
struct sockaddr_un *addr)
{
char temp[PATH_MAX];
- int ret;
+ int ret, fd;
pr_info("found duplicate unix socket bound at %s\n", addr->sun_path);
@@ -1325,6 +1404,16 @@ static int bind_deleted_unix_sk(int sk, struct unix_sk_info *ui,
return -1;;
}
+ fd = open(addr->sun_path, O_PATH);
+ if (fd < 0) {
+ pr_perror("Unable to open %s", addr->sun_path);
+ return -1;
+ }
+ ui->fdstore_id = fdstore_add(fd);
+ if (ui->fdstore_id < 0)
+ return -1;
+ close(fd);
+
ret = rename(temp, addr->sun_path);
if (ret < 0) {
pr_perror("couldn't move socket back");
@@ -1376,6 +1465,18 @@ static int bind_unix_sk(int sk, struct unix_sk_info *ui)
pr_perror("Can't bind socket");
goto done;
}
+ } else if (ui->ue->deleted) {
+ int fd;
+
+ fd = open(addr.sun_path, O_PATH);
+ if (fd < 0) {
+ pr_perror("Unable to open %s", addr.sun_path);
+ return -1;
+ }
+ ui->fdstore_id = fdstore_add(fd);
+ if (ui->fdstore_id < 0)
+ return -1;
+ close(fd);
}
if (*ui->name && ui->ue->file_perms) {
@@ -1857,6 +1958,7 @@ static int collect_one_unixsk(void *o, ProtobufCMessage *base, struct cr_img *i)
ui->peer_resolve.actor = post_prepare_unix_sk;
add_post_prepare_cb(&ui->peer_resolve);
}
+ ui->fdstore_id = -1;
list_add_tail(&ui->list, &unix_sockets);
return file_desc_add(&ui->d, ui->ue->id, &unix_desc_ops);
diff --git a/test/zdtm/static/sk-unix01.c b/test/zdtm/static/sk-unix01.c
index 024338c24..ece4b2a56 100644
--- a/test/zdtm/static/sk-unix01.c
+++ b/test/zdtm/static/sk-unix01.c
@@ -204,7 +204,7 @@ int main(int argc, char **argv)
}
unlink(filename);
- rmdir(subdir_dg);
+// rmdir(subdir_dg);
/*
* STREAM sockets
@@ -262,8 +262,8 @@ int main(int argc, char **argv)
unlink(filename);
- rmdir(subdir_dg);
- rmdir(subdir_st);
+// rmdir(subdir_dg);
+// rmdir(subdir_st);
test_daemon();
test_waitsig();
More information about the CRIU
mailing list