From e49090106b634fbe2d7d613cba7b9d5550fe3f43 Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Wed, 6 Dec 2017 11:43:32 +0100 Subject: [PATCH] merge gluster fixes * 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 --- ...-block-gluster-glfs_lseek-workaround.patch | 107 +++++++++++ ...add-support-for-PREALLOC_MODE_FALLOC.patch | 180 ++++++++++++++++++ debian/patches/series | 2 + 3 files changed, 289 insertions(+) create mode 100644 debian/patches/extra/0025-block-gluster-glfs_lseek-workaround.patch create mode 100644 debian/patches/extra/0026-gluster-add-support-for-PREALLOC_MODE_FALLOC.patch 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 index 0000000..566e00f --- /dev/null +++ b/debian/patches/extra/0025-block-gluster-glfs_lseek-workaround.patch @@ -0,0 +1,107 @@ +From 3a2be75872e6670a81410ecb175a447be45cfd15 Mon Sep 17 00:00:00 2001 +From: Jeff Cody +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 +Reviewed-by: Eric Blake +Reviewed-by: Niels de Vos +Message-id: 87c0140e9407c08f6e74b04131b610f2e27c014c.1495560397.git.jcody@redhat.com +Signed-off-by: Jeff Cody +--- + 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 index 0000000..d6609bb --- /dev/null +++ b/debian/patches/extra/0026-gluster-add-support-for-PREALLOC_MODE_FALLOC.patch @@ -0,0 +1,180 @@ +From ca3e533f0335aa248e10f9f5a715dc5b8ec7e442 Mon Sep 17 00:00:00 2001 +From: Niels de Vos +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 +Signed-off-by: Niels de Vos +Message-id: 20170528063114.28691-1-ndevos@redhat.com +URL: https://bugzilla.redhat.com/1450759 +Signed-off-by: Niels de Vos +Signed-off-by: Jeff Cody +--- + 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 + diff --git a/debian/patches/series b/debian/patches/series index 4fc68f0..c44620c 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -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 -- 2.39.2