mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-08-02 06:43:00 +00:00
mount/btrfs: make check_mountpoint_fd fallback to get_sdev_from_fd
We face that btrfs returns anonymous device in stat instead of real superblock dev for volumes, thus all btrfs volume mounts does not pass check_mountpoint_fd due to dev missmatch between stat and mountinfo. We can use special helper get_sdev_from_fd instead of stat to try to get real dev of fd for btrfs. We move check_mountpoint_fd from open_mountpoint into get_clean_fd and ns_open_mountpoint to the point where temporary mount we open fd to is still in mountinfo, thus get_sdev_from_fd would be able to find tmp mount in mountinfo. Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This commit is contained in:
parent
bbf5f642de
commit
8ec214d3cb
2 changed files with 46 additions and 4 deletions
|
|
@ -109,6 +109,7 @@ extern int mntns_get_root_by_mnt_id(int mnt_id);
|
|||
extern struct ns_id *lookup_nsid_by_mnt_id(int mnt_id);
|
||||
|
||||
extern int open_mount(unsigned int s_dev);
|
||||
extern int __check_mountpoint_fd(struct mount_info *pm, int mnt_fd, bool parse_mountinfo);
|
||||
extern int check_mountpoint_fd(struct mount_info *pm, int mnt_fd);
|
||||
extern int __open_mountpoint(struct mount_info *pm);
|
||||
extern int mnt_is_dir(struct mount_info *pm);
|
||||
|
|
|
|||
49
criu/mount.c
49
criu/mount.c
|
|
@ -1018,10 +1018,11 @@ int mnt_is_dir(struct mount_info *pm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int check_mountpoint_fd(struct mount_info *pm, int mnt_fd)
|
||||
int __check_mountpoint_fd(struct mount_info *pm, int mnt_fd, bool parse_mountinfo)
|
||||
{
|
||||
struct stat st;
|
||||
int ret, dev;
|
||||
unsigned int dev;
|
||||
int ret;
|
||||
|
||||
ret = fstat(mnt_fd, &st);
|
||||
if (ret < 0) {
|
||||
|
|
@ -1042,6 +1043,14 @@ int check_mountpoint_fd(struct mount_info *pm, int mnt_fd)
|
|||
* allocates new device ID).
|
||||
*/
|
||||
if (dev != pm->s_dev_rt) {
|
||||
/*
|
||||
* For btrfs device numbers in stat and mountinfo can be
|
||||
* different, fallback to get_sdev_from_fd to get right dev.
|
||||
*/
|
||||
if (!strcmp(pm->fstype->name, "btrfs") && !get_sdev_from_fd(mnt_fd, &dev, parse_mountinfo) &&
|
||||
dev == pm->s_dev_rt)
|
||||
return 0;
|
||||
|
||||
pr_err("The file system %#x %#x (%#x) %s %s is inaccessible\n", pm->s_dev, pm->s_dev_rt, dev,
|
||||
pm->fstype->name, pm->ns_mountpoint);
|
||||
return -1;
|
||||
|
|
@ -1050,6 +1059,11 @@ int check_mountpoint_fd(struct mount_info *pm, int mnt_fd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int check_mountpoint_fd(struct mount_info *pm, int mnt_fd)
|
||||
{
|
||||
return __check_mountpoint_fd(pm, mnt_fd, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* mnt_fd is a file descriptor on the mountpoint, which is closed in an error case.
|
||||
* If mnt_fd is -1, the mountpoint will be opened by this function.
|
||||
|
|
@ -1114,12 +1128,34 @@ static int get_clean_fd(struct mount_info *mi)
|
|||
char *mnt_path = NULL;
|
||||
char mnt_path_tmp[] = "/tmp/cr-tmpfs.XXXXXX";
|
||||
char mnt_path_root[] = "/cr-tmpfs.XXXXXX";
|
||||
int fd;
|
||||
|
||||
mnt_path = get_clean_mnt(mi, mnt_path_tmp, mnt_path_root);
|
||||
if (!mnt_path)
|
||||
return -1;
|
||||
|
||||
return open_detach_mount(mnt_path);
|
||||
fd = open(mnt_path, O_RDONLY | O_DIRECTORY, 0);
|
||||
if (fd < 0) {
|
||||
pr_perror("Can't open directory %s", mnt_path);
|
||||
} else {
|
||||
if (__check_mountpoint_fd(mi, fd, true))
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
if (umount2(mnt_path, MNT_DETACH)) {
|
||||
pr_perror("Can't detach mount %s", mnt_path);
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
if (rmdir(mnt_path)) {
|
||||
pr_perror("Can't remove tmp dir %s", mnt_path);
|
||||
goto err_close;
|
||||
}
|
||||
|
||||
return fd;
|
||||
err_close:
|
||||
close_safe(&fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1337,6 +1373,11 @@ int ns_open_mountpoint(void *arg)
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (__check_mountpoint_fd(mi, *fd, true)) {
|
||||
close(*fd);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
return 1;
|
||||
|
|
@ -1411,7 +1452,7 @@ int open_mountpoint(struct mount_info *pm)
|
|||
goto err;
|
||||
}
|
||||
|
||||
return fd < 0 ? __open_mountpoint(pm) : check_mountpoint_fd(pm, fd);
|
||||
return fd < 0 ? __open_mountpoint(pm) : fd;
|
||||
err:
|
||||
if (ns_old >= 0)
|
||||
/* coverity[check_return] */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue