2 * QEMU Block driver for Archipelago
4 * Copyright (C) 2014 Chrysostomos Nanakos <cnanakos@grnet.gr>
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.
12 * VM Image on Archipelago volume is specified like this:
14 * file.driver=archipelago,file.volume=<volumename>
15 * [,file.mport=<mapperd_port>[,file.vport=<vlmcd_port>]
16 * [,file.segment=<segment_name>]]
20 * file=archipelago:<volumename>[/mport=<mapperd_port>[:vport=<vlmcd_port>][:
21 * segment=<segment_name>]]
23 * 'archipelago' is the protocol.
25 * 'mport' is the port number on which mapperd is listening. This is optional
26 * and if not specified, QEMU will make Archipelago to use the default port.
28 * 'vport' is the port number on which vlmcd is listening. This is optional
29 * and if not specified, QEMU will make Archipelago to use the default port.
31 * 'segment' is the name of the shared memory segment Archipelago stack
32 * is using. This is optional and if not specified, QEMU will make Archipelago
33 * to use the default value, 'archipelago'.
37 * file.driver=archipelago,file.volume=my_vm_volume
38 * file.driver=archipelago,file.volume=my_vm_volume,file.mport=123
39 * file.driver=archipelago,file.volume=my_vm_volume,file.mport=123,
41 * file.driver=archipelago,file.volume=my_vm_volume,file.mport=123,
42 * file.vport=1234,file.segment=my_segment
46 * file=archipelago:my_vm_volume
47 * file=archipelago:my_vm_volume/mport=123
48 * file=archipelago:my_vm_volume/mport=123:vport=1234
49 * file=archipelago:my_vm_volume/mport=123:vport=1234:segment=my_segment
53 #include "qemu-common.h"
54 #include "block/block_int.h"
55 #include "qemu/error-report.h"
56 #include "qemu/thread.h"
57 #include "qapi/qmp/qint.h"
58 #include "qapi/qmp/qstring.h"
59 #include "qapi/qmp/qjson.h"
60 #include "qemu/atomic.h"
63 #include <xseg/xseg.h>
64 #include <xseg/protocol.h>
66 #define MAX_REQUEST_SIZE 524288
68 #define ARCHIPELAGO_OPT_VOLUME "volume"
69 #define ARCHIPELAGO_OPT_SEGMENT "segment"
70 #define ARCHIPELAGO_OPT_MPORT "mport"
71 #define ARCHIPELAGO_OPT_VPORT "vport"
72 #define ARCHIPELAGO_DFL_MPORT 1001
73 #define ARCHIPELAGO_DFL_VPORT 501
75 #define archipelagolog(fmt, ...) \
77 fprintf(stderr, "archipelago\t%-24s: " fmt, __func__, ##__VA_ARGS__); \
88 typedef struct ArchipelagoAIOCB
{
89 BlockDriverAIOCB common
;
91 struct BDRVArchipelagoState
*s
;
100 typedef struct BDRVArchipelagoState
{
101 ArchipelagoAIOCB
*event_acb
;
105 /* Archipelago specific */
107 struct xseg_port
*port
;
112 QemuMutex archip_mutex
;
113 QemuCond archip_cond
;
115 /* Request handler specific */
116 QemuThread request_th
;
117 QemuCond request_cond
;
118 QemuMutex request_mutex
;
121 } BDRVArchipelagoState
;
123 typedef struct ArchipelagoSegmentedRequest
{
128 } ArchipelagoSegmentedRequest
;
130 typedef struct AIORequestData
{
137 ArchipelagoAIOCB
*aio_cb
;
138 ArchipelagoSegmentedRequest
*segreq
;
141 static void qemu_archipelago_complete_aio(void *opaque
);
143 static void init_local_signal(struct xseg
*xseg
, xport sport
, xport srcport
)
145 if (xseg
&& (sport
!= srcport
)) {
146 xseg_init_local_signal(xseg
, srcport
);
151 static void archipelago_finish_aiocb(AIORequestData
*reqdata
)
153 if (reqdata
->aio_cb
->ret
!= reqdata
->segreq
->total
) {
154 reqdata
->aio_cb
->ret
= -EIO
;
155 } else if (reqdata
->aio_cb
->ret
== reqdata
->segreq
->total
) {
156 reqdata
->aio_cb
->ret
= 0;
158 reqdata
->aio_cb
->bh
= aio_bh_new(
159 bdrv_get_aio_context(reqdata
->aio_cb
->common
.bs
),
160 qemu_archipelago_complete_aio
, reqdata
162 qemu_bh_schedule(reqdata
->aio_cb
->bh
);
165 static int wait_reply(struct xseg
*xseg
, xport srcport
, struct xseg_port
*port
,
166 struct xseg_request
*expected_req
)
168 struct xseg_request
*req
;
169 xseg_prepare_wait(xseg
, srcport
);
170 void *psd
= xseg_get_signal_desc(xseg
, port
);
172 req
= xseg_receive(xseg
, srcport
, X_NONBLOCK
);
174 if (req
!= expected_req
) {
175 archipelagolog("Unknown received request\n");
176 xseg_put_request(xseg
, req
, srcport
);
177 } else if (!(req
->state
& XS_SERVED
)) {
183 xseg_wait_signal(xseg
, psd
, 100000UL);
185 xseg_cancel_wait(xseg
, srcport
);
189 static void xseg_request_handler(void *state
)
191 BDRVArchipelagoState
*s
= (BDRVArchipelagoState
*) state
;
192 void *psd
= xseg_get_signal_desc(s
->xseg
, s
->port
);
193 qemu_mutex_lock(&s
->request_mutex
);
195 while (!s
->stopping
) {
196 struct xseg_request
*req
;
198 xseg_prepare_wait(s
->xseg
, s
->srcport
);
199 req
= xseg_receive(s
->xseg
, s
->srcport
, X_NONBLOCK
);
201 AIORequestData
*reqdata
;
202 ArchipelagoSegmentedRequest
*segreq
;
203 xseg_get_req_data(s
->xseg
, req
, (void **)&reqdata
);
205 switch (reqdata
->op
) {
207 data
= xseg_get_data(s
->xseg
, req
);
208 segreq
= reqdata
->segreq
;
209 segreq
->count
+= req
->serviced
;
211 qemu_iovec_from_buf(reqdata
->aio_cb
->qiov
, reqdata
->bufidx
,
215 xseg_put_request(s
->xseg
, req
, s
->srcport
);
217 if (atomic_fetch_dec(&segreq
->ref
) == 1) {
218 if (!segreq
->failed
) {
219 reqdata
->aio_cb
->ret
= segreq
->count
;
220 archipelago_finish_aiocb(reqdata
);
230 case ARCHIP_OP_WRITE
:
231 case ARCHIP_OP_FLUSH
:
232 segreq
= reqdata
->segreq
;
233 segreq
->count
+= req
->serviced
;
234 xseg_put_request(s
->xseg
, req
, s
->srcport
);
236 if (atomic_fetch_dec(&segreq
->ref
) == 1) {
237 if (!segreq
->failed
) {
238 reqdata
->aio_cb
->ret
= segreq
->count
;
239 archipelago_finish_aiocb(reqdata
);
249 case ARCHIP_OP_VOLINFO
:
250 case ARCHIP_OP_TRUNCATE
:
251 s
->is_signaled
= true;
252 qemu_cond_signal(&s
->archip_cond
);
256 xseg_wait_signal(s
->xseg
, psd
, 100000UL);
258 xseg_cancel_wait(s
->xseg
, s
->srcport
);
261 s
->th_is_signaled
= true;
262 qemu_cond_signal(&s
->request_cond
);
263 qemu_mutex_unlock(&s
->request_mutex
);
264 qemu_thread_exit(NULL
);
267 static int qemu_archipelago_xseg_init(BDRVArchipelagoState
*s
)
269 if (xseg_initialize()) {
270 archipelagolog("Cannot initialize XSEG\n");
274 s
->xseg
= xseg_join("posix", s
->segment_name
,
277 archipelagolog("Cannot join XSEG shared memory segment\n");
280 s
->port
= xseg_bind_dynport(s
->xseg
);
281 s
->srcport
= s
->port
->portno
;
282 init_local_signal(s
->xseg
, s
->sport
, s
->srcport
);
289 static int qemu_archipelago_init(BDRVArchipelagoState
*s
)
293 ret
= qemu_archipelago_xseg_init(s
);
295 error_report("Cannot initialize XSEG. Aborting...\n");
299 qemu_cond_init(&s
->archip_cond
);
300 qemu_mutex_init(&s
->archip_mutex
);
301 qemu_cond_init(&s
->request_cond
);
302 qemu_mutex_init(&s
->request_mutex
);
303 s
->th_is_signaled
= false;
304 qemu_thread_create(&s
->request_th
, "xseg_io_th",
305 (void *) xseg_request_handler
,
306 (void *) s
, QEMU_THREAD_JOINABLE
);
312 static void qemu_archipelago_complete_aio(void *opaque
)
314 AIORequestData
*reqdata
= (AIORequestData
*) opaque
;
315 ArchipelagoAIOCB
*aio_cb
= (ArchipelagoAIOCB
*) reqdata
->aio_cb
;
317 qemu_bh_delete(aio_cb
->bh
);
318 aio_cb
->common
.cb(aio_cb
->common
.opaque
, aio_cb
->ret
);
321 if (!aio_cb
->cancelled
) {
322 qemu_aio_release(aio_cb
);
327 static void xseg_find_port(char *pstr
, const char *needle
, xport
*aport
)
332 if (strstart(pstr
, needle
, &a
)) {
334 port
= strtoul(a
, &endptr
, 10);
335 if (strlen(endptr
)) {
339 *aport
= (xport
) port
;
344 static void xseg_find_segment(char *pstr
, const char *needle
,
348 if (strstart(pstr
, needle
, &a
)) {
350 *segment_name
= g_strdup(a
);
355 static void parse_filename_opts(const char *filename
, Error
**errp
,
356 char **volume
, char **segment_name
,
357 xport
*mport
, xport
*vport
)
360 char *tokens
[4], *ds
;
362 xport lmport
= NoPort
, lvport
= NoPort
;
364 strstart(filename
, "archipelago:", &start
);
366 ds
= g_strdup(start
);
367 tokens
[0] = strtok(ds
, "/");
368 tokens
[1] = strtok(NULL
, ":");
369 tokens
[2] = strtok(NULL
, ":");
370 tokens
[3] = strtok(NULL
, "\0");
372 if (!strlen(tokens
[0])) {
373 error_setg(errp
, "volume name must be specified first");
378 for (idx
= 1; idx
< 4; idx
++) {
379 if (tokens
[idx
] != NULL
) {
380 if (strstart(tokens
[idx
], "mport=", NULL
)) {
381 xseg_find_port(tokens
[idx
], "mport=", &lmport
);
383 if (strstart(tokens
[idx
], "vport=", NULL
)) {
384 xseg_find_port(tokens
[idx
], "vport=", &lvport
);
386 if (strstart(tokens
[idx
], "segment=", NULL
)) {
387 xseg_find_segment(tokens
[idx
], "segment=", segment_name
);
392 if ((lmport
== -2) || (lvport
== -2)) {
393 error_setg(errp
, "mport and/or vport must be set");
397 *volume
= g_strdup(tokens
[0]);
403 static void archipelago_parse_filename(const char *filename
, QDict
*options
,
407 char *volume
= NULL
, *segment_name
= NULL
;
408 xport mport
= NoPort
, vport
= NoPort
;
410 if (qdict_haskey(options
, ARCHIPELAGO_OPT_VOLUME
)
411 || qdict_haskey(options
, ARCHIPELAGO_OPT_SEGMENT
)
412 || qdict_haskey(options
, ARCHIPELAGO_OPT_MPORT
)
413 || qdict_haskey(options
, ARCHIPELAGO_OPT_VPORT
)) {
414 error_setg(errp
, "volume/mport/vport/segment and a file name may not"
415 " be specified at the same time");
419 if (!strstart(filename
, "archipelago:", &start
)) {
420 error_setg(errp
, "File name must start with 'archipelago:'");
424 if (!strlen(start
) || strstart(start
, "/", NULL
)) {
425 error_setg(errp
, "volume name must be specified");
429 parse_filename_opts(filename
, errp
, &volume
, &segment_name
, &mport
, &vport
);
432 qdict_put(options
, ARCHIPELAGO_OPT_VOLUME
, qstring_from_str(volume
));
436 qdict_put(options
, ARCHIPELAGO_OPT_SEGMENT
,
437 qstring_from_str(segment_name
));
438 g_free(segment_name
);
440 if (mport
!= NoPort
) {
441 qdict_put(options
, ARCHIPELAGO_OPT_MPORT
, qint_from_int(mport
));
443 if (vport
!= NoPort
) {
444 qdict_put(options
, ARCHIPELAGO_OPT_VPORT
, qint_from_int(vport
));
448 static QemuOptsList archipelago_runtime_opts
= {
449 .name
= "archipelago",
450 .head
= QTAILQ_HEAD_INITIALIZER(archipelago_runtime_opts
.head
),
453 .name
= ARCHIPELAGO_OPT_VOLUME
,
454 .type
= QEMU_OPT_STRING
,
455 .help
= "Name of the volume image",
458 .name
= ARCHIPELAGO_OPT_SEGMENT
,
459 .type
= QEMU_OPT_STRING
,
460 .help
= "Name of the Archipelago shared memory segment",
463 .name
= ARCHIPELAGO_OPT_MPORT
,
464 .type
= QEMU_OPT_NUMBER
,
465 .help
= "Archipelago mapperd port number"
468 .name
= ARCHIPELAGO_OPT_VPORT
,
469 .type
= QEMU_OPT_NUMBER
,
470 .help
= "Archipelago vlmcd port number"
473 { /* end of list */ }
477 static int qemu_archipelago_open(BlockDriverState
*bs
,
483 const char *volume
, *segment_name
;
485 Error
*local_err
= NULL
;
486 BDRVArchipelagoState
*s
= bs
->opaque
;
488 opts
= qemu_opts_create(&archipelago_runtime_opts
, NULL
, 0, &error_abort
);
489 qemu_opts_absorb_qdict(opts
, options
, &local_err
);
491 error_propagate(errp
, local_err
);
496 s
->mportno
= qemu_opt_get_number(opts
, ARCHIPELAGO_OPT_MPORT
,
497 ARCHIPELAGO_DFL_MPORT
);
498 s
->vportno
= qemu_opt_get_number(opts
, ARCHIPELAGO_OPT_VPORT
,
499 ARCHIPELAGO_DFL_VPORT
);
501 segment_name
= qemu_opt_get(opts
, ARCHIPELAGO_OPT_SEGMENT
);
502 if (segment_name
== NULL
) {
503 s
->segment_name
= g_strdup("archipelago");
505 s
->segment_name
= g_strdup(segment_name
);
508 volume
= qemu_opt_get(opts
, ARCHIPELAGO_OPT_VOLUME
);
509 if (volume
== NULL
) {
510 error_setg(errp
, "archipelago block driver requires the 'volume'"
515 s
->volname
= g_strdup(volume
);
517 /* Initialize XSEG, join shared memory segment */
518 ret
= qemu_archipelago_init(s
);
520 error_setg(errp
, "cannot initialize XSEG and join shared "
530 g_free(s
->segment_name
);
535 static void qemu_archipelago_close(BlockDriverState
*bs
)
539 struct xseg_request
*req
;
540 BDRVArchipelagoState
*s
= bs
->opaque
;
544 qemu_mutex_lock(&s
->request_mutex
);
545 while (!s
->th_is_signaled
) {
546 qemu_cond_wait(&s
->request_cond
,
549 qemu_mutex_unlock(&s
->request_mutex
);
550 qemu_thread_join(&s
->request_th
);
551 qemu_cond_destroy(&s
->request_cond
);
552 qemu_mutex_destroy(&s
->request_mutex
);
554 qemu_cond_destroy(&s
->archip_cond
);
555 qemu_mutex_destroy(&s
->archip_mutex
);
557 targetlen
= strlen(s
->volname
);
558 req
= xseg_get_request(s
->xseg
, s
->srcport
, s
->vportno
, X_ALLOC
);
560 archipelagolog("Cannot get XSEG request\n");
563 r
= xseg_prep_request(s
->xseg
, req
, targetlen
, 0);
565 xseg_put_request(s
->xseg
, req
, s
->srcport
);
566 archipelagolog("Cannot prepare XSEG close request\n");
570 target
= xseg_get_target(s
->xseg
, req
);
571 memcpy(target
, s
->volname
, targetlen
);
572 req
->size
= req
->datalen
;
576 xport p
= xseg_submit(s
->xseg
, req
, s
->srcport
, X_ALLOC
);
578 xseg_put_request(s
->xseg
, req
, s
->srcport
);
579 archipelagolog("Cannot submit XSEG close request\n");
583 xseg_signal(s
->xseg
, p
);
584 wait_reply(s
->xseg
, s
->srcport
, s
->port
, req
);
586 xseg_put_request(s
->xseg
, req
, s
->srcport
);
590 g_free(s
->segment_name
);
591 xseg_quit_local_signal(s
->xseg
, s
->srcport
);
592 xseg_leave_dynport(s
->xseg
, s
->port
);
596 static int qemu_archipelago_create_volume(Error
**errp
, const char *volname
,
598 uint64_t size
, xport mportno
,
602 struct xseg
*xseg
= NULL
;
603 struct xseg_request
*req
;
604 struct xseg_request_clone
*xclone
;
605 struct xseg_port
*port
;
606 xport srcport
= NoPort
, sport
= NoPort
;
609 /* Try default values if none has been set */
610 if (mportno
== (xport
) -1) {
611 mportno
= ARCHIPELAGO_DFL_MPORT
;
614 if (vportno
== (xport
) -1) {
615 vportno
= ARCHIPELAGO_DFL_VPORT
;
618 if (xseg_initialize()) {
619 error_setg(errp
, "Cannot initialize XSEG");
623 xseg
= xseg_join("posix", segment_name
,
627 error_setg(errp
, "Cannot join XSEG shared memory segment");
631 port
= xseg_bind_dynport(xseg
);
632 srcport
= port
->portno
;
633 init_local_signal(xseg
, sport
, srcport
);
635 req
= xseg_get_request(xseg
, srcport
, mportno
, X_ALLOC
);
637 error_setg(errp
, "Cannot get XSEG request");
641 targetlen
= strlen(volname
);
642 ret
= xseg_prep_request(xseg
, req
, targetlen
,
643 sizeof(struct xseg_request_clone
));
645 error_setg(errp
, "Cannot prepare XSEG request");
649 target
= xseg_get_target(xseg
, req
);
651 error_setg(errp
, "Cannot get XSEG target.\n");
654 memcpy(target
, volname
, targetlen
);
655 xclone
= (struct xseg_request_clone
*) xseg_get_data(xseg
, req
);
656 memset(xclone
->target
, 0 , XSEG_MAX_TARGETLEN
);
657 xclone
->targetlen
= 0;
660 req
->size
= req
->datalen
;
663 xport p
= xseg_submit(xseg
, req
, srcport
, X_ALLOC
);
665 error_setg(errp
, "Could not submit XSEG request");
668 xseg_signal(xseg
, p
);
670 ret
= wait_reply(xseg
, srcport
, port
, req
);
672 error_setg(errp
, "wait_reply() error.");
675 xseg_put_request(xseg
, req
, srcport
);
676 xseg_quit_local_signal(xseg
, srcport
);
677 xseg_leave_dynport(xseg
, port
);
682 xseg_put_request(xseg
, req
, srcport
);
683 xseg_quit_local_signal(xseg
, srcport
);
684 xseg_leave_dynport(xseg
, port
);
689 static int qemu_archipelago_create(const char *filename
,
694 uint64_t total_size
= 0;
695 char *volname
= NULL
, *segment_name
= NULL
;
697 xport mport
= NoPort
, vport
= NoPort
;
699 if (!strstart(filename
, "archipelago:", &start
)) {
700 error_setg(errp
, "File name must start with 'archipelago:'");
704 if (!strlen(start
) || strstart(start
, "/", NULL
)) {
705 error_setg(errp
, "volume name must be specified");
709 parse_filename_opts(filename
, errp
, &volname
, &segment_name
, &mport
,
711 total_size
= ROUND_UP(qemu_opt_get_size_del(options
, BLOCK_OPT_SIZE
, 0),
714 if (segment_name
== NULL
) {
715 segment_name
= g_strdup("archipelago");
718 /* Create an Archipelago volume */
719 ret
= qemu_archipelago_create_volume(errp
, volname
, segment_name
,
724 g_free(segment_name
);
728 static void qemu_archipelago_aio_cancel(BlockDriverAIOCB
*blockacb
)
730 ArchipelagoAIOCB
*aio_cb
= (ArchipelagoAIOCB
*) blockacb
;
731 aio_cb
->cancelled
= true;
732 while (aio_cb
->status
== -EINPROGRESS
) {
733 aio_poll(bdrv_get_aio_context(aio_cb
->common
.bs
), true);
735 qemu_aio_release(aio_cb
);
738 static const AIOCBInfo archipelago_aiocb_info
= {
739 .aiocb_size
= sizeof(ArchipelagoAIOCB
),
740 .cancel
= qemu_archipelago_aio_cancel
,
743 static int archipelago_submit_request(BDRVArchipelagoState
*s
,
747 ArchipelagoAIOCB
*aio_cb
,
748 ArchipelagoSegmentedRequest
*segreq
,
754 struct xseg_request
*req
;
755 AIORequestData
*reqdata
= g_new(AIORequestData
, 1);
757 targetlen
= strlen(s
->volname
);
758 req
= xseg_get_request(s
->xseg
, s
->srcport
, s
->vportno
, X_ALLOC
);
760 archipelagolog("Cannot get XSEG request\n");
763 ret
= xseg_prep_request(s
->xseg
, req
, targetlen
, count
);
765 archipelagolog("Cannot prepare XSEG request\n");
768 target
= xseg_get_target(s
->xseg
, req
);
770 archipelagolog("Cannot get XSEG target\n");
773 memcpy(target
, s
->volname
, targetlen
);
775 req
->offset
= offset
;
781 case ARCHIP_OP_WRITE
:
784 case ARCHIP_OP_FLUSH
:
788 reqdata
->volname
= s
->volname
;
789 reqdata
->offset
= offset
;
790 reqdata
->size
= count
;
791 reqdata
->bufidx
= bufidx
;
792 reqdata
->aio_cb
= aio_cb
;
793 reqdata
->segreq
= segreq
;
796 xseg_set_req_data(s
->xseg
, req
, reqdata
);
797 if (op
== ARCHIP_OP_WRITE
) {
798 data
= xseg_get_data(s
->xseg
, req
);
800 archipelagolog("Cannot get XSEG data\n");
803 qemu_iovec_to_buf(aio_cb
->qiov
, bufidx
, data
, count
);
806 xport p
= xseg_submit(s
->xseg
, req
, s
->srcport
, X_ALLOC
);
808 archipelagolog("Could not submit XSEG request\n");
811 xseg_signal(s
->xseg
, p
);
816 xseg_put_request(s
->xseg
, req
, s
->srcport
);
823 static int archipelago_aio_segmented_rw(BDRVArchipelagoState
*s
,
826 ArchipelagoAIOCB
*aio_cb
,
829 int ret
, segments_nr
;
831 ArchipelagoSegmentedRequest
*segreq
;
833 segreq
= g_new0(ArchipelagoSegmentedRequest
, 1);
835 if (op
== ARCHIP_OP_FLUSH
) {
838 segments_nr
= (int)(count
/ MAX_REQUEST_SIZE
) + \
839 ((count
% MAX_REQUEST_SIZE
) ? 1 : 0);
841 segreq
->total
= count
;
842 atomic_mb_set(&segreq
->ref
, segments_nr
);
844 while (segments_nr
> 1) {
845 ret
= archipelago_submit_request(s
, pos
,
853 count
-= MAX_REQUEST_SIZE
;
854 pos
+= MAX_REQUEST_SIZE
;
857 ret
= archipelago_submit_request(s
, pos
, count
, offset
+ pos
,
867 if (atomic_fetch_sub(&segreq
->ref
, segments_nr
) == segments_nr
) {
873 static BlockDriverAIOCB
*qemu_archipelago_aio_rw(BlockDriverState
*bs
,
877 BlockDriverCompletionFunc
*cb
,
881 ArchipelagoAIOCB
*aio_cb
;
882 BDRVArchipelagoState
*s
= bs
->opaque
;
886 aio_cb
= qemu_aio_get(&archipelago_aiocb_info
, bs
, cb
, opaque
);
892 aio_cb
->cancelled
= false;
893 aio_cb
->status
= -EINPROGRESS
;
895 off
= sector_num
* BDRV_SECTOR_SIZE
;
896 size
= nb_sectors
* BDRV_SECTOR_SIZE
;
899 ret
= archipelago_aio_segmented_rw(s
, size
, off
,
904 return &aio_cb
->common
;
907 error_report("qemu_archipelago_aio_rw(): I/O Error\n");
908 qemu_aio_release(aio_cb
);
912 static BlockDriverAIOCB
*qemu_archipelago_aio_readv(BlockDriverState
*bs
,
913 int64_t sector_num
, QEMUIOVector
*qiov
, int nb_sectors
,
914 BlockDriverCompletionFunc
*cb
, void *opaque
)
916 return qemu_archipelago_aio_rw(bs
, sector_num
, qiov
, nb_sectors
, cb
,
917 opaque
, ARCHIP_OP_READ
);
920 static BlockDriverAIOCB
*qemu_archipelago_aio_writev(BlockDriverState
*bs
,
921 int64_t sector_num
, QEMUIOVector
*qiov
, int nb_sectors
,
922 BlockDriverCompletionFunc
*cb
, void *opaque
)
924 return qemu_archipelago_aio_rw(bs
, sector_num
, qiov
, nb_sectors
, cb
,
925 opaque
, ARCHIP_OP_WRITE
);
928 static int64_t archipelago_volume_info(BDRVArchipelagoState
*s
)
932 struct xseg_request
*req
;
933 struct xseg_reply_info
*xinfo
;
934 AIORequestData
*reqdata
= g_new(AIORequestData
, 1);
936 const char *volname
= s
->volname
;
937 targetlen
= strlen(volname
);
938 req
= xseg_get_request(s
->xseg
, s
->srcport
, s
->mportno
, X_ALLOC
);
940 archipelagolog("Cannot get XSEG request\n");
943 ret
= xseg_prep_request(s
->xseg
, req
, targetlen
,
944 sizeof(struct xseg_reply_info
));
946 archipelagolog("Cannot prepare XSEG request\n");
949 char *target
= xseg_get_target(s
->xseg
, req
);
951 archipelagolog("Cannot get XSEG target\n");
954 memcpy(target
, volname
, targetlen
);
955 req
->size
= req
->datalen
;
959 reqdata
->op
= ARCHIP_OP_VOLINFO
;
960 reqdata
->volname
= volname
;
961 xseg_set_req_data(s
->xseg
, req
, reqdata
);
963 xport p
= xseg_submit(s
->xseg
, req
, s
->srcport
, X_ALLOC
);
965 archipelagolog("Cannot submit XSEG request\n");
968 xseg_signal(s
->xseg
, p
);
969 qemu_mutex_lock(&s
->archip_mutex
);
970 while (!s
->is_signaled
) {
971 qemu_cond_wait(&s
->archip_cond
, &s
->archip_mutex
);
973 s
->is_signaled
= false;
974 qemu_mutex_unlock(&s
->archip_mutex
);
976 xinfo
= (struct xseg_reply_info
*) xseg_get_data(s
->xseg
, req
);
978 xseg_put_request(s
->xseg
, req
, s
->srcport
);
984 xseg_put_request(s
->xseg
, req
, s
->srcport
);
990 static int64_t qemu_archipelago_getlength(BlockDriverState
*bs
)
993 BDRVArchipelagoState
*s
= bs
->opaque
;
995 ret
= archipelago_volume_info(s
);
999 static int qemu_archipelago_truncate(BlockDriverState
*bs
, int64_t offset
)
1002 struct xseg_request
*req
;
1003 BDRVArchipelagoState
*s
= bs
->opaque
;
1004 AIORequestData
*reqdata
= g_new(AIORequestData
, 1);
1006 const char *volname
= s
->volname
;
1007 targetlen
= strlen(volname
);
1008 req
= xseg_get_request(s
->xseg
, s
->srcport
, s
->mportno
, X_ALLOC
);
1010 archipelagolog("Cannot get XSEG request\n");
1014 ret
= xseg_prep_request(s
->xseg
, req
, targetlen
, 0);
1016 archipelagolog("Cannot prepare XSEG request\n");
1019 char *target
= xseg_get_target(s
->xseg
, req
);
1021 archipelagolog("Cannot get XSEG target\n");
1024 memcpy(target
, volname
, targetlen
);
1025 req
->offset
= offset
;
1026 req
->op
= X_TRUNCATE
;
1028 reqdata
->op
= ARCHIP_OP_TRUNCATE
;
1029 reqdata
->volname
= volname
;
1031 xseg_set_req_data(s
->xseg
, req
, reqdata
);
1033 xport p
= xseg_submit(s
->xseg
, req
, s
->srcport
, X_ALLOC
);
1035 archipelagolog("Cannot submit XSEG request\n");
1039 xseg_signal(s
->xseg
, p
);
1040 qemu_mutex_lock(&s
->archip_mutex
);
1041 while (!s
->is_signaled
) {
1042 qemu_cond_wait(&s
->archip_cond
, &s
->archip_mutex
);
1044 s
->is_signaled
= false;
1045 qemu_mutex_unlock(&s
->archip_mutex
);
1046 xseg_put_request(s
->xseg
, req
, s
->srcport
);
1051 xseg_put_request(s
->xseg
, req
, s
->srcport
);
1057 static QemuOptsList qemu_archipelago_create_opts
= {
1058 .name
= "archipelago-create-opts",
1059 .head
= QTAILQ_HEAD_INITIALIZER(qemu_archipelago_create_opts
.head
),
1062 .name
= BLOCK_OPT_SIZE
,
1063 .type
= QEMU_OPT_SIZE
,
1064 .help
= "Virtual disk size"
1066 { /* end of list */ }
1070 static BlockDriverAIOCB
*qemu_archipelago_aio_flush(BlockDriverState
*bs
,
1071 BlockDriverCompletionFunc
*cb
, void *opaque
)
1073 return qemu_archipelago_aio_rw(bs
, 0, NULL
, 0, cb
, opaque
,
1077 static BlockDriver bdrv_archipelago
= {
1078 .format_name
= "archipelago",
1079 .protocol_name
= "archipelago",
1080 .instance_size
= sizeof(BDRVArchipelagoState
),
1081 .bdrv_parse_filename
= archipelago_parse_filename
,
1082 .bdrv_file_open
= qemu_archipelago_open
,
1083 .bdrv_close
= qemu_archipelago_close
,
1084 .bdrv_create
= qemu_archipelago_create
,
1085 .bdrv_getlength
= qemu_archipelago_getlength
,
1086 .bdrv_truncate
= qemu_archipelago_truncate
,
1087 .bdrv_aio_readv
= qemu_archipelago_aio_readv
,
1088 .bdrv_aio_writev
= qemu_archipelago_aio_writev
,
1089 .bdrv_aio_flush
= qemu_archipelago_aio_flush
,
1090 .bdrv_has_zero_init
= bdrv_has_zero_init_1
,
1091 .create_opts
= &qemu_archipelago_create_opts
,
1094 static void bdrv_archipelago_init(void)
1096 bdrv_register(&bdrv_archipelago
);
1099 block_init(bdrv_archipelago_init
);