Blame SOURCES/0001-Tools-hv-vss-fix-loop-device-detection.patch

820bc1
From 60c1606cbb7cc86f963a202c156e56ccdf1b57d9 Mon Sep 17 00:00:00 2001
820bc1
From: Vitaly Kuznetsov <vkuznets@redhat.com>
820bc1
Date: Tue, 5 Jun 2018 13:37:56 -0700
820bc1
Subject: [PATCH] Tools: hv: vss: fix loop device detection
820bc1
820bc1
Commit ea81fdf0981d ("Tools: hv: vss: Skip freezing filesystems backed by
820bc1
loop") added skip for filesystems backed by loop device. However, it seems
820bc1
the detection of such cases is incomplete.
820bc1
820bc1
It was found that with 'devicemapper' storage driver docker creates the
820bc1
following chain:
820bc1
820bc1
NAME					MAJ:MIN
820bc1
loop0					7:0
820bc1
..docker-8:4-8473394-pool		253:0
820bc1
  ..docker-8:4-8473394-eac...		253:1
820bc1
820bc1
so when we're looking at the mounted device we see major '253' and not '7'.
820bc1
820bc1
Solve the issue by walking /sys/dev/block/*/slaves chain and checking if
820bc1
there's a loop device somewhere.
820bc1
820bc1
Other than that, don't skip mountpoints silently when stat() fails. In case
820bc1
e.g. SELinux is failing stat we don't want to skip freezing everything
820bc1
without letting user know about the failure.
820bc1
820bc1
Fixes: ea81fdf0981d ("Tools: hv: vss: Skip freezing filesystems backed by loop")
820bc1
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
820bc1
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
820bc1
---
820bc1
 tools/hv/hv_vss_daemon.c | 65 +++++++++++++++++++++++++++++++++++++++++++++---
820bc1
 1 file changed, 61 insertions(+), 4 deletions(-)
820bc1
820bc1
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c
820bc1
index 34031a297f02..b13300172762 100644
820bc1
--- a/tools/hv/hv_vss_daemon.c
820bc1
+++ b/tools/hv/hv_vss_daemon.c
820bc1
@@ -36,6 +36,8 @@
820bc1
 #include <linux/hyperv.h>
820bc1
 #include <syslog.h>
820bc1
 #include <getopt.h>
820bc1
+#include <stdbool.h>
820bc1
+#include <dirent.h>
820bc1
 
820bc1
 /* Don't use syslog() in the function since that can cause write to disk */
820bc1
 static int vss_do_freeze(char *dir, unsigned int cmd)
820bc1
@@ -68,6 +70,55 @@ static int vss_do_freeze(char *dir, unsigned int cmd)
820bc1
 	return !!ret;
820bc1
 }
820bc1
 
820bc1
+static bool is_dev_loop(const char *blkname)
820bc1
+{
820bc1
+	char *buffer;
820bc1
+	DIR *dir;
820bc1
+	struct dirent *entry;
820bc1
+	bool ret = false;
820bc1
+
820bc1
+	buffer = malloc(PATH_MAX);
820bc1
+	if (!buffer) {
820bc1
+		syslog(LOG_ERR, "Can't allocate memory!");
820bc1
+		exit(1);
820bc1
+	}
820bc1
+
820bc1
+	snprintf(buffer, PATH_MAX, "%s/loop", blkname);
820bc1
+	if (!access(buffer, R_OK | X_OK)) {
820bc1
+		ret = true;
820bc1
+		goto free_buffer;
820bc1
+	} else if (errno != ENOENT) {
820bc1
+		syslog(LOG_ERR, "Can't access: %s; error:%d %s!",
820bc1
+		       buffer, errno, strerror(errno));
820bc1
+	}
820bc1
+
820bc1
+	snprintf(buffer, PATH_MAX, "%s/slaves", blkname);
820bc1
+	dir = opendir(buffer);
820bc1
+	if (!dir) {
820bc1
+		if (errno != ENOENT)
820bc1
+			syslog(LOG_ERR, "Can't opendir: %s; error:%d %s!",
820bc1
+			       buffer, errno, strerror(errno));
820bc1
+		goto free_buffer;
820bc1
+	}
820bc1
+
820bc1
+	while ((entry = readdir(dir)) != NULL) {
820bc1
+		if (strcmp(entry->d_name, ".") == 0 ||
820bc1
+		    strcmp(entry->d_name, "..") == 0)
820bc1
+			continue;
820bc1
+
820bc1
+		snprintf(buffer, PATH_MAX, "%s/slaves/%s", blkname,
820bc1
+			 entry->d_name);
820bc1
+		if (is_dev_loop(buffer)) {
820bc1
+			ret = true;
820bc1
+			break;
820bc1
+		}
820bc1
+	}
820bc1
+	closedir(dir);
820bc1
+free_buffer:
820bc1
+	free(buffer);
820bc1
+	return ret;
820bc1
+}
820bc1
+
820bc1
 static int vss_operate(int operation)
820bc1
 {
820bc1
 	char match[] = "/dev/";
820bc1
@@ -75,6 +126,7 @@ static int vss_operate(int operation)
820bc1
 	struct mntent *ent;
820bc1
 	struct stat sb;
820bc1
 	char errdir[1024] = {0};
820bc1
+	char blkdir[23]; /* /sys/dev/block/XXX:XXX */
820bc1
 	unsigned int cmd;
820bc1
 	int error = 0, root_seen = 0, save_errno = 0;
820bc1
 
820bc1
@@ -96,10 +148,15 @@ static int vss_operate(int operation)
820bc1
 	while ((ent = getmntent(mounts))) {
820bc1
 		if (strncmp(ent->mnt_fsname, match, strlen(match)))
820bc1
 			continue;
820bc1
-		if (stat(ent->mnt_fsname, &sb) == -1)
820bc1
-			continue;
820bc1
-		if (S_ISBLK(sb.st_mode) && major(sb.st_rdev) == LOOP_MAJOR)
820bc1
-			continue;
820bc1
+		if (stat(ent->mnt_fsname, &sb)) {
820bc1
+			syslog(LOG_ERR, "Can't stat: %s; error:%d %s!",
820bc1
+			       ent->mnt_fsname, errno, strerror(errno));
820bc1
+		} else {
820bc1
+			sprintf(blkdir, "/sys/dev/block/%d:%d",
820bc1
+				major(sb.st_rdev), minor(sb.st_rdev));
820bc1
+			if (is_dev_loop(blkdir))
820bc1
+				continue;
820bc1
+		}
820bc1
 		if (hasmntopt(ent, MNTOPT_RO) != NULL)
820bc1
 			continue;
820bc1
 		if (strcmp(ent->mnt_type, "vfat") == 0)
820bc1
-- 
820bc1
2.14.4
820bc1