@samitouri / QOSamiQemu / commits / 3822df47c2

Remove the deprecated glusterfs block driver

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> Message-ID: <20260511063013.39805-1-thuth@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>

Thomas Huth committed May 11, 2026 at 08:30 UTC 3822df47c240d91ea4789ab2812d1eafce2bd21a
30 files changed +8 -1907
MAINTAINERS
-6
@@ -4268,12 +4268,6 @@ L: qemu-block@nongnu.org
4268 S: Odd Fixes
4269 F: block/curl.c
4270
4271 -GLUSTER
4272 -L: qemu-block@nongnu.org
4273 -L: integration@gluster.org
4274 -S: Odd Fixes
4275 -F: block/gluster.c
4276 -
4271 Null Block Driver
4272 M: Fam Zheng <fam@euphon.net>
4273 L: qemu-block@nongnu.org
block/gluster.c deleted
-1644
@@ -1,1644 +0,0 @@
1 -/*
2 - * GlusterFS backend for QEMU
3 - *
4 - * Copyright (C) 2012 Bharata B Rao <bharata@linux.vnet.ibm.com>
5 - *
6 - * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 - * See the COPYING file in the top-level directory.
8 - *
9 - */
10 -
11 -#include "qemu/osdep.h"
12 -#include "qemu/units.h"
13 -#include <glusterfs/api/glfs.h>
14 -#include "block/block-io.h"
15 -#include "block/block_int.h"
16 -#include "block/qdict.h"
17 -#include "qapi/error.h"
18 -#include "qobject/qdict.h"
19 -#include "qapi/qmp/qerror.h"
20 -#include "qemu/error-report.h"
21 -#include "qemu/module.h"
22 -#include "qemu/option.h"
23 -#include "qemu/cutils.h"
24 -
25 -#ifdef CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT
26 -# define glfs_ftruncate(fd, offset) glfs_ftruncate(fd, offset, NULL, NULL)
27 -#endif
28 -
29 -#define GLUSTER_OPT_FILENAME "filename"
30 -#define GLUSTER_OPT_VOLUME "volume"
31 -#define GLUSTER_OPT_PATH "path"
32 -#define GLUSTER_OPT_TYPE "type"
33 -#define GLUSTER_OPT_SERVER_PATTERN "server."
34 -#define GLUSTER_OPT_HOST "host"
35 -#define GLUSTER_OPT_PORT "port"
36 -#define GLUSTER_OPT_TO "to"
37 -#define GLUSTER_OPT_IPV4 "ipv4"
38 -#define GLUSTER_OPT_IPV6 "ipv6"
39 -#define GLUSTER_OPT_SOCKET "socket"
40 -#define GLUSTER_OPT_DEBUG "debug"
41 -#define GLUSTER_DEFAULT_PORT 24007
42 -#define GLUSTER_DEBUG_DEFAULT 4
43 -#define GLUSTER_DEBUG_MAX 9
44 -#define GLUSTER_OPT_LOGFILE "logfile"
45 -#define GLUSTER_LOGFILE_DEFAULT "-" /* handled in libgfapi as /dev/stderr */
46 -/*
47 - * Several versions of GlusterFS (3.12? -> 6.0.1) fail when the transfer size
48 - * is greater or equal to 1024 MiB, so we are limiting the transfer size to 512
49 - * MiB to avoid this rare issue.
50 - */
51 -#define GLUSTER_MAX_TRANSFER (512 * MiB)
52 -
53 -#define GERR_INDEX_HINT "hint: check in 'server' array index '%d'\n"
54 -
55 -typedef struct GlusterAIOCB {
56 - int64_t size;
57 - int ret;
58 - Coroutine *coroutine;
59 -} GlusterAIOCB;
60 -
61 -typedef struct BDRVGlusterState {
62 - struct glfs *glfs;
63 - struct glfs_fd *fd;
64 - char *logfile;
65 - bool supports_seek_data;
66 - int debug;
67 -} BDRVGlusterState;
68 -
69 -typedef struct BDRVGlusterReopenState {
70 - struct glfs *glfs;
71 - struct glfs_fd *fd;
72 -} BDRVGlusterReopenState;
73 -
74 -
75 -typedef struct GlfsPreopened {
76 - char *volume;
77 - glfs_t *fs;
78 - int ref;
79 -} GlfsPreopened;
80 -
81 -typedef struct ListElement {
82 - QLIST_ENTRY(ListElement) list;
83 - GlfsPreopened saved;
84 -} ListElement;
85 -
86 -static QLIST_HEAD(, ListElement) glfs_list;
87 -
88 -static QemuOptsList qemu_gluster_create_opts = {
89 - .name = "qemu-gluster-create-opts",
90 - .head = QTAILQ_HEAD_INITIALIZER(qemu_gluster_create_opts.head),
91 - .desc = {
92 - {
93 - .name = BLOCK_OPT_SIZE,
94 - .type = QEMU_OPT_SIZE,
95 - .help = "Virtual disk size"
96 - },
97 - {
98 - .name = BLOCK_OPT_PREALLOC,
99 - .type = QEMU_OPT_STRING,
100 - .help = "Preallocation mode (allowed values: off"
101 -#ifdef CONFIG_GLUSTERFS_FALLOCATE
102 - ", falloc"
103 -#endif
104 -#ifdef CONFIG_GLUSTERFS_ZEROFILL
105 - ", full"
106 -#endif
107 - ")"
108 - },
109 - {
110 - .name = GLUSTER_OPT_DEBUG,
111 - .type = QEMU_OPT_NUMBER,
112 - .help = "Gluster log level, valid range is 0-9",
113 - },
114 - {
115 - .name = GLUSTER_OPT_LOGFILE,
116 - .type = QEMU_OPT_STRING,
117 - .help = "Logfile path of libgfapi",
118 - },
119 - { /* end of list */ }
120 - }
121 -};
122 -
123 -static QemuOptsList runtime_opts = {
124 - .name = "gluster",
125 - .head = QTAILQ_HEAD_INITIALIZER(runtime_opts.head),
126 - .desc = {
127 - {
128 - .name = GLUSTER_OPT_FILENAME,
129 - .type = QEMU_OPT_STRING,
130 - .help = "URL to the gluster image",
131 - },
132 - {
133 - .name = GLUSTER_OPT_DEBUG,
134 - .type = QEMU_OPT_NUMBER,
135 - .help = "Gluster log level, valid range is 0-9",
136 - },
137 - {
138 - .name = GLUSTER_OPT_LOGFILE,
139 - .type = QEMU_OPT_STRING,
140 - .help = "Logfile path of libgfapi",
141 - },
142 - { /* end of list */ }
143 - },
144 -};
145 -
146 -static QemuOptsList runtime_json_opts = {
147 - .name = "gluster_json",
148 - .head = QTAILQ_HEAD_INITIALIZER(runtime_json_opts.head),
149 - .desc = {
150 - {
151 - .name = GLUSTER_OPT_VOLUME,
152 - .type = QEMU_OPT_STRING,
153 - .help = "name of gluster volume where VM image resides",
154 - },
155 - {
156 - .name = GLUSTER_OPT_PATH,
157 - .type = QEMU_OPT_STRING,
158 - .help = "absolute path to image file in gluster volume",
159 - },
160 - {
161 - .name = GLUSTER_OPT_DEBUG,
162 - .type = QEMU_OPT_NUMBER,
163 - .help = "Gluster log level, valid range is 0-9",
164 - },
165 - { /* end of list */ }
166 - },
167 -};
168 -
169 -static QemuOptsList runtime_type_opts = {
170 - .name = "gluster_type",
171 - .head = QTAILQ_HEAD_INITIALIZER(runtime_type_opts.head),
172 - .desc = {
173 - {
174 - .name = GLUSTER_OPT_TYPE,
175 - .type = QEMU_OPT_STRING,
176 - .help = "inet|unix",
177 - },
178 - { /* end of list */ }
179 - },
180 -};
181 -
182 -static QemuOptsList runtime_unix_opts = {
183 - .name = "gluster_unix",
184 - .head = QTAILQ_HEAD_INITIALIZER(runtime_unix_opts.head),
185 - .desc = {
186 - {
187 - .name = GLUSTER_OPT_SOCKET,
188 - .type = QEMU_OPT_STRING,
189 - .help = "socket file path (legacy)",
190 - },
191 - {
192 - .name = GLUSTER_OPT_PATH,
193 - .type = QEMU_OPT_STRING,
194 - .help = "socket file path (QAPI)",
195 - },
196 - { /* end of list */ }
197 - },
198 -};
199 -
200 -static QemuOptsList runtime_inet_opts = {
201 - .name = "gluster_inet",
202 - .head = QTAILQ_HEAD_INITIALIZER(runtime_inet_opts.head),
203 - .desc = {
204 - {
205 - .name = GLUSTER_OPT_TYPE,
206 - .type = QEMU_OPT_STRING,
207 - .help = "inet|unix",
208 - },
209 - {
210 - .name = GLUSTER_OPT_HOST,
211 - .type = QEMU_OPT_STRING,
212 - .help = "host address (hostname/ipv4/ipv6 addresses)",
213 - },
214 - {
215 - .name = GLUSTER_OPT_PORT,
216 - .type = QEMU_OPT_STRING,
217 - .help = "port number on which glusterd is listening (default 24007)",
218 - },
219 - {
220 - .name = "to",
221 - .type = QEMU_OPT_NUMBER,
222 - .help = "max port number, not supported by gluster",
223 - },
224 - {
225 - .name = "ipv4",
226 - .type = QEMU_OPT_BOOL,
227 - .help = "ipv4 bool value, not supported by gluster",
228 - },
229 - {
230 - .name = "ipv6",
231 - .type = QEMU_OPT_BOOL,
232 - .help = "ipv6 bool value, not supported by gluster",
233 - },
234 - { /* end of list */ }
235 - },
236 -};
237 -
238 -static void glfs_set_preopened(const char *volume, glfs_t *fs)
239 -{
240 - ListElement *entry = NULL;
241 -
242 - entry = g_new(ListElement, 1);
243 -
244 - entry->saved.volume = g_strdup(volume);
245 -
246 - entry->saved.fs = fs;
247 - entry->saved.ref = 1;
248 -
249 - QLIST_INSERT_HEAD(&glfs_list, entry, list);
250 -}
251 -
252 -static glfs_t *glfs_find_preopened(const char *volume)
253 -{
254 - ListElement *entry;
255 -
256 - QLIST_FOREACH(entry, &glfs_list, list) {
257 - if (strcmp(entry->saved.volume, volume) == 0) {
258 - entry->saved.ref++;
259 - return entry->saved.fs;
260 - }
261 - }
262 -
263 - return NULL;
264 -}
265 -
266 -static void glfs_clear_preopened(glfs_t *fs)
267 -{
268 - ListElement *entry;
269 - ListElement *next;
270 -
271 - if (fs == NULL) {
272 - return;
273 - }
274 -
275 - QLIST_FOREACH_SAFE(entry, &glfs_list, list, next) {
276 - if (entry->saved.fs == fs) {
277 - if (--entry->saved.ref) {
278 - return;
279 - }
280 -
281 - QLIST_REMOVE(entry, list);
282 -
283 - glfs_fini(entry->saved.fs);
284 - g_free(entry->saved.volume);
285 - g_free(entry);
286 - }
287 - }
288 -}
289 -
290 -static int parse_volume_options(BlockdevOptionsGluster *gconf, const char *path)
291 -{
292 - const char *p, *q;
293 -
294 - if (!path) {
295 - return -EINVAL;
296 - }
297 -
298 - /* volume */
299 - p = q = path + strspn(path, "/");
300 - p += strcspn(p, "/");
301 - if (*p == '\0') {
302 - return -EINVAL;
303 - }
304 - gconf->volume = g_strndup(q, p - q);
305 -
306 - /* path */
307 - p += strspn(p, "/");
308 - if (*p == '\0') {
309 - return -EINVAL;
310 - }
311 - gconf->path = g_strdup(p);
312 - return 0;
313 -}
314 -
315 -/*
316 - * file=gluster[+transport]://[host[:port]]/volume/path[?socket=...]
317 - *
318 - * 'gluster' is the protocol.
319 - *
320 - * 'transport' specifies the transport type used to connect to gluster
321 - * management daemon (glusterd). Valid transport types are
322 - * tcp or unix. If a transport type isn't specified, then tcp type is assumed.
323 - *
324 - * 'host' specifies the host where the volume file specification for
325 - * the given volume resides. This can be either hostname or ipv4 address.
326 - * If transport type is 'unix', then 'host' field should not be specified.
327 - * The 'socket' field needs to be populated with the path to unix domain
328 - * socket.
329 - *
330 - * 'port' is the port number on which glusterd is listening. This is optional
331 - * and if not specified, QEMU will send 0 which will make gluster to use the
332 - * default port. If the transport type is unix, then 'port' should not be
333 - * specified.
334 - *
335 - * 'volume' is the name of the gluster volume which contains the VM image.
336 - *
337 - * 'path' is the path to the actual VM image that resides on gluster volume.
338 - *
339 - * Examples:
340 - *
341 - * file=gluster://1.2.3.4/testvol/a.img
342 - * file=gluster+tcp://1.2.3.4/testvol/a.img
343 - * file=gluster+tcp://1.2.3.4:24007/testvol/dir/a.img
344 - * file=gluster+tcp://host.domain.com:24007/testvol/dir/a.img
345 - * file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket
346 - */
347 -static int qemu_gluster_parse_uri(BlockdevOptionsGluster *gconf,
348 - const char *filename)
349 -{
350 - g_autoptr(GUri) uri = g_uri_parse(filename, G_URI_FLAGS_NONE, NULL);
351 - g_autoptr(GHashTable) qp = NULL;
352 - SocketAddress *gsconf;
353 - bool is_unix = false;
354 - const char *uri_scheme, *uri_query, *uri_server;
355 - int uri_port, ret;
356 -
357 - if (!uri) {
358 - return -EINVAL;
359 - }
360 -
361 - gsconf = g_new0(SocketAddress, 1);
362 - QAPI_LIST_PREPEND(gconf->server, gsconf);
363 -
364 - /* transport */
365 - uri_scheme = g_uri_get_scheme(uri);
366 - if (!uri_scheme || !strcmp(uri_scheme, "gluster")) {
367 - gsconf->type = SOCKET_ADDRESS_TYPE_INET;
368 - } else if (!strcmp(uri_scheme, "gluster+tcp")) {
369 - gsconf->type = SOCKET_ADDRESS_TYPE_INET;
370 - } else if (!strcmp(uri_scheme, "gluster+unix")) {
371 - gsconf->type = SOCKET_ADDRESS_TYPE_UNIX;
372 - is_unix = true;
373 - } else {
374 - return -EINVAL;
375 - }
376 -
377 - ret = parse_volume_options(gconf, g_uri_get_path(uri));
378 - if (ret < 0) {
379 - return ret;
380 - }
381 -
382 - uri_query = g_uri_get_query(uri);
383 - if (uri_query) {
384 - qp = g_uri_parse_params(uri_query, -1, "&", G_URI_PARAMS_NONE, NULL);
385 - if (!qp) {
386 - return -EINVAL;
387 - }
388 - ret = g_hash_table_size(qp);
389 - if (ret > 1 || (is_unix && !ret) || (!is_unix && ret)) {
390 - return -EINVAL;
391 - }
392 - }
393 -
394 - uri_server = g_uri_get_host(uri);
395 - uri_port = g_uri_get_port(uri);
396 -
397 - if (is_unix) {
398 - char *uri_socket = g_hash_table_lookup(qp, "socket");
399 - if (uri_server || uri_port != -1 || !uri_socket) {
400 - return -EINVAL;
401 - }
402 - gsconf->u.q_unix.path = g_strdup(uri_socket);
403 - } else {
404 - gsconf->u.inet.host = g_strdup(uri_server ? uri_server : "localhost");
405 - if (uri_port > 0) {
406 - gsconf->u.inet.port = g_strdup_printf("%d", uri_port);
407 - } else {
408 - gsconf->u.inet.port = g_strdup_printf("%d", GLUSTER_DEFAULT_PORT);
409 - }
410 - }
411 -
412 - return 0;
413 -}
414 -
415 -static struct glfs *qemu_gluster_glfs_init(BlockdevOptionsGluster *gconf,
416 - Error **errp)
417 -{
418 - struct glfs *glfs;
419 - int ret;
420 - int old_errno;
421 - SocketAddressList *server;
422 - uint64_t port;
423 -
424 - glfs = glfs_find_preopened(gconf->volume);
425 - if (glfs) {
426 - return glfs;
427 - }
428 -
429 - glfs = glfs_new(gconf->volume);
430 - if (!glfs) {
431 - goto out;
432 - }
433 -
434 - glfs_set_preopened(gconf->volume, glfs);
435 -
436 - for (server = gconf->server; server; server = server->next) {
437 - switch (server->value->type) {
438 - case SOCKET_ADDRESS_TYPE_UNIX:
439 - ret = glfs_set_volfile_server(glfs, "unix",
440 - server->value->u.q_unix.path, 0);
441 - break;
442 - case SOCKET_ADDRESS_TYPE_INET:
443 - if (parse_uint_full(server->value->u.inet.port, 10, &port) < 0 ||
444 - port > 65535) {
445 - error_setg(errp, "'%s' is not a valid port number",
446 - server->value->u.inet.port);
447 - errno = EINVAL;
448 - goto out;
449 - }
450 - ret = glfs_set_volfile_server(glfs, "tcp",
451 - server->value->u.inet.host,
452 - (int)port);
453 - break;
454 - case SOCKET_ADDRESS_TYPE_VSOCK:
455 - case SOCKET_ADDRESS_TYPE_FD:
456 - default:
457 - abort();
458 - }
459 -
460 - if (ret < 0) {
461 - goto out;
462 - }
463 - }
464 -
465 - ret = glfs_set_logging(glfs, gconf->logfile, gconf->debug);
466 - if (ret < 0) {
467 - goto out;
468 - }
469 -
470 - ret = glfs_init(glfs);
471 - if (ret) {
472 - error_setg(errp, "Gluster connection for volume %s, path %s failed"
473 - " to connect", gconf->volume, gconf->path);
474 - for (server = gconf->server; server; server = server->next) {
475 - if (server->value->type == SOCKET_ADDRESS_TYPE_UNIX) {
476 - error_append_hint(errp, "hint: failed on socket %s ",
477 - server->value->u.q_unix.path);
478 - } else {
479 - error_append_hint(errp, "hint: failed on host %s and port %s ",
480 - server->value->u.inet.host,
481 - server->value->u.inet.port);
482 - }
483 - }
484 -
485 - error_append_hint(errp, "Please refer to gluster logs for more info\n");
486 -
487 - /* glfs_init sometimes doesn't set errno although docs suggest that */
488 - if (errno == 0) {
489 - errno = EINVAL;
490 - }
491 -
492 - goto out;
493 - }
494 - return glfs;
495 -
496 -out:
497 - if (glfs) {
498 - old_errno = errno;
499 - glfs_clear_preopened(glfs);
500 - errno = old_errno;
501 - }
502 - return NULL;
503 -}
504 -
505 -/*
506 - * Convert the json formatted command line into qapi.
507 -*/
508 -static int qemu_gluster_parse_json(BlockdevOptionsGluster *gconf,
509 - QDict *options, Error **errp)
510 -{
511 - QemuOpts *opts;
512 - SocketAddress *gsconf = NULL;
513 - SocketAddressList **tail;
514 - QDict *backing_options = NULL;
515 - Error *local_err = NULL;
516 - const char *ptr;
517 - int i, type, num_servers;
518 -
519 - /* create opts info from runtime_json_opts list */
520 - opts = qemu_opts_create(&runtime_json_opts, NULL, 0, &error_abort);
521 - if (!qemu_opts_absorb_qdict(opts, options, errp)) {
522 - goto out;
523 - }
524 -
525 - num_servers = qdict_array_entries(options, GLUSTER_OPT_SERVER_PATTERN);
526 - if (num_servers < 1) {
527 - error_setg(&local_err, QERR_MISSING_PARAMETER, "server");
528 - goto out;
529 - }
530 -
531 - ptr = qemu_opt_get(opts, GLUSTER_OPT_VOLUME);
532 - if (!ptr) {
533 - error_setg(&local_err, QERR_MISSING_PARAMETER, GLUSTER_OPT_VOLUME);
534 - goto out;
535 - }
536 - gconf->volume = g_strdup(ptr);
537 -
538 - ptr = qemu_opt_get(opts, GLUSTER_OPT_PATH);
539 - if (!ptr) {
540 - error_setg(&local_err, QERR_MISSING_PARAMETER, GLUSTER_OPT_PATH);
541 - goto out;
542 - }
543 - gconf->path = g_strdup(ptr);
544 - qemu_opts_del(opts);
545 - tail = &gconf->server;
546 -
547 - for (i = 0; i < num_servers; i++) {
548 - g_autofree char *str = g_strdup_printf(GLUSTER_OPT_SERVER_PATTERN"%d.",
549 - i);
550 - qdict_extract_subqdict(options, &backing_options, str);
551 -
552 - /* create opts info from runtime_type_opts list */
553 - opts = qemu_opts_create(&runtime_type_opts, NULL, 0, &error_abort);
554 - if (!qemu_opts_absorb_qdict(opts, backing_options, errp)) {
555 - goto out;
556 - }
557 -
558 - ptr = qemu_opt_get(opts, GLUSTER_OPT_TYPE);
559 - if (!ptr) {
560 - error_setg(&local_err, QERR_MISSING_PARAMETER, GLUSTER_OPT_TYPE);
561 - error_append_hint(&local_err, GERR_INDEX_HINT, i);
562 - goto out;
563 -
564 - }
565 - gsconf = g_new0(SocketAddress, 1);
566 - if (!strcmp(ptr, "tcp")) {
567 - ptr = "inet"; /* accept legacy "tcp" */
568 - }
569 - type = qapi_enum_parse(&SocketAddressType_lookup, ptr, -1, NULL);
570 - if (type != SOCKET_ADDRESS_TYPE_INET
571 - && type != SOCKET_ADDRESS_TYPE_UNIX) {
572 - error_setg(&local_err,
573 - "Parameter '%s' may be 'inet' or 'unix'",
574 - GLUSTER_OPT_TYPE);
575 - error_append_hint(&local_err, GERR_INDEX_HINT, i);
576 - goto out;
577 - }
578 - gsconf->type = type;
579 - qemu_opts_del(opts);
580 -
581 - if (gsconf->type == SOCKET_ADDRESS_TYPE_INET) {
582 - /* create opts info from runtime_inet_opts list */
583 - opts = qemu_opts_create(&runtime_inet_opts, NULL, 0, &error_abort);
584 - if (!qemu_opts_absorb_qdict(opts, backing_options, errp)) {
585 - goto out;
586 - }
587 -
588 - ptr = qemu_opt_get(opts, GLUSTER_OPT_HOST);
589 - if (!ptr) {
590 - error_setg(&local_err, QERR_MISSING_PARAMETER,
591 - GLUSTER_OPT_HOST);
592 - error_append_hint(&local_err, GERR_INDEX_HINT, i);
593 - goto out;
594 - }
595 - gsconf->u.inet.host = g_strdup(ptr);
596 - ptr = qemu_opt_get(opts, GLUSTER_OPT_PORT);
597 - if (!ptr) {
598 - error_setg(&local_err, QERR_MISSING_PARAMETER,
599 - GLUSTER_OPT_PORT);
600 - error_append_hint(&local_err, GERR_INDEX_HINT, i);
601 - goto out;
602 - }
603 - gsconf->u.inet.port = g_strdup(ptr);
604 -
605 - /* defend for unsupported fields in InetSocketAddress,
606 - * i.e. @ipv4, @ipv6 and @to
607 - */
608 - ptr = qemu_opt_get(opts, GLUSTER_OPT_TO);
609 - if (ptr) {
610 - gsconf->u.inet.has_to = true;
611 - }
612 - ptr = qemu_opt_get(opts, GLUSTER_OPT_IPV4);
613 - if (ptr) {
614 - gsconf->u.inet.has_ipv4 = true;
615 - }
616 - ptr = qemu_opt_get(opts, GLUSTER_OPT_IPV6);
617 - if (ptr) {
618 - gsconf->u.inet.has_ipv6 = true;
619 - }
620 - if (gsconf->u.inet.has_to) {
621 - error_setg(&local_err, "Parameter 'to' not supported");
622 - goto out;
623 - }
624 - if (gsconf->u.inet.has_ipv4 || gsconf->u.inet.has_ipv6) {
625 - error_setg(&local_err, "Parameters 'ipv4/ipv6' not supported");
626 - goto out;
627 - }
628 - qemu_opts_del(opts);
629 - } else {
630 - /* create opts info from runtime_unix_opts list */
631 - opts = qemu_opts_create(&runtime_unix_opts, NULL, 0, &error_abort);
632 - if (!qemu_opts_absorb_qdict(opts, backing_options, errp)) {
633 - goto out;
634 - }
635 -
636 - ptr = qemu_opt_get(opts, GLUSTER_OPT_PATH);
637 - if (!ptr) {
638 - ptr = qemu_opt_get(opts, GLUSTER_OPT_SOCKET);
639 - } else if (qemu_opt_get(opts, GLUSTER_OPT_SOCKET)) {
640 - error_setg(&local_err,
641 - "Conflicting parameters 'path' and 'socket'");
642 - error_append_hint(&local_err, GERR_INDEX_HINT, i);
643 - goto out;
644 - }
645 - if (!ptr) {
646 - error_setg(&local_err, QERR_MISSING_PARAMETER,
647 - GLUSTER_OPT_PATH);
648 - error_append_hint(&local_err, GERR_INDEX_HINT, i);
649 - goto out;
650 - }
651 - gsconf->u.q_unix.path = g_strdup(ptr);
652 - qemu_opts_del(opts);
653 - }
654 -
655 - QAPI_LIST_APPEND(tail, gsconf);
656 - gsconf = NULL;
657 -
658 - qobject_unref(backing_options);
659 - backing_options = NULL;
660 - }
661 -
662 - return 0;
663 -
664 -out:
665 - error_propagate(errp, local_err);
666 - qapi_free_SocketAddress(gsconf);
667 - qemu_opts_del(opts);
668 - qobject_unref(backing_options);
669 - errno = EINVAL;
670 - return -errno;
671 -}
672 -
673 -/* Converts options given in @filename and the @options QDict into the QAPI
674 - * object @gconf. */
675 -static int qemu_gluster_parse(BlockdevOptionsGluster *gconf,
676 - const char *filename,
677 - QDict *options, Error **errp)
678 -{
679 - int ret;
680 - if (filename) {
681 - ret = qemu_gluster_parse_uri(gconf, filename);
682 - if (ret < 0) {
683 - error_setg(errp, "invalid URI %s", filename);
684 - error_append_hint(errp, "Usage: file=gluster[+transport]://"
685 - "[host[:port]]volume/path[?socket=...]"
686 - "[,file.debug=N]"
687 - "[,file.logfile=/path/filename.log]\n");
688 - return ret;
689 - }
690 - } else {
691 - ret = qemu_gluster_parse_json(gconf, options, errp);
692 - if (ret < 0) {
693 - error_append_hint(errp, "Usage: "
694 - "-drive driver=qcow2,file.driver=gluster,"
695 - "file.volume=testvol,file.path=/path/a.qcow2"
696 - "[,file.debug=9]"
697 - "[,file.logfile=/path/filename.log],"
698 - "file.server.0.type=inet,"
699 - "file.server.0.host=1.2.3.4,"
700 - "file.server.0.port=24007,"
701 - "file.server.1.transport=unix,"
702 - "file.server.1.path=/var/run/glusterd.socket ..."
703 - "\n");
704 - return ret;
705 - }
706 - }
707 -
708 - return 0;
709 -}
710 -
711 -static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf,
712 - const char *filename,
713 - QDict *options, Error **errp)
714 -{
715 - int ret;
716 -
717 - ret = qemu_gluster_parse(gconf, filename, options, errp);
718 - if (ret < 0) {
719 - errno = -ret;
720 - return NULL;
721 - }
722 -
723 - return qemu_gluster_glfs_init(gconf, errp);
724 -}
725 -
726 -/*
727 - * AIO callback routine called from GlusterFS thread.
728 - */
729 -static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret,
730 -#ifdef CONFIG_GLUSTERFS_IOCB_HAS_STAT
731 - struct glfs_stat *pre, struct glfs_stat *post,
732 -#endif
733 - void *arg)
734 -{
735 - GlusterAIOCB *acb = (GlusterAIOCB *)arg;
736 -
737 - if (!ret || ret == acb->size) {
738 - acb->ret = 0; /* Success */
739 - } else if (ret < 0) {
740 - acb->ret = -errno; /* Read/Write failed */
741 - } else {
742 - acb->ret = -EIO; /* Partial read/write - fail it */
743 - }
744 -
745 - /*
746 - * Safe to call: The coroutine will yield exactly once awaiting this
747 - * scheduling, and the context is its own context, so it will be scheduled
748 - * once it does yield.
749 - *
750 - * (aio_co_wake() would call qemu_get_current_aio_context() to check whether
751 - * we are in the same context, but we are not in a qemu thread, so we cannot
752 - * do that. Use aio_co_schedule() directly.)
753 - */
754 - aio_co_schedule(qemu_coroutine_get_aio_context(acb->coroutine),
755 - acb->coroutine);
756 -}
757 -
758 -static void qemu_gluster_parse_flags(int bdrv_flags, int *open_flags)
759 -{
760 - assert(open_flags != NULL);
761 -
762 - *open_flags |= O_BINARY;
763 -
764 - if (bdrv_flags & BDRV_O_RDWR) {
765 - *open_flags |= O_RDWR;
766 - } else {
767 - *open_flags |= O_RDONLY;
768 - }
769 -
770 - if ((bdrv_flags & BDRV_O_NOCACHE)) {
771 - *open_flags |= O_DIRECT;
772 - }
773 -}
774 -
775 -/*
776 - * Do SEEK_DATA/HOLE to detect if it is functional. Older broken versions of
777 - * gfapi incorrectly return the current offset when SEEK_DATA/HOLE is used.
778 - * - Corrected versions return -1 and set errno to EINVAL.
779 - * - Versions that support SEEK_DATA/HOLE correctly, will return -1 and set
780 - * errno to ENXIO when SEEK_DATA is called with a position of EOF.
781 - */
782 -static bool qemu_gluster_test_seek(struct glfs_fd *fd)
783 -{
784 - off_t ret = 0;
785 -
786 -#if defined SEEK_HOLE && defined SEEK_DATA
787 - off_t eof;
788 -
789 - eof = glfs_lseek(fd, 0, SEEK_END);
790 - if (eof < 0) {
791 - /* this should never occur */
792 - return false;
793 - }
794 -
795 - /* this should always fail with ENXIO if SEEK_DATA is supported */
796 - ret = glfs_lseek(fd, eof, SEEK_DATA);
797 -#endif
798 -
799 - return (ret < 0) && (errno == ENXIO);
800 -}
801 -
802 -static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
803 - int bdrv_flags, Error **errp)
804 -{
805 - BDRVGlusterState *s = bs->opaque;
806 - int open_flags = 0;
807 - int ret = 0;
808 - BlockdevOptionsGluster *gconf = NULL;
809 - QemuOpts *opts;
810 - const char *filename, *logfile;
811 -
812 - opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
813 - if (!qemu_opts_absorb_qdict(opts, options, errp)) {
814 - ret = -EINVAL;
815 - goto out;
816 - }
817 -
818 - warn_report_once("'gluster' is deprecated");
819 -
820 - filename = qemu_opt_get(opts, GLUSTER_OPT_FILENAME);
821 -
822 - s->debug = qemu_opt_get_number(opts, GLUSTER_OPT_DEBUG,
823 - GLUSTER_DEBUG_DEFAULT);
824 - if (s->debug < 0) {
825 - s->debug = 0;
826 - } else if (s->debug > GLUSTER_DEBUG_MAX) {
827 - s->debug = GLUSTER_DEBUG_MAX;
828 - }
829 -
830 - gconf = g_new0(BlockdevOptionsGluster, 1);
831 - gconf->debug = s->debug;
832 - gconf->has_debug = true;
833 -
834 - logfile = qemu_opt_get(opts, GLUSTER_OPT_LOGFILE);
835 - s->logfile = g_strdup(logfile ? logfile : GLUSTER_LOGFILE_DEFAULT);
836 -
837 - gconf->logfile = g_strdup(s->logfile);
838 -
839 - s->glfs = qemu_gluster_init(gconf, filename, options, errp);
840 - if (!s->glfs) {
841 - ret = -errno;
842 - goto out;
843 - }
844 -
845 -#ifdef CONFIG_GLUSTERFS_XLATOR_OPT
846 - /* Without this, if fsync fails for a recoverable reason (for instance,
847 - * ENOSPC), gluster will dump its cache, preventing retries. This means
848 - * almost certain data loss. Not all gluster versions support the
849 - * 'resync-failed-syncs-after-fsync' key value, but there is no way to
850 - * discover during runtime if it is supported (this api returns success for
851 - * unknown key/value pairs) */
852 - ret = glfs_set_xlator_option(s->glfs, "*-write-behind",
853 - "resync-failed-syncs-after-fsync",
854 - "on");
855 - if (ret < 0) {
856 - error_setg_errno(errp, errno, "Unable to set xlator key/value pair");
857 - ret = -errno;
858 - goto out;
859 - }
860 -#endif
861 -
862 - qemu_gluster_parse_flags(bdrv_flags, &open_flags);
863 -
864 - s->fd = glfs_open(s->glfs, gconf->path, open_flags);
865 - ret = s->fd ? 0 : -errno;
866 -
867 - if (ret == -EACCES || ret == -EROFS) {
868 - /* Try to degrade to read-only, but if it doesn't work, still use the
869 - * normal error message. */
870 - bdrv_graph_rdlock_main_loop();
871 - if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
872 - open_flags = (open_flags & ~O_RDWR) | O_RDONLY;
873 - s->fd = glfs_open(s->glfs, gconf->path, open_flags);
874 - ret = s->fd ? 0 : -errno;
875 - }
876 - bdrv_graph_rdunlock_main_loop();
877 - }
878 -
879 - s->supports_seek_data = qemu_gluster_test_seek(s->fd);
880 -
881 -out:
882 - qemu_opts_del(opts);
883 - qapi_free_BlockdevOptionsGluster(gconf);
884 - if (!ret) {
885 - return ret;
886 - }
887 - g_free(s->logfile);
888 - if (s->fd) {
889 - glfs_close(s->fd);
890 - }
891 -
892 - glfs_clear_preopened(s->glfs);
893 -
894 - return ret;
895 -}
896 -
897 -static void qemu_gluster_refresh_limits(BlockDriverState *bs, Error **errp)
898 -{
899 - bs->bl.max_transfer = GLUSTER_MAX_TRANSFER;
900 - bs->bl.max_pdiscard = MIN(SIZE_MAX, INT64_MAX);
901 -}
902 -
903 -static int qemu_gluster_reopen_prepare(BDRVReopenState *state,
904 - BlockReopenQueue *queue, Error **errp)
905 -{
906 - int ret = 0;
907 - BDRVGlusterState *s;
908 - BDRVGlusterReopenState *reop_s;
909 - BlockdevOptionsGluster *gconf;
910 - int open_flags = 0;
911 -
912 - assert(state != NULL);
913 - assert(state->bs != NULL);
914 -
915 - s = state->bs->opaque;
916 -
917 - state->opaque = g_new0(BDRVGlusterReopenState, 1);
918 - reop_s = state->opaque;
919 -
920 - qemu_gluster_parse_flags(state->flags, &open_flags);
921 -
922 - gconf = g_new0(BlockdevOptionsGluster, 1);
923 - gconf->debug = s->debug;
924 - gconf->has_debug = true;
925 - gconf->logfile = g_strdup(s->logfile);
926 -
927 - /*
928 - * If 'state->bs->exact_filename' is empty, 'state->options' should contain
929 - * the JSON parameters already parsed.
930 - */
931 - if (state->bs->exact_filename[0] != '\0') {
932 - reop_s->glfs = qemu_gluster_init(gconf, state->bs->exact_filename, NULL,
933 - errp);
934 - } else {
935 - reop_s->glfs = qemu_gluster_init(gconf, NULL, state->options, errp);
936 - }
937 - if (reop_s->glfs == NULL) {
938 - ret = -errno;
939 - goto exit;
940 - }
941 -
942 -#ifdef CONFIG_GLUSTERFS_XLATOR_OPT
943 - ret = glfs_set_xlator_option(reop_s->glfs, "*-write-behind",
944 - "resync-failed-syncs-after-fsync", "on");
945 - if (ret < 0) {
946 - error_setg_errno(errp, errno, "Unable to set xlator key/value pair");
947 - ret = -errno;
948 - goto exit;
949 - }
950 -#endif
951 -
952 - reop_s->fd = glfs_open(reop_s->glfs, gconf->path, open_flags);
953 - if (reop_s->fd == NULL) {
954 - /* reops->glfs will be cleaned up in _abort */
955 - ret = -errno;
956 - goto exit;
957 - }
958 -
959 -exit:
960 - /* state->opaque will be freed in either the _abort or _commit */
961 - qapi_free_BlockdevOptionsGluster(gconf);
962 - return ret;
963 -}
964 -
965 -static void qemu_gluster_reopen_commit(BDRVReopenState *state)
966 -{
967 - BDRVGlusterReopenState *reop_s = state->opaque;
968 - BDRVGlusterState *s = state->bs->opaque;
969 -
970 -
971 - /* close the old */
972 - if (s->fd) {
973 - glfs_close(s->fd);
974 - }
975 -
976 - glfs_clear_preopened(s->glfs);
977 -
978 - /* use the newly opened image / connection */
979 - s->fd = reop_s->fd;
980 - s->glfs = reop_s->glfs;
981 -
982 - g_free(state->opaque);
983 - state->opaque = NULL;
984 -}
985 -
986 -
987 -static void qemu_gluster_reopen_abort(BDRVReopenState *state)
988 -{
989 - BDRVGlusterReopenState *reop_s = state->opaque;
990 -
991 - if (reop_s == NULL) {
992 - return;
993 - }
994 -
995 - if (reop_s->fd) {
996 - glfs_close(reop_s->fd);
997 - }
998 -
999 - glfs_clear_preopened(reop_s->glfs);
1000 -
1001 - g_free(state->opaque);
1002 - state->opaque = NULL;
1003 -}
1004 -
1005 -#ifdef CONFIG_GLUSTERFS_ZEROFILL
1006 -static coroutine_fn int qemu_gluster_co_pwrite_zeroes(BlockDriverState *bs,
1007 - int64_t offset,
1008 - int64_t bytes,
1009 - BdrvRequestFlags flags)
1010 -{
1011 - int ret;
1012 - GlusterAIOCB acb;
1013 - BDRVGlusterState *s = bs->opaque;
1014 -
1015 - acb.size = bytes;
1016 - acb.ret = 0;
1017 - acb.coroutine = qemu_coroutine_self();
1018 -
1019 - ret = glfs_zerofill_async(s->fd, offset, bytes, gluster_finish_aiocb, &acb);
1020 - if (ret < 0) {
1021 - return -errno;
1022 - }
1023 -
1024 - qemu_coroutine_yield();
1025 - return acb.ret;
1026 -}
1027 -#endif
1028 -
1029 -static int qemu_gluster_do_truncate(struct glfs_fd *fd, int64_t offset,
1030 - PreallocMode prealloc, Error **errp)
1031 -{
1032 - int64_t current_length;
1033 -
1034 - current_length = glfs_lseek(fd, 0, SEEK_END);
1035 - if (current_length < 0) {
1036 - error_setg_errno(errp, errno, "Failed to determine current size");
1037 - return -errno;
1038 - }
1039 -
1040 - if (current_length > offset && prealloc != PREALLOC_MODE_OFF) {
1041 - error_setg(errp, "Cannot use preallocation for shrinking files");
1042 - return -ENOTSUP;
1043 - }
1044 -
1045 - if (current_length == offset) {
1046 - return 0;
1047 - }
1048 -
1049 - switch (prealloc) {
1050 -#ifdef CONFIG_GLUSTERFS_FALLOCATE
1051 - case PREALLOC_MODE_FALLOC:
1052 - if (glfs_fallocate(fd, 0, current_length, offset - current_length)) {
1053 - error_setg_errno(errp, errno, "Could not preallocate data");
1054 - return -errno;
1055 - }
1056 - break;
1057 -#endif /* CONFIG_GLUSTERFS_FALLOCATE */
1058 -#ifdef CONFIG_GLUSTERFS_ZEROFILL
1059 - case PREALLOC_MODE_FULL:
1060 - if (glfs_ftruncate(fd, offset)) {
1061 - error_setg_errno(errp, errno, "Could not resize file");
1062 - return -errno;
1063 - }
1064 - if (glfs_zerofill(fd, current_length, offset - current_length)) {
1065 - error_setg_errno(errp, errno, "Could not zerofill the new area");
1066 - return -errno;
1067 - }
1068 - break;
1069 -#endif /* CONFIG_GLUSTERFS_ZEROFILL */
1070 - case PREALLOC_MODE_OFF:
1071 - if (glfs_ftruncate(fd, offset)) {
1072 - error_setg_errno(errp, errno, "Could not resize file");
1073 - return -errno;
1074 - }
1075 - break;
1076 - default:
1077 - error_setg(errp, "Unsupported preallocation mode: %s",
1078 - PreallocMode_str(prealloc));
1079 - return -EINVAL;
1080 - }
1081 -
1082 - return 0;
1083 -}
1084 -
1085 -static int qemu_gluster_co_create(BlockdevCreateOptions *options,
1086 - Error **errp)
1087 -{
1088 - BlockdevCreateOptionsGluster *opts = &options->u.gluster;
1089 - struct glfs *glfs;
1090 - struct glfs_fd *fd = NULL;
1091 - int ret = 0;
1092 -
1093 - assert(options->driver == BLOCKDEV_DRIVER_GLUSTER);
1094 -
1095 - glfs = qemu_gluster_glfs_init(opts->location, errp);
1096 - if (!glfs) {
1097 - ret = -errno;
1098 - goto out;
1099 - }
1100 -
1101 - fd = glfs_creat(glfs, opts->location->path,
1102 - O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR);
1103 - if (!fd) {
1104 - ret = -errno;
1105 - goto out;
1106 - }
1107 -
1108 - ret = qemu_gluster_do_truncate(fd, opts->size, opts->preallocation, errp);
1109 -
1110 -out:
1111 - if (fd) {
1112 - if (glfs_close(fd) != 0 && ret == 0) {
1113 - ret = -errno;
1114 - }
1115 - }
1116 - glfs_clear_preopened(glfs);
1117 - return ret;
1118 -}
1119 -
1120 -static int coroutine_fn qemu_gluster_co_create_opts(BlockDriver *drv,
1121 - const char *filename,
1122 - QemuOpts *opts,
1123 - Error **errp)
1124 -{
1125 - BlockdevCreateOptions *options;
1126 - BlockdevCreateOptionsGluster *gopts;
1127 - BlockdevOptionsGluster *gconf;
1128 - char *tmp = NULL;
1129 - Error *local_err = NULL;
1130 - int ret;
1131 -
1132 - options = g_new0(BlockdevCreateOptions, 1);
1133 - options->driver = BLOCKDEV_DRIVER_GLUSTER;
1134 - gopts = &options->u.gluster;
1135 -
1136 - gconf = g_new0(BlockdevOptionsGluster, 1);
1137 - gopts->location = gconf;
1138 -
1139 - gopts->size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
1140 - BDRV_SECTOR_SIZE);
1141 -
1142 - tmp = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC);
1143 - gopts->preallocation = qapi_enum_parse(&PreallocMode_lookup, tmp,
1144 - PREALLOC_MODE_OFF, &local_err);
1145 - g_free(tmp);
1146 - if (local_err) {
1147 - error_propagate(errp, local_err);
1148 - ret = -EINVAL;
1149 - goto fail;
1150 - }
1151 -
1152 - gconf->debug = qemu_opt_get_number_del(opts, GLUSTER_OPT_DEBUG,
1153 - GLUSTER_DEBUG_DEFAULT);
1154 - if (gconf->debug < 0) {
1155 - gconf->debug = 0;
1156 - } else if (gconf->debug > GLUSTER_DEBUG_MAX) {
1157 - gconf->debug = GLUSTER_DEBUG_MAX;
1158 - }
1159 - gconf->has_debug = true;
1160 -
1161 - gconf->logfile = qemu_opt_get_del(opts, GLUSTER_OPT_LOGFILE);
1162 - if (!gconf->logfile) {
1163 - gconf->logfile = g_strdup(GLUSTER_LOGFILE_DEFAULT);
1164 - }
1165 -
1166 - ret = qemu_gluster_parse(gconf, filename, NULL, errp);
1167 - if (ret < 0) {
1168 - goto fail;
1169 - }
1170 -
1171 - ret = qemu_gluster_co_create(options, errp);
1172 - if (ret < 0) {
1173 - goto fail;
1174 - }
1175 -
1176 - ret = 0;
1177 -fail:
1178 - qapi_free_BlockdevCreateOptions(options);
1179 - return ret;
1180 -}
1181 -
1182 -static coroutine_fn int qemu_gluster_co_rw(BlockDriverState *bs,
1183 - int64_t sector_num, int nb_sectors,
1184 - QEMUIOVector *qiov, int write)
1185 -{
1186 - int ret;
1187 - GlusterAIOCB acb;
1188 - BDRVGlusterState *s = bs->opaque;
1189 - size_t size = nb_sectors * BDRV_SECTOR_SIZE;
1190 - off_t offset = sector_num * BDRV_SECTOR_SIZE;
1191 -
1192 - acb.size = size;
1193 - acb.ret = 0;
1194 - acb.coroutine = qemu_coroutine_self();
1195 -
1196 - if (write) {
1197 - ret = glfs_pwritev_async(s->fd, qiov->iov, qiov->niov, offset, 0,
1198 - gluster_finish_aiocb, &acb);
1199 - } else {
1200 - ret = glfs_preadv_async(s->fd, qiov->iov, qiov->niov, offset, 0,
1201 - gluster_finish_aiocb, &acb);
1202 - }
1203 -
1204 - if (ret < 0) {
1205 - return -errno;
1206 - }
1207 -
1208 - qemu_coroutine_yield();
1209 - return acb.ret;
1210 -}
1211 -
1212 -static coroutine_fn int qemu_gluster_co_truncate(BlockDriverState *bs,
1213 - int64_t offset,
1214 - bool exact,
1215 - PreallocMode prealloc,
1216 - BdrvRequestFlags flags,
1217 - Error **errp)
1218 -{
1219 - BDRVGlusterState *s = bs->opaque;
1220 - return qemu_gluster_do_truncate(s->fd, offset, prealloc, errp);
1221 -}
1222 -
1223 -static coroutine_fn int qemu_gluster_co_readv(BlockDriverState *bs,
1224 - int64_t sector_num,
1225 - int nb_sectors,
1226 - QEMUIOVector *qiov)
1227 -{
1228 - return qemu_gluster_co_rw(bs, sector_num, nb_sectors, qiov, 0);
1229 -}
1230 -
1231 -static coroutine_fn int qemu_gluster_co_writev(BlockDriverState *bs,
1232 - int64_t sector_num,
1233 - int nb_sectors,
1234 - QEMUIOVector *qiov,
1235 - int flags)
1236 -{
1237 - return qemu_gluster_co_rw(bs, sector_num, nb_sectors, qiov, 1);
1238 -}
1239 -
1240 -static void qemu_gluster_close(BlockDriverState *bs)
1241 -{
1242 - BDRVGlusterState *s = bs->opaque;
1243 -
1244 - g_free(s->logfile);
1245 - if (s->fd) {
1246 - glfs_close(s->fd);
1247 - s->fd = NULL;
1248 - }
1249 - glfs_clear_preopened(s->glfs);
1250 -}
1251 -
1252 -static coroutine_fn int qemu_gluster_co_flush_to_disk(BlockDriverState *bs)
1253 -{
1254 - int ret;
1255 - GlusterAIOCB acb;
1256 - BDRVGlusterState *s = bs->opaque;
1257 -
1258 - acb.size = 0;
1259 - acb.ret = 0;
1260 - acb.coroutine = qemu_coroutine_self();
1261 -
1262 - ret = glfs_fsync_async(s->fd, gluster_finish_aiocb, &acb);
1263 - if (ret < 0) {
1264 - ret = -errno;
1265 - goto error;
1266 - }
1267 -
1268 - qemu_coroutine_yield();
1269 - if (acb.ret < 0) {
1270 - ret = acb.ret;
1271 - goto error;
1272 - }
1273 -
1274 - return acb.ret;
1275 -
1276 -error:
1277 - /* Some versions of Gluster (3.5.6 -> 3.5.8?) will not retain its cache
1278 - * after a fsync failure, so we have no way of allowing the guest to safely
1279 - * continue. Gluster versions prior to 3.5.6 don't retain the cache
1280 - * either, but will invalidate the fd on error, so this is again our only
1281 - * option.
1282 - *
1283 - * The 'resync-failed-syncs-after-fsync' xlator option for the
1284 - * write-behind cache will cause later gluster versions to retain its
1285 - * cache after error, so long as the fd remains open. However, we
1286 - * currently have no way of knowing if this option is supported.
1287 - *
1288 - * TODO: Once gluster provides a way for us to determine if the option
1289 - * is supported, bypass the closure and setting drv to NULL. */
1290 - qemu_gluster_close(bs);
1291 - bs->drv = NULL;
1292 - return ret;
1293 -}
1294 -
1295 -#ifdef CONFIG_GLUSTERFS_DISCARD
1296 -static coroutine_fn int qemu_gluster_co_pdiscard(BlockDriverState *bs,
1297 - int64_t offset, int64_t bytes)
1298 -{
1299 - int ret;
1300 - GlusterAIOCB acb;
1301 - BDRVGlusterState *s = bs->opaque;
1302 -
1303 - assert(bytes <= SIZE_MAX); /* rely on max_pdiscard */
1304 -
1305 - acb.size = 0;
1306 - acb.ret = 0;
1307 - acb.coroutine = qemu_coroutine_self();
1308 -
1309 - ret = glfs_discard_async(s->fd, offset, bytes, gluster_finish_aiocb, &acb);
1310 - if (ret < 0) {
1311 - return -errno;
1312 - }
1313 -
1314 - qemu_coroutine_yield();
1315 - return acb.ret;
1316 -}
1317 -#endif
1318 -
1319 -static int64_t coroutine_fn qemu_gluster_co_getlength(BlockDriverState *bs)
1320 -{
1321 - BDRVGlusterState *s = bs->opaque;
1322 - int64_t ret;
1323 -
1324 - ret = glfs_lseek(s->fd, 0, SEEK_END);
1325 - if (ret < 0) {
1326 - return -errno;
1327 - } else {
1328 - return ret;
1329 - }
1330 -}
1331 -
1332 -static int64_t coroutine_fn
1333 -qemu_gluster_co_get_allocated_file_size(BlockDriverState *bs)
1334 -{
1335 - BDRVGlusterState *s = bs->opaque;
1336 - struct stat st;
1337 - int ret;
1338 -
1339 - ret = glfs_fstat(s->fd, &st);
1340 - if (ret < 0) {
1341 - return -errno;
1342 - } else {
1343 - return st.st_blocks * 512;
1344 - }
1345 -}
1346 -
1347 -/*
1348 - * Find allocation range in @bs around offset @start.
1349 - * May change underlying file descriptor's file offset.
1350 - * If @start is not in a hole, store @start in @data, and the
1351 - * beginning of the next hole in @hole, and return 0.
1352 - * If @start is in a non-trailing hole, store @start in @hole and the
1353 - * beginning of the next non-hole in @data, and return 0.
1354 - * If @start is in a trailing hole or beyond EOF, return -ENXIO.
1355 - * If we can't find out, return a negative errno other than -ENXIO.
1356 - *
1357 - * (Shamefully copied from file-posix.c, only minuscule adaptions.)
1358 - */
1359 -static int find_allocation(BlockDriverState *bs, off_t start,
1360 - off_t *data, off_t *hole)
1361 -{
1362 - BDRVGlusterState *s = bs->opaque;
1363 -
1364 - if (!s->supports_seek_data) {
1365 - goto exit;
1366 - }
1367 -
1368 -#if defined SEEK_HOLE && defined SEEK_DATA
1369 - off_t offs;
1370 -
1371 - /*
1372 - * SEEK_DATA cases:
1373 - * D1. offs == start: start is in data
1374 - * D2. offs > start: start is in a hole, next data at offs
1375 - * D3. offs < 0, errno = ENXIO: either start is in a trailing hole
1376 - * or start is beyond EOF
1377 - * If the latter happens, the file has been truncated behind
1378 - * our back since we opened it. All bets are off then.
1379 - * Treating like a trailing hole is simplest.
1380 - * D4. offs < 0, errno != ENXIO: we learned nothing
1381 - */
1382 - offs = glfs_lseek(s->fd, start, SEEK_DATA);
1383 - if (offs < 0) {
1384 - return -errno; /* D3 or D4 */
1385 - }
1386 -
1387 - if (offs < start) {
1388 - /* This is not a valid return by lseek(). We are safe to just return
1389 - * -EIO in this case, and we'll treat it like D4. Unfortunately some
1390 - * versions of gluster server will return offs < start, so an assert
1391 - * here will unnecessarily abort QEMU. */
1392 - return -EIO;
1393 - }
1394 -
1395 - if (offs > start) {
1396 - /* D2: in hole, next data at offs */
1397 - *hole = start;
1398 - *data = offs;
1399 - return 0;
1400 - }
1401 -
1402 - /* D1: in data, end not yet known */
1403 -
1404 - /*
1405 - * SEEK_HOLE cases:
1406 - * H1. offs == start: start is in a hole
1407 - * If this happens here, a hole has been dug behind our back
1408 - * since the previous lseek().
1409 - * H2. offs > start: either start is in data, next hole at offs,
1410 - * or start is in trailing hole, EOF at offs
1411 - * Linux treats trailing holes like any other hole: offs ==
1412 - * start. Solaris seeks to EOF instead: offs > start (blech).
1413 - * If that happens here, a hole has been dug behind our back
1414 - * since the previous lseek().
1415 - * H3. offs < 0, errno = ENXIO: start is beyond EOF
1416 - * If this happens, the file has been truncated behind our
1417 - * back since we opened it. Treat it like a trailing hole.
1418 - * H4. offs < 0, errno != ENXIO: we learned nothing
1419 - * Pretend we know nothing at all, i.e. "forget" about D1.
1420 - */
1421 - offs = glfs_lseek(s->fd, start, SEEK_HOLE);
1422 - if (offs < 0) {
1423 - return -errno; /* D1 and (H3 or H4) */
1424 - }
1425 -
1426 - if (offs < start) {
1427 - /* This is not a valid return by lseek(). We are safe to just return
1428 - * -EIO in this case, and we'll treat it like H4. Unfortunately some
1429 - * versions of gluster server will return offs < start, so an assert
1430 - * here will unnecessarily abort QEMU. */
1431 - return -EIO;
1432 - }
1433 -
1434 - if (offs > start) {
1435 - /*
1436 - * D1 and H2: either in data, next hole at offs, or it was in
1437 - * data but is now in a trailing hole. In the latter case,
1438 - * all bets are off. Treating it as if it there was data all
1439 - * the way to EOF is safe, so simply do that.
1440 - */
1441 - *data = start;
1442 - *hole = offs;
1443 - return 0;
1444 - }
1445 -
1446 - /* D1 and H1 */
1447 - return -EBUSY;
1448 -#endif
1449 -
1450 -exit:
1451 - return -ENOTSUP;
1452 -}
1453 -
1454 -/*
1455 - * Returns the allocation status of the specified offset.
1456 - *
1457 - * The block layer guarantees 'offset' and 'bytes' are within bounds.
1458 - *
1459 - * 'pnum' is set to the number of bytes (including and immediately following
1460 - * the specified offset) that are known to be in the same
1461 - * allocated/unallocated state.
1462 - *
1463 - * 'bytes' is a soft cap for 'pnum'. If the information is free, 'pnum' may
1464 - * well exceed it.
1465 - *
1466 - * (Based on raw_co_block_status() from file-posix.c.)
1467 - */
1468 -static int coroutine_fn qemu_gluster_co_block_status(BlockDriverState *bs,
1469 - unsigned int mode,
1470 - int64_t offset,
1471 - int64_t bytes,
1472 - int64_t *pnum,
1473 - int64_t *map,
1474 - BlockDriverState **file)
1475 -{
1476 - BDRVGlusterState *s = bs->opaque;
1477 - off_t data = 0, hole = 0;
1478 - int ret = -EINVAL;
1479 -
1480 - assert(QEMU_IS_ALIGNED(offset | bytes, bs->bl.request_alignment));
1481 -
1482 - if (!s->fd) {
1483 - return ret;
1484 - }
1485 -
1486 - if (!(mode & BDRV_WANT_ZERO)) {
1487 - *pnum = bytes;
1488 - *map = offset;
1489 - *file = bs;
1490 - return BDRV_BLOCK_DATA | BDRV_BLOCK_OFFSET_VALID;
1491 - }
1492 -
1493 - ret = find_allocation(bs, offset, &data, &hole);
1494 - if (ret == -ENXIO) {
1495 - /* Trailing hole */
1496 - *pnum = bytes;
1497 - ret = BDRV_BLOCK_ZERO;
1498 - } else if (ret < 0) {
1499 - /* No info available, so pretend there are no holes */
1500 - *pnum = bytes;
1501 - ret = BDRV_BLOCK_DATA;
1502 - } else if (data == offset) {
1503 - /* On a data extent, compute bytes to the end of the extent,
1504 - * possibly including a partial sector at EOF. */
1505 - *pnum = hole - offset;
1506 -
1507 - /*
1508 - * We are not allowed to return partial sectors, though, so
1509 - * round up if necessary.
1510 - */
1511 - if (!QEMU_IS_ALIGNED(*pnum, bs->bl.request_alignment)) {
1512 - int64_t file_length = qemu_gluster_co_getlength(bs);
1513 - if (file_length > 0) {
1514 - /* Ignore errors, this is just a safeguard */
1515 - assert(hole == file_length);
1516 - }
1517 - *pnum = ROUND_UP(*pnum, bs->bl.request_alignment);
1518 - }
1519 -
1520 - ret = BDRV_BLOCK_DATA;
1521 - } else {
1522 - /* On a hole, compute bytes to the beginning of the next extent. */
1523 - assert(hole == offset);
1524 - *pnum = data - offset;
1525 - ret = BDRV_BLOCK_ZERO;
1526 - }
1527 -
1528 - *map = offset;
1529 - *file = bs;
1530 -
1531 - return ret | BDRV_BLOCK_OFFSET_VALID;
1532 -}
1533 -
1534 -
1535 -static const char *const gluster_strong_open_opts[] = {
1536 - GLUSTER_OPT_VOLUME,
1537 - GLUSTER_OPT_PATH,
1538 - GLUSTER_OPT_TYPE,
1539 - GLUSTER_OPT_SERVER_PATTERN,
1540 - GLUSTER_OPT_HOST,
1541 - GLUSTER_OPT_PORT,
1542 - GLUSTER_OPT_TO,
1543 - GLUSTER_OPT_IPV4,
1544 - GLUSTER_OPT_IPV6,
1545 - GLUSTER_OPT_SOCKET,
1546 -
1547 - NULL
1548 -};
1549 -
1550 -static BlockDriver bdrv_gluster = {
1551 - .format_name = "gluster",
1552 - .protocol_name = "gluster",
1553 - .instance_size = sizeof(BDRVGlusterState),
1554 - .bdrv_open = qemu_gluster_open,
1555 - .bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
1556 - .bdrv_reopen_commit = qemu_gluster_reopen_commit,
1557 - .bdrv_reopen_abort = qemu_gluster_reopen_abort,
1558 - .bdrv_close = qemu_gluster_close,
1559 - .bdrv_co_create = qemu_gluster_co_create,
1560 - .bdrv_co_create_opts = qemu_gluster_co_create_opts,
1561 - .bdrv_co_getlength = qemu_gluster_co_getlength,
1562 - .bdrv_co_get_allocated_file_size = qemu_gluster_co_get_allocated_file_size,
1563 - .bdrv_co_truncate = qemu_gluster_co_truncate,
1564 - .bdrv_co_readv = qemu_gluster_co_readv,
1565 - .bdrv_co_writev = qemu_gluster_co_writev,
1566 - .bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
1567 -#ifdef CONFIG_GLUSTERFS_DISCARD
1568 - .bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
1569 -#endif
1570 -#ifdef CONFIG_GLUSTERFS_ZEROFILL
1571 - .bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
1572 -#endif
1573 - .bdrv_co_block_status = qemu_gluster_co_block_status,
1574 - .bdrv_refresh_limits = qemu_gluster_refresh_limits,
1575 - .create_opts = &qemu_gluster_create_opts,
1576 - .strong_runtime_opts = gluster_strong_open_opts,
1577 -};
1578 -
1579 -static BlockDriver bdrv_gluster_tcp = {
1580 - .format_name = "gluster",
1581 - .protocol_name = "gluster+tcp",
1582 - .instance_size = sizeof(BDRVGlusterState),
1583 - .bdrv_open = qemu_gluster_open,
1584 - .bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
1585 - .bdrv_reopen_commit = qemu_gluster_reopen_commit,
1586 - .bdrv_reopen_abort = qemu_gluster_reopen_abort,
1587 - .bdrv_close = qemu_gluster_close,
1588 - .bdrv_co_create = qemu_gluster_co_create,
1589 - .bdrv_co_create_opts = qemu_gluster_co_create_opts,
1590 - .bdrv_co_getlength = qemu_gluster_co_getlength,
1591 - .bdrv_co_get_allocated_file_size = qemu_gluster_co_get_allocated_file_size,
1592 - .bdrv_co_truncate = qemu_gluster_co_truncate,
1593 - .bdrv_co_readv = qemu_gluster_co_readv,
1594 - .bdrv_co_writev = qemu_gluster_co_writev,
1595 - .bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
1596 -#ifdef CONFIG_GLUSTERFS_DISCARD
1597 - .bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
1598 -#endif
1599 -#ifdef CONFIG_GLUSTERFS_ZEROFILL
1600 - .bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
1601 -#endif
1602 - .bdrv_co_block_status = qemu_gluster_co_block_status,
1603 - .bdrv_refresh_limits = qemu_gluster_refresh_limits,
1604 - .create_opts = &qemu_gluster_create_opts,
1605 - .strong_runtime_opts = gluster_strong_open_opts,
1606 -};
1607 -
1608 -static BlockDriver bdrv_gluster_unix = {
1609 - .format_name = "gluster",
1610 - .protocol_name = "gluster+unix",
1611 - .instance_size = sizeof(BDRVGlusterState),
1612 - .bdrv_open = qemu_gluster_open,
1613 - .bdrv_reopen_prepare = qemu_gluster_reopen_prepare,
1614 - .bdrv_reopen_commit = qemu_gluster_reopen_commit,
1615 - .bdrv_reopen_abort = qemu_gluster_reopen_abort,
1616 - .bdrv_close = qemu_gluster_close,
1617 - .bdrv_co_create = qemu_gluster_co_create,
1618 - .bdrv_co_create_opts = qemu_gluster_co_create_opts,
1619 - .bdrv_co_getlength = qemu_gluster_co_getlength,
1620 - .bdrv_co_get_allocated_file_size = qemu_gluster_co_get_allocated_file_size,
1621 - .bdrv_co_truncate = qemu_gluster_co_truncate,
1622 - .bdrv_co_readv = qemu_gluster_co_readv,
1623 - .bdrv_co_writev = qemu_gluster_co_writev,
1624 - .bdrv_co_flush_to_disk = qemu_gluster_co_flush_to_disk,
1625 -#ifdef CONFIG_GLUSTERFS_DISCARD
1626 - .bdrv_co_pdiscard = qemu_gluster_co_pdiscard,
1627 -#endif
1628 -#ifdef CONFIG_GLUSTERFS_ZEROFILL
1629 - .bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
1630 -#endif
1631 - .bdrv_co_block_status = qemu_gluster_co_block_status,
1632 - .bdrv_refresh_limits = qemu_gluster_refresh_limits,
1633 - .create_opts = &qemu_gluster_create_opts,
1634 - .strong_runtime_opts = gluster_strong_open_opts,
1635 -};
1636 -
1637 -static void bdrv_gluster_init(void)
1638 -{
1639 - bdrv_register(&bdrv_gluster_unix);
1640 - bdrv_register(&bdrv_gluster_tcp);
1641 - bdrv_register(&bdrv_gluster);
1642 -}
1643 -
1644 -block_init(bdrv_gluster_init);
block/meson.build
-1
@@ -109,7 +109,6 @@ modsrc = []
109 foreach m : [
110 [blkio, 'blkio', files('blkio.c')],
111 [curl, 'curl', files('curl.c')],
112 - [glusterfs, 'gluster', files('gluster.c')],
112 [libiscsi, 'iscsi', files('iscsi.c')],
113 [libnfs, 'nfs', files('nfs.c')],
114 [libssh, 'ssh', files('ssh.c')],
docs/about/deprecated.rst
-8
@@ -382,14 +382,6 @@ Specifying the iSCSI password in plain text on the command line using the
382 used instead, to refer to a ``--object secret...`` instance that provides
383 a password via a file, or encrypted.
384
385 -``gluster`` backend (since 9.2)
386 -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
387 -
388 -According to https://marc.info/?l=fedora-devel-list&m=171934833215726
389 -the GlusterFS development effectively ended. Unless the development
390 -gains momentum again, the QEMU project will remove the gluster backend
391 -in a future release.
392 -
385
386 Character device options
387 ''''''''''''''''''''''''
docs/about/removed-features.rst
+7
@@ -1429,6 +1429,13 @@ The corresponding upstream server project is no longer maintained.
1429 Users are recommended to switch to an alternative distributed block
1430 device driver such as RBD.
1431
1432 +``gluster`` backend (removed in 11.1)
1433 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1434 +
1435 +According to https://marc.info/?l=fedora-devel-list&m=171934833215726
1436 +the GlusterFS development effectively ended.
1437 +
1438 +
1439 VFIO devices
1440 ------------
1441
docs/system/device-url-syntax.rst.inc
-39
@@ -85,45 +85,6 @@ These are specified using a special URL syntax.
85 Currently authentication must be done using ssh-agent. Other
86 authentication methods may be supported in future.
87
88 -``GlusterFS``
89 - GlusterFS is a user space distributed file system. QEMU supports the
90 - use of GlusterFS volumes for hosting VM disk images using TCP and Unix
91 - Domain Sockets transport protocols.
92 -
93 - Syntax for specifying a VM disk image on GlusterFS volume is
94 -
95 - .. parsed-literal::
96 -
97 - URI:
98 - gluster[+type]://[host[:port]]/volume/path[?socket=...][,debug=N][,logfile=...]
99 -
100 - JSON:
101 - 'json:{"driver":"qcow2","file":{"driver":"gluster","volume":"testvol","path":"a.img","debug":N,"logfile":"...",
102 -   "server":[{"type":"tcp","host":"...","port":"..."},
103 -   {"type":"unix","socket":"..."}]}}'
104 -
105 - Example
106 -
107 - .. parsed-literal::
108 -
109 - URI:
110 - |qemu_system| --drive file=gluster://192.0.2.1/testvol/a.img,
111 -   file.debug=9,file.logfile=/var/log/qemu-gluster.log
112 -
113 - JSON:
114 - |qemu_system| 'json:{"driver":"qcow2",
115 -   "file":{"driver":"gluster",
116 -   "volume":"testvol","path":"a.img",
117 -   "debug":9,"logfile":"/var/log/qemu-gluster.log",
118 -   "server":[{"type":"tcp","host":"1.2.3.4","port":24007},
119 -   {"type":"unix","socket":"/var/run/glusterd.socket"}]}}'
120 - |qemu_system| -drive driver=qcow2,file.driver=gluster,file.volume=testvol,file.path=/path/a.img,
121 -   file.debug=9,file.logfile=/var/log/qemu-gluster.log,
122 -   file.server.0.type=tcp,file.server.0.host=1.2.3.4,file.server.0.port=24007,
123 -   file.server.1.type=unix,file.server.1.socket=/var/run/glusterd.socket
124 -
125 - See also http://www.gluster.org.
126 -
88 ``HTTP/HTTPS/FTP/FTPS``
89 QEMU supports read-only access to files accessed over http(s) and
90 ftp(s).
docs/system/qemu-block-drivers.rst.inc
-84
@@ -665,90 +665,6 @@ systems as the package 'scsi-target-utils'.
665 -boot d -drive file=iscsi://127.0.0.1/iqn.qemu.test/1 \\
666 -cdrom iscsi://127.0.0.1/iqn.qemu.test/2
667
668 -GlusterFS disk images
669 -~~~~~~~~~~~~~~~~~~~~~
670 -
671 -GlusterFS is a user space distributed file system.
672 -
673 -You can boot from the GlusterFS disk image with the command:
674 -
675 -URI:
676 -
677 -.. parsed-literal::
678 -
679 - |qemu_system| -drive file=gluster[+TYPE]://[HOST}[:PORT]]/VOLUME/PATH
680 - [?socket=...][,file.debug=9][,file.logfile=...]
681 -
682 -JSON:
683 -
684 -.. parsed-literal::
685 -
686 - |qemu_system| 'json:{"driver":"qcow2",
687 - "file":{"driver":"gluster",
688 - "volume":"testvol","path":"a.img","debug":9,"logfile":"...",
689 - "server":[{"type":"tcp","host":"...","port":"..."},
690 - {"type":"unix","socket":"..."}]}}'
691 -
692 -*gluster* is the protocol.
693 -
694 -*TYPE* specifies the transport type used to connect to gluster
695 -management daemon (glusterd). Valid transport types are
696 -tcp and unix. In the URI form, if a transport type isn't specified,
697 -then tcp type is assumed.
698 -
699 -*HOST* specifies the server where the volume file specification for
700 -the given volume resides. This can be either a hostname or an ipv4 address.
701 -If transport type is unix, then *HOST* field should not be specified.
702 -Instead *socket* field needs to be populated with the path to unix domain
703 -socket.
704 -
705 -*PORT* is the port number on which glusterd is listening. This is optional
706 -and if not specified, it defaults to port 24007. If the transport type is unix,
707 -then *PORT* should not be specified.
708 -
709 -*VOLUME* is the name of the gluster volume which contains the disk image.
710 -
711 -*PATH* is the path to the actual disk image that resides on gluster volume.
712 -
713 -*debug* is the logging level of the gluster protocol driver. Debug levels
714 -are 0-9, with 9 being the most verbose, and 0 representing no debugging output.
715 -The default level is 4. The current logging levels defined in the gluster source
716 -are 0 - None, 1 - Emergency, 2 - Alert, 3 - Critical, 4 - Error, 5 - Warning,
717 -6 - Notice, 7 - Info, 8 - Debug, 9 - Trace
718 -
719 -*logfile* is a commandline option to mention log file path which helps in
720 -logging to the specified file and also help in persisting the gfapi logs. The
721 -default is stderr.
722 -
723 -You can create a GlusterFS disk image with the command:
724 -
725 -.. parsed-literal::
726 -
727 - qemu-img create gluster://HOST/VOLUME/PATH SIZE
728 -
729 -Examples
730 -
731 -.. parsed-literal::
732 -
733 - |qemu_system| -drive file=gluster://1.2.3.4/testvol/a.img
734 - |qemu_system| -drive file=gluster+tcp://1.2.3.4/testvol/a.img
735 - |qemu_system| -drive file=gluster+tcp://1.2.3.4:24007/testvol/dir/a.img
736 - |qemu_system| -drive file=gluster+tcp://[1:2:3:4:5:6:7:8]/testvol/dir/a.img
737 - |qemu_system| -drive file=gluster+tcp://[1:2:3:4:5:6:7:8]:24007/testvol/dir/a.img
738 - |qemu_system| -drive file=gluster+tcp://server.domain.com:24007/testvol/dir/a.img
739 - |qemu_system| -drive file=gluster+unix:///testvol/dir/a.img?socket=/tmp/glusterd.socket
740 - |qemu_system| -drive file=gluster://1.2.3.4/testvol/a.img,file.debug=9,file.logfile=/var/log/qemu-gluster.log
741 - |qemu_system| 'json:{"driver":"qcow2",
742 - "file":{"driver":"gluster",
743 - "volume":"testvol","path":"a.img",
744 - "debug":9,"logfile":"/var/log/qemu-gluster.log",
745 - "server":[{"type":"tcp","host":"1.2.3.4","port":24007},
746 - {"type":"unix","socket":"/var/run/glusterd.socket"}]}}'
747 - |qemu_system| -drive driver=qcow2,file.driver=gluster,file.volume=testvol,file.path=/path/a.img,
748 - file.debug=9,file.logfile=/var/log/qemu-gluster.log,
749 - file.server.0.type=tcp,file.server.0.host=1.2.3.4,file.server.0.port=24007,
750 - file.server.1.type=unix,file.server.1.socket=/var/run/glusterd.socket
751 -
668 Secure Shell (ssh) disk images
669 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
670
meson.build
-47
@@ -1662,43 +1662,6 @@ if not get_option('rbd').auto() or have_block
1662 endif
1663 endif
1664
1665 -glusterfs = not_found
1666 -glusterfs_ftruncate_has_stat = false
1667 -glusterfs_iocb_has_stat = false
1668 -if not get_option('glusterfs').auto() or have_block
1669 - glusterfs = dependency('glusterfs-api', version: '>=3',
1670 - required: get_option('glusterfs'),
1671 - method: 'pkg-config')
1672 - if glusterfs.found()
1673 - glusterfs_ftruncate_has_stat = cc.links('''
1674 - #include <glusterfs/api/glfs.h>
1675 -
1676 - int
1677 - main(void)
1678 - {
1679 - /* new glfs_ftruncate() passes two additional args */
1680 - return glfs_ftruncate(NULL, 0, NULL, NULL);
1681 - }
1682 - ''', dependencies: glusterfs)
1683 - glusterfs_iocb_has_stat = cc.links('''
1684 - #include <glusterfs/api/glfs.h>
1685 -
1686 - /* new glfs_io_cbk() passes two additional glfs_stat structs */
1687 - static void
1688 - glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data)
1689 - {}
1690 -
1691 - int
1692 - main(void)
1693 - {
1694 - glfs_io_cbk iocb = &glusterfs_iocb;
1695 - iocb(NULL, 0 , NULL, NULL, NULL);
1696 - return 0;
1697 - }
1698 - ''', dependencies: glusterfs)
1699 - endif
1700 -endif
1701 -
1665 hv_balloon = false
1666 if get_option('hv_balloon').allowed() and have_system
1667 if cc.links('''
@@ -2478,15 +2441,6 @@ config_host_data.set('CONFIG_CURL', curl.found())
2441 config_host_data.set('CONFIG_CURSES', curses.found())
2442 config_host_data.set('CONFIG_GBM', gbm.found())
2443 config_host_data.set('CONFIG_GIO', gio.found())
2481 -config_host_data.set('CONFIG_GLUSTERFS', glusterfs.found())
2482 -if glusterfs.found()
2483 - config_host_data.set('CONFIG_GLUSTERFS_XLATOR_OPT', glusterfs.version().version_compare('>=4'))
2484 - config_host_data.set('CONFIG_GLUSTERFS_DISCARD', glusterfs.version().version_compare('>=5'))
2485 - config_host_data.set('CONFIG_GLUSTERFS_FALLOCATE', glusterfs.version().version_compare('>=6'))
2486 - config_host_data.set('CONFIG_GLUSTERFS_ZEROFILL', glusterfs.version().version_compare('>=6'))
2487 - config_host_data.set('CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT', glusterfs_ftruncate_has_stat)
2488 - config_host_data.set('CONFIG_GLUSTERFS_IOCB_HAS_STAT', glusterfs_iocb_has_stat)
2489 -endif
2444 config_host_data.set('CONFIG_GTK', gtk.found())
2445 config_host_data.set('CONFIG_VTE', vte.found())
2446 config_host_data.set('CONFIG_HEXAGON_IDEF_PARSER', get_option('hexagon_idef_parser'))
@@ -5014,7 +4968,6 @@ if host_os == 'windows'
4968 endif
4969 endif
4970 summary_info += {'seccomp support': seccomp}
5017 -summary_info += {'GlusterFS support': glusterfs}
4971 summary_info += {'hv-balloon support': hv_balloon}
4972 summary_info += {'TPM support': have_tpm}
4973 summary_info += {'IGVM support': igvm}
meson_options.txt
-2
@@ -160,8 +160,6 @@ option('curl', type : 'feature', value : 'auto',
160 description: 'CURL block device driver')
161 option('gio', type : 'feature', value : 'auto',
162 description: 'use libgio for D-Bus support')
163 -option('glusterfs', type : 'feature', value : 'auto',
164 - description: 'Glusterfs block device driver')
163 option('hv_balloon', type : 'feature', value : 'auto',
164 description: 'hv-balloon driver (requires Glib 2.68+ GTree API)')
165 option('libdw', type : 'feature', value : 'auto',
qapi/block-core.json
-52
@@ -3334,18 +3334,12 @@
3334 #
3335 # @snapshot-access: Since 7.0
3336 #
3337 -# Features:
3338 -#
3339 -# @deprecated: Member @gluster is deprecated because GlusterFS
3340 -# development ceased.
3341 -#
3337 # Since: 2.9
3338 ##
3339 { 'enum': 'BlockdevDriver',
3340 'data': [ 'blkdebug', 'blklogwrites', 'blkreplay', 'blkverify', 'bochs',
3341 'cloop', 'compress', 'copy-before-write', 'copy-on-read', 'dmg',
3342 'file', 'snapshot-access', 'ftp', 'ftps',
3348 - {'name': 'gluster', 'features': [ 'deprecated' ] },
3343 {'name': 'host_cdrom', 'if': 'HAVE_HOST_BLOCK_DEVICE' },
3344 {'name': 'host_device', 'if': 'HAVE_HOST_BLOCK_DEVICE' },
3345 'http', 'https',
@@ -4118,30 +4112,6 @@
4112 '*rewrite-corrupted': 'bool',
4113 '*read-pattern': 'QuorumReadPattern' } }
4114
4121 -##
4122 -# @BlockdevOptionsGluster:
4123 -#
4124 -# Driver specific block device options for Gluster
4125 -#
4126 -# @volume: name of gluster volume where VM image resides
4127 -#
4128 -# @path: absolute path to image file in gluster volume
4129 -#
4130 -# @server: gluster servers description
4131 -#
4132 -# @debug: libgfapi log level (default '4' which is Error) (Since 2.8)
4133 -#
4134 -# @logfile: libgfapi log file (default /dev/stderr) (Since 2.8)
4135 -#
4136 -# Since: 2.9
4137 -##
4138 -{ 'struct': 'BlockdevOptionsGluster',
4139 - 'data': { 'volume': 'str',
4140 - 'path': 'str',
4141 - 'server': ['SocketAddress'],
4142 - '*debug': 'int',
4143 - '*logfile': 'str' } }
4144 -
4115 ##
4116 # @BlockdevOptionsIoUring:
4117 #
@@ -4875,7 +4845,6 @@
4845 'file': 'BlockdevOptionsFile',
4846 'ftp': 'BlockdevOptionsCurlFtp',
4847 'ftps': 'BlockdevOptionsCurlFtps',
4878 - 'gluster': 'BlockdevOptionsGluster',
4848 'host_cdrom': { 'type': 'BlockdevOptionsFile',
4849 'if': 'HAVE_HOST_BLOCK_DEVICE' },
4850 'host_device': { 'type': 'BlockdevOptionsFile',
@@ -5146,26 +5115,6 @@
5115 '*nocow': 'bool',
5116 '*extent-size-hint': 'size'} }
5117
5149 -##
5150 -# @BlockdevCreateOptionsGluster:
5151 -#
5152 -# Driver specific image creation options for gluster.
5153 -#
5154 -# @location: Where to store the new image file
5155 -#
5156 -# @size: Size of the virtual disk in bytes
5157 -#
5158 -# @preallocation: Preallocation mode for the new image (default: off;
5159 -# allowed values: off, falloc (if CONFIG_GLUSTERFS_FALLOCATE),
5160 -# full (if CONFIG_GLUSTERFS_ZEROFILL))
5161 -#
5162 -# Since: 2.12
5163 -##
5164 -{ 'struct': 'BlockdevCreateOptionsGluster',
5165 - 'data': { 'location': 'BlockdevOptionsGluster',
5166 - 'size': 'size',
5167 - '*preallocation': 'PreallocMode' } }
5168 -
5118 ##
5119 # @BlockdevCreateOptionsLUKS:
5120 #
@@ -5593,7 +5542,6 @@
5542 'discriminator': 'driver',
5543 'data': {
5544 'file': 'BlockdevCreateOptionsFile',
5596 - 'gluster': 'BlockdevCreateOptionsGluster',
5545 'luks': 'BlockdevCreateOptionsLUKS',
5546 'nfs': 'BlockdevCreateOptionsNfs',
5547 'parallels': 'BlockdevCreateOptionsParallels',
scripts/ci/setup/debian/debian-13-ppc64le.yaml
-1
@@ -50,7 +50,6 @@ packages:
50 - libgbm-dev
51 - libgcrypt20-dev
52 - libglib2.0-dev
53 - - libglusterfs-dev
53 - libgnutls28-dev
54 - libgtk-3-dev
55 - libgtk-vnc-2.0-dev
scripts/ci/setup/ubuntu/ubuntu-2404-aarch64.yaml
-1
@@ -50,7 +50,6 @@ packages:
50 - libgbm-dev
51 - libgcrypt20-dev
52 - libglib2.0-dev
53 - - libglusterfs-dev
53 - libgnutls28-dev
54 - libgtk-3-dev
55 - libgtk-vnc-2.0-dev
scripts/ci/setup/ubuntu/ubuntu-2404-s390x.yaml
-1
@@ -50,7 +50,6 @@ packages:
50 - libgbm-dev
51 - libgcrypt20-dev
52 - libglib2.0-dev
53 - - libglusterfs-dev
53 - libgnutls28-dev
54 - libgtk-3-dev
55 - libgtk-vnc-2.0-dev
scripts/coverity-scan/coverity-scan.docker
-1
@@ -61,7 +61,6 @@ exec "$@"' > /usr/bin/nosync && \
61 glib2-static \
62 glibc-langpack-en \
63 glibc-static \
64 - glusterfs-api-devel \
64 gnutls-devel \
65 gtk3-devel \
66 hostname \
scripts/coverity-scan/run-coverity-scan
+1 -1
@@ -427,7 +427,7 @@ echo "Configuring..."
427 --enable-libiscsi --enable-seccomp \
428 --enable-tpm --enable-libssh --enable-lzo --enable-snappy --enable-bzip2 \
429 --enable-numa --enable-rdma --enable-smartcard --enable-virglrenderer \
430 - --enable-mpath --enable-glusterfs \
430 + --enable-mpath \
431 --enable-virtfs --enable-zstd
432
433 echo "Running cov-build..."
scripts/meson-buildoptions.sh
-3
@@ -121,7 +121,6 @@ meson_options_help() {
121 printf "%s\n" ' gcrypt libgcrypt cryptography support'
122 printf "%s\n" ' gettext Localization of the GTK+ user interface'
123 printf "%s\n" ' gio use libgio for D-Bus support'
124 - printf "%s\n" ' glusterfs Glusterfs block device driver'
124 printf "%s\n" ' gnutls GNUTLS cryptography support'
125 printf "%s\n" ' gtk GTK+ user interface'
126 printf "%s\n" ' guest-agent Build QEMU Guest Agent'
@@ -330,8 +329,6 @@ _meson_option_parse() {
329 --disable-gettext) printf "%s" -Dgettext=disabled ;;
330 --enable-gio) printf "%s" -Dgio=enabled ;;
331 --disable-gio) printf "%s" -Dgio=disabled ;;
333 - --enable-glusterfs) printf "%s" -Dglusterfs=enabled ;;
334 - --disable-glusterfs) printf "%s" -Dglusterfs=disabled ;;
332 --enable-gnutls) printf "%s" -Dgnutls=enabled ;;
333 --disable-gnutls) printf "%s" -Dgnutls=disabled ;;
334 --enable-gtk) printf "%s" -Dgtk=enabled ;;
tests/docker/dockerfiles/debian-amd64-cross.docker
-1
@@ -108,7 +108,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
108 libgbm-dev:amd64 \
109 libgcrypt20-dev:amd64 \
110 libglib2.0-dev:amd64 \
111 - libglusterfs-dev:amd64 \
111 libgnutls28-dev:amd64 \
112 libgtk-3-dev:amd64 \
113 libgtk-vnc-2.0-dev:amd64 \
tests/docker/dockerfiles/debian-arm64-cross.docker
-1
@@ -108,7 +108,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
108 libgbm-dev:arm64 \
109 libgcrypt20-dev:arm64 \
110 libglib2.0-dev:arm64 \
111 - libglusterfs-dev:arm64 \
111 libgnutls28-dev:arm64 \
112 libgtk-3-dev:arm64 \
113 libgtk-vnc-2.0-dev:arm64 \
tests/docker/dockerfiles/debian-mips64el-cross.docker
-1
@@ -106,7 +106,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
106 libgbm-dev:mips64el \
107 libgcrypt20-dev:mips64el \
108 libglib2.0-dev:mips64el \
109 - libglusterfs-dev:mips64el \
109 libgnutls28-dev:mips64el \
110 libgtk-3-dev:mips64el \
111 libgtk-vnc-2.0-dev:mips64el \
tests/docker/dockerfiles/debian-mipsel-cross.docker
-1
@@ -106,7 +106,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
106 libgbm-dev:mipsel \
107 libgcrypt20-dev:mipsel \
108 libglib2.0-dev:mipsel \
109 - libglusterfs-dev:mipsel \
109 libgnutls28-dev:mipsel \
110 libgtk-3-dev:mipsel \
111 libgtk-vnc-2.0-dev:mipsel \
tests/docker/dockerfiles/debian-ppc64el-cross.docker
-1
@@ -108,7 +108,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
108 libgbm-dev:ppc64el \
109 libgcrypt20-dev:ppc64el \
110 libglib2.0-dev:ppc64el \
111 - libglusterfs-dev:ppc64el \
111 libgnutls28-dev:ppc64el \
112 libgtk-3-dev:ppc64el \
113 libgtk-vnc-2.0-dev:ppc64el \
tests/docker/dockerfiles/debian-riscv64-cross.docker
-1
@@ -108,7 +108,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
108 libgbm-dev:riscv64 \
109 libgcrypt20-dev:riscv64 \
110 libglib2.0-dev:riscv64 \
111 - libglusterfs-dev:riscv64 \
111 libgnutls28-dev:riscv64 \
112 libgtk-3-dev:riscv64 \
113 libgtk-vnc-2.0-dev:riscv64 \
tests/docker/dockerfiles/debian-s390x-cross.docker
-1
@@ -108,7 +108,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
108 libgbm-dev:s390x \
109 libgcrypt20-dev:s390x \
110 libglib2.0-dev:s390x \
111 - libglusterfs-dev:s390x \
111 libgnutls28-dev:s390x \
112 libgtk-3-dev:s390x \
113 libgtk-vnc-2.0-dev:s390x \
tests/docker/dockerfiles/debian.docker
-1
@@ -56,7 +56,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
56 libgbm-dev \
57 libgcrypt20-dev \
58 libglib2.0-dev \
59 - libglusterfs-dev \
59 libgnutls28-dev \
60 libgtk-3-dev \
61 libgtk-vnc-2.0-dev \
tests/docker/dockerfiles/fedora-rust-nightly.docker
-1
@@ -50,7 +50,6 @@ exec "$@"\n' > /usr/bin/nosync && \
50 glib2-static \
51 glibc-langpack-en \
52 glibc-static \
53 - glusterfs-api-devel \
53 gnutls-devel \
54 gtk-vnc2-devel \
55 gtk3-devel \
tests/docker/dockerfiles/fedora.docker
-1
@@ -50,7 +50,6 @@ exec "$@"\n' > /usr/bin/nosync && \
50 glib2-static \
51 glibc-langpack-en \
52 glibc-static \
53 - glusterfs-api-devel \
53 gnutls-devel \
54 gtk-vnc2-devel \
55 gtk3-devel \
tests/docker/dockerfiles/opensuse-leap.docker
-1
@@ -34,7 +34,6 @@ RUN zypper update -y && \
34 glib2-devel \
35 glibc-locale \
36 glibc-static \
37 - glusterfs-devel \
37 gtk-vnc-devel \
38 gtk3-devel \
39 hostname \
tests/docker/dockerfiles/ubuntu2204.docker
-1
@@ -55,7 +55,6 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
55 libgbm-dev \
56 libgcrypt20-dev \
57 libglib2.0-dev \
58 - libglusterfs-dev \
58 libgnutls28-dev \
59 libgtk-3-dev \
60 libgtk-vnc-2.0-dev \
tests/lcitool/projects/qemu.yml
-1
@@ -31,7 +31,6 @@ packages:
31 - glib2
32 - glib2-native
33 - glib2-static
34 - - glusterfs
34 - gnutls
35 - gtk3
36 - gtk-vnc
tests/qtest/modules-test.c
-3
@@ -22,9 +22,6 @@ int main(int argc, char *argv[])
22 #ifdef CONFIG_CURL
23 "block-", "curl",
24 #endif
25 -#ifdef CONFIG_GLUSTERFS
26 - "block-", "gluster",
27 -#endif
25 #ifdef CONFIG_LIBISCSI
26 "block-", "iscsi",
27 #endif