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

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