|
|
76daa3 |
From 9df594fcb09af8318fa5d0abc32fd5dddbeb4ce3 Mon Sep 17 00:00:00 2001
|
|
|
76daa3 |
From: Jeffrey Cody <jcody@redhat.com>
|
|
|
76daa3 |
Date: Tue, 30 May 2017 20:18:21 +0200
|
|
|
76daa3 |
Subject: [PATCH 02/13] block/gluster: glfs_lseek() workaround
|
|
|
76daa3 |
|
|
|
76daa3 |
RH-Author: Jeffrey Cody <jcody@redhat.com>
|
|
|
76daa3 |
Message-id: <2fe278e911ea53cdc0d24b547ed3012c0dbedbb9.1496175329.git.jcody@redhat.com>
|
|
|
76daa3 |
Patchwork-id: 75436
|
|
|
76daa3 |
O-Subject: [RHEV-7.4 qemu-kvm-rhev PATCH v2] block/gluster: glfs_lseek() workaround
|
|
|
76daa3 |
Bugzilla: 1451191
|
|
|
76daa3 |
RH-Acked-by: Eric Blake <eblake@redhat.com>
|
|
|
76daa3 |
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
|
|
|
76daa3 |
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
76daa3 |
|
|
|
76daa3 |
On current released versions of glusterfs, glfs_lseek() will sometimes
|
|
|
76daa3 |
return invalid values for SEEK_DATA or SEEK_HOLE. For SEEK_DATA and
|
|
|
76daa3 |
SEEK_HOLE, the returned value should be >= the passed offset, or < 0 in
|
|
|
76daa3 |
the case of error:
|
|
|
76daa3 |
|
|
|
76daa3 |
LSEEK(2):
|
|
|
76daa3 |
|
|
|
76daa3 |
off_t lseek(int fd, off_t offset, int whence);
|
|
|
76daa3 |
|
|
|
76daa3 |
[...]
|
|
|
76daa3 |
|
|
|
76daa3 |
SEEK_HOLE
|
|
|
76daa3 |
Adjust the file offset to the next hole in the file greater
|
|
|
76daa3 |
than or equal to offset. If offset points into the middle of
|
|
|
76daa3 |
a hole, then the file offset is set to offset. If there is no
|
|
|
76daa3 |
hole past offset, then the file offset is adjusted to the end
|
|
|
76daa3 |
of the file (i.e., there is an implicit hole at the end of
|
|
|
76daa3 |
any file).
|
|
|
76daa3 |
|
|
|
76daa3 |
[...]
|
|
|
76daa3 |
|
|
|
76daa3 |
RETURN VALUE
|
|
|
76daa3 |
Upon successful completion, lseek() returns the resulting
|
|
|
76daa3 |
offset location as measured in bytes from the beginning of the
|
|
|
76daa3 |
file. On error, the value (off_t) -1 is returned and errno is
|
|
|
76daa3 |
set to indicate the error
|
|
|
76daa3 |
|
|
|
76daa3 |
However, occasionally glfs_lseek() for SEEK_HOLE/DATA will return a
|
|
|
76daa3 |
value less than the passed offset, yet greater than zero.
|
|
|
76daa3 |
|
|
|
76daa3 |
For instance, here are example values observed from this call:
|
|
|
76daa3 |
|
|
|
76daa3 |
offs = glfs_lseek(s->fd, start, SEEK_HOLE);
|
|
|
76daa3 |
if (offs < 0) {
|
|
|
76daa3 |
return -errno; /* D1 and (H3 or H4) */
|
|
|
76daa3 |
}
|
|
|
76daa3 |
|
|
|
76daa3 |
start == 7608336384
|
|
|
76daa3 |
offs == 7607877632
|
|
|
76daa3 |
|
|
|
76daa3 |
This causes QEMU to abort on the assert test. When this value is
|
|
|
76daa3 |
returned, errno is also 0.
|
|
|
76daa3 |
|
|
|
76daa3 |
This is a reported and known bug to glusterfs:
|
|
|
76daa3 |
https://bugzilla.redhat.com/show_bug.cgi?id=1425293
|
|
|
76daa3 |
|
|
|
76daa3 |
Although this is being fixed in gluster, we still should work around it
|
|
|
76daa3 |
in QEMU, given that multiple released versions of gluster behave this
|
|
|
76daa3 |
way.
|
|
|
76daa3 |
|
|
|
76daa3 |
This patch treats the return case of (offs < start) the same as if an
|
|
|
76daa3 |
error value other than ENXIO is returned; we will assume we learned
|
|
|
76daa3 |
nothing, and there are no holes in the file.
|
|
|
76daa3 |
|
|
|
76daa3 |
Signed-off-by: Jeff Cody <jcody@redhat.com>
|
|
|
76daa3 |
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
|
76daa3 |
Reviewed-by: Niels de Vos <ndevos@redhat.com>
|
|
|
76daa3 |
Message-id: 87c0140e9407c08f6e74b04131b610f2e27c014c.1495560397.git.jcody@redhat.com
|
|
|
76daa3 |
Signed-off-by: Jeff Cody <jcody@redhat.com>
|
|
|
76daa3 |
(cherry picked from commit 223a23c198787328ae75bc65d84edf5fde33c0b6)
|
|
|
76daa3 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
76daa3 |
---
|
|
|
76daa3 |
block/gluster.c | 18 ++++++++++++++++--
|
|
|
76daa3 |
1 file changed, 16 insertions(+), 2 deletions(-)
|
|
|
76daa3 |
|
|
|
76daa3 |
diff --git a/block/gluster.c b/block/gluster.c
|
|
|
76daa3 |
index cf29b5f..6ea91ef 100644
|
|
|
76daa3 |
--- a/block/gluster.c
|
|
|
76daa3 |
+++ b/block/gluster.c
|
|
|
76daa3 |
@@ -1272,7 +1272,14 @@ static int find_allocation(BlockDriverState *bs, off_t start,
|
|
|
76daa3 |
if (offs < 0) {
|
|
|
76daa3 |
return -errno; /* D3 or D4 */
|
|
|
76daa3 |
}
|
|
|
76daa3 |
- assert(offs >= start);
|
|
|
76daa3 |
+
|
|
|
76daa3 |
+ if (offs < start) {
|
|
|
76daa3 |
+ /* This is not a valid return by lseek(). We are safe to just return
|
|
|
76daa3 |
+ * -EIO in this case, and we'll treat it like D4. Unfortunately some
|
|
|
76daa3 |
+ * versions of gluster server will return offs < start, so an assert
|
|
|
76daa3 |
+ * here will unnecessarily abort QEMU. */
|
|
|
76daa3 |
+ return -EIO;
|
|
|
76daa3 |
+ }
|
|
|
76daa3 |
|
|
|
76daa3 |
if (offs > start) {
|
|
|
76daa3 |
/* D2: in hole, next data at offs */
|
|
|
76daa3 |
@@ -1304,7 +1311,14 @@ static int find_allocation(BlockDriverState *bs, off_t start,
|
|
|
76daa3 |
if (offs < 0) {
|
|
|
76daa3 |
return -errno; /* D1 and (H3 or H4) */
|
|
|
76daa3 |
}
|
|
|
76daa3 |
- assert(offs >= start);
|
|
|
76daa3 |
+
|
|
|
76daa3 |
+ if (offs < start) {
|
|
|
76daa3 |
+ /* This is not a valid return by lseek(). We are safe to just return
|
|
|
76daa3 |
+ * -EIO in this case, and we'll treat it like H4. Unfortunately some
|
|
|
76daa3 |
+ * versions of gluster server will return offs < start, so an assert
|
|
|
76daa3 |
+ * here will unnecessarily abort QEMU. */
|
|
|
76daa3 |
+ return -EIO;
|
|
|
76daa3 |
+ }
|
|
|
76daa3 |
|
|
|
76daa3 |
if (offs > start) {
|
|
|
76daa3 |
/*
|
|
|
76daa3 |
--
|
|
|
76daa3 |
1.8.3.1
|
|
|
76daa3 |
|