Upstream-Status: Backport Signed-off-by: Jonathan Liu From e3b6cb87e0ba1304fa07ec316784de1c6243b28e Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 13 May 2013 10:54:41 +0200 Subject: [PATCH] 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 Signed-off-by: Karel Zak --- lib/loopdev.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/loopdev.c b/lib/loopdev.c index c35e306..3b65b5d 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) -- 1.8.2.3