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 ARCHIP_FD_READ 0
67 #define ARCHIP_FD_WRITE 1
68 #define MAX_REQUEST_SIZE 524288
70 #define ARCHIPELAGO_OPT_VOLUME "volume"
71 #define ARCHIPELAGO_OPT_SEGMENT "segment"
72 #define ARCHIPELAGO_OPT_MPORT "mport"
73 #define ARCHIPELAGO_OPT_VPORT "vport"
74 #define ARCHIPELAGO_DFL_MPORT 1001
75 #define ARCHIPELAGO_DFL_VPORT 501
77 #define archipelagolog(fmt, ...) \
79 fprintf(stderr, "archipelago\t%-24s: " fmt, __func__, ##__VA_ARGS__); \
89 typedef struct ArchipelagoAIOCB
{
90 BlockDriverAIOCB common
;
92 struct BDRVArchipelagoState
*s
;
101 typedef struct BDRVArchipelagoState
{
102 ArchipelagoAIOCB
*event_acb
;
106 /* Archipelago specific */
108 struct xseg_port
*port
;
113 QemuMutex archip_mutex
;
114 QemuCond archip_cond
;
116 /* Request handler specific */
117 QemuThread request_th
;
118 QemuCond request_cond
;
119 QemuMutex request_mutex
;
122 } BDRVArchipelagoState
;
124 typedef struct ArchipelagoSegmentedRequest
{
129 } ArchipelagoSegmentedRequest
;
131 typedef struct AIORequestData
{
138 ArchipelagoAIOCB
*aio_cb
;
139 ArchipelagoSegmentedRequest
*segreq
;
142 static void qemu_archipelago_complete_aio(void *opaque
);
144 static void init_local_signal(struct xseg
*xseg
, xport sport
, xport srcport
)
146 if (xseg
&& (sport
!= srcport
)) {
147 xseg_init_local_signal(xseg
, srcport
);
152 static void archipelago_finish_aiocb(AIORequestData
*reqdata
)
154 if (reqdata
->aio_cb
->ret
!= reqdata
->segreq
->total
) {
155 reqdata
->aio_cb
->ret
= -EIO
;
156 } else if (reqdata
->aio_cb
->ret
== reqdata
->segreq
->total
) {
157 reqdata
->aio_cb
->ret
= 0;
159 reqdata
->aio_cb
->bh
= aio_bh_new(
160 bdrv_get_aio_context(reqdata
->aio_cb
->common
.bs
),
161 qemu_archipelago_complete_aio
, reqdata
163 qemu_bh_schedule(reqdata
->aio_cb
->bh
);
166 static int wait_reply(struct xseg
*xseg
, xport srcport
, struct xseg_port
*port
,
167 struct xseg_request
*expected_req
)
169 struct xseg_request
*req
;
170 xseg_prepare_wait(xseg
, srcport
);
171 void *psd
= xseg_get_signal_desc(xseg
, port
);
173 req
= xseg_receive(xseg
, srcport
, X_NONBLOCK
);
175 if (req
!= expected_req
) {
176 archipelagolog("Unknown received request\n");
177 xseg_put_request(xseg
, req
, srcport
);
178 } else if (!(req
->state
& XS_SERVED
)) {
184 xseg_wait_signal(xseg
, psd
, 100000UL);
186 xseg_cancel_wait(xseg
, srcport
);
190 static void xseg_request_handler(void *state
)
192 BDRVArchipelagoState
*s
= (BDRVArchipelagoState
*) state
;
193 void *psd
= xseg_get_signal_desc(s
->xseg
, s
->port
);
194 qemu_mutex_lock(&s
->request_mutex
);
196 while (!s
->stopping
) {
197 struct xseg_request
*req
;
199 xseg_prepare_wait(s
->xseg
, s
->srcport
);
200 req
= xseg_receive(s
->xseg
, s
->srcport
, X_NONBLOCK
);
202 AIORequestData
*reqdata
;
203 ArchipelagoSegmentedRequest
*segreq
;
204 xseg_get_req_data(s
->xseg
, req
, (void **)&reqdata
);
206 switch (reqdata
->op
) {
208 data
= xseg_get_data(s
->xseg
, req
);
209 segreq
= reqdata
->segreq
;
210 segreq
->count
+= req
->serviced
;
212 qemu_iovec_from_buf(reqdata
->aio_cb
->qiov
, reqdata
->bufidx
,
216 xseg_put_request(s
->xseg
, req
, s
->srcport
);
218 if (atomic_fetch_dec(&segreq
->ref
) == 1) {
219 if (!segreq
->failed
) {
220 reqdata
->aio_cb
->ret
= segreq
->count
;
221 archipelago_finish_aiocb(reqdata
);
231 case ARCHIP_OP_WRITE
:
232 case ARCHIP_OP_FLUSH
:
233 segreq
= reqdata
->segreq
;
234 segreq
->count
+= req
->serviced
;
235 xseg_put_request(s
->xseg
, req
, s
->srcport
);
237 if (atomic_fetch_dec(&segreq
->ref
) == 1) {
238 if (!segreq
->failed
) {
239 reqdata
->aio_cb
->ret
= segreq
->count
;
240 archipelago_finish_aiocb(reqdata
);
250 case ARCHIP_OP_VOLINFO
:
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
= qemu_opt_get_size_del(options
, BLOCK_OPT_SIZE
, 0);
713 if (segment_name
== NULL
) {
714 segment_name
= g_strdup("archipelago");
717 /* Create an Archipelago volume */
718 ret
= qemu_archipelago_create_volume(errp
, volname
, segment_name
,
723 g_free(segment_name
);
727 static void qemu_archipelago_aio_cancel(BlockDriverAIOCB
*blockacb
)
729 ArchipelagoAIOCB
*aio_cb
= (ArchipelagoAIOCB
*) blockacb
;
730 aio_cb
->cancelled
= true;
731 while (aio_cb
->status
== -EINPROGRESS
) {
732 aio_poll(bdrv_get_aio_context(aio_cb
->common
.bs
), true);
734 qemu_aio_release(aio_cb
);
737 static const AIOCBInfo archipelago_aiocb_info
= {
738 .aiocb_size
= sizeof(ArchipelagoAIOCB
),
739 .cancel
= qemu_archipelago_aio_cancel
,
742 static int archipelago_submit_request(BDRVArchipelagoState
*s
,
746 ArchipelagoAIOCB
*aio_cb
,
747 ArchipelagoSegmentedRequest
*segreq
,
753 struct xseg_request
*req
;
754 AIORequestData
*reqdata
= g_new(AIORequestData
, 1);
756 targetlen
= strlen(s
->volname
);
757 req
= xseg_get_request(s
->xseg
, s
->srcport
, s
->vportno
, X_ALLOC
);
759 archipelagolog("Cannot get XSEG request\n");
762 ret
= xseg_prep_request(s
->xseg
, req
, targetlen
, count
);
764 archipelagolog("Cannot prepare XSEG request\n");
767 target
= xseg_get_target(s
->xseg
, req
);
769 archipelagolog("Cannot get XSEG target\n");
772 memcpy(target
, s
->volname
, targetlen
);
774 req
->offset
= offset
;
780 case ARCHIP_OP_WRITE
:
783 case ARCHIP_OP_FLUSH
:
787 reqdata
->volname
= s
->volname
;
788 reqdata
->offset
= offset
;
789 reqdata
->size
= count
;
790 reqdata
->bufidx
= bufidx
;
791 reqdata
->aio_cb
= aio_cb
;
792 reqdata
->segreq
= segreq
;
795 xseg_set_req_data(s
->xseg
, req
, reqdata
);
796 if (op
== ARCHIP_OP_WRITE
) {
797 data
= xseg_get_data(s
->xseg
, req
);
799 archipelagolog("Cannot get XSEG data\n");
802 qemu_iovec_to_buf(aio_cb
->qiov
, bufidx
, data
, count
);
805 xport p
= xseg_submit(s
->xseg
, req
, s
->srcport
, X_ALLOC
);
807 archipelagolog("Could not submit XSEG request\n");
810 xseg_signal(s
->xseg
, p
);
815 xseg_put_request(s
->xseg
, req
, s
->srcport
);
822 static int archipelago_aio_segmented_rw(BDRVArchipelagoState
*s
,
825 ArchipelagoAIOCB
*aio_cb
,
828 int ret
, segments_nr
;
830 ArchipelagoSegmentedRequest
*segreq
;
832 segreq
= g_new0(ArchipelagoSegmentedRequest
, 1);
834 if (op
== ARCHIP_OP_FLUSH
) {
837 segments_nr
= (int)(count
/ MAX_REQUEST_SIZE
) + \
838 ((count
% MAX_REQUEST_SIZE
) ? 1 : 0);
840 segreq
->total
= count
;
841 atomic_mb_set(&segreq
->ref
, segments_nr
);
843 while (segments_nr
> 1) {
844 ret
= archipelago_submit_request(s
, pos
,
852 count
-= MAX_REQUEST_SIZE
;
853 pos
+= MAX_REQUEST_SIZE
;
856 ret
= archipelago_submit_request(s
, pos
, count
, offset
+ pos
,
866 if (atomic_fetch_sub(&segreq
->ref
, segments_nr
) == segments_nr
) {
872 static BlockDriverAIOCB
*qemu_archipelago_aio_rw(BlockDriverState
*bs
,
876 BlockDriverCompletionFunc
*cb
,
880 ArchipelagoAIOCB
*aio_cb
;
881 BDRVArchipelagoState
*s
= bs
->opaque
;
885 aio_cb
= qemu_aio_get(&archipelago_aiocb_info
, bs
, cb
, opaque
);
891 aio_cb
->cancelled
= false;
892 aio_cb
->status
= -EINPROGRESS
;
894 off
= sector_num
* BDRV_SECTOR_SIZE
;
895 size
= nb_sectors
* BDRV_SECTOR_SIZE
;
898 ret
= archipelago_aio_segmented_rw(s
, size
, off
,
903 return &aio_cb
->common
;
906 error_report("qemu_archipelago_aio_rw(): I/O Error\n");
907 qemu_aio_release(aio_cb
);
911 static BlockDriverAIOCB
*qemu_archipelago_aio_readv(BlockDriverState
*bs
,
912 int64_t sector_num
, QEMUIOVector
*qiov
, int nb_sectors
,
913 BlockDriverCompletionFunc
*cb
, void *opaque
)
915 return qemu_archipelago_aio_rw(bs
, sector_num
, qiov
, nb_sectors
, cb
,
916 opaque
, ARCHIP_OP_READ
);
919 static BlockDriverAIOCB
*qemu_archipelago_aio_writev(BlockDriverState
*bs
,
920 int64_t sector_num
, QEMUIOVector
*qiov
, int nb_sectors
,
921 BlockDriverCompletionFunc
*cb
, void *opaque
)
923 return qemu_archipelago_aio_rw(bs
, sector_num
, qiov
, nb_sectors
, cb
,
924 opaque
, ARCHIP_OP_WRITE
);
927 static int64_t archipelago_volume_info(BDRVArchipelagoState
*s
)
931 struct xseg_request
*req
;
932 struct xseg_reply_info
*xinfo
;
933 AIORequestData
*reqdata
= g_new(AIORequestData
, 1);
935 const char *volname
= s
->volname
;
936 targetlen
= strlen(volname
);
937 req
= xseg_get_request(s
->xseg
, s
->srcport
, s
->mportno
, X_ALLOC
);
939 archipelagolog("Cannot get XSEG request\n");
942 ret
= xseg_prep_request(s
->xseg
, req
, targetlen
,
943 sizeof(struct xseg_reply_info
));
945 archipelagolog("Cannot prepare XSEG request\n");
948 char *target
= xseg_get_target(s
->xseg
, req
);
950 archipelagolog("Cannot get XSEG target\n");
953 memcpy(target
, volname
, targetlen
);
954 req
->size
= req
->datalen
;
958 reqdata
->op
= ARCHIP_OP_VOLINFO
;
959 reqdata
->volname
= volname
;
960 xseg_set_req_data(s
->xseg
, req
, reqdata
);
962 xport p
= xseg_submit(s
->xseg
, req
, s
->srcport
, X_ALLOC
);
964 archipelagolog("Cannot submit XSEG request\n");
967 xseg_signal(s
->xseg
, p
);
968 qemu_mutex_lock(&s
->archip_mutex
);
969 while (!s
->is_signaled
) {
970 qemu_cond_wait(&s
->archip_cond
, &s
->archip_mutex
);
972 s
->is_signaled
= false;
973 qemu_mutex_unlock(&s
->archip_mutex
);
975 xinfo
= (struct xseg_reply_info
*) xseg_get_data(s
->xseg
, req
);
977 xseg_put_request(s
->xseg
, req
, s
->srcport
);
983 xseg_put_request(s
->xseg
, req
, s
->srcport
);
989 static int64_t qemu_archipelago_getlength(BlockDriverState
*bs
)
992 BDRVArchipelagoState
*s
= bs
->opaque
;
994 ret
= archipelago_volume_info(s
);
998 static QemuOptsList qemu_archipelago_create_opts
= {
999 .name
= "archipelago-create-opts",
1000 .head
= QTAILQ_HEAD_INITIALIZER(qemu_archipelago_create_opts
.head
),
1003 .name
= BLOCK_OPT_SIZE
,
1004 .type
= QEMU_OPT_SIZE
,
1005 .help
= "Virtual disk size"
1007 { /* end of list */ }
1011 static BlockDriverAIOCB
*qemu_archipelago_aio_flush(BlockDriverState
*bs
,
1012 BlockDriverCompletionFunc
*cb
, void *opaque
)
1014 return qemu_archipelago_aio_rw(bs
, 0, NULL
, 0, cb
, opaque
,
1018 static BlockDriver bdrv_archipelago
= {
1019 .format_name
= "archipelago",
1020 .protocol_name
= "archipelago",
1021 .instance_size
= sizeof(BDRVArchipelagoState
),
1022 .bdrv_parse_filename
= archipelago_parse_filename
,
1023 .bdrv_file_open
= qemu_archipelago_open
,
1024 .bdrv_close
= qemu_archipelago_close
,
1025 .bdrv_create
= qemu_archipelago_create
,
1026 .bdrv_getlength
= qemu_archipelago_getlength
,
1027 .bdrv_aio_readv
= qemu_archipelago_aio_readv
,
1028 .bdrv_aio_writev
= qemu_archipelago_aio_writev
,
1029 .bdrv_aio_flush
= qemu_archipelago_aio_flush
,
1030 .bdrv_has_zero_init
= bdrv_has_zero_init_1
,
1031 .create_opts
= &qemu_archipelago_create_opts
,
1034 static void bdrv_archipelago_init(void)
1036 bdrv_register(&bdrv_archipelago
);
1039 block_init(bdrv_archipelago_init
);