]> git.proxmox.com Git - pve-qemu.git/commitdiff
merge gluster fixes
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Wed, 6 Dec 2017 10:43:32 +0000 (11:43 +0100)
committerWolfgang Bumiller <w.bumiller@proxmox.com>
Thu, 7 Dec 2017 10:36:53 +0000 (11:36 +0100)
* block/gluster: glfs_lseek() workaround
     https://bugzilla.redhat.com/show_bug.cgi?id=1425293
     https://bugzilla.redhat.com/show_bug.cgi?id=1451191

* gluster: add support for PREALLOC_MODE_FALLOC

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
debian/patches/extra/0025-block-gluster-glfs_lseek-workaround.patch [new file with mode: 0644]
debian/patches/extra/0026-gluster-add-support-for-PREALLOC_MODE_FALLOC.patch [new file with mode: 0644]
debian/patches/series

diff --git a/debian/patches/extra/0025-block-gluster-glfs_lseek-workaround.patch b/debian/patches/extra/0025-block-gluster-glfs_lseek-workaround.patch
new file mode 100644 (file)
index 0000000..566e00f
--- /dev/null
@@ -0,0 +1,107 @@
+From 3a2be75872e6670a81410ecb175a447be45cfd15 Mon Sep 17 00:00:00 2001
+From: Jeff Cody <jcody@redhat.com>
+Date: Tue, 23 May 2017 13:27:50 -0400
+Subject: [PATCH 1/2] block/gluster: glfs_lseek() workaround
+
+On current released versions of glusterfs, glfs_lseek() will sometimes
+return invalid values for SEEK_DATA or SEEK_HOLE.  For SEEK_DATA and
+SEEK_HOLE, the returned value should be >= the passed offset, or < 0 in
+the case of error:
+
+LSEEK(2):
+
+    off_t lseek(int fd, off_t offset, int whence);
+
+    [...]
+
+    SEEK_HOLE
+              Adjust  the file offset to the next hole in the file greater
+              than or equal to offset.  If offset points into the middle of
+              a hole, then the file offset is set to offset.  If there is no
+              hole past offset, then the file offset is adjusted to the end
+              of the file (i.e., there is  an implicit hole at the end of
+              any file).
+
+    [...]
+
+    RETURN VALUE
+              Upon  successful  completion,  lseek()  returns  the resulting
+              offset location as measured in bytes from the beginning of the
+              file.  On error, the value (off_t) -1 is returned and errno is
+              set to indicate the error
+
+However, occasionally glfs_lseek() for SEEK_HOLE/DATA will return a
+value less than the passed offset, yet greater than zero.
+
+For instance, here are example values observed from this call:
+
+    offs = glfs_lseek(s->fd, start, SEEK_HOLE);
+    if (offs < 0) {
+        return -errno;          /* D1 and (H3 or H4) */
+    }
+
+start == 7608336384
+offs == 7607877632
+
+This causes QEMU to abort on the assert test.  When this value is
+returned, errno is also 0.
+
+This is a reported and known bug to glusterfs:
+https://bugzilla.redhat.com/show_bug.cgi?id=1425293
+
+Although this is being fixed in gluster, we still should work around it
+in QEMU, given that multiple released versions of gluster behave this
+way.
+
+This patch treats the return case of (offs < start) the same as if an
+error value other than ENXIO is returned; we will assume we learned
+nothing, and there are no holes in the file.
+
+Signed-off-by: Jeff Cody <jcody@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Reviewed-by: Niels de Vos <ndevos@redhat.com>
+Message-id: 87c0140e9407c08f6e74b04131b610f2e27c014c.1495560397.git.jcody@redhat.com
+Signed-off-by: Jeff Cody <jcody@redhat.com>
+---
+ block/gluster.c | 18 ++++++++++++++++--
+ 1 file changed, 16 insertions(+), 2 deletions(-)
+
+diff --git a/block/gluster.c b/block/gluster.c
+index 4fdf68f1fc..06421ef79d 100644
+--- a/block/gluster.c
++++ b/block/gluster.c
+@@ -1287,7 +1287,14 @@ static int find_allocation(BlockDriverState *bs, off_t start,
+     if (offs < 0) {
+         return -errno;          /* D3 or D4 */
+     }
+-    assert(offs >= start);
++
++    if (offs < start) {
++        /* This is not a valid return by lseek().  We are safe to just return
++         * -EIO in this case, and we'll treat it like D4. Unfortunately some
++         *  versions of gluster server will return offs < start, so an assert
++         *  here will unnecessarily abort QEMU. */
++        return -EIO;
++    }
+     if (offs > start) {
+         /* D2: in hole, next data at offs */
+@@ -1319,7 +1326,14 @@ static int find_allocation(BlockDriverState *bs, off_t start,
+     if (offs < 0) {
+         return -errno;          /* D1 and (H3 or H4) */
+     }
+-    assert(offs >= start);
++
++    if (offs < start) {
++        /* This is not a valid return by lseek().  We are safe to just return
++         * -EIO in this case, and we'll treat it like H4. Unfortunately some
++         *  versions of gluster server will return offs < start, so an assert
++         *  here will unnecessarily abort QEMU. */
++        return -EIO;
++    }
+     if (offs > start) {
+         /*
+-- 
+2.11.0
+
diff --git a/debian/patches/extra/0026-gluster-add-support-for-PREALLOC_MODE_FALLOC.patch b/debian/patches/extra/0026-gluster-add-support-for-PREALLOC_MODE_FALLOC.patch
new file mode 100644 (file)
index 0000000..d6609bb
--- /dev/null
@@ -0,0 +1,180 @@
+From ca3e533f0335aa248e10f9f5a715dc5b8ec7e442 Mon Sep 17 00:00:00 2001
+From: Niels de Vos <ndevos@redhat.com>
+Date: Sun, 28 May 2017 12:01:14 +0530
+Subject: [PATCH 2/2] gluster: add support for PREALLOC_MODE_FALLOC
+
+Add missing support for "preallocation=falloc" to the Gluster block
+driver. This change bases its logic on that of block/file-posix.c and
+removed the gluster_supports_zerofill() and qemu_gluster_zerofill()
+functions in favour of #ifdef checks in an easy to read
+switch-statement.
+
+Both glfs_zerofill() and glfs_fallocate() have been introduced with
+GlusterFS 3.5.0 (pkg-config glusterfs-api = 6). A #define for the
+availability of glfs_fallocate() has been added to ./configure.
+
+Reported-by: Satheesaran Sundaramoorthi <sasundar@redhat.com>
+Signed-off-by: Niels de Vos <ndevos@redhat.com>
+Message-id: 20170528063114.28691-1-ndevos@redhat.com
+URL: https://bugzilla.redhat.com/1450759
+Signed-off-by: Niels de Vos <ndevos@redhat.com>
+Signed-off-by: Jeff Cody <jcody@redhat.com>
+---
+ block/gluster.c | 76 ++++++++++++++++++++++++++++++---------------------------
+ configure       |  6 +++++
+ 2 files changed, 46 insertions(+), 36 deletions(-)
+
+diff --git a/block/gluster.c b/block/gluster.c
+index 06421ef79d..8108c89c7f 100644
+--- a/block/gluster.c
++++ b/block/gluster.c
+@@ -975,29 +975,6 @@ static coroutine_fn int qemu_gluster_co_pwrite_zeroes(BlockDriverState *bs,
+     qemu_coroutine_yield();
+     return acb.ret;
+ }
+-
+-static inline bool gluster_supports_zerofill(void)
+-{
+-    return 1;
+-}
+-
+-static inline int qemu_gluster_zerofill(struct glfs_fd *fd, int64_t offset,
+-                                        int64_t size)
+-{
+-    return glfs_zerofill(fd, offset, size);
+-}
+-
+-#else
+-static inline bool gluster_supports_zerofill(void)
+-{
+-    return 0;
+-}
+-
+-static inline int qemu_gluster_zerofill(struct glfs_fd *fd, int64_t offset,
+-                                        int64_t size)
+-{
+-    return 0;
+-}
+ #endif
+ static int qemu_gluster_create(const char *filename,
+@@ -1007,9 +984,10 @@ static int qemu_gluster_create(const char *filename,
+     struct glfs *glfs;
+     struct glfs_fd *fd;
+     int ret = 0;
+-    int prealloc = 0;
++    PreallocMode prealloc;
+     int64_t total_size = 0;
+     char *tmp = NULL;
++    Error *local_err = NULL;
+     gconf = g_new0(BlockdevOptionsGluster, 1);
+     gconf->debug = qemu_opt_get_number_del(opts, GLUSTER_OPT_DEBUG,
+@@ -1037,13 +1015,12 @@ static int qemu_gluster_create(const char *filename,
+                           BDRV_SECTOR_SIZE);
+     tmp = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
+-    if (!tmp || !strcmp(tmp, "off")) {
+-        prealloc = 0;
+-    } else if (!strcmp(tmp, "full") && gluster_supports_zerofill()) {
+-        prealloc = 1;
+-    } else {
+-        error_setg(errp, "Invalid preallocation mode: '%s'"
+-                         " or GlusterFS doesn't support zerofill API", tmp);
++    prealloc = qapi_enum_parse(PreallocMode_lookup, tmp,
++                               PREALLOC_MODE__MAX, PREALLOC_MODE_OFF,
++                               &local_err);
++    g_free(tmp);
++    if (local_err) {
++        error_propagate(errp, local_err);
+         ret = -EINVAL;
+         goto out;
+     }
+@@ -1052,21 +1029,48 @@ static int qemu_gluster_create(const char *filename,
+                     O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR);
+     if (!fd) {
+         ret = -errno;
+-    } else {
++        goto out;
++    }
++
++    switch (prealloc) {
++#ifdef CONFIG_GLUSTERFS_FALLOCATE
++    case PREALLOC_MODE_FALLOC:
++        if (glfs_fallocate(fd, 0, 0, total_size)) {
++            error_setg(errp, "Could not preallocate data for the new file");
++            ret = -errno;
++        }
++        break;
++#endif /* CONFIG_GLUSTERFS_FALLOCATE */
++#ifdef CONFIG_GLUSTERFS_ZEROFILL
++    case PREALLOC_MODE_FULL:
+         if (!glfs_ftruncate(fd, total_size)) {
+-            if (prealloc && qemu_gluster_zerofill(fd, 0, total_size)) {
++            if (glfs_zerofill(fd, 0, total_size)) {
++                error_setg(errp, "Could not zerofill the new file");
+                 ret = -errno;
+             }
+         } else {
++            error_setg(errp, "Could not resize file");
+             ret = -errno;
+         }
+-
+-        if (glfs_close(fd) != 0) {
++        break;
++#endif /* CONFIG_GLUSTERFS_ZEROFILL */
++    case PREALLOC_MODE_OFF:
++        if (glfs_ftruncate(fd, total_size) != 0) {
+             ret = -errno;
++            error_setg(errp, "Could not resize file");
+         }
++        break;
++    default:
++        ret = -EINVAL;
++        error_setg(errp, "Unsupported preallocation mode: %s",
++                   PreallocMode_lookup[prealloc]);
++        break;
++    }
++
++    if (glfs_close(fd) != 0) {
++        ret = -errno;
+     }
+ out:
+-    g_free(tmp);
+     qapi_free_BlockdevOptionsGluster(gconf);
+     glfs_clear_preopened(glfs);
+     return ret;
+diff --git a/configure b/configure
+index 841f7a8fae..3667da6f07 100755
+--- a/configure
++++ b/configure
+@@ -300,6 +300,7 @@ seccomp=""
+ glusterfs=""
+ glusterfs_xlator_opt="no"
+ glusterfs_discard="no"
++glusterfs_fallocate="no"
+ glusterfs_zerofill="no"
+ gtk=""
+ gtkabi=""
+@@ -3537,6 +3538,7 @@ if test "$glusterfs" != "no" ; then
+       glusterfs_discard="yes"
+     fi
+     if $pkg_config --atleast-version=6 glusterfs-api; then
++      glusterfs_fallocate="yes"
+       glusterfs_zerofill="yes"
+     fi
+   else
+@@ -5717,6 +5719,10 @@ if test "$glusterfs_discard" = "yes" ; then
+   echo "CONFIG_GLUSTERFS_DISCARD=y" >> $config_host_mak
+ fi
++if test "$glusterfs_fallocate" = "yes" ; then
++  echo "CONFIG_GLUSTERFS_FALLOCATE=y" >> $config_host_mak
++fi
++
+ if test "$glusterfs_zerofill" = "yes" ; then
+   echo "CONFIG_GLUSTERFS_ZEROFILL=y" >> $config_host_mak
+ fi
+-- 
+2.11.0
+
index 4fc68f082a761615d79a40865d7f05250610ae60..c44620c11e3fb9f4d0800c6c8f4b79af32898c40 100644 (file)
@@ -51,3 +51,5 @@ extra/0021-io-monitor-encoutput-buffer-size-from-websocket-GSou.patch
 extra/0022-9pfs-use-g_malloc0-to-allocate-space-for-xattr.patch
 extra/0023-cirrus-fix-oob-access-in-mode4and5-write-functions.patch
 extra/0024-virtio-check-VirtQueue-Vring-object-is-set.patch
+extra/0025-block-gluster-glfs_lseek-workaround.patch
+extra/0026-gluster-add-support-for-PREALLOC_MODE_FALLOC.patch