2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-31 14:25:49 +00:00

sk-unix: make criu respect existing files while restoring ghost unix socket fd

If there are any file in place of ghost unix socket, criu will delete it at
restore while trying to recreate ghost one.

Reviewed-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko@virtuozzo.com>
This commit is contained in:
Andrey Zhadchenko
2021-01-11 18:17:40 +03:00
committed by Andrei Vagin
parent 49889baa20
commit d0308e5ecc

View File

@@ -1470,56 +1470,49 @@ static int bind_on_deleted(int sk, struct unix_sk_info *ui)
addr.sun_family = AF_UNIX;
memcpy(&addr.sun_path, ui->name, ui->ue->name.len);
ret = access(ui->name, F_OK);
if (!ret) {
snprintf(path_parked, sizeof(path_parked), UNIX_GHOST_FMT, ui->name);
/*
* In case if there exist any file with same name
* just move it aside for a while, we will move it back
* once ghost socket is processed.
*/
if (unlinkat(AT_FDCWD, path_parked, 0) == 0)
pr_debug("ghost: Unlinked stale socket id %#x ino %d name %s\n",
ui->ue->id, ui->ue->ino, path_parked);
if (rename(ui->name, path_parked)) {
ret = -errno;
pr_perror("ghost: Can't rename id %#x ino %u addr %s -> %s",
ui->ue->id, ui->ue->ino, ui->name, path_parked);
return ret;
}
pr_debug("ghost: id %#x ino %d renamed %s -> %s\n",
ui->ue->id, ui->ue->ino, ui->name, path_parked);
renamed = true;
}
ret = bind(sk, (struct sockaddr *)&addr,
sizeof(addr.sun_family) + ui->ue->name.len);
if (ret < 0) {
/*
* In case if there some real living socket
* with same name just move it aside for a
* while, we will move it back once ghost
* socket is processed.
*/
if (errno == EADDRINUSE) {
snprintf(path_parked, sizeof(path_parked), UNIX_GHOST_FMT, ui->name);
/*
* Say previous restore get killed in a middle due to
* any reason, be ready the file might already exist,
* clean it up.
*/
if (unlinkat(AT_FDCWD, path_parked, 0) == 0)
pr_debug("ghost: Unlinked stale socket id %#x ino %u name %s\n",
ui->ue->id, ui->ue->ino, path_parked);
if (rename(ui->name, path_parked)) {
ret = -errno;
pr_perror("ghost: Can't rename id %#x ino %u addr %s -> %s",
ui->ue->id, ui->ue->ino, ui->name, path_parked);
return ret;
}
pr_debug("ghost: id %#x ino %u renamed %s -> %s\n",
ui->ue->id, ui->ue->ino, ui->name, path_parked);
renamed = true;
ret = bind(sk, (struct sockaddr *)&addr,
sizeof(addr.sun_family) + ui->ue->name.len);
}
if (ret < 0) {
ret = -errno;
pr_perror("ghost: Can't bind on socket id %#x ino %u addr %s",
ui->ue->id, ui->ue->ino, ui->name);
return ret;
}
ret = -errno;
pr_perror("ghost: Can't bind on socket id %#x ino %d addr %s",
ui->ue->id, ui->ue->ino, ui->name);
goto out_rename;
}
ret = restore_file_perms(ui);
if (ret < 0)
return ret;
goto out;
ret = keep_deleted(ui);
if (ret < 0) {
pr_err("ghost: Can't save socket %#x ino %u addr %s into fdstore\n",
ui->ue->id, ui->ue->ino, ui->name);
return -EIO;
ret = -EIO;
}
out:
/*
* Once everything is ready, just remove the socket from the
* filesystem and rename back the original one if it were here.
@@ -1529,19 +1522,18 @@ static int bind_on_deleted(int sk, struct unix_sk_info *ui)
ret = -errno;
pr_perror("ghost: Can't unlink socket %#x ino %u addr %s",
ui->ue->id, ui->ue->ino, ui->name);
return ret;
}
out_rename:
if (renamed) {
if (rename(path_parked, ui->name)) {
ret = -errno;
pr_perror("ghost: Can't rename id %#x ino %u addr %s -> %s",
ui->ue->id, ui->ue->ino, path_parked, ui->name);
return ret;
} else {
pr_debug("ghost: id %#x ino %d renamed %s -> %s\n",
ui->ue->id, ui->ue->ino, path_parked, ui->name);
}
pr_debug("ghost: id %#x ino %u renamed %s -> %s\n",
ui->ue->id, ui->ue->ino, path_parked, ui->name);
}
/*
@@ -1988,6 +1980,7 @@ static struct file_desc_ops unix_desc_ops = {
static int unlink_sk(struct unix_sk_info *ui)
{
int ret = 0, cwd_fd = -1, root_fd = -1, ns_fd = -1;
struct stat statbuf;
if (!ui->name || ui->name[0] == '\0' || (ui->ue->uflags & USK_EXTERN))
return 0;
@@ -1995,6 +1988,15 @@ static int unlink_sk(struct unix_sk_info *ui)
if (prep_unix_sk_cwd(ui, &cwd_fd, &root_fd, NULL))
return -1;
ret = stat(ui->name, &statbuf);
if (!ret) {
/* Do not cleanup non-socket files */
if (!S_ISSOCK(statbuf.st_mode)) {
ret = 0;
goto out;
}
}
ret = unlinkat(AT_FDCWD, ui->name, 0) ? -1 : 0;
if (ret < 0 && errno != ENOENT) {
pr_warn("Can't unlink socket %u peer %u (name %s dir %s)\n",