diff options
author | Karel Zak | 2013-05-13 10:54:41 +0200 |
---|---|---|
committer | Karel Zak | 2013-05-13 10:54:41 +0200 |
commit | e3b6cb87e0ba1304fa07ec316784de1c6243b28e (patch) | |
tree | b8c627bd2e5d31330a9c81c6a0526bc9045064b9 /lib/loopdev.c | |
parent | libfdisk: don't re-allocate range string in Ask API (diff) | |
download | kernel-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.c | 16 |
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) |