kpartx: compare image filenames with backing files
authorYuval Turgeman <yturgema@redhat.com>
Mon, 16 Jul 2018 12:52:13 +0000 (15:52 +0300)
committerChristophe Varoqui <christophe.varoqui@opensvc.com>
Tue, 7 Aug 2018 13:28:04 +0000 (15:28 +0200)
When running `kpartx -d`, find_loop_by_file tries to compare the image's
realpath with the output from loopinfo.lo_name, which may hold only the
basename of the image, making kpartx exit without finding the loopdev
for the image.

In case the original comparison fails, this patch will check the image's
realpath with the loop device's backing_file so that find_loop_by_file
will return the correct value.

Signed-off-by: Yuval Turgeman <yturgema@redhat.com>
kpartx/lopart.c

index 69c1eda..9b65255 100644 (file)
@@ -69,6 +69,8 @@ char *find_loop_by_file(const char *filename)
        struct loop_info loopinfo;
        const char VIRT_BLOCK[] = "/sys/devices/virtual/block";
        char path[PATH_MAX];
+       char bf_path[PATH_MAX];
+       char backing_file[PATH_MAX];
 
        dir = opendir(VIRT_BLOCK);
        if (!dir)
@@ -122,6 +124,34 @@ char *find_loop_by_file(const char *filename)
                        found = realpath(path, NULL);
                        break;
                }
+
+               /*
+                * filename is a realpath, while loopinfo.lo_name may hold just the
+                * basename.  If that's the case, try to match filename against the
+                * backing_file entry for this loop entry
+                */
+               if (snprintf(bf_path, PATH_MAX, "%s/%s/loop/backing_file", VIRT_BLOCK,
+                                        dent->d_name) >= PATH_MAX)
+                       continue;
+
+               fd = open(bf_path, O_RDONLY);
+               if (fd < 0)
+                       continue;
+
+               bytes_read = read(fd, backing_file, sizeof(backing_file) - 1);
+               if (bytes_read <= 0) {
+                       close(fd);
+                       continue;
+               }
+
+               close(fd);
+
+               backing_file[bytes_read-1] = '\0';
+
+               if (0 == strcmp(filename, backing_file)) {
+                       found = realpath(path, NULL);
+                       break;
+               }
        }
        closedir(dir);
        return found;