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"
62 #include <xseg/xseg.h>
63 #include <xseg/protocol.h>
65 #define ARCHIP_FD_READ 0
66 #define ARCHIP_FD_WRITE 1
67 #define MAX_REQUEST_SIZE 524288
69 #define ARCHIPELAGO_OPT_VOLUME "volume"
70 #define ARCHIPELAGO_OPT_SEGMENT "segment"
71 #define ARCHIPELAGO_OPT_MPORT "mport"
72 #define ARCHIPELAGO_OPT_VPORT "vport"
73 #define ARCHIPELAGO_DFL_MPORT 1001
74 #define ARCHIPELAGO_DFL_VPORT 501
76 #define archipelagolog(fmt, ...) \
78 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 ((__sync_add_and_fetch(&segreq
->ref
, -1)) == 0) {
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 ((__sync_add_and_fetch(&segreq
->ref
, -1)) == 0) {
237 if (!segreq
->failed
) {
238 reqdata
->aio_cb
->ret
= segreq
->count
;
239 archipelago_finish_aiocb(reqdata
);
249 case ARCHIP_OP_VOLINFO
:
250 s
->is_signaled
= true;
251 qemu_cond_signal(&s
->archip_cond
);
255 xseg_wait_signal(s
->xseg
, psd
, 100000UL);
257 xseg_cancel_wait(s
->xseg
, s
->srcport
);
260 s
->th_is_signaled
= true;
261 qemu_cond_signal(&s
->request_cond
);
262 qemu_mutex_unlock(&s
->request_mutex
);
263 qemu_thread_exit(NULL
);
266 static int qemu_archipelago_xseg_init(BDRVArchipelagoState
*s
)
268 if (xseg_initialize()) {
269 archipelagolog("Cannot initialize XSEG\n");
273 s
->xseg
= xseg_join("posix", s
->segment_name
,
276 archipelagolog("Cannot join XSEG shared memory segment\n");
279 s
->port
= xseg_bind_dynport(s
->xseg
);
280 s
->srcport
= s
->port
->portno
;
281 init_local_signal(s
->xseg
, s
->sport
, s
->srcport
);
288 static int qemu_archipelago_init(BDRVArchipelagoState
*s
)
292 ret
= qemu_archipelago_xseg_init(s
);
294 error_report("Cannot initialize XSEG. Aborting...\n");
298 qemu_cond_init(&s
->archip_cond
);
299 qemu_mutex_init(&s
->archip_mutex
);
300 qemu_cond_init(&s
->request_cond
);
301 qemu_mutex_init(&s
->request_mutex
);
302 s
->th_is_signaled
= false;
303 qemu_thread_create(&s
->request_th
, "xseg_io_th",
304 (void *) xseg_request_handler
,
305 (void *) s
, QEMU_THREAD_JOINABLE
);
311 static void qemu_archipelago_complete_aio(void *opaque
)
313 AIORequestData
*reqdata
= (AIORequestData
*) opaque
;
314 ArchipelagoAIOCB
*aio_cb
= (ArchipelagoAIOCB
*) reqdata
->aio_cb
;
316 qemu_bh_delete(aio_cb
->bh
);
317 aio_cb
->common
.cb(aio_cb
->common
.opaque
, aio_cb
->ret
);
320 if (!aio_cb
->cancelled
) {
321 qemu_aio_release(aio_cb
);
326 static void xseg_find_port(char *pstr
, const char *needle
, xport
*aport
)
331 if (strstart(pstr
, needle
, &a
)) {
333 port
= strtoul(a
, &endptr
, 10);
334 if (strlen(endptr
)) {
338 *aport
= (xport
) port
;
343 static void xseg_find_segment(char *pstr
, const char *needle
,
347 if (strstart(pstr
, needle
, &a
)) {
349 *segment_name
= g_strdup(a
);
354 static void parse_filename_opts(const char *filename
, Error
**errp
,
355 char **volume
, char **segment_name
,
356 xport
*mport
, xport
*vport
)
359 char *tokens
[4], *ds
;
361 xport lmport
= NoPort
, lvport
= NoPort
;
363 strstart(filename
, "archipelago:", &start
);
365 ds
= g_strdup(start
);
366 tokens
[0] = strtok(ds
, "/");
367 tokens
[1] = strtok(NULL
, ":");
368 tokens
[2] = strtok(NULL
, ":");
369 tokens
[3] = strtok(NULL
, "\0");
371 if (!strlen(tokens
[0])) {
372 error_setg(errp
, "volume name must be specified first");
377 for (idx
= 1; idx
< 4; idx
++) {
378 if (tokens
[idx
] != NULL
) {
379 if (strstart(tokens
[idx
], "mport=", NULL
)) {
380 xseg_find_port(tokens
[idx
], "mport=", &lmport
);
382 if (strstart(tokens
[idx
], "vport=", NULL
)) {
383 xseg_find_port(tokens
[idx
], "vport=", &lvport
);
385 if (strstart(tokens
[idx
], "segment=", NULL
)) {
386 xseg_find_segment(tokens
[idx
], "segment=", segment_name
);
391 if ((lmport
== -2) || (lvport
== -2)) {
392 error_setg(errp
, "mport and/or vport must be set");
396 *volume
= g_strdup(tokens
[0]);
402 static void archipelago_parse_filename(const char *filename
, QDict
*options
,
406 char *volume
= NULL
, *segment_name
= NULL
;
407 xport mport
= NoPort
, vport
= NoPort
;
409 if (qdict_haskey(options
, ARCHIPELAGO_OPT_VOLUME
)
410 || qdict_haskey(options
, ARCHIPELAGO_OPT_SEGMENT
)
411 || qdict_haskey(options
, ARCHIPELAGO_OPT_MPORT
)
412 || qdict_haskey(options
, ARCHIPELAGO_OPT_VPORT
)) {
413 error_setg(errp
, "volume/mport/vport/segment and a file name may not"
414 " be specified at the same time");
418 if (!strstart(filename
, "archipelago:", &start
)) {
419 error_setg(errp
, "File name must start with 'archipelago:'");
423 if (!strlen(start
) || strstart(start
, "/", NULL
)) {
424 error_setg(errp
, "volume name must be specified");
428 parse_filename_opts(filename
, errp
, &volume
, &segment_name
, &mport
, &vport
);
431 qdict_put(options
, ARCHIPELAGO_OPT_VOLUME
, qstring_from_str(volume
));
435 qdict_put(options
, ARCHIPELAGO_OPT_SEGMENT
,
436 qstring_from_str(segment_name
));
437 g_free(segment_name
);
439 if (mport
!= NoPort
) {
440 qdict_put(options
, ARCHIPELAGO_OPT_MPORT
, qint_from_int(mport
));
442 if (vport
!= NoPort
) {
443 qdict_put(options
, ARCHIPELAGO_OPT_VPORT
, qint_from_int(vport
));
447 static QemuOptsList archipelago_runtime_opts
= {
448 .name
= "archipelago",
449 .head
= QTAILQ_HEAD_INITIALIZER(archipelago_runtime_opts
.head
),
452 .name
= ARCHIPELAGO_OPT_VOLUME
,
453 .type
= QEMU_OPT_STRING
,
454 .help
= "Name of the volume image",
457 .name
= ARCHIPELAGO_OPT_SEGMENT
,
458 .type
= QEMU_OPT_STRING
,
459 .help
= "Name of the Archipelago shared memory segment",
462 .name
= ARCHIPELAGO_OPT_MPORT
,
463 .type
= QEMU_OPT_NUMBER
,
464 .help
= "Archipelago mapperd port number"
467 .name
= ARCHIPELAGO_OPT_VPORT
,
468 .type
= QEMU_OPT_NUMBER
,
469 .help
= "Archipelago vlmcd port number"
472 { /* end of list */ }
476 static int qemu_archipelago_open(BlockDriverState
*bs
,
482 const char *volume
, *segment_name
;
484 Error
*local_err
= NULL
;
485 BDRVArchipelagoState
*s
= bs
->opaque
;
487 opts
= qemu_opts_create(&archipelago_runtime_opts
, NULL
, 0, &error_abort
);
488 qemu_opts_absorb_qdict(opts
, options
, &local_err
);
490 error_propagate(errp
, local_err
);
495 s
->mportno
= qemu_opt_get_number(opts
, ARCHIPELAGO_OPT_MPORT
,
496 ARCHIPELAGO_DFL_MPORT
);
497 s
->vportno
= qemu_opt_get_number(opts
, ARCHIPELAGO_OPT_VPORT
,
498 ARCHIPELAGO_DFL_VPORT
);
500 segment_name
= qemu_opt_get(opts
, ARCHIPELAGO_OPT_SEGMENT
);
501 if (segment_name
== NULL
) {
502 s
->segment_name
= g_strdup("archipelago");
504 s
->segment_name
= g_strdup(segment_name
);
507 volume
= qemu_opt_get(opts
, ARCHIPELAGO_OPT_VOLUME
);
508 if (volume
== NULL
) {
509 error_setg(errp
, "archipelago block driver requires the 'volume'"
514 s
->volname
= g_strdup(volume
);
516 /* Initialize XSEG, join shared memory segment */
517 ret
= qemu_archipelago_init(s
);
519 error_setg(errp
, "cannot initialize XSEG and join shared "
529 g_free(s
->segment_name
);
534 static void qemu_archipelago_close(BlockDriverState
*bs
)
538 struct xseg_request
*req
;
539 BDRVArchipelagoState
*s
= bs
->opaque
;
543 qemu_mutex_lock(&s
->request_mutex
);
544 while (!s
->th_is_signaled
) {
545 qemu_cond_wait(&s
->request_cond
,
548 qemu_mutex_unlock(&s
->request_mutex
);
549 qemu_thread_join(&s
->request_th
);
550 qemu_cond_destroy(&s
->request_cond
);
551 qemu_mutex_destroy(&s
->request_mutex
);
553 qemu_cond_destroy(&s
->archip_cond
);
554 qemu_mutex_destroy(&s
->archip_mutex
);
556 targetlen
= strlen(s
->volname
);
557 req
= xseg_get_request(s
->xseg
, s
->srcport
, s
->vportno
, X_ALLOC
);
559 archipelagolog("Cannot get XSEG request\n");
562 r
= xseg_prep_request(s
->xseg
, req
, targetlen
, 0);
564 xseg_put_request(s
->xseg
, req
, s
->srcport
);
565 archipelagolog("Cannot prepare XSEG close request\n");
569 target
= xseg_get_target(s
->xseg
, req
);
570 memcpy(target
, s
->volname
, targetlen
);
571 req
->size
= req
->datalen
;
575 xport p
= xseg_submit(s
->xseg
, req
, s
->srcport
, X_ALLOC
);
577 xseg_put_request(s
->xseg
, req
, s
->srcport
);
578 archipelagolog("Cannot submit XSEG close request\n");
582 xseg_signal(s
->xseg
, p
);
583 wait_reply(s
->xseg
, s
->srcport
, s
->port
, req
);
585 xseg_put_request(s
->xseg
, req
, s
->srcport
);
589 g_free(s
->segment_name
);
590 xseg_quit_local_signal(s
->xseg
, s
->srcport
);
591 xseg_leave_dynport(s
->xseg
, s
->port
);
595 static int qemu_archipelago_create_volume(Error
**errp
, const char *volname
,
597 uint64_t size
, xport mportno
,
601 struct xseg
*xseg
= NULL
;
602 struct xseg_request
*req
;
603 struct xseg_request_clone
*xclone
;
604 struct xseg_port
*port
;
605 xport srcport
= NoPort
, sport
= NoPort
;
608 /* Try default values if none has been set */
609 if (mportno
== (xport
) -1) {
610 mportno
= ARCHIPELAGO_DFL_MPORT
;
613 if (vportno
== (xport
) -1) {
614 vportno
= ARCHIPELAGO_DFL_VPORT
;
617 if (xseg_initialize()) {
618 error_setg(errp
, "Cannot initialize XSEG");
622 xseg
= xseg_join("posix", segment_name
,
626 error_setg(errp
, "Cannot join XSEG shared memory segment");
630 port
= xseg_bind_dynport(xseg
);
631 srcport
= port
->portno
;
632 init_local_signal(xseg
, sport
, srcport
);
634 req
= xseg_get_request(xseg
, srcport
, mportno
, X_ALLOC
);
636 error_setg(errp
, "Cannot get XSEG request");
640 targetlen
= strlen(volname
);
641 ret
= xseg_prep_request(xseg
, req
, targetlen
,
642 sizeof(struct xseg_request_clone
));
644 error_setg(errp
, "Cannot prepare XSEG request");
648 target
= xseg_get_target(xseg
, req
);
650 error_setg(errp
, "Cannot get XSEG target.\n");
653 memcpy(target
, volname
, targetlen
);
654 xclone
= (struct xseg_request_clone
*) xseg_get_data(xseg
, req
);
655 memset(xclone
->target
, 0 , XSEG_MAX_TARGETLEN
);
656 xclone
->targetlen
= 0;
659 req
->size
= req
->datalen
;
662 xport p
= xseg_submit(xseg
, req
, srcport
, X_ALLOC
);
664 error_setg(errp
, "Could not submit XSEG request");
667 xseg_signal(xseg
, p
);
669 ret
= wait_reply(xseg
, srcport
, port
, req
);
671 error_setg(errp
, "wait_reply() error.");
674 xseg_put_request(xseg
, req
, srcport
);
675 xseg_quit_local_signal(xseg
, srcport
);
676 xseg_leave_dynport(xseg
, port
);
681 xseg_put_request(xseg
, req
, srcport
);
682 xseg_quit_local_signal(xseg
, srcport
);
683 xseg_leave_dynport(xseg
, port
);
688 static int qemu_archipelago_create(const char *filename
,
693 uint64_t total_size
= 0;
694 char *volname
= NULL
, *segment_name
= NULL
;
696 xport mport
= NoPort
, vport
= NoPort
;
698 if (!strstart(filename
, "archipelago:", &start
)) {
699 error_setg(errp
, "File name must start with 'archipelago:'");
703 if (!strlen(start
) || strstart(start
, "/", NULL
)) {
704 error_setg(errp
, "volume name must be specified");
708 parse_filename_opts(filename
, errp
, &volname
, &segment_name
, &mport
,
710 total_size
= qemu_opt_get_size_del(options
, BLOCK_OPT_SIZE
, 0);
712 if (segment_name
== NULL
) {
713 segment_name
= g_strdup("archipelago");
716 /* Create an Archipelago volume */
717 ret
= qemu_archipelago_create_volume(errp
, volname
, segment_name
,
722 g_free(segment_name
);
726 static void qemu_archipelago_aio_cancel(BlockDriverAIOCB
*blockacb
)
728 ArchipelagoAIOCB
*aio_cb
= (ArchipelagoAIOCB
*) blockacb
;
729 aio_cb
->cancelled
= true;
730 while (aio_cb
->status
== -EINPROGRESS
) {
731 aio_poll(bdrv_get_aio_context(aio_cb
->common
.bs
), true);
733 qemu_aio_release(aio_cb
);
736 static const AIOCBInfo archipelago_aiocb_info
= {
737 .aiocb_size
= sizeof(ArchipelagoAIOCB
),
738 .cancel
= qemu_archipelago_aio_cancel
,
741 static int archipelago_submit_request(BDRVArchipelagoState
*s
,
745 ArchipelagoAIOCB
*aio_cb
,
746 ArchipelagoSegmentedRequest
*segreq
,
752 struct xseg_request
*req
;
753 AIORequestData
*reqdata
= g_new(AIORequestData
, 1);
755 targetlen
= strlen(s
->volname
);
756 req
= xseg_get_request(s
->xseg
, s
->srcport
, s
->vportno
, X_ALLOC
);
758 archipelagolog("Cannot get XSEG request\n");
761 ret
= xseg_prep_request(s
->xseg
, req
, targetlen
, count
);
763 archipelagolog("Cannot prepare XSEG request\n");
766 target
= xseg_get_target(s
->xseg
, req
);
768 archipelagolog("Cannot get XSEG target\n");
771 memcpy(target
, s
->volname
, targetlen
);
773 req
->offset
= offset
;
779 case ARCHIP_OP_WRITE
:
782 case ARCHIP_OP_FLUSH
:
786 reqdata
->volname
= s
->volname
;
787 reqdata
->offset
= offset
;
788 reqdata
->size
= count
;
789 reqdata
->bufidx
= bufidx
;
790 reqdata
->aio_cb
= aio_cb
;
791 reqdata
->segreq
= segreq
;
794 xseg_set_req_data(s
->xseg
, req
, reqdata
);
795 if (op
== ARCHIP_OP_WRITE
) {
796 data
= xseg_get_data(s
->xseg
, req
);
798 archipelagolog("Cannot get XSEG data\n");
801 qemu_iovec_to_buf(aio_cb
->qiov
, bufidx
, data
, count
);
804 xport p
= xseg_submit(s
->xseg
, req
, s
->srcport
, X_ALLOC
);
806 archipelagolog("Could not submit XSEG request\n");
809 xseg_signal(s
->xseg
, p
);
814 xseg_put_request(s
->xseg
, req
, s
->srcport
);
821 static int archipelago_aio_segmented_rw(BDRVArchipelagoState
*s
,
824 ArchipelagoAIOCB
*aio_cb
,
827 int i
, ret
, segments_nr
, last_segment_size
;
828 ArchipelagoSegmentedRequest
*segreq
;
830 segreq
= g_new(ArchipelagoSegmentedRequest
, 1);
832 if (op
== ARCHIP_OP_FLUSH
) {
834 segreq
->ref
= segments_nr
;
835 segreq
->total
= count
;
838 ret
= archipelago_submit_request(s
, 0, count
, offset
, aio_cb
,
839 segreq
, ARCHIP_OP_FLUSH
);
846 segments_nr
= (int)(count
/ MAX_REQUEST_SIZE
) + \
847 ((count
% MAX_REQUEST_SIZE
) ? 1 : 0);
848 last_segment_size
= (int)(count
% MAX_REQUEST_SIZE
);
850 segreq
->ref
= segments_nr
;
851 segreq
->total
= count
;
855 for (i
= 0; i
< segments_nr
- 1; i
++) {
856 ret
= archipelago_submit_request(s
, i
* MAX_REQUEST_SIZE
,
858 offset
+ i
* MAX_REQUEST_SIZE
,
866 if ((segments_nr
> 1) && last_segment_size
) {
867 ret
= archipelago_submit_request(s
, i
* MAX_REQUEST_SIZE
,
869 offset
+ i
* MAX_REQUEST_SIZE
,
871 } else if ((segments_nr
> 1) && !last_segment_size
) {
872 ret
= archipelago_submit_request(s
, i
* MAX_REQUEST_SIZE
,
874 offset
+ i
* MAX_REQUEST_SIZE
,
876 } else if (segments_nr
== 1) {
877 ret
= archipelago_submit_request(s
, 0, count
, offset
, aio_cb
,
888 __sync_add_and_fetch(&segreq
->failed
, 1);
889 if (segments_nr
== 1) {
890 if (__sync_add_and_fetch(&segreq
->ref
, -1) == 0) {
894 if ((__sync_add_and_fetch(&segreq
->ref
, -segments_nr
+ i
)) == 0) {
902 static BlockDriverAIOCB
*qemu_archipelago_aio_rw(BlockDriverState
*bs
,
906 BlockDriverCompletionFunc
*cb
,
910 ArchipelagoAIOCB
*aio_cb
;
911 BDRVArchipelagoState
*s
= bs
->opaque
;
915 aio_cb
= qemu_aio_get(&archipelago_aiocb_info
, bs
, cb
, opaque
);
921 aio_cb
->cancelled
= false;
922 aio_cb
->status
= -EINPROGRESS
;
924 off
= sector_num
* BDRV_SECTOR_SIZE
;
925 size
= nb_sectors
* BDRV_SECTOR_SIZE
;
928 ret
= archipelago_aio_segmented_rw(s
, size
, off
,
933 return &aio_cb
->common
;
936 error_report("qemu_archipelago_aio_rw(): I/O Error\n");
937 qemu_aio_release(aio_cb
);
941 static BlockDriverAIOCB
*qemu_archipelago_aio_readv(BlockDriverState
*bs
,
942 int64_t sector_num
, QEMUIOVector
*qiov
, int nb_sectors
,
943 BlockDriverCompletionFunc
*cb
, void *opaque
)
945 return qemu_archipelago_aio_rw(bs
, sector_num
, qiov
, nb_sectors
, cb
,
946 opaque
, ARCHIP_OP_READ
);
949 static BlockDriverAIOCB
*qemu_archipelago_aio_writev(BlockDriverState
*bs
,
950 int64_t sector_num
, QEMUIOVector
*qiov
, int nb_sectors
,
951 BlockDriverCompletionFunc
*cb
, void *opaque
)
953 return qemu_archipelago_aio_rw(bs
, sector_num
, qiov
, nb_sectors
, cb
,
954 opaque
, ARCHIP_OP_WRITE
);
957 static int64_t archipelago_volume_info(BDRVArchipelagoState
*s
)
961 struct xseg_request
*req
;
962 struct xseg_reply_info
*xinfo
;
963 AIORequestData
*reqdata
= g_new(AIORequestData
, 1);
965 const char *volname
= s
->volname
;
966 targetlen
= strlen(volname
);
967 req
= xseg_get_request(s
->xseg
, s
->srcport
, s
->mportno
, X_ALLOC
);
969 archipelagolog("Cannot get XSEG request\n");
972 ret
= xseg_prep_request(s
->xseg
, req
, targetlen
,
973 sizeof(struct xseg_reply_info
));
975 archipelagolog("Cannot prepare XSEG request\n");
978 char *target
= xseg_get_target(s
->xseg
, req
);
980 archipelagolog("Cannot get XSEG target\n");
983 memcpy(target
, volname
, targetlen
);
984 req
->size
= req
->datalen
;
988 reqdata
->op
= ARCHIP_OP_VOLINFO
;
989 reqdata
->volname
= volname
;
990 xseg_set_req_data(s
->xseg
, req
, reqdata
);
992 xport p
= xseg_submit(s
->xseg
, req
, s
->srcport
, X_ALLOC
);
994 archipelagolog("Cannot submit XSEG request\n");
997 xseg_signal(s
->xseg
, p
);
998 qemu_mutex_lock(&s
->archip_mutex
);
999 while (!s
->is_signaled
) {
1000 qemu_cond_wait(&s
->archip_cond
, &s
->archip_mutex
);
1002 s
->is_signaled
= false;
1003 qemu_mutex_unlock(&s
->archip_mutex
);
1005 xinfo
= (struct xseg_reply_info
*) xseg_get_data(s
->xseg
, req
);
1007 xseg_put_request(s
->xseg
, req
, s
->srcport
);
1013 xseg_put_request(s
->xseg
, req
, s
->srcport
);
1019 static int64_t qemu_archipelago_getlength(BlockDriverState
*bs
)
1022 BDRVArchipelagoState
*s
= bs
->opaque
;
1024 ret
= archipelago_volume_info(s
);
1028 static QemuOptsList qemu_archipelago_create_opts
= {
1029 .name
= "archipelago-create-opts",
1030 .head
= QTAILQ_HEAD_INITIALIZER(qemu_archipelago_create_opts
.head
),
1033 .name
= BLOCK_OPT_SIZE
,
1034 .type
= QEMU_OPT_SIZE
,
1035 .help
= "Virtual disk size"
1037 { /* end of list */ }
1041 static BlockDriverAIOCB
*qemu_archipelago_aio_flush(BlockDriverState
*bs
,
1042 BlockDriverCompletionFunc
*cb
, void *opaque
)
1044 return qemu_archipelago_aio_rw(bs
, 0, NULL
, 0, cb
, opaque
,
1048 static BlockDriver bdrv_archipelago
= {
1049 .format_name
= "archipelago",
1050 .protocol_name
= "archipelago",
1051 .instance_size
= sizeof(BDRVArchipelagoState
),
1052 .bdrv_parse_filename
= archipelago_parse_filename
,
1053 .bdrv_file_open
= qemu_archipelago_open
,
1054 .bdrv_close
= qemu_archipelago_close
,
1055 .bdrv_create
= qemu_archipelago_create
,
1056 .bdrv_getlength
= qemu_archipelago_getlength
,
1057 .bdrv_aio_readv
= qemu_archipelago_aio_readv
,
1058 .bdrv_aio_writev
= qemu_archipelago_aio_writev
,
1059 .bdrv_aio_flush
= qemu_archipelago_aio_flush
,
1060 .bdrv_has_zero_init
= bdrv_has_zero_init_1
,
1061 .create_opts
= &qemu_archipelago_create_opts
,
1064 static void bdrv_archipelago_init(void)
1066 bdrv_register(&bdrv_archipelago
);
1069 block_init(bdrv_archipelago_init
);