From: Thomas Huth <thuth@redhat.com>
To: qemu-devel@nongnu.org, qemu-block@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>, Hanna Reitz <hreitz@redhat.com>,
Eric Blake <eblake@redhat.com>,
Markus Armbruster <armbru@redhat.com>
Subject: [PATCH v2] Remove the deprecated glusterfs block driver
Date: Mon, 11 May 2026 08:30:13 +0200 [thread overview]
Message-ID: <20260511063013.39805-1-thuth@redhat.com> (raw)
From: Thomas Huth <thuth@redhat.com>
Glusterfs has been marked as deprecated since QEMU v9.2, and as far
as I know, nobody spoke up 'til today that it should be kept.
The listed e-mail address integration@gluster.org in our MAINTAINERS
file seems to be bouncing nowadays, and looking at their website
https://www.gluster.org/ the most recent news are from 2020 / 2021 ...
so it seems like there is really hardly any interest in Glusterfs
anymore. Thus it's time to remove the code now from QEMU.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
v2: Rebase to master to fix a conflict with a patch that has been merged
in between.
MAINTAINERS | 6 -
docs/about/deprecated.rst | 8 -
docs/about/removed-features.rst | 7 +
docs/system/device-url-syntax.rst.inc | 39 -
docs/system/qemu-block-drivers.rst.inc | 84 -
meson.build | 47 -
qapi/block-core.json | 52 -
block/gluster.c | 1644 -----------------
tests/qtest/modules-test.c | 3 -
block/meson.build | 1 -
meson_options.txt | 2 -
.../ci/setup/debian/debian-13-ppc64le.yaml | 1 -
.../ci/setup/ubuntu/ubuntu-2404-aarch64.yaml | 1 -
.../ci/setup/ubuntu/ubuntu-2404-s390x.yaml | 1 -
scripts/coverity-scan/coverity-scan.docker | 1 -
scripts/coverity-scan/run-coverity-scan | 2 +-
scripts/meson-buildoptions.sh | 3 -
.../dockerfiles/debian-amd64-cross.docker | 1 -
.../dockerfiles/debian-arm64-cross.docker | 1 -
.../dockerfiles/debian-mips64el-cross.docker | 1 -
.../dockerfiles/debian-mipsel-cross.docker | 1 -
.../dockerfiles/debian-ppc64el-cross.docker | 1 -
.../dockerfiles/debian-riscv64-cross.docker | 1 -
.../dockerfiles/debian-s390x-cross.docker | 1 -
tests/docker/dockerfiles/debian.docker | 1 -
.../dockerfiles/fedora-rust-nightly.docker | 1 -
tests/docker/dockerfiles/fedora.docker | 1 -
tests/docker/dockerfiles/opensuse-leap.docker | 1 -
tests/docker/dockerfiles/ubuntu2204.docker | 1 -
tests/lcitool/projects/qemu.yml | 1 -
30 files changed, 8 insertions(+), 1907 deletions(-)
delete mode 100644 block/gluster.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 9d3d6459537..a9b0b65ec5f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4252,12 +4252,6 @@ L: qemu-block@nongnu.org
S: Odd Fixes
F: block/curl.c
-GLUSTER
-L: qemu-block@nongnu.org
-L: integration@gluster.org
-S: Odd Fixes
-F: block/gluster.c
-
Null Block Driver
M: Fam Zheng <fam@euphon.net>
L: qemu-block@nongnu.org
diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index 5551bd12ad8..b9f5e2e06ae 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -419,14 +419,6 @@ Specifying the iSCSI password in plain text on the command line using the
used instead, to refer to a ``--object secret...`` instance that provides
a password via a file, or encrypted.
-``gluster`` backend (since 9.2)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-According to https://marc.info/?l=fedora-devel-list&m=171934833215726
-the GlusterFS development effectively ended. Unless the development
-gains momentum again, the QEMU project will remove the gluster backend
-in a future release.
-
Character device options
''''''''''''''''''''''''
diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst
index 626162022a8..3105f62ff8a 100644
--- a/docs/about/removed-features.rst
+++ b/docs/about/removed-features.rst
@@ -1393,6 +1393,13 @@ The corresponding upstream server project is no longer maintained.
Users are recommended to switch to an alternative distributed block
device driver such as RBD.
+``gluster`` backend (removed in 11.1)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+According to https://marc.info/?l=fedora-devel-list&m=171934833215726
+the GlusterFS development effectively ended.
+
+
VFIO devices
------------
diff --git a/docs/system/device-url-syntax.rst.inc b/docs/system/device-url-syntax.rst.inc
index 996ce5418ff..3521a3d053f 100644
--- a/docs/system/device-url-syntax.rst.inc
+++ b/docs/system/device-url-syntax.rst.inc
@@ -85,45 +85,6 @@ These are specified using a special URL syntax.
Currently authentication must be done using ssh-agent. Other
authentication methods may be supported in future.
-``GlusterFS``
- GlusterFS is a user space distributed file system. QEMU supports the
- use of GlusterFS volumes for hosting VM disk images using TCP and Unix
- Domain Sockets transport protocols.
-
- Syntax for specifying a VM disk image on GlusterFS volume is
-
- .. parsed-literal::
-
- URI:
- gluster[+type]://[host[:port]]/volume/path[?socket=...][,debug=N][,logfile=...]
-
- JSON:
- 'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol","path":"a.img","debug":N,"logfile":"...",
- "server":[{"type":"tcp","host":"...","port":"..."},
- {"type":"unix","socket":"..."}]}}'
-
- Example
-
- .. parsed-literal::
-
- URI:
- |qemu_system| --drive file=gluster://192.0.2.1/testvol/a.img,
- file.debug=9,file.logfile=/var/log/qemu-gluster.log
-
- JSON:
- |qemu_system| 'json:{"driver":"qcow2",
- "file":{"driver":"gluster",
- "volume":"testvol","path":"a.img",
- "debug":9,"logfile":"/var/log/qemu-gluster.log",
- "server":[{"type":"tcp","host":"1.2.3.4","port":24007},
- {"type":"unix","socket":"/var/run/glusterd.socket"}]}}'
- |qemu_system| -drive driver=qcow2,file.driver=gluster,file.volume=testvol,file.path=/path/a.img,
- file.debug=9,file.logfile=/var/log/qemu-gluster.log,
- file.server.0.type=tcp,file.server.0.host=1.2.3.4,file.server.0.port=24007,
- file.server.1.type=unix,file.server.1.socket=/var/run/glusterd.socket
-
- See also http://www.gluster.org.
-
``HTTP/HTTPS/FTP/FTPS``
QEMU supports read-only access to files accessed over http(s) and
ftp(s).
diff --git a/docs/system/qemu-block-drivers.rst.inc b/docs/system/qemu-block-drivers.rst.inc
index 384e95ba765..675daa72f97 100644
--- a/docs/system/qemu-block-drivers.rst.inc
+++ b/docs/system/qemu-block-drivers.rst.inc
@@ -665,90 +665,6 @@ systems as the package 'scsi-target-utils'.
-boot d -drive file=iscsi://127.0.0.1/iqn.qemu.test/1 \\
-cdrom iscsi://127.0.0.1/iqn.qemu.test/2
-GlusterFS disk images
-~~~~~~~~~~~~~~~~~~~~~
-
-GlusterFS is a user space distributed file system.
-
-You can boot from the GlusterFS disk image with the command:
-
-URI:
-
-.. parsed-literal::
-
- |qemu_system| -drive file=gluster[+TYPE]://[HOST}[:PORT]]/VOLUME/PATH
- [?socket=...][,file.debug=9][,file.logfile=...]
-
-JSON:
-
-.. parsed-literal::
-
- |qemu_system| 'json:{"driver":"qcow2",
- "file":{"driver":"gluster",
- "volume":"testvol","path":"a.img","debug":9,"logfile":"...",
- "server":[{"type":"tcp","host":"...","port":"..."},
- {"type":"unix","socket":"..."}]}}'
-
-*gluster* is the protocol.
-
-*TYPE* specifies the transport type used to connect to gluster
-management daemon (glusterd). Valid transport types are
-tcp and unix. In the URI form, if a transport type isn't specified,
-then tcp type is assumed.
-
-*HOST* specifies the server where the volume file specification for
-the given volume resides. This can be either a hostname or an ipv4 address.
-If transport type is unix, then *HOST* field should not be specified.
-Instead *socket* field needs to be populated with the path to unix domain
-socket.
-
-*PORT* is the port number on which glusterd is listening. This is optional
-and if not specified, it defaults to port 24007. If the transport type is unix,
-then *PORT* should not be specified.
-
-*VOLUME* is the name of the gluster volume which contains the disk image.
-
-*PATH* is the path to the actual disk image that resides on gluster volume.
-
-*debug* is the logging level of the gluster protocol driver. Debug levels
-are 0-9, with 9 being the most verbose, and 0 representing no debugging output.
-The default level is 4. The current logging levels defined in the gluster source
-are 0 - None, 1 - Emergency, 2 - Alert, 3 - Critical, 4 - Error, 5 - Warning,
-6 - Notice, 7 - Info, 8 - Debug, 9 - Trace
-
-*logfile* is a commandline option to mention log file path which helps in
-logging to the specified file and also help in persisting the gfapi logs. The
-default is stderr.
-
-You can create a GlusterFS disk image with the command:
-
-.. parsed-literal::
-
- qemu-img create gluster://HOST/VOLUME/PATH SIZE
-
-Examples
-
-.. parsed-literal::
-
- |qemu_system| -drive file=gluster://1.2.3.4/testvol/a.img
- |qemu_system| -drive file=gluster+tcp://1.2.3.4/testvol/a.img
- |qemu_system| -drive file=gluster+tcp://1.2.3.4:24007/testvol/dir/a.img
- |qemu_system| -drive file=gluster+tcp://[1:2:3:4:5:6:7:8]/testvol/dir/a.img
- |qemu_system| -drive file=gluster+tcp://[1:2:3:4:5:6:7:8]:24007/testvol/dir/a.img
- |qemu_system| -drive file=gluster+tcp://server.domain.com:24007/testvol/dir/a.img
- |qemu_system| -drive file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket
- |qemu_system| -drive file=gluster://1.2.3.4/testvol/a.img,file.debug=9,file.logfile=/var/log/qemu-gluster.log
- |qemu_system| 'json:{"driver":"qcow2",
- "file":{"driver":"gluster",
- "volume":"testvol","path":"a.img",
- "debug":9,"logfile":"/var/log/qemu-gluster.log",
- "server":[{"type":"tcp","host":"1.2.3.4","port":24007},
- {"type":"unix","socket":"/var/run/glusterd.socket"}]}}'
- |qemu_system| -drive driver=qcow2,file.driver=gluster,file.volume=testvol,file.path=/path/a.img,
- file.debug=9,file.logfile=/var/log/qemu-gluster.log,
- file.server.0.type=tcp,file.server.0.host=1.2.3.4,file.server.0.port=24007,
- file.server.1.type=unix,file.server.1.socket=/var/run/glusterd.socket
-
Secure Shell (ssh) disk images
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/meson.build b/meson.build
index 5fbdc75a0fc..0bd97e3e9a9 100644
--- a/meson.build
+++ b/meson.build
@@ -1656,43 +1656,6 @@ if not get_option('rbd').auto() or have_block
endif
endif
-glusterfs = not_found
-glusterfs_ftruncate_has_stat = false
-glusterfs_iocb_has_stat = false
-if not get_option('glusterfs').auto() or have_block
- glusterfs = dependency('glusterfs-api', version: '>=3',
- required: get_option('glusterfs'),
- method: 'pkg-config')
- if glusterfs.found()
- glusterfs_ftruncate_has_stat = cc.links('''
- #include <glusterfs/api/glfs.h>
-
- int
- main(void)
- {
- /* new glfs_ftruncate() passes two additional args */
- return glfs_ftruncate(NULL, 0, NULL, NULL);
- }
- ''', dependencies: glusterfs)
- glusterfs_iocb_has_stat = cc.links('''
- #include <glusterfs/api/glfs.h>
-
- /* new glfs_io_cbk() passes two additional glfs_stat structs */
- static void
- glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data)
- {}
-
- int
- main(void)
- {
- glfs_io_cbk iocb = &glusterfs_iocb;
- iocb(NULL, 0 , NULL, NULL, NULL);
- return 0;
- }
- ''', dependencies: glusterfs)
- endif
-endif
-
hv_balloon = false
if get_option('hv_balloon').allowed() and have_system
if cc.links('''
@@ -2461,15 +2424,6 @@ config_host_data.set('CONFIG_CURL', curl.found())
config_host_data.set('CONFIG_CURSES', curses.found())
config_host_data.set('CONFIG_GBM', gbm.found())
config_host_data.set('CONFIG_GIO', gio.found())
-config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
-if glusterfs.found()
- config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
- config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
- config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
- config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
- config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
- config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
-endif
config_host_data.set('CONFIG_GTK', gtk.found())
config_host_data.set('CONFIG_VTE', vte.found())
config_host_data.set('CONFIG_HEXAGON_IDEF_PARSER', get_option('hexagon_idef_parser'))
@@ -4990,7 +4944,6 @@ if host_os == 'windows'
endif
endif
summary_info += {'seccomp support': seccomp}
-summary_info += {'GlusterFS support': glusterfs}
summary_info += {'hv-balloon support': hv_balloon}
summary_info += {'TPM support': have_tpm}
summary_info += {'IGVM support': igvm}
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 508b081ac16..b5a77db27c4 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -3334,18 +3334,12 @@
#
# @snapshot-access: Since 7.0
#
-# Features:
-#
-# @deprecated: Member @gluster is deprecated because GlusterFS
-# development ceased.
-#
# Since: 2.9
##
{ 'enum': 'BlockdevDriver',
'data': [ 'blkdebug', 'blklogwrites', 'blkreplay', 'blkverify', 'bochs',
'cloop', 'compress', 'copy-before-write', 'copy-on-read', 'dmg',
'file', 'snapshot-access', 'ftp', 'ftps',
- {'name': 'gluster', 'features': [ 'deprecated' ] },
{'name': 'host_cdrom', 'if': 'HAVE_HOST_BLOCK_DEVICE' },
{'name': 'host_device', 'if': 'HAVE_HOST_BLOCK_DEVICE' },
'http', 'https',
@@ -4114,30 +4108,6 @@
'*rewrite-corrupted': 'bool',
'*read-pattern': 'QuorumReadPattern' } }
-##
-# @BlockdevOptionsGluster:
-#
-# Driver specific block device options for Gluster
-#
-# @volume: name of gluster volume where VM image resides
-#
-# @path: absolute path to image file in gluster volume
-#
-# @server: gluster servers description
-#
-# @debug: libgfapi log level (default '4' which is Error) (Since 2.8)
-#
-# @logfile: libgfapi log file (default /dev/stderr) (Since 2.8)
-#
-# Since: 2.9
-##
-{ 'struct': 'BlockdevOptionsGluster',
- 'data': { 'volume': 'str',
- 'path': 'str',
- 'server': ['SocketAddress'],
- '*debug': 'int',
- '*logfile': 'str' } }
-
##
# @BlockdevOptionsIoUring:
#
@@ -4871,7 +4841,6 @@
'file': 'BlockdevOptionsFile',
'ftp': 'BlockdevOptionsCurlFtp',
'ftps': 'BlockdevOptionsCurlFtps',
- 'gluster': 'BlockdevOptionsGluster',
'host_cdrom': { 'type': 'BlockdevOptionsFile',
'if': 'HAVE_HOST_BLOCK_DEVICE' },
'host_device': { 'type': 'BlockdevOptionsFile',
@@ -5142,26 +5111,6 @@
'*nocow': 'bool',
'*extent-size-hint': 'size'} }
-##
-# @BlockdevCreateOptionsGluster:
-#
-# Driver specific image creation options for gluster.
-#
-# @location: Where to store the new image file
-#
-# @size: Size of the virtual disk in bytes
-#
-# @preallocation: Preallocation mode for the new image (default: off;
-# allowed values: off, falloc (if CONFIG_GLUSTERFS_FALLOCATE),
-# full (if CONFIG_GLUSTERFS_ZEROFILL))
-#
-# Since: 2.12
-##
-{ 'struct': 'BlockdevCreateOptionsGluster',
- 'data': { 'location': 'BlockdevOptionsGluster',
- 'size': 'size',
- '*preallocation': 'PreallocMode' } }
-
##
# @BlockdevCreateOptionsLUKS:
#
@@ -5589,7 +5538,6 @@
'discriminator': 'driver',
'data': {
'file': 'BlockdevCreateOptionsFile',
- 'gluster': 'BlockdevCreateOptionsGluster',
'luks': 'BlockdevCreateOptionsLUKS',
'nfs': 'BlockdevCreateOptionsNfs',
'parallels': 'BlockdevCreateOptionsParallels',
diff --git a/block/gluster.c b/block/gluster.c
deleted file mode 100644
index 279f650241c..00000000000
--- a/block/gluster.c
+++ /dev/null
@@ -1,1644 +0,0 @@
-/*
- * GlusterFS backend for QEMU
- *
- * Copyright (C) 2012 Bharata B Rao <bharata@linux.vnet.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qemu/units.h"
-#include <glusterfs/api/glfs.h>
-#include "block/block-io.h"
-#include "block/block_int.h"
-#include "block/qdict.h"
-#include "qapi/error.h"
-#include "qobject/qdict.h"
-#include "qapi/qmp/qerror.h"
-#include "qemu/error-report.h"
-#include "qemu/module.h"
-#include "qemu/option.h"
-#include "qemu/cutils.h"
-
-#ifdef CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT
-# define glfs_ftruncate(fd, offset) glfs_ftruncate(fd, offset, NULL, NULL)
-#endif
-
-#define GLUSTER_OPT_FILENAME "filename"
-#define GLUSTER_OPT_VOLUME "volume"
-#define GLUSTER_OPT_PATH "path"
-#define GLUSTER_OPT_TYPE "type"
-#define GLUSTER_OPT_SERVER_PATTERN "server."
-#define GLUSTER_OPT_HOST "host"
-#define GLUSTER_OPT_PORT "port"
-#define GLUSTER_OPT_TO "to"
-#define GLUSTER_OPT_IPV4 "ipv4"
-#define GLUSTER_OPT_IPV6 "ipv6"
-#define GLUSTER_OPT_SOCKET "socket"
-#define GLUSTER_OPT_DEBUG "debug"
-#define GLUSTER_DEFAULT_PORT 24007
-#define GLUSTER_DEBUG_DEFAULT 4
-#define GLUSTER_DEBUG_MAX 9
-#define GLUSTER_OPT_LOGFILE "logfile"
-#define GLUSTER_LOGFILE_DEFAULT "-" /* handled in libgfapi as /dev/stderr */
-/*
- * Several versions of GlusterFS (3.12? -> 6.0.1) fail when the transfer size
- * is greater or equal to 1024 MiB, so we are limiting the transfer size to 512
- * MiB to avoid this rare issue.
- */
-#define GLUSTER_MAX_TRANSFER (512 * MiB)
-
-#define GERR_INDEX_HINT "hint: check in 'server' array index '%d'\n"
-
-typedef struct GlusterAIOCB {
- int64_t size;
- int ret;
- Coroutine *coroutine;
-} GlusterAIOCB;
-
-typedef struct BDRVGlusterState {
- struct glfs *glfs;
- struct glfs_fd *fd;
- char *logfile;
- bool supports_seek_data;
- int debug;
-} BDRVGlusterState;
-
-typedef struct BDRVGlusterReopenState {
- struct glfs *glfs;
- struct glfs_fd *fd;
-} BDRVGlusterReopenState;
-
-
-typedef struct GlfsPreopened {
- char *volume;
- glfs_t *fs;
- int ref;
-} GlfsPreopened;
-
-typedef struct ListElement {
- QLIST_ENTRY(ListElement) list;
- GlfsPreopened saved;
-} ListElement;
-
-static QLIST_HEAD(, ListElement) glfs_list;
-
-static QemuOptsList qemu_gluster_create_opts = {
- .name = "qemu-gluster-create-opts",
- .head = QTAILQ_HEAD_INITIALIZER(qemu_gluster_create_opts.head),
- .desc = {
- {
- .name = BLOCK_OPT_SIZE,
- .type = QEMU_OPT_SIZE,
- .help = "Virtual disk size"
- },
- {
- .name = BLOCK_OPT_PREALLOC,
- .type = QEMU_OPT_STRING,
- .help = "Preallocation mode (allowed values: off"
-#ifdef CONFIG_GLUSTERFS_FALLOCATE
- ", falloc"
-#endif
-#ifdef CONFIG_GLUSTERFS_ZEROFILL
- ", full"
-#endif
- ")"
- },
- {
- .name = GLUSTER_OPT_DEBUG,
- .type = QEMU_OPT_NUMBER,
- .help = "Gluster log level, valid range is 0-9",
- },
- {
- .name = GLUSTER_OPT_LOGFILE,
- .type = QEMU_OPT_STRING,
- .help = "Logfile path of libgfapi",
- },
- { /* end of list */ }
- }
-};
-
-static QemuOptsList runtime_opts = {
- .name = "gluster",
- .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
- .desc = {
- {
- .name = GLUSTER_OPT_FILENAME,
- .type = QEMU_OPT_STRING,
- .help = "URL to the gluster image",
- },
- {
- .name = GLUSTER_OPT_DEBUG,
- .type = QEMU_OPT_NUMBER,
- .help = "Gluster log level, valid range is 0-9",
- },
- {
- .name = GLUSTER_OPT_LOGFILE,
- .type = QEMU_OPT_STRING,
- .help = "Logfile path of libgfapi",
- },
- { /* end of list */ }
- },
-};
-
-static QemuOptsList runtime_json_opts = {
- .name = "gluster_json",
- .head = QTAILQ_HEAD_INITIALIZER(runtime_json_opts.head),
- .desc = {
- {
- .name = GLUSTER_OPT_VOLUME,
- .type = QEMU_OPT_STRING,
- .help = "name of gluster volume where VM image resides",
- },
- {
- .name = GLUSTER_OPT_PATH,
- .type = QEMU_OPT_STRING,
- .help = "absolute path to image file in gluster volume",
- },
- {
- .name = GLUSTER_OPT_DEBUG,
- .type = QEMU_OPT_NUMBER,
- .help = "Gluster log level, valid range is 0-9",
- },
- { /* end of list */ }
- },
-};
-
-static QemuOptsList runtime_type_opts = {
- .name = "gluster_type",
- .head = QTAILQ_HEAD_INITIALIZER(runtime_type_opts.head),
- .desc = {
- {
- .name = GLUSTER_OPT_TYPE,
- .type = QEMU_OPT_STRING,
- .help = "inet|unix",
- },
- { /* end of list */ }
- },
-};
-
-static QemuOptsList runtime_unix_opts = {
- .name = "gluster_unix",
- .head = QTAILQ_HEAD_INITIALIZER(runtime_unix_opts.head),
- .desc = {
- {
- .name = GLUSTER_OPT_SOCKET,
- .type = QEMU_OPT_STRING,
- .help = "socket file path (legacy)",
- },
- {
- .name = GLUSTER_OPT_PATH,
- .type = QEMU_OPT_STRING,
- .help = "socket file path (QAPI)",
- },
- { /* end of list */ }
- },
-};
-
-static QemuOptsList runtime_inet_opts = {
- .name = "gluster_inet",
- .head = QTAILQ_HEAD_INITIALIZER(runtime_inet_opts.head),
- .desc = {
- {
- .name = GLUSTER_OPT_TYPE,
- .type = QEMU_OPT_STRING,
- .help = "inet|unix",
- },
- {
- .name = GLUSTER_OPT_HOST,
- .type = QEMU_OPT_STRING,
- .help = "host address (hostname/ipv4/ipv6 addresses)",
- },
- {
- .name = GLUSTER_OPT_PORT,
- .type = QEMU_OPT_STRING,
- .help = "port number on which glusterd is listening (default 24007)",
- },
- {
- .name = "to",
- .type = QEMU_OPT_NUMBER,
- .help = "max port number, not supported by gluster",
- },
- {
- .name = "ipv4",
- .type = QEMU_OPT_BOOL,
- .help = "ipv4 bool value, not supported by gluster",
- },
- {
- .name = "ipv6",
- .type = QEMU_OPT_BOOL,
- .help = "ipv6 bool value, not supported by gluster",
- },
- { /* end of list */ }
- },
-};
-
-static void glfs_set_preopened(const char *volume, glfs_t *fs)
-{
- ListElement *entry = NULL;
-
- entry = g_new(ListElement, 1);
-
- entry->saved.volume = g_strdup(volume);
-
- entry->saved.fs = fs;
- entry->saved.ref = 1;
-
- QLIST_INSERT_HEAD(&glfs_list, entry, list);
-}
-
-static glfs_t *glfs_find_preopened(const char *volume)
-{
- ListElement *entry;
-
- QLIST_FOREACH(entry, &glfs_list, list) {
- if (strcmp(entry->saved.volume, volume) == 0) {
- entry->saved.ref++;
- return entry->saved.fs;
- }
- }
-
- return NULL;
-}
-
-static void glfs_clear_preopened(glfs_t *fs)
-{
- ListElement *entry;
- ListElement *next;
-
- if (fs == NULL) {
- return;
- }
-
- QLIST_FOREACH_SAFE(entry, &glfs_list, list, next) {
- if (entry->saved.fs == fs) {
- if (--entry->saved.ref) {
- return;
- }
-
- QLIST_REMOVE(entry, list);
-
- glfs_fini(entry->saved.fs);
- g_free(entry->saved.volume);
- g_free(entry);
- }
- }
-}
-
-static int parse_volume_options(BlockdevOptionsGluster *gconf, const char *path)
-{
- const char *p, *q;
-
- if (!path) {
- return -EINVAL;
- }
-
- /* volume */
- p = q = path + strspn(path, "/");
- p += strcspn(p, "/");
- if (*p == '\0') {
- return -EINVAL;
- }
- gconf->volume = g_strndup(q, p - q);
-
- /* path */
- p += strspn(p, "/");
- if (*p == '\0') {
- return -EINVAL;
- }
- gconf->path = g_strdup(p);
- return 0;
-}
-
-/*
- * file=gluster[+transport]://[host[:port]]/volume/path[?socket=...]
- *
- * 'gluster' is the protocol.
- *
- * 'transport' specifies the transport type used to connect to gluster
- * management daemon (glusterd). Valid transport types are
- * tcp or unix. If a transport type isn't specified, then tcp type is assumed.
- *
- * 'host' specifies the host where the volume file specification for
- * the given volume resides. This can be either hostname or ipv4 address.
- * If transport type is 'unix', then 'host' field should not be specified.
- * The 'socket' field needs to be populated with the path to unix domain
- * socket.
- *
- * 'port' is the port number on which glusterd is listening. This is optional
- * and if not specified, QEMU will send 0 which will make gluster to use the
- * default port. If the transport type is unix, then 'port' should not be
- * specified.
- *
- * 'volume' is the name of the gluster volume which contains the VM image.
- *
- * 'path' is the path to the actual VM image that resides on gluster volume.
- *
- * Examples:
- *
- * file=gluster://1.2.3.4/testvol/a.img
- * file=gluster+tcp://1.2.3.4/testvol/a.img
- * file=gluster+tcp://1.2.3.4:24007/testvol/dir/a.img
- * file=gluster+tcp://host.domain.com:24007/testvol/dir/a.img
- * file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket
- */
-static int qemu_gluster_parse_uri(BlockdevOptionsGluster *gconf,
- const char *filename)
-{
- g_autoptr(GUri) uri = g_uri_parse(filename, G_URI_FLAGS_NONE, NULL);
- g_autoptr(GHashTable) qp = NULL;
- SocketAddress *gsconf;
- bool is_unix = false;
- const char *uri_scheme, *uri_query, *uri_server;
- int uri_port, ret;
-
- if (!uri) {
- return -EINVAL;
- }
-
- gsconf = g_new0(SocketAddress, 1);
- QAPI_LIST_PREPEND(gconf->server, gsconf);
-
- /* transport */
- uri_scheme = g_uri_get_scheme(uri);
- if (!uri_scheme || !strcmp(uri_scheme, "gluster")) {
- gsconf->type = SOCKET_ADDRESS_TYPE_INET;
- } else if (!strcmp(uri_scheme, "gluster+tcp")) {
- gsconf->type = SOCKET_ADDRESS_TYPE_INET;
- } else if (!strcmp(uri_scheme, "gluster+unix")) {
- gsconf->type = SOCKET_ADDRESS_TYPE_UNIX;
- is_unix = true;
- } else {
- return -EINVAL;
- }
-
- ret = parse_volume_options(gconf, g_uri_get_path(uri));
- if (ret < 0) {
- return ret;
- }
-
- uri_query = g_uri_get_query(uri);
- if (uri_query) {
- qp = g_uri_parse_params(uri_query, -1, "&", G_URI_PARAMS_NONE, NULL);
- if (!qp) {
- return -EINVAL;
- }
- ret = g_hash_table_size(qp);
- if (ret > 1 || (is_unix && !ret) || (!is_unix && ret)) {
- return -EINVAL;
- }
- }
-
- uri_server = g_uri_get_host(uri);
- uri_port = g_uri_get_port(uri);
-
- if (is_unix) {
- char *uri_socket = g_hash_table_lookup(qp, "socket");
- if (uri_server || uri_port != -1 || !uri_socket) {
- return -EINVAL;
- }
- gsconf->u.q_unix.path = g_strdup(uri_socket);
- } else {
- gsconf->u.inet.host = g_strdup(uri_server ? uri_server : "localhost");
- if (uri_port > 0) {
- gsconf->u.inet.port = g_strdup_printf("%d", uri_port);
- } else {
- gsconf->u.inet.port = g_strdup_printf("%d", GLUSTER_DEFAULT_PORT);
- }
- }
-
- return 0;
-}
-
-static struct glfs *qemu_gluster_glfs_init(BlockdevOptionsGluster *gconf,
- Error **errp)
-{
- struct glfs *glfs;
- int ret;
- int old_errno;
- SocketAddressList *server;
- uint64_t port;
-
- glfs = glfs_find_preopened(gconf->volume);
- if (glfs) {
- return glfs;
- }
-
- glfs = glfs_new(gconf->volume);
- if (!glfs) {
- goto out;
- }
-
- glfs_set_preopened(gconf->volume, glfs);
-
- for (server = gconf->server; server; server = server->next) {
- switch (server->value->type) {
- case SOCKET_ADDRESS_TYPE_UNIX:
- ret = glfs_set_volfile_server(glfs, "unix",
- server->value->u.q_unix.path, 0);
- break;
- case SOCKET_ADDRESS_TYPE_INET:
- if (parse_uint_full(server->value->u.inet.port, 10, &port) < 0 ||
- port > 65535) {
- error_setg(errp, "'%s' is not a valid port number",
- server->value->u.inet.port);
- errno = EINVAL;
- goto out;
- }
- ret = glfs_set_volfile_server(glfs, "tcp",
- server->value->u.inet.host,
- (int)port);
- break;
- case SOCKET_ADDRESS_TYPE_VSOCK:
- case SOCKET_ADDRESS_TYPE_FD:
- default:
- abort();
- }
-
- if (ret < 0) {
- goto out;
- }
- }
-
- ret = glfs_set_logging(glfs, gconf->logfile, gconf->debug);
- if (ret < 0) {
- goto out;
- }
-
- ret = glfs_init(glfs);
- if (ret) {
- error_setg(errp, "Gluster connection for volume %s, path %s failed"
- " to connect", gconf->volume, gconf->path);
- for (server = gconf->server; server; server = server->next) {
- if (server->value->type == SOCKET_ADDRESS_TYPE_UNIX) {
- error_append_hint(errp, "hint: failed on socket %s ",
- server->value->u.q_unix.path);
- } else {
- error_append_hint(errp, "hint: failed on host %s and port %s ",
- server->value->u.inet.host,
- server->value->u.inet.port);
- }
- }
-
- error_append_hint(errp, "Please refer to gluster logs for more info\n");
-
- /* glfs_init sometimes doesn't set errno although docs suggest that */
- if (errno == 0) {
- errno = EINVAL;
- }
-
- goto out;
- }
- return glfs;
-
-out:
- if (glfs) {
- old_errno = errno;
- glfs_clear_preopened(glfs);
- errno = old_errno;
- }
- return NULL;
-}
-
-/*
- * Convert the json formatted command line into qapi.
-*/
-static int qemu_gluster_parse_json(BlockdevOptionsGluster *gconf,
- QDict *options, Error **errp)
-{
- QemuOpts *opts;
- SocketAddress *gsconf = NULL;
- SocketAddressList **tail;
- QDict *backing_options = NULL;
- Error *local_err = NULL;
- const char *ptr;
- int i, type, num_servers;
-
- /* create opts info from runtime_json_opts list */
- opts = qemu_opts_create(&runtime_json_opts, NULL, 0, &error_abort);
- if (!qemu_opts_absorb_qdict(opts, options, errp)) {
- goto out;
- }
-
- num_servers = qdict_array_entries(options, GLUSTER_OPT_SERVER_PATTERN);
- if (num_servers < 1) {
- error_setg(&local_err, QERR_MISSING_PARAMETER, "server");
- goto out;
- }
-
- ptr = qemu_opt_get(opts, GLUSTER_OPT_VOLUME);
- if (!ptr) {
- error_setg(&local_err, QERR_MISSING_PARAMETER, GLUSTER_OPT_VOLUME);
- goto out;
- }
- gconf->volume = g_strdup(ptr);
-
- ptr = qemu_opt_get(opts, GLUSTER_OPT_PATH);
- if (!ptr) {
- error_setg(&local_err, QERR_MISSING_PARAMETER, GLUSTER_OPT_PATH);
- goto out;
- }
- gconf->path = g_strdup(ptr);
- qemu_opts_del(opts);
- tail = &gconf->server;
-
- for (i = 0; i < num_servers; i++) {
- g_autofree char *str = g_strdup_printf(GLUSTER_OPT_SERVER_PATTERN"%d.",
- i);
- qdict_extract_subqdict(options, &backing_options, str);
-
- /* create opts info from runtime_type_opts list */
- opts = qemu_opts_create(&runtime_type_opts, NULL, 0, &error_abort);
- if (!qemu_opts_absorb_qdict(opts, backing_options, errp)) {
- goto out;
- }
-
- ptr = qemu_opt_get(opts, GLUSTER_OPT_TYPE);
- if (!ptr) {
- error_setg(&local_err, QERR_MISSING_PARAMETER, GLUSTER_OPT_TYPE);
- error_append_hint(&local_err, GERR_INDEX_HINT, i);
- goto out;
-
- }
- gsconf = g_new0(SocketAddress, 1);
- if (!strcmp(ptr, "tcp")) {
- ptr = "inet"; /* accept legacy "tcp" */
- }
- type = qapi_enum_parse(&SocketAddressType_lookup, ptr, -1, NULL);
- if (type != SOCKET_ADDRESS_TYPE_INET
- && type != SOCKET_ADDRESS_TYPE_UNIX) {
- error_setg(&local_err,
- "Parameter '%s' may be 'inet' or 'unix'",
- GLUSTER_OPT_TYPE);
- error_append_hint(&local_err, GERR_INDEX_HINT, i);
- goto out;
- }
- gsconf->type = type;
- qemu_opts_del(opts);
-
- if (gsconf->type == SOCKET_ADDRESS_TYPE_INET) {
- /* create opts info from runtime_inet_opts list */
- opts = qemu_opts_create(&runtime_inet_opts, NULL, 0, &error_abort);
- if (!qemu_opts_absorb_qdict(opts, backing_options, errp)) {
- goto out;
- }
-
- ptr = qemu_opt_get(opts, GLUSTER_OPT_HOST);
- if (!ptr) {
- error_setg(&local_err, QERR_MISSING_PARAMETER,
- GLUSTER_OPT_HOST);
- error_append_hint(&local_err, GERR_INDEX_HINT, i);
- goto out;
- }
- gsconf->u.inet.host = g_strdup(ptr);
- ptr = qemu_opt_get(opts, GLUSTER_OPT_PORT);
- if (!ptr) {
- error_setg(&local_err, QERR_MISSING_PARAMETER,
- GLUSTER_OPT_PORT);
- error_append_hint(&local_err, GERR_INDEX_HINT, i);
- goto out;
- }
- gsconf->u.inet.port = g_strdup(ptr);
-
- /* defend for unsupported fields in InetSocketAddress,
- * i.e. @ipv4, @ipv6 and @to
- */
- ptr = qemu_opt_get(opts, GLUSTER_OPT_TO);
- if (ptr) {
- gsconf->u.inet.has_to = true;
- }
- ptr = qemu_opt_get(opts, GLUSTER_OPT_IPV4);
- if (ptr) {
- gsconf->u.inet.has_ipv4 = true;
- }
- ptr = qemu_opt_get(opts, GLUSTER_OPT_IPV6);
- if (ptr) {
- gsconf->u.inet.has_ipv6 = true;
- }
- if (gsconf->u.inet.has_to) {
- error_setg(&local_err, "Parameter 'to' not supported");
- goto out;
- }
- if (gsconf->u.inet.has_ipv4 || gsconf->u.inet.has_ipv6) {
- error_setg(&local_err, "Parameters 'ipv4/ipv6' not supported");
- goto out;
- }
- qemu_opts_del(opts);
- } else {
- /* create opts info from runtime_unix_opts list */
- opts = qemu_opts_create(&runtime_unix_opts, NULL, 0, &error_abort);
- if (!qemu_opts_absorb_qdict(opts, backing_options, errp)) {
- goto out;
- }
-
- ptr = qemu_opt_get(opts, GLUSTER_OPT_PATH);
- if (!ptr) {
- ptr = qemu_opt_get(opts, GLUSTER_OPT_SOCKET);
- } else if (qemu_opt_get(opts, GLUSTER_OPT_SOCKET)) {
- error_setg(&local_err,
- "Conflicting parameters 'path' and 'socket'");
- error_append_hint(&local_err, GERR_INDEX_HINT, i);
- goto out;
- }
- if (!ptr) {
- error_setg(&local_err, QERR_MISSING_PARAMETER,
- GLUSTER_OPT_PATH);
- error_append_hint(&local_err, GERR_INDEX_HINT, i);
- goto out;
- }
- gsconf->u.q_unix.path = g_strdup(ptr);
- qemu_opts_del(opts);
- }
-
- QAPI_LIST_APPEND(tail, gsconf);
- gsconf = NULL;
-
- qobject_unref(backing_options);
- backing_options = NULL;
- }
-
- return 0;
-
-out:
- error_propagate(errp, local_err);
- qapi_free_SocketAddress(gsconf);
- qemu_opts_del(opts);
- qobject_unref(backing_options);
- errno = EINVAL;
- return -errno;
-}
-
-/* Converts options given in @filename and the @options QDict into the QAPI
- * object @gconf. */
-static int qemu_gluster_parse(BlockdevOptionsGluster *gconf,
- const char *filename,
- QDict *options, Error **errp)
-{
- int ret;
- if (filename) {
- ret = qemu_gluster_parse_uri(gconf, filename);
- if (ret < 0) {
- error_setg(errp, "invalid URI %s", filename);
- error_append_hint(errp, "Usage: file=gluster[+transport]://"
- "[host[:port]]volume/path[?socket=...]"
- "[,file.debug=N]"
- "[,file.logfile=/path/filename.log]\n");
- return ret;
- }
- } else {
- ret = qemu_gluster_parse_json(gconf, options, errp);
- if (ret < 0) {
- error_append_hint(errp, "Usage: "
- "-drive driver=qcow2,file.driver=gluster,"
- "file.volume=testvol,file.path=/path/a.qcow2"
- "[,file.debug=9]"
- "[,file.logfile=/path/filename.log],"
- "file.server.0.type=inet,"
- "file.server.0.host=1.2.3.4,"
- "file.server.0.port=24007,"
- "file.server.1.transport=unix,"
- "file.server.1.path=/var/run/glusterd.socket ..."
- "\n");
- return ret;
- }
- }
-
- return 0;
-}
-
-static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
- const char *filename,
- QDict *options, Error **errp)
-{
- int ret;
-
- ret = qemu_gluster_parse(gconf, filename, options, errp);
- if (ret < 0) {
- errno = -ret;
- return NULL;
- }
-
- return qemu_gluster_glfs_init(gconf, errp);
-}
-
-/*
- * AIO callback routine called from GlusterFS thread.
- */
-static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret,
-#ifdef CONFIG_GLUSTERFS_IOCB_HAS_STAT
- struct glfs_stat *pre, struct glfs_stat *post,
-#endif
- void *arg)
-{
- GlusterAIOCB *acb = (GlusterAIOCB *)arg;
-
- if (!ret || ret == acb->size) {
- acb->ret = 0; /* Success */
- } else if (ret < 0) {
- acb->ret = -errno; /* Read/Write failed */
- } else {
- acb->ret = -EIO; /* Partial read/write - fail it */
- }
-
- /*
- * Safe to call: The coroutine will yield exactly once awaiting this
- * scheduling, and the context is its own context, so it will be scheduled
- * once it does yield.
- *
- * (aio_co_wake() would call qemu_get_current_aio_context() to check whether
- * we are in the same context, but we are not in a qemu thread, so we cannot
- * do that. Use aio_co_schedule() directly.)
- */
- aio_co_schedule(qemu_coroutine_get_aio_context(acb->coroutine),
- acb->coroutine);
-}
-
-static void qemu_gluster_parse_flags(int bdrv_flags, int *open_flags)
-{
- assert(open_flags != NULL);
-
- *open_flags |= O_BINARY;
-
- if (bdrv_flags & BDRV_O_RDWR) {
- *open_flags |= O_RDWR;
- } else {
- *open_flags |= O_RDONLY;
- }
-
- if ((bdrv_flags & BDRV_O_NOCACHE)) {
- *open_flags |= O_DIRECT;
- }
-}
-
-/*
- * Do SEEK_DATA/HOLE to detect if it is functional. Older broken versions of
- * gfapi incorrectly return the current offset when SEEK_DATA/HOLE is used.
- * - Corrected versions return -1 and set errno to EINVAL.
- * - Versions that support SEEK_DATA/HOLE correctly, will return -1 and set
- * errno to ENXIO when SEEK_DATA is called with a position of EOF.
- */
-static bool qemu_gluster_test_seek(struct glfs_fd *fd)
-{
- off_t ret = 0;
-
-#if defined SEEK_HOLE && defined SEEK_DATA
- off_t eof;
-
- eof = glfs_lseek(fd, 0, SEEK_END);
- if (eof < 0) {
- /* this should never occur */
- return false;
- }
-
- /* this should always fail with ENXIO if SEEK_DATA is supported */
- ret = glfs_lseek(fd, eof, SEEK_DATA);
-#endif
-
- return (ret < 0) && (errno == ENXIO);
-}
-
-static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
- int bdrv_flags, Error **errp)
-{
- BDRVGlusterState *s = bs->opaque;
- int open_flags = 0;
- int ret = 0;
- BlockdevOptionsGluster *gconf = NULL;
- QemuOpts *opts;
- const char *filename, *logfile;
-
- opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
- if (!qemu_opts_absorb_qdict(opts, options, errp)) {
- ret = -EINVAL;
- goto out;
- }
-
- warn_report_once("'gluster' is deprecated");
-
- filename = qemu_opt_get(opts, GLUSTER_OPT_FILENAME);
-
- s->debug = qemu_opt_get_number(opts, GLUSTER_OPT_DEBUG,
- GLUSTER_DEBUG_DEFAULT);
- if (s->debug < 0) {
- s->debug = 0;
- } else if (s->debug > GLUSTER_DEBUG_MAX) {
- s->debug = GLUSTER_DEBUG_MAX;
- }
-
- gconf = g_new0(BlockdevOptionsGluster, 1);
- gconf->debug = s->debug;
- gconf->has_debug = true;
-
- logfile = qemu_opt_get(opts, GLUSTER_OPT_LOGFILE);
- s->logfile = g_strdup(logfile ? logfile : GLUSTER_LOGFILE_DEFAULT);
-
- gconf->logfile = g_strdup(s->logfile);
-
- s->glfs = qemu_gluster_init(gconf, filename, options, errp);
- if (!s->glfs) {
- ret = -errno;
- goto out;
- }
-
-#ifdef CONFIG_GLUSTERFS_XLATOR_OPT
- /* Without this, if fsync fails for a recoverable reason (for instance,
- * ENOSPC), gluster will dump its cache, preventing retries. This means
- * almost certain data loss. Not all gluster versions support the
- * 'resync-failed-syncs-after-fsync' key value, but there is no way to
- * discover during runtime if it is supported (this api returns success for
- * unknown key/value pairs) */
- ret = glfs_set_xlator_option(s->glfs, "*-write-behind",
- "resync-failed-syncs-after-fsync",
- "on");
- if (ret < 0) {
- error_setg_errno(errp, errno, "Unable to set xlator key/value pair");
- ret = -errno;
- goto out;
- }
-#endif
-
- qemu_gluster_parse_flags(bdrv_flags, &open_flags);
-
- s->fd = glfs_open(s->glfs, gconf->path, open_flags);
- ret = s->fd ? 0 : -errno;
-
- if (ret == -EACCES || ret == -EROFS) {
- /* Try to degrade to read-only, but if it doesn't work, still use the
- * normal error message. */
- bdrv_graph_rdlock_main_loop();
- if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
- open_flags = (open_flags & ~O_RDWR) | O_RDONLY;
- s->fd = glfs_open(s->glfs, gconf->path, open_flags);
- ret = s->fd ? 0 : -errno;
- }
- bdrv_graph_rdunlock_main_loop();
- }
-
- s->supports_seek_data = qemu_gluster_test_seek(s->fd);
-
-out:
- qemu_opts_del(opts);
- qapi_free_BlockdevOptionsGluster(gconf);
- if (!ret) {
- return ret;
- }
- g_free(s->logfile);
- if (s->fd) {
- glfs_close(s->fd);
- }
-
- glfs_clear_preopened(s->glfs);
-
- return ret;
-}
-
-static void qemu_gluster_refresh_limits(BlockDriverState *bs, Error **errp)
-{
- bs->bl.max_transfer = GLUSTER_MAX_TRANSFER;
- bs->bl.max_pdiscard = MIN(SIZE_MAX, INT64_MAX);
-}
-
-static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
- BlockReopenQueue *queue, Error **errp)
-{
- int ret = 0;
- BDRVGlusterState *s;
- BDRVGlusterReopenState *reop_s;
- BlockdevOptionsGluster *gconf;
- int open_flags = 0;
-
- assert(state != NULL);
- assert(state->bs != NULL);
-
- s = state->bs->opaque;
-
- state->opaque = g_new0(BDRVGlusterReopenState, 1);
- reop_s = state->opaque;
-
- qemu_gluster_parse_flags(state->flags, &open_flags);
-
- gconf = g_new0(BlockdevOptionsGluster, 1);
- gconf->debug = s->debug;
- gconf->has_debug = true;
- gconf->logfile = g_strdup(s->logfile);
-
- /*
- * If 'state->bs->exact_filename' is empty, 'state->options' should contain
- * the JSON parameters already parsed.
- */
- if (state->bs->exact_filename[0] != '\0') {
- reop_s->glfs = qemu_gluster_init(gconf, state->bs->exact_filename, NULL,
- errp);
- } else {
- reop_s->glfs = qemu_gluster_init(gconf, NULL, state->options, errp);
- }
- if (reop_s->glfs == NULL) {
- ret = -errno;
- goto exit;
- }
-
-#ifdef CONFIG_GLUSTERFS_XLATOR_OPT
- ret = glfs_set_xlator_option(reop_s->glfs, "*-write-behind",
- "resync-failed-syncs-after-fsync", "on");
- if (ret < 0) {
- error_setg_errno(errp, errno, "Unable to set xlator key/value pair");
- ret = -errno;
- goto exit;
- }
-#endif
-
- reop_s->fd = glfs_open(reop_s->glfs, gconf->path, open_flags);
- if (reop_s->fd == NULL) {
- /* reops->glfs will be cleaned up in _abort */
- ret = -errno;
- goto exit;
- }
-
-exit:
- /* state->opaque will be freed in either the _abort or _commit */
- qapi_free_BlockdevOptionsGluster(gconf);
- return ret;
-}
-
-static void qemu_gluster_reopen_commit(BDRVReopenState *state)
-{
- BDRVGlusterReopenState *reop_s = state->opaque;
- BDRVGlusterState *s = state->bs->opaque;
-
-
- /* close the old */
- if (s->fd) {
- glfs_close(s->fd);
- }
-
- glfs_clear_preopened(s->glfs);
-
- /* use the newly opened image / connection */
- s->fd = reop_s->fd;
- s->glfs = reop_s->glfs;
-
- g_free(state->opaque);
- state->opaque = NULL;
-}
-
-
-static void qemu_gluster_reopen_abort(BDRVReopenState *state)
-{
- BDRVGlusterReopenState *reop_s = state->opaque;
-
- if (reop_s == NULL) {
- return;
- }
-
- if (reop_s->fd) {
- glfs_close(reop_s->fd);
- }
-
- glfs_clear_preopened(reop_s->glfs);
-
- g_free(state->opaque);
- state->opaque = NULL;
-}
-
-#ifdef CONFIG_GLUSTERFS_ZEROFILL
-static coroutine_fn int qemu_gluster_co_pwrite_zeroes(BlockDriverState *bs,
- int64_t offset,
- int64_t bytes,
- BdrvRequestFlags flags)
-{
- int ret;
- GlusterAIOCB acb;
- BDRVGlusterState *s = bs->opaque;
-
- acb.size = bytes;
- acb.ret = 0;
- acb.coroutine = qemu_coroutine_self();
-
- ret = glfs_zerofill_async(s->fd, offset, bytes, gluster_finish_aiocb, &acb);
- if (ret < 0) {
- return -errno;
- }
-
- qemu_coroutine_yield();
- return acb.ret;
-}
-#endif
-
-static int qemu_gluster_do_truncate(struct glfs_fd *fd, int64_t offset,
- PreallocMode prealloc, Error **errp)
-{
- int64_t current_length;
-
- current_length = glfs_lseek(fd, 0, SEEK_END);
- if (current_length < 0) {
- error_setg_errno(errp, errno, "Failed to determine current size");
- return -errno;
- }
-
- if (current_length > offset && prealloc != PREALLOC_MODE_OFF) {
- error_setg(errp, "Cannot use preallocation for shrinking files");
- return -ENOTSUP;
- }
-
- if (current_length == offset) {
- return 0;
- }
-
- switch (prealloc) {
-#ifdef CONFIG_GLUSTERFS_FALLOCATE
- case PREALLOC_MODE_FALLOC:
- if (glfs_fallocate(fd, 0, current_length, offset - current_length)) {
- error_setg_errno(errp, errno, "Could not preallocate data");
- return -errno;
- }
- break;
-#endif /* CONFIG_GLUSTERFS_FALLOCATE */
-#ifdef CONFIG_GLUSTERFS_ZEROFILL
- case PREALLOC_MODE_FULL:
- if (glfs_ftruncate(fd, offset)) {
- error_setg_errno(errp, errno, "Could not resize file");
- return -errno;
- }
- if (glfs_zerofill(fd, current_length, offset - current_length)) {
- error_setg_errno(errp, errno, "Could not zerofill the new area");
- return -errno;
- }
- break;
-#endif /* CONFIG_GLUSTERFS_ZEROFILL */
- case PREALLOC_MODE_OFF:
- if (glfs_ftruncate(fd, offset)) {
- error_setg_errno(errp, errno, "Could not resize file");
- return -errno;
- }
- break;
- default:
- error_setg(errp, "Unsupported preallocation mode: %s",
- PreallocMode_str(prealloc));
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int qemu_gluster_co_create(BlockdevCreateOptions *options,
- Error **errp)
-{
- BlockdevCreateOptionsGluster *opts = &options->u.gluster;
- struct glfs *glfs;
- struct glfs_fd *fd = NULL;
- int ret = 0;
-
- assert(options->driver == BLOCKDEV_DRIVER_GLUSTER);
-
- glfs = qemu_gluster_glfs_init(opts->location, errp);
- if (!glfs) {
- ret = -errno;
- goto out;
- }
-
- fd = glfs_creat(glfs, opts->location->path,
- O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR);
- if (!fd) {
- ret = -errno;
- goto out;
- }
-
- ret = qemu_gluster_do_truncate(fd, opts->size, opts->preallocation, errp);
-
-out:
- if (fd) {
- if (glfs_close(fd) != 0 && ret == 0) {
- ret = -errno;
- }
- }
- glfs_clear_preopened(glfs);
- return ret;
-}
-
-static int coroutine_fn qemu_gluster_co_create_opts(BlockDriver *drv,
- const char *filename,
- QemuOpts *opts,
- Error **errp)
-{
- BlockdevCreateOptions *options;
- BlockdevCreateOptionsGluster *gopts;
- BlockdevOptionsGluster *gconf;
- char *tmp = NULL;
- Error *local_err = NULL;
- int ret;
-
- options = g_new0(BlockdevCreateOptions, 1);
- options->driver = BLOCKDEV_DRIVER_GLUSTER;
- gopts = &options->u.gluster;
-
- gconf = g_new0(BlockdevOptionsGluster, 1);
- gopts->location = gconf;
-
- gopts->size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
- BDRV_SECTOR_SIZE);
-
- tmp = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
- gopts->preallocation = qapi_enum_parse(&PreallocMode_lookup, tmp,
- PREALLOC_MODE_OFF, &local_err);
- g_free(tmp);
- if (local_err) {
- error_propagate(errp, local_err);
- ret = -EINVAL;
- goto fail;
- }
-
- gconf->debug = qemu_opt_get_number_del(opts, GLUSTER_OPT_DEBUG,
- GLUSTER_DEBUG_DEFAULT);
- if (gconf->debug < 0) {
- gconf->debug = 0;
- } else if (gconf->debug > GLUSTER_DEBUG_MAX) {
- gconf->debug = GLUSTER_DEBUG_MAX;
- }
- gconf->has_debug = true;
-
- gconf->logfile = qemu_opt_get_del(opts, GLUSTER_OPT_LOGFILE);
- if (!gconf->logfile) {
- gconf->logfile = g_strdup(GLUSTER_LOGFILE_DEFAULT);
- }
-
- ret = qemu_gluster_parse(gconf, filename, NULL, errp);
- if (ret < 0) {
- goto fail;
- }
-
- ret = qemu_gluster_co_create(options, errp);
- if (ret < 0) {
- goto fail;
- }
-
- ret = 0;
-fail:
- qapi_free_BlockdevCreateOptions(options);
- return ret;
-}
-
-static coroutine_fn int qemu_gluster_co_rw(BlockDriverState *bs,
- int64_t sector_num, int nb_sectors,
- QEMUIOVector *qiov, int write)
-{
- int ret;
- GlusterAIOCB acb;
- BDRVGlusterState *s = bs->opaque;
- size_t size = nb_sectors * BDRV_SECTOR_SIZE;
- off_t offset = sector_num * BDRV_SECTOR_SIZE;
-
- acb.size = size;
- acb.ret = 0;
- acb.coroutine = qemu_coroutine_self();
-
- if (write) {
- ret = glfs_pwritev_async(s->fd, qiov->iov, qiov->niov, offset, 0,
- gluster_finish_aiocb, &acb);
- } else {
- ret = glfs_preadv_async(s->fd, qiov->iov, qiov->niov, offset, 0,
- gluster_finish_aiocb, &acb);
- }
-
- if (ret < 0) {
- return -errno;
- }
-
- qemu_coroutine_yield();
- return acb.ret;
-}
-
-static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs,
- int64_t offset,
- bool exact,
- PreallocMode prealloc,
- BdrvRequestFlags flags,
- Error **errp)
-{
- BDRVGlusterState *s = bs->opaque;
- return qemu_gluster_do_truncate(s->fd, offset, prealloc, errp);
-}
-
-static coroutine_fn int qemu_gluster_co_readv(BlockDriverState *bs,
- int64_t sector_num,
- int nb_sectors,
- QEMUIOVector *qiov)
-{
- return qemu_gluster_co_rw(bs, sector_num, nb_sectors, qiov, 0);
-}
-
-static coroutine_fn int qemu_gluster_co_writev(BlockDriverState *bs,
- int64_t sector_num,
- int nb_sectors,
- QEMUIOVector *qiov,
- int flags)
-{
- return qemu_gluster_co_rw(bs, sector_num, nb_sectors, qiov, 1);
-}
-
-static void qemu_gluster_close(BlockDriverState *bs)
-{
- BDRVGlusterState *s = bs->opaque;
-
- g_free(s->logfile);
- if (s->fd) {
- glfs_close(s->fd);
- s->fd = NULL;
- }
- glfs_clear_preopened(s->glfs);
-}
-
-static coroutine_fn int qemu_gluster_co_flush_to_disk(BlockDriverState *bs)
-{
- int ret;
- GlusterAIOCB acb;
- BDRVGlusterState *s = bs->opaque;
-
- acb.size = 0;
- acb.ret = 0;
- acb.coroutine = qemu_coroutine_self();
-
- ret = glfs_fsync_async(s->fd, gluster_finish_aiocb, &acb);
- if (ret < 0) {
- ret = -errno;
- goto error;
- }
-
- qemu_coroutine_yield();
- if (acb.ret < 0) {
- ret = acb.ret;
- goto error;
- }
-
- return acb.ret;
-
-error:
- /* Some versions of Gluster (3.5.6 -> 3.5.8?) will not retain its cache
- * after a fsync failure, so we have no way of allowing the guest to safely
- * continue. Gluster versions prior to 3.5.6 don't retain the cache
- * either, but will invalidate the fd on error, so this is again our only
- * option.
- *
- * The 'resync-failed-syncs-after-fsync' xlator option for the
- * write-behind cache will cause later gluster versions to retain its
- * cache after error, so long as the fd remains open. However, we
- * currently have no way of knowing if this option is supported.
- *
- * TODO: Once gluster provides a way for us to determine if the option
- * is supported, bypass the closure and setting drv to NULL. */
- qemu_gluster_close(bs);
- bs->drv = NULL;
- return ret;
-}
-
-#ifdef CONFIG_GLUSTERFS_DISCARD
-static coroutine_fn int qemu_gluster_co_pdiscard(BlockDriverState *bs,
- int64_t offset, int64_t bytes)
-{
- int ret;
- GlusterAIOCB acb;
- BDRVGlusterState *s = bs->opaque;
-
- assert(bytes <= SIZE_MAX); /* rely on max_pdiscard */
-
- acb.size = 0;
- acb.ret = 0;
- acb.coroutine = qemu_coroutine_self();
-
- ret = glfs_discard_async(s->fd, offset, bytes, gluster_finish_aiocb, &acb);
- if (ret < 0) {
- return -errno;
- }
-
- qemu_coroutine_yield();
- return acb.ret;
-}
-#endif
-
-static int64_t coroutine_fn qemu_gluster_co_getlength(BlockDriverState *bs)
-{
- BDRVGlusterState *s = bs->opaque;
- int64_t ret;
-
- ret = glfs_lseek(s->fd, 0, SEEK_END);
- if (ret < 0) {
- return -errno;
- } else {
- return ret;
- }
-}
-
-static int64_t coroutine_fn
-qemu_gluster_co_get_allocated_file_size(BlockDriverState *bs)
-{
- BDRVGlusterState *s = bs->opaque;
- struct stat st;
- int ret;
-
- ret = glfs_fstat(s->fd, &st);
- if (ret < 0) {
- return -errno;
- } else {
- return st.st_blocks * 512;
- }
-}
-
-/*
- * Find allocation range in @bs around offset @start.
- * May change underlying file descriptor's file offset.
- * If @start is not in a hole, store @start in @data, and the
- * beginning of the next hole in @hole, and return 0.
- * If @start is in a non-trailing hole, store @start in @hole and the
- * beginning of the next non-hole in @data, and return 0.
- * If @start is in a trailing hole or beyond EOF, return -ENXIO.
- * If we can't find out, return a negative errno other than -ENXIO.
- *
- * (Shamefully copied from file-posix.c, only minuscule adaptions.)
- */
-static int find_allocation(BlockDriverState *bs, off_t start,
- off_t *data, off_t *hole)
-{
- BDRVGlusterState *s = bs->opaque;
-
- if (!s->supports_seek_data) {
- goto exit;
- }
-
-#if defined SEEK_HOLE && defined SEEK_DATA
- off_t offs;
-
- /*
- * SEEK_DATA cases:
- * D1. offs == start: start is in data
- * D2. offs > start: start is in a hole, next data at offs
- * D3. offs < 0, errno = ENXIO: either start is in a trailing hole
- * or start is beyond EOF
- * If the latter happens, the file has been truncated behind
- * our back since we opened it. All bets are off then.
- * Treating like a trailing hole is simplest.
- * D4. offs < 0, errno != ENXIO: we learned nothing
- */
- offs = glfs_lseek(s->fd, start, SEEK_DATA);
- if (offs < 0) {
- return -errno; /* D3 or D4 */
- }
-
- 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 */
- *hole = start;
- *data = offs;
- return 0;
- }
-
- /* D1: in data, end not yet known */
-
- /*
- * SEEK_HOLE cases:
- * H1. offs == start: start is in a hole
- * If this happens here, a hole has been dug behind our back
- * since the previous lseek().
- * H2. offs > start: either start is in data, next hole at offs,
- * or start is in trailing hole, EOF at offs
- * Linux treats trailing holes like any other hole: offs ==
- * start. Solaris seeks to EOF instead: offs > start (blech).
- * If that happens here, a hole has been dug behind our back
- * since the previous lseek().
- * H3. offs < 0, errno = ENXIO: start is beyond EOF
- * If this happens, the file has been truncated behind our
- * back since we opened it. Treat it like a trailing hole.
- * H4. offs < 0, errno != ENXIO: we learned nothing
- * Pretend we know nothing at all, i.e. "forget" about D1.
- */
- offs = glfs_lseek(s->fd, start, SEEK_HOLE);
- if (offs < 0) {
- return -errno; /* D1 and (H3 or H4) */
- }
-
- 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) {
- /*
- * D1 and H2: either in data, next hole at offs, or it was in
- * data but is now in a trailing hole. In the latter case,
- * all bets are off. Treating it as if it there was data all
- * the way to EOF is safe, so simply do that.
- */
- *data = start;
- *hole = offs;
- return 0;
- }
-
- /* D1 and H1 */
- return -EBUSY;
-#endif
-
-exit:
- return -ENOTSUP;
-}
-
-/*
- * Returns the allocation status of the specified offset.
- *
- * The block layer guarantees 'offset' and 'bytes' are within bounds.
- *
- * 'pnum' is set to the number of bytes (including and immediately following
- * the specified offset) that are known to be in the same
- * allocated/unallocated state.
- *
- * 'bytes' is a soft cap for 'pnum'. If the information is free, 'pnum' may
- * well exceed it.
- *
- * (Based on raw_co_block_status() from file-posix.c.)
- */
-static int coroutine_fn qemu_gluster_co_block_status(BlockDriverState *bs,
- unsigned int mode,
- int64_t offset,
- int64_t bytes,
- int64_t *pnum,
- int64_t *map,
- BlockDriverState **file)
-{
- BDRVGlusterState *s = bs->opaque;
- off_t data = 0, hole = 0;
- int ret = -EINVAL;
-
- assert(QEMU_IS_ALIGNED(offset | bytes, bs->bl.request_alignment));
-
- if (!s->fd) {
- return ret;
- }
-
- if (!(mode & BDRV_WANT_ZERO)) {
- *pnum = bytes;
- *map = offset;
- *file = bs;
- return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
- }
-
- ret = find_allocation(bs, offset, &data, &hole);
- if (ret == -ENXIO) {
- /* Trailing hole */
- *pnum = bytes;
- ret = BDRV_BLOCK_ZERO;
- } else if (ret < 0) {
- /* No info available, so pretend there are no holes */
- *pnum = bytes;
- ret = BDRV_BLOCK_DATA;
- } else if (data == offset) {
- /* On a data extent, compute bytes to the end of the extent,
- * possibly including a partial sector at EOF. */
- *pnum = hole - offset;
-
- /*
- * We are not allowed to return partial sectors, though, so
- * round up if necessary.
- */
- if (!QEMU_IS_ALIGNED(*pnum, bs->bl.request_alignment)) {
- int64_t file_length = qemu_gluster_co_getlength(bs);
- if (file_length > 0) {
- /* Ignore errors, this is just a safeguard */
- assert(hole == file_length);
- }
- *pnum = ROUND_UP(*pnum, bs->bl.request_alignment);
- }
-
- ret = BDRV_BLOCK_DATA;
- } else {
- /* On a hole, compute bytes to the beginning of the next extent. */
- assert(hole == offset);
- *pnum = data - offset;
- ret = BDRV_BLOCK_ZERO;
- }
-
- *map = offset;
- *file = bs;
-
- return ret | BDRV_BLOCK_OFFSET_VALID;
-}
-
-
-static const char *const gluster_strong_open_opts[] = {
- GLUSTER_OPT_VOLUME,
- GLUSTER_OPT_PATH,
- GLUSTER_OPT_TYPE,
- GLUSTER_OPT_SERVER_PATTERN,
- GLUSTER_OPT_HOST,
- GLUSTER_OPT_PORT,
- GLUSTER_OPT_TO,
- GLUSTER_OPT_IPV4,
- GLUSTER_OPT_IPV6,
- GLUSTER_OPT_SOCKET,
-
- NULL
-};
-
-static BlockDriver bdrv_gluster = {
- .format_name = "gluster",
- .protocol_name = "gluster",
- .instance_size = sizeof(BDRVGlusterState),
- .bdrv_open = qemu_gluster_open,
- .bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
- .bdrv_reopen_commit = qemu_gluster_reopen_commit,
- .bdrv_reopen_abort = qemu_gluster_reopen_abort,
- .bdrv_close = qemu_gluster_close,
- .bdrv_co_create = qemu_gluster_co_create,
- .bdrv_co_create_opts = qemu_gluster_co_create_opts,
- .bdrv_co_getlength = qemu_gluster_co_getlength,
- .bdrv_co_get_allocated_file_size = qemu_gluster_co_get_allocated_file_size,
- .bdrv_co_truncate = qemu_gluster_co_truncate,
- .bdrv_co_readv = qemu_gluster_co_readv,
- .bdrv_co_writev = qemu_gluster_co_writev,
- .bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
-#ifdef CONFIG_GLUSTERFS_DISCARD
- .bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
-#endif
-#ifdef CONFIG_GLUSTERFS_ZEROFILL
- .bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
-#endif
- .bdrv_co_block_status = qemu_gluster_co_block_status,
- .bdrv_refresh_limits = qemu_gluster_refresh_limits,
- .create_opts = &qemu_gluster_create_opts,
- .strong_runtime_opts = gluster_strong_open_opts,
-};
-
-static BlockDriver bdrv_gluster_tcp = {
- .format_name = "gluster",
- .protocol_name = "gluster+tcp",
- .instance_size = sizeof(BDRVGlusterState),
- .bdrv_open = qemu_gluster_open,
- .bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
- .bdrv_reopen_commit = qemu_gluster_reopen_commit,
- .bdrv_reopen_abort = qemu_gluster_reopen_abort,
- .bdrv_close = qemu_gluster_close,
- .bdrv_co_create = qemu_gluster_co_create,
- .bdrv_co_create_opts = qemu_gluster_co_create_opts,
- .bdrv_co_getlength = qemu_gluster_co_getlength,
- .bdrv_co_get_allocated_file_size = qemu_gluster_co_get_allocated_file_size,
- .bdrv_co_truncate = qemu_gluster_co_truncate,
- .bdrv_co_readv = qemu_gluster_co_readv,
- .bdrv_co_writev = qemu_gluster_co_writev,
- .bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
-#ifdef CONFIG_GLUSTERFS_DISCARD
- .bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
-#endif
-#ifdef CONFIG_GLUSTERFS_ZEROFILL
- .bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
-#endif
- .bdrv_co_block_status = qemu_gluster_co_block_status,
- .bdrv_refresh_limits = qemu_gluster_refresh_limits,
- .create_opts = &qemu_gluster_create_opts,
- .strong_runtime_opts = gluster_strong_open_opts,
-};
-
-static BlockDriver bdrv_gluster_unix = {
- .format_name = "gluster",
- .protocol_name = "gluster+unix",
- .instance_size = sizeof(BDRVGlusterState),
- .bdrv_open = qemu_gluster_open,
- .bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
- .bdrv_reopen_commit = qemu_gluster_reopen_commit,
- .bdrv_reopen_abort = qemu_gluster_reopen_abort,
- .bdrv_close = qemu_gluster_close,
- .bdrv_co_create = qemu_gluster_co_create,
- .bdrv_co_create_opts = qemu_gluster_co_create_opts,
- .bdrv_co_getlength = qemu_gluster_co_getlength,
- .bdrv_co_get_allocated_file_size = qemu_gluster_co_get_allocated_file_size,
- .bdrv_co_truncate = qemu_gluster_co_truncate,
- .bdrv_co_readv = qemu_gluster_co_readv,
- .bdrv_co_writev = qemu_gluster_co_writev,
- .bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
-#ifdef CONFIG_GLUSTERFS_DISCARD
- .bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
-#endif
-#ifdef CONFIG_GLUSTERFS_ZEROFILL
- .bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
-#endif
- .bdrv_co_block_status = qemu_gluster_co_block_status,
- .bdrv_refresh_limits = qemu_gluster_refresh_limits,
- .create_opts = &qemu_gluster_create_opts,
- .strong_runtime_opts = gluster_strong_open_opts,
-};
-
-static void bdrv_gluster_init(void)
-{
- bdrv_register(&bdrv_gluster_unix);
- bdrv_register(&bdrv_gluster_tcp);
- bdrv_register(&bdrv_gluster);
-}
-
-block_init(bdrv_gluster_init);
diff --git a/tests/qtest/modules-test.c b/tests/qtest/modules-test.c
index be2575ae6d7..040251c11ec 100644
--- a/tests/qtest/modules-test.c
+++ b/tests/qtest/modules-test.c
@@ -22,9 +22,6 @@ int main(int argc, char *argv[])
#ifdef CONFIG_CURL
"block-", "curl",
#endif
-#ifdef CONFIG_GLUSTERFS
- "block-", "gluster",
-#endif
#ifdef CONFIG_LIBISCSI
"block-", "iscsi",
#endif
diff --git a/block/meson.build b/block/meson.build
index 34b1b2a3063..bc419aebf08 100644
--- a/block/meson.build
+++ b/block/meson.build
@@ -109,7 +109,6 @@ modsrc = []
foreach m : [
[blkio, 'blkio', files('blkio.c')],
[curl, 'curl', files('curl.c')],
- [glusterfs, 'gluster', files('gluster.c')],
[libiscsi, 'iscsi', files('iscsi.c')],
[libnfs, 'nfs', files('nfs.c')],
[libssh, 'ssh', files('ssh.c')],
diff --git a/meson_options.txt b/meson_options.txt
index 286461129bd..9c0bf907773 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -158,8 +158,6 @@ option('curl', type : 'feature', value : 'auto',
description: 'CURL block device driver')
option('gio', type : 'feature', value : 'auto',
description: 'use libgio for D-Bus support')
-option('glusterfs', type : 'feature', value : 'auto',
- description: 'Glusterfs block device driver')
option('hv_balloon', type : 'feature', value : 'auto',
description: 'hv-balloon driver (requires Glib 2.68+ GTree API)')
option('libdw', type : 'feature', value : 'auto',
diff --git a/scripts/ci/setup/debian/debian-13-ppc64le.yaml b/scripts/ci/setup/debian/debian-13-ppc64le.yaml
index b16d6d58f8e..e64321357da 100644
--- a/scripts/ci/setup/debian/debian-13-ppc64le.yaml
+++ b/scripts/ci/setup/debian/debian-13-ppc64le.yaml
@@ -50,7 +50,6 @@ packages:
- libgbm-dev
- libgcrypt20-dev
- libglib2.0-dev
- - libglusterfs-dev
- libgnutls28-dev
- libgtk-3-dev
- libgtk-vnc-2.0-dev
diff --git a/scripts/ci/setup/ubuntu/ubuntu-2404-aarch64.yaml b/scripts/ci/setup/ubuntu/ubuntu-2404-aarch64.yaml
index b58fcda0fa3..12b0e38a220 100644
--- a/scripts/ci/setup/ubuntu/ubuntu-2404-aarch64.yaml
+++ b/scripts/ci/setup/ubuntu/ubuntu-2404-aarch64.yaml
@@ -50,7 +50,6 @@ packages:
- libgbm-dev
- libgcrypt20-dev
- libglib2.0-dev
- - libglusterfs-dev
- libgnutls28-dev
- libgtk-3-dev
- libgtk-vnc-2.0-dev
diff --git a/scripts/ci/setup/ubuntu/ubuntu-2404-s390x.yaml b/scripts/ci/setup/ubuntu/ubuntu-2404-s390x.yaml
index fa439db4ca1..56299f4cc2b 100644
--- a/scripts/ci/setup/ubuntu/ubuntu-2404-s390x.yaml
+++ b/scripts/ci/setup/ubuntu/ubuntu-2404-s390x.yaml
@@ -50,7 +50,6 @@ packages:
- libgbm-dev
- libgcrypt20-dev
- libglib2.0-dev
- - libglusterfs-dev
- libgnutls28-dev
- libgtk-3-dev
- libgtk-vnc-2.0-dev
diff --git a/scripts/coverity-scan/coverity-scan.docker b/scripts/coverity-scan/coverity-scan.docker
index a349578526d..93e558c8623 100644
--- a/scripts/coverity-scan/coverity-scan.docker
+++ b/scripts/coverity-scan/coverity-scan.docker
@@ -61,7 +61,6 @@ exec "$@"' > /usr/bin/nosync && \
glib2-static \
glibc-langpack-en \
glibc-static \
- glusterfs-api-devel \
gnutls-devel \
gtk3-devel \
hostname \
diff --git a/scripts/coverity-scan/run-coverity-scan b/scripts/coverity-scan/run-coverity-scan
index 9b89a3303f5..2f9ccd5e44b 100755
--- a/scripts/coverity-scan/run-coverity-scan
+++ b/scripts/coverity-scan/run-coverity-scan
@@ -427,7 +427,7 @@ echo "Configuring..."
--enable-libiscsi --enable-seccomp \
--enable-tpm --enable-libssh --enable-lzo --enable-snappy --enable-bzip2 \
--enable-numa --enable-rdma --enable-smartcard --enable-virglrenderer \
- --enable-mpath --enable-glusterfs \
+ --enable-mpath \
--enable-virtfs --enable-zstd
echo "Running cov-build..."
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
index 80de8c4af42..1cb38b2a2a9 100644
--- a/scripts/meson-buildoptions.sh
+++ b/scripts/meson-buildoptions.sh
@@ -121,7 +121,6 @@ meson_options_help() {
printf "%s\n" ' gcrypt libgcrypt cryptography support'
printf "%s\n" ' gettext Localization of the GTK+ user interface'
printf "%s\n" ' gio use libgio for D-Bus support'
- printf "%s\n" ' glusterfs Glusterfs block device driver'
printf "%s\n" ' gnutls GNUTLS cryptography support'
printf "%s\n" ' gtk GTK+ user interface'
printf "%s\n" ' guest-agent Build QEMU Guest Agent'
@@ -329,8 +328,6 @@ _meson_option_parse() {
--disable-gettext) printf "%s" -Dgettext=disabled ;;
--enable-gio) printf "%s" -Dgio=enabled ;;
--disable-gio) printf "%s" -Dgio=disabled ;;
- --enable-glusterfs) printf "%s" -Dglusterfs=enabled ;;
- --disable-glusterfs) printf "%s" -Dglusterfs=disabled ;;
--enable-gnutls) printf "%s" -Dgnutls=enabled ;;
--disable-gnutls) printf "%s" -Dgnutls=disabled ;;
--enable-gtk) printf "%s" -Dgtk=enabled ;;
diff --git a/tests/docker/dockerfiles/debian-amd64-cross.docker b/tests/docker/dockerfiles/debian-amd64-cross.docker
index 6fad808e1b6..35c593502fc 100644
--- a/tests/docker/dockerfiles/debian-amd64-cross.docker
+++ b/tests/docker/dockerfiles/debian-amd64-cross.docker
@@ -108,7 +108,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libgbm-dev:amd64 \
libgcrypt20-dev:amd64 \
libglib2.0-dev:amd64 \
- libglusterfs-dev:amd64 \
libgnutls28-dev:amd64 \
libgtk-3-dev:amd64 \
libgtk-vnc-2.0-dev:amd64 \
diff --git a/tests/docker/dockerfiles/debian-arm64-cross.docker b/tests/docker/dockerfiles/debian-arm64-cross.docker
index 889d8a1a755..d188d538365 100644
--- a/tests/docker/dockerfiles/debian-arm64-cross.docker
+++ b/tests/docker/dockerfiles/debian-arm64-cross.docker
@@ -108,7 +108,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libgbm-dev:arm64 \
libgcrypt20-dev:arm64 \
libglib2.0-dev:arm64 \
- libglusterfs-dev:arm64 \
libgnutls28-dev:arm64 \
libgtk-3-dev:arm64 \
libgtk-vnc-2.0-dev:arm64 \
diff --git a/tests/docker/dockerfiles/debian-mips64el-cross.docker b/tests/docker/dockerfiles/debian-mips64el-cross.docker
index 90a2ef15574..d139c10c555 100644
--- a/tests/docker/dockerfiles/debian-mips64el-cross.docker
+++ b/tests/docker/dockerfiles/debian-mips64el-cross.docker
@@ -106,7 +106,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libgbm-dev:mips64el \
libgcrypt20-dev:mips64el \
libglib2.0-dev:mips64el \
- libglusterfs-dev:mips64el \
libgnutls28-dev:mips64el \
libgtk-3-dev:mips64el \
libgtk-vnc-2.0-dev:mips64el \
diff --git a/tests/docker/dockerfiles/debian-mipsel-cross.docker b/tests/docker/dockerfiles/debian-mipsel-cross.docker
index b7e36b3d974..2cfc33e8249 100644
--- a/tests/docker/dockerfiles/debian-mipsel-cross.docker
+++ b/tests/docker/dockerfiles/debian-mipsel-cross.docker
@@ -106,7 +106,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libgbm-dev:mipsel \
libgcrypt20-dev:mipsel \
libglib2.0-dev:mipsel \
- libglusterfs-dev:mipsel \
libgnutls28-dev:mipsel \
libgtk-3-dev:mipsel \
libgtk-vnc-2.0-dev:mipsel \
diff --git a/tests/docker/dockerfiles/debian-ppc64el-cross.docker b/tests/docker/dockerfiles/debian-ppc64el-cross.docker
index a70fbee0c1d..7198036380b 100644
--- a/tests/docker/dockerfiles/debian-ppc64el-cross.docker
+++ b/tests/docker/dockerfiles/debian-ppc64el-cross.docker
@@ -108,7 +108,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libgbm-dev:ppc64el \
libgcrypt20-dev:ppc64el \
libglib2.0-dev:ppc64el \
- libglusterfs-dev:ppc64el \
libgnutls28-dev:ppc64el \
libgtk-3-dev:ppc64el \
libgtk-vnc-2.0-dev:ppc64el \
diff --git a/tests/docker/dockerfiles/debian-riscv64-cross.docker b/tests/docker/dockerfiles/debian-riscv64-cross.docker
index 9ada5ecce0d..eb49da9781a 100644
--- a/tests/docker/dockerfiles/debian-riscv64-cross.docker
+++ b/tests/docker/dockerfiles/debian-riscv64-cross.docker
@@ -108,7 +108,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libgbm-dev:riscv64 \
libgcrypt20-dev:riscv64 \
libglib2.0-dev:riscv64 \
- libglusterfs-dev:riscv64 \
libgnutls28-dev:riscv64 \
libgtk-3-dev:riscv64 \
libgtk-vnc-2.0-dev:riscv64 \
diff --git a/tests/docker/dockerfiles/debian-s390x-cross.docker b/tests/docker/dockerfiles/debian-s390x-cross.docker
index a1de94ff9aa..f4c7896a75f 100644
--- a/tests/docker/dockerfiles/debian-s390x-cross.docker
+++ b/tests/docker/dockerfiles/debian-s390x-cross.docker
@@ -108,7 +108,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libgbm-dev:s390x \
libgcrypt20-dev:s390x \
libglib2.0-dev:s390x \
- libglusterfs-dev:s390x \
libgnutls28-dev:s390x \
libgtk-3-dev:s390x \
libgtk-vnc-2.0-dev:s390x \
diff --git a/tests/docker/dockerfiles/debian.docker b/tests/docker/dockerfiles/debian.docker
index c34923b253d..85b78f7e5f8 100644
--- a/tests/docker/dockerfiles/debian.docker
+++ b/tests/docker/dockerfiles/debian.docker
@@ -56,7 +56,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libgbm-dev \
libgcrypt20-dev \
libglib2.0-dev \
- libglusterfs-dev \
libgnutls28-dev \
libgtk-3-dev \
libgtk-vnc-2.0-dev \
diff --git a/tests/docker/dockerfiles/fedora-rust-nightly.docker b/tests/docker/dockerfiles/fedora-rust-nightly.docker
index 8766f952ac8..5e88354f133 100644
--- a/tests/docker/dockerfiles/fedora-rust-nightly.docker
+++ b/tests/docker/dockerfiles/fedora-rust-nightly.docker
@@ -50,7 +50,6 @@ exec "$@"\n' > /usr/bin/nosync && \
glib2-static \
glibc-langpack-en \
glibc-static \
- glusterfs-api-devel \
gnutls-devel \
gtk-vnc2-devel \
gtk3-devel \
diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker
index ec787aa7027..393ac0cce73 100644
--- a/tests/docker/dockerfiles/fedora.docker
+++ b/tests/docker/dockerfiles/fedora.docker
@@ -50,7 +50,6 @@ exec "$@"\n' > /usr/bin/nosync && \
glib2-static \
glibc-langpack-en \
glibc-static \
- glusterfs-api-devel \
gnutls-devel \
gtk-vnc2-devel \
gtk3-devel \
diff --git a/tests/docker/dockerfiles/opensuse-leap.docker b/tests/docker/dockerfiles/opensuse-leap.docker
index 66e90fa3634..4b126b7e7de 100644
--- a/tests/docker/dockerfiles/opensuse-leap.docker
+++ b/tests/docker/dockerfiles/opensuse-leap.docker
@@ -34,7 +34,6 @@ RUN zypper update -y && \
glib2-devel \
glibc-locale \
glibc-static \
- glusterfs-devel \
gtk-vnc-devel \
gtk3-devel \
hostname \
diff --git a/tests/docker/dockerfiles/ubuntu2204.docker b/tests/docker/dockerfiles/ubuntu2204.docker
index fb5b03e7a1b..4617bbe1f65 100644
--- a/tests/docker/dockerfiles/ubuntu2204.docker
+++ b/tests/docker/dockerfiles/ubuntu2204.docker
@@ -55,7 +55,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
libgbm-dev \
libgcrypt20-dev \
libglib2.0-dev \
- libglusterfs-dev \
libgnutls28-dev \
libgtk-3-dev \
libgtk-vnc-2.0-dev \
diff --git a/tests/lcitool/projects/qemu.yml b/tests/lcitool/projects/qemu.yml
index 131d9c4ec81..7d185cda3cc 100644
--- a/tests/lcitool/projects/qemu.yml
+++ b/tests/lcitool/projects/qemu.yml
@@ -31,7 +31,6 @@ packages:
- glib2
- glib2-native
- glib2-static
- - glusterfs
- gnutls
- gtk3
- gtk-vnc
--
2.54.0
next reply other threads:[~2026-05-11 6:31 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-11 6:30 Thomas Huth [this message]
2026-05-12 12:04 ` [PATCH v2] Remove the deprecated glusterfs block driver Kevin Wolf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260511063013.39805-1-thuth@redhat.com \
--to=thuth@redhat.com \
--cc=armbru@redhat.com \
--cc=eblake@redhat.com \
--cc=hreitz@redhat.com \
--cc=kwolf@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox