summaryrefslogtreecommitdiffstats
path: root/lib/loopdev.c
diff options
context:
space:
mode:
authorKarel Zak2013-05-13 10:54:41 +0200
committerKarel Zak2013-05-13 10:54:41 +0200
commite3b6cb87e0ba1304fa07ec316784de1c6243b28e (patch)
treeb8c627bd2e5d31330a9c81c6a0526bc9045064b9 /lib/loopdev.c
parentlibfdisk: don't re-allocate range string in Ask API (diff)
downloadkernel-qcow2-util-linux-e3b6cb87e0ba1304fa07ec316784de1c6243b28e.tar.gz
kernel-qcow2-util-linux-e3b6cb87e0ba1304fa07ec316784de1c6243b28e.tar.xz
kernel-qcow2-util-linux-e3b6cb87e0ba1304fa07ec316784de1c6243b28e.zip
lib/loopdev: fix loopcxt_check_size() to work with blkdevs
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>
Diffstat (limited to 'lib/loopdev.c')
-rw-r--r--lib/loopdev.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/lib/loopdev.c b/lib/loopdev.c
index c35e306f9..3b65b5d29 100644
--- a/lib/loopdev.c
+++ b/lib/loopdev.c
@@ -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)