|
|
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 |
|