mirror of
https://github.com/torvalds/linux.git
synced 2024-12-26 04:42:12 +00:00
Tools: hv: vss: fix loop device detection
Commitea81fdf098
("Tools: hv: vss: Skip freezing filesystems backed by loop") added skip for filesystems backed by loop device. However, it seems the detection of such cases is incomplete. It was found that with 'devicemapper' storage driver docker creates the following chain: NAME MAJ:MIN loop0 7:0 ..docker-8:4-8473394-pool 253:0 ..docker-8:4-8473394-eac... 253:1 so when we're looking at the mounted device we see major '253' and not '7'. Solve the issue by walking /sys/dev/block/*/slaves chain and checking if there's a loop device somewhere. Other than that, don't skip mountpoints silently when stat() fails. In case e.g. SELinux is failing stat we don't want to skip freezing everything without letting user know about the failure. Fixes:ea81fdf098
("Tools: hv: vss: Skip freezing filesystems backed by loop") Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
8a99c92009
commit
07136793cc
@ -36,6 +36,8 @@
|
||||
#include <linux/hyperv.h>
|
||||
#include <syslog.h>
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <dirent.h>
|
||||
|
||||
/* Don't use syslog() in the function since that can cause write to disk */
|
||||
static int vss_do_freeze(char *dir, unsigned int cmd)
|
||||
@ -68,6 +70,55 @@ static int vss_do_freeze(char *dir, unsigned int cmd)
|
||||
return !!ret;
|
||||
}
|
||||
|
||||
static bool is_dev_loop(const char *blkname)
|
||||
{
|
||||
char *buffer;
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
bool ret = false;
|
||||
|
||||
buffer = malloc(PATH_MAX);
|
||||
if (!buffer) {
|
||||
syslog(LOG_ERR, "Can't allocate memory!");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
snprintf(buffer, PATH_MAX, "%s/loop", blkname);
|
||||
if (!access(buffer, R_OK | X_OK)) {
|
||||
ret = true;
|
||||
goto free_buffer;
|
||||
} else if (errno != ENOENT) {
|
||||
syslog(LOG_ERR, "Can't access: %s; error:%d %s!",
|
||||
buffer, errno, strerror(errno));
|
||||
}
|
||||
|
||||
snprintf(buffer, PATH_MAX, "%s/slaves", blkname);
|
||||
dir = opendir(buffer);
|
||||
if (!dir) {
|
||||
if (errno != ENOENT)
|
||||
syslog(LOG_ERR, "Can't opendir: %s; error:%d %s!",
|
||||
buffer, errno, strerror(errno));
|
||||
goto free_buffer;
|
||||
}
|
||||
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
if (strcmp(entry->d_name, ".") == 0 ||
|
||||
strcmp(entry->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
snprintf(buffer, PATH_MAX, "%s/slaves/%s", blkname,
|
||||
entry->d_name);
|
||||
if (is_dev_loop(buffer)) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
free_buffer:
|
||||
free(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vss_operate(int operation)
|
||||
{
|
||||
char match[] = "/dev/";
|
||||
@ -75,6 +126,7 @@ static int vss_operate(int operation)
|
||||
struct mntent *ent;
|
||||
struct stat sb;
|
||||
char errdir[1024] = {0};
|
||||
char blkdir[23]; /* /sys/dev/block/XXX:XXX */
|
||||
unsigned int cmd;
|
||||
int error = 0, root_seen = 0, save_errno = 0;
|
||||
|
||||
@ -96,10 +148,15 @@ static int vss_operate(int operation)
|
||||
while ((ent = getmntent(mounts))) {
|
||||
if (strncmp(ent->mnt_fsname, match, strlen(match)))
|
||||
continue;
|
||||
if (stat(ent->mnt_fsname, &sb) == -1)
|
||||
continue;
|
||||
if (S_ISBLK(sb.st_mode) && major(sb.st_rdev) == LOOP_MAJOR)
|
||||
continue;
|
||||
if (stat(ent->mnt_fsname, &sb)) {
|
||||
syslog(LOG_ERR, "Can't stat: %s; error:%d %s!",
|
||||
ent->mnt_fsname, errno, strerror(errno));
|
||||
} else {
|
||||
sprintf(blkdir, "/sys/dev/block/%d:%d",
|
||||
major(sb.st_rdev), minor(sb.st_rdev));
|
||||
if (is_dev_loop(blkdir))
|
||||
continue;
|
||||
}
|
||||
if (hasmntopt(ent, MNTOPT_RO) != NULL)
|
||||
continue;
|
||||
if (strcmp(ent->mnt_type, "vfat") == 0)
|
||||
|
Loading…
Reference in New Issue
Block a user