summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitaly Kuznetsov <vkuznets@redhat.com>2018-06-05 13:37:56 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-07-03 13:02:33 +0200
commit07136793ccad877727afada2b0c926031f10cf52 (patch)
tree86bbf9cffe842672847c5323e5fc3c09f34f2712
parent8a99c920092f444cf9f1d737ae76527102886d8e (diff)
Tools: hv: vss: fix loop device detection
Commit ea81fdf0981d ("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: ea81fdf0981d ("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>
-rw-r--r--tools/hv/hv_vss_daemon.c65
1 files changed, 61 insertions, 4 deletions
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c
index 34031a297f02..b13300172762 100644
--- a/tools/hv/hv_vss_daemon.c
+++ b/tools/hv/hv_vss_daemon.c
@@ -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)