]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lib/loopdev: fix loopcxt_check_size() to work with blkdevs
authorKarel Zak <kzak@redhat.com>
Mon, 13 May 2013 08:54:41 +0000 (10:54 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 27 May 2013 13:43:55 +0000 (15:43 +0200)
The loopcxt_check_size() is workaround for kernels < v3.9, kernel has
been fixed by commit 541c742a7559eb65f0e36d3e2338c2ca532a3e61.

The function sets loopdev size according to backing file size. The
problem is that the backing file could be a block device where
stat.st_size is zero, so we have to use blkdev_get_size() for block
devices.

Addresses: https://bugs.archlinux.org/task/35193
Reported-by: Dave Reisner <d@falconindy.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
lib/loopdev.c

index c35e306f94a3c96cfd9cf8d7c9cd3b67c62c57eb..3b65b5d29f186b2a2cf9229dd9961aca6d1ffe13 100644 (file)
@@ -1097,7 +1097,17 @@ static int loopcxt_check_size(struct loopdev_cxt *lc, int file_fd)
        if (fstat(file_fd, &st))
                return -errno;
 
-       expected_size = st.st_size;
+       if (S_ISBLK(st.st_mode)) {
+               if (blkdev_get_size(file_fd,
+                               (unsigned long long *) &expected_size))
+                       return -errno;
+       } else
+               expected_size = st.st_size;
+
+       if (expected_size == 0 || expected_size <= lc->info.lo_offset) {
+               DBG(lc, loopdev_debug("failed to determine expected size"));
+               return 0;       /* ignore this error */
+       }
 
        if (lc->info.lo_offset > 0)
                expected_size -= lc->info.lo_offset;
@@ -1113,6 +1123,10 @@ static int loopcxt_check_size(struct loopdev_cxt *lc, int file_fd)
                return -errno;
 
        if (expected_size != size) {
+               DBG(lc, loopdev_debug("warning: loopdev and expected "
+                                     "size dismatch (%ju/%ju)",
+                                     size, expected_size));
+
                if (loopcxt_set_capacity(lc)) {
                        /* ioctl not available */
                        if (errno == ENOTTY || errno == EINVAL)