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