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