2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-22 09:58:09 +00:00
criu/mount.c

205 lines
3.8 KiB
C
Raw Normal View History

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include "crtools.h"
#include "types.h"
#include "util.h"
#include "log.h"
#include "mount.h"
#include "proc_parse.h"
#include "image.h"
static struct mount_info *mntinfo;
int open_mount(unsigned int s_dev)
{
struct mount_info *i;
for (i = mntinfo; i != NULL; i = i->next)
if (s_dev == i->s_dev)
return open(i->mountpoint, O_RDONLY);
return -ENOENT;
}
int collect_mount_info(void)
{
mntinfo = parse_mountinfo(getpid());
if (!mntinfo) {
pr_err("Parsing mountinfo %d failed\n", getpid());
return -1;
}
return 0;
}
static char *fstypes[] = {
"unsupported",
"proc",
"sysfs",
};
static u32 encode_fstype(char *fst)
{
int i;
/*
* This fn is required for two things.
* 1st -- to check supported filesystems (as just mounting
* anything is wrong, almost every fs has its own features)
* 2nd -- save some space in the image (since we scan all
* names anyway)
*/
for (i = 0; i < ARRAY_SIZE(fstypes); i++)
if (!strcmp(fstypes[i], fst))
return i;
return 0;
}
static char *decode_fstype(u32 fst)
{
static char uns[12];
if (fst >= ARRAY_SIZE(fstypes)) {
sprintf(uns, "x%d", fst);
return uns;
}
return fstypes[fst];
}
static inline int is_root(char *p)
{
return p[0] == '/' && p[1] == '\0';
}
static inline int is_root_mount(struct mount_info *mi)
{
return is_root(mi->mountpoint);
}
static int dump_one_mountpoint(struct mount_info *pm, int fd)
{
struct mnt_entry me;
pr_info("\t%d: %x:%s @ %s\n", pm->mnt_id, pm->s_dev,
pm->root, pm->mountpoint);
me.mnt_id = pm->mnt_id;
me.root_dev = pm->s_dev;
me.root_dentry_len = strlen(pm->root);
me.parent_mnt_id = pm->parent_mnt_id;
me.mountpoint_path_len = strlen(pm->mountpoint);
me.fstype = encode_fstype(pm->fstype);
if (!me.fstype && !is_root_mount(pm)) {
pr_err("FS %s unsupported\n", pm->fstype);
return -1;
}
me.flags = pm->flags;
me.source_len = strlen(pm->source);
me.options_len = strlen(pm->options);
if (write_img(fd, &me))
return -1;
if (write_img_buf(fd, pm->root, me.root_dentry_len))
return -1;
if (write_img_buf(fd, pm->mountpoint, me.mountpoint_path_len))
return -1;
if (write_img_buf(fd, pm->source, me.source_len))
return -1;
if (write_img_buf(fd, pm->options, me.options_len))
return -1;
return 0;
}
int dump_mnt_ns(int ns_pid, struct cr_fdset *fdset)
{
struct mount_info *pm;
int img_fd;
pm = parse_mountinfo(ns_pid);
if (!pm) {
pr_err("Can't parse %d's mountinfo\n", ns_pid);
return -1;
}
pr_info("Dumping mountpoints\n");
img_fd = fdset_fd(fdset, CR_FD_MOUNTPOINTS);
do {
struct mount_info *n = pm->next;
if (dump_one_mountpoint(pm, img_fd))
return -1;
xfree(pm);
pm = n;
} while (pm);
return 0;
}
void show_mountpoints(int fd, struct cr_options *o)
{
struct mnt_entry me;
char buf[PATH_MAX];
pr_img_head(CR_FD_MOUNTPOINTS);
while (1) {
int ret;
ret = read_img_eof(fd, &me);
if (ret <= 0)
break;
pr_msg("%d:%d [%s] ", me.mnt_id, me.parent_mnt_id,
decode_fstype(me.fstype));
ret = read_img_buf(fd, buf, me.root_dentry_len);
if (ret < 0)
break;
buf[me.root_dentry_len] = '\0';
pr_msg("%d:%d %s ", kdev_major(me.root_dev),
kdev_minor(me.root_dev), buf);
ret = read_img_buf(fd, buf, me.mountpoint_path_len);
if (ret < 0)
break;
buf[me.mountpoint_path_len] = '\0';
pr_msg("@ %s ", buf);
pr_msg("flags %08x ", me.flags);
ret = read_img_buf(fd, buf, me.source_len);
if (ret < 0)
break;
buf[me.source_len] = '\0';
pr_msg("dev %s ", buf);
ret = read_img_buf(fd, buf, me.options_len);
if (ret < 0)
break;
buf[me.options_len] = '\0';
pr_msg("options %s\n", buf);
}
pr_img_tail(CR_FD_MOUNTPOINTS);
}