Commit 58e22f31 authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

mount: Add support of tmpfs (v3)

When dumping a tmpfs mount we need to take its contents with us.
So, use tar for it and put it into the image dir.
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent b0d7cc97
...@@ -127,6 +127,7 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = { ...@@ -127,6 +127,7 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = {
FD_ENTRY(NETDEV, "netdev-%d", show_netdevices), FD_ENTRY(NETDEV, "netdev-%d", show_netdevices),
FD_ENTRY(IFADDR, "ifaddr-%d", show_raw_image), FD_ENTRY(IFADDR, "ifaddr-%d", show_raw_image),
FD_ENTRY(ROUTE, "route-%d", show_raw_image), FD_ENTRY(ROUTE, "route-%d", show_raw_image),
FD_ENTRY(TMPFS, "tmpfs-%d.tar.gz", show_raw_image),
}; };
static struct cr_fdset *alloc_cr_fdset(int nr) static struct cr_fdset *alloc_cr_fdset(int nr)
......
...@@ -75,6 +75,8 @@ enum { ...@@ -75,6 +75,8 @@ enum {
CR_FD_INOTIFY_WD, CR_FD_INOTIFY_WD,
_CR_FD_GLOB_TO, _CR_FD_GLOB_TO,
CR_FD_TMPFS,
CR_FD_MAX CR_FD_MAX
}; };
......
...@@ -62,6 +62,7 @@ ...@@ -62,6 +62,7 @@
#define IFADDR_MAGIC RAW_IMAGE_MAGIC #define IFADDR_MAGIC RAW_IMAGE_MAGIC
#define ROUTE_MAGIC RAW_IMAGE_MAGIC #define ROUTE_MAGIC RAW_IMAGE_MAGIC
#define TMPFS_MAGIC RAW_IMAGE_MAGIC
#define PAGE_IMAGE_SIZE 4096 #define PAGE_IMAGE_SIZE 4096
#define PAGE_RSS 1 #define PAGE_RSS 1
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "crtools.h" #include "crtools.h"
#include "types.h" #include "types.h"
...@@ -231,6 +233,137 @@ static int close_mountpoint(DIR *dfd) ...@@ -231,6 +233,137 @@ static int close_mountpoint(DIR *dfd)
return 0; return 0;
} }
static int tmpfs_dump(struct mount_info *pm)
{
int ret, status;
pid_t pid;
pid = fork();
if (pid == -1) {
pr_perror("fork() failed\n");
return -1;
} else if (pid == 0) {
char tmpfs_path[PATH_MAX];
int fd, fd_img;
DIR *fdir;
fdir = open_mountpoint(pm);
if (fdir == NULL)
exit(1);
fd = dirfd(fdir);
if (fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) & ~FD_CLOEXEC) == -1) {
pr_perror("Can not drop FD_CLOEXEC");
exit(1);
}
fd_img = open_image(CR_FD_TMPFS, O_DUMP, pm->mnt_id);
if (fd_img < 0)
exit(1);
ret = dup2(fd_img, STDOUT_FILENO);
if (ret < 0) {
pr_perror("dup2() failed");
exit(1);
}
ret = dup2(log_get_fd(), STDERR_FILENO);
if (ret < 0) {
pr_perror("dup2() failed");
exit(1);
}
close(fd_img);
/* tmpfs is in another mount namespace,
* a direct path is inaccessible */
snprintf(tmpfs_path, sizeof(tmpfs_path),
"/proc/self/fd/%d", fd);
execlp("tar", "tar", "-czlp",
"--sparse",
"--numeric-owner",
"-C", tmpfs_path, ".", NULL);
pr_perror("exec failed");
exit(1);
}
ret = waitpid(pid, &status, 0);
if (ret == -1) {
pr_perror("waitpid() failed");
return -1;
}
if (status) {
pr_err("Can't dump tmpfs content\n");
return -1;
}
return 0;
}
static int tmpfs_restore(struct mount_info *pm)
{
int ret, status = -1;
sigset_t mask, oldmask;
pid_t pid;
ret = sigprocmask(SIG_SETMASK, NULL, &oldmask);
if (ret == -1) {
pr_perror("Can not get mask of blocked signals");
return -1;
}
mask = oldmask;
sigaddset(&mask, SIGCHLD);
ret = sigprocmask(SIG_SETMASK, &mask, NULL);
if (ret == -1) {
pr_perror("Can not set mask of blocked signals");
return -1;
}
pid = fork();
if (pid == -1) {
pr_perror("fork() failed\n");
goto out_unlock;
} else if (pid == 0) {
int fd_img;
fd_img = open_image_ro(CR_FD_TMPFS, pm->mnt_id);
if (fd_img < 0)
exit(1);
ret = dup2(fd_img, STDIN_FILENO);
if (ret < 0) {
pr_perror("dup2() failed");
exit(1);
}
close(fd_img);
execlp("tar", "tar", "-xz", "-C", pm->mountpoint, NULL);
pr_perror("exec failed");
exit(1);
}
ret = waitpid(pid, &status, 0);
if (ret == -1) {
pr_perror("waitpid() failed");
goto out_unlock;
}
if (status) {
pr_err("Can't restore tmpfs content\n");
status = -1;
goto out_unlock;
}
out_unlock:
ret = sigprocmask(SIG_SETMASK, &oldmask, NULL);
if (ret == -1) {
pr_perror("Can not set mask of blocked signals");
BUG_ON(1);
}
return status;
}
static int binfmt_misc_dump(struct mount_info *pm) static int binfmt_misc_dump(struct mount_info *pm)
{ {
int ret = -1; int ret = -1;
...@@ -267,6 +400,7 @@ static struct fstype fstypes[] = { ...@@ -267,6 +400,7 @@ static struct fstype fstypes[] = {
{ "sysfs" }, { "sysfs" },
{ "devtmpfs" }, { "devtmpfs" },
{ "binfmt_misc", binfmt_misc_dump }, { "binfmt_misc", binfmt_misc_dump },
{ "tmpfs", tmpfs_dump, tmpfs_restore },
}; };
struct fstype *find_fstype_by_name(char *fst) struct fstype *find_fstype_by_name(char *fst)
......
...@@ -16,7 +16,7 @@ static char buf[1024]; ...@@ -16,7 +16,7 @@ static char buf[1024];
static int test_fn(int argc, char **argv) static int test_fn(int argc, char **argv)
{ {
FILE *f; FILE *f;
int fd; int fd, tmpfs_fd;
unsigned fs_cnt, fs_cnt_last = 0; unsigned fs_cnt, fs_cnt_last = 0;
again: again:
...@@ -74,6 +74,16 @@ done: ...@@ -74,6 +74,16 @@ done:
return 1; return 1;
} }
if (mount("none", MPTS_ROOT"/dev", "tmpfs", 0, "") < 0) {
fail("Can't mount tmpfs");
return 1;
}
tmpfs_fd = open(MPTS_ROOT"/dev/test", O_WRONLY | O_CREAT);
if (write(tmpfs_fd, "hello", 5) <= 0) {
err("write() failed");
return 1;
}
if (mount("none", MPTS_ROOT"/kernel", "proc", 0, "") < 0) { if (mount("none", MPTS_ROOT"/kernel", "proc", 0, "") < 0) {
fail("Can't mount proc"); fail("Can't mount proc");
return 1; return 1;
......
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