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/osdep.h"
54 #include "qemu/cutils.h"
55 #include "block/block_int.h"
56 #include "qemu/error-report.h"
57 #include "qemu/thread.h"
58 #include "qapi/qmp/qint.h"
59 #include "qapi/qmp/qstring.h"
60 #include "qapi/qmp/qjson.h"
61 #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
{
90 struct BDRVArchipelagoState
*s
;
98 typedef struct BDRVArchipelagoState
{
99 ArchipelagoAIOCB
*event_acb
;
103 /* Archipelago specific */
105 struct xseg_port
*port
;
110 QemuMutex archip_mutex
;
111 QemuCond archip_cond
;
113 /* Request handler specific */
114 QemuThread request_th
;
115 QemuCond request_cond
;
116 QemuMutex request_mutex
;
119 } BDRVArchipelagoState
;
121 typedef struct ArchipelagoSegmentedRequest
{
126 } ArchipelagoSegmentedRequest
;
128 typedef struct AIORequestData
{
135 ArchipelagoAIOCB
*aio_cb
;
136 ArchipelagoSegmentedRequest
*segreq
;
139 static void qemu_archipelago_complete_aio(void *opaque
);
141 static void init_local_signal(struct xseg
*xseg
, xport sport
, xport srcport
)
143 if (xseg
&& (sport
!= srcport
)) {
144 xseg_init_local_signal(xseg
, srcport
);
149 static void archipelago_finish_aiocb(AIORequestData
*reqdata
)
151 if (reqdata
->aio_cb
->ret
!= reqdata
->segreq
->total
) {
152 reqdata
->aio_cb
->ret
= -EIO
;
153 } else if (reqdata
->aio_cb
->ret
== reqdata
->segreq
->total
) {
154 reqdata
->aio_cb
->ret
= 0;
156 aio_bh_schedule_oneshot(
157 bdrv_get_aio_context(reqdata
->aio_cb
->common
.bs
),
158 qemu_archipelago_complete_aio
, reqdata
162 static int wait_reply(struct xseg
*xseg
, xport srcport
, struct xseg_port
*port
,
163 struct xseg_request
*expected_req
)
165 struct xseg_request
*req
;
166 xseg_prepare_wait(xseg
, srcport
);
167 void *psd
= xseg_get_signal_desc(xseg
, port
);
169 req
= xseg_receive(xseg
, srcport
, X_NONBLOCK
);
171 if (req
!= expected_req
) {
172 archipelagolog("Unknown received request\n");
173 xseg_put_request(xseg
, req
, srcport
);
174 } else if (!(req
->state
& XS_SERVED
)) {
180 xseg_wait_signal(xseg
, psd
, 100000UL);
182 xseg_cancel_wait(xseg
, srcport
);
186 static void xseg_request_handler(void *state
)
188 BDRVArchipelagoState
*s
= (BDRVArchipelagoState
*) state
;
189 void *psd
= xseg_get_signal_desc(s
->xseg
, s
->port
);
190 qemu_mutex_lock(&s
->request_mutex
);
192 while (!s
->stopping
) {
193 struct xseg_request
*req
;
195 xseg_prepare_wait(s
->xseg
, s
->srcport
);
196 req
= xseg_receive(s
->xseg
, s
->srcport
, X_NONBLOCK
);
198 AIORequestData
*reqdata
;
199 ArchipelagoSegmentedRequest
*segreq
;
200 xseg_get_req_data(s
->xseg
, req
, (void **)&reqdata
);
202 switch (reqdata
->op
) {
204 data
= xseg_get_data(s
->xseg
, req
);
205 segreq
= reqdata
->segreq
;
206 segreq
->count
+= req
->serviced
;
208 qemu_iovec_from_buf(reqdata
->aio_cb
->qiov
, reqdata
->bufidx
,
212 xseg_put_request(s
->xseg
, req
, s
->srcport
);
214 if (atomic_fetch_dec(&segreq
->ref
) == 1) {
215 if (!segreq
->failed
) {
216 reqdata
->aio_cb
->ret
= segreq
->count
;
217 archipelago_finish_aiocb(reqdata
);
227 case ARCHIP_OP_WRITE
:
228 case ARCHIP_OP_FLUSH
:
229 segreq
= reqdata
->segreq
;
230 segreq
->count
+= req
->serviced
;
231 xseg_put_request(s
->xseg
, req
, s
->srcport
);
233 if (atomic_fetch_dec(&segreq
->ref
) == 1) {
234 if (!segreq
->failed
) {
235 reqdata
->aio_cb
->ret
= segreq
->count
;
236 archipelago_finish_aiocb(reqdata
);
246 case ARCHIP_OP_VOLINFO
:
247 case ARCHIP_OP_TRUNCATE
:
248 s
->is_signaled
= true;
249 qemu_cond_signal(&s
->archip_cond
);
253 xseg_wait_signal(s
->xseg
, psd
, 100000UL);
255 xseg_cancel_wait(s
->xseg
, s
->srcport
);
258 s
->th_is_signaled
= true;
259 qemu_cond_signal(&s
->request_cond
);
260 qemu_mutex_unlock(&s
->request_mutex
);
261 qemu_thread_exit(NULL
);
264 static int qemu_archipelago_xseg_init(BDRVArchipelagoState
*s
)
266 if (xseg_initialize()) {
267 archipelagolog("Cannot initialize XSEG\n");
271 s
->xseg
= xseg_join("posix", s
->segment_name
,
274 archipelagolog("Cannot join XSEG shared memory segment\n");
277 s
->port
= xseg_bind_dynport(s
->xseg
);
278 s
->srcport
= s
->port
->portno
;
279 init_local_signal(s
->xseg
, s
->sport
, s
->srcport
);
286 static int qemu_archipelago_init(BDRVArchipelagoState
*s
)
290 ret
= qemu_archipelago_xseg_init(s
);
292 error_report("Cannot initialize XSEG. Aborting...");
296 qemu_cond_init(&s
->archip_cond
);
297 qemu_mutex_init(&s
->archip_mutex
);
298 qemu_cond_init(&s
->request_cond
);
299 qemu_mutex_init(&s
->request_mutex
);
300 s
->th_is_signaled
= false;
301 qemu_thread_create(&s
->request_th
, "xseg_io_th",
302 (void *) xseg_request_handler
,
303 (void *) s
, QEMU_THREAD_JOINABLE
);
309 static void qemu_archipelago_complete_aio(void *opaque
)
311 AIORequestData
*reqdata
= (AIORequestData
*) opaque
;
312 ArchipelagoAIOCB
*aio_cb
= (ArchipelagoAIOCB
*) reqdata
->aio_cb
;
313 AioContext
*ctx
= bdrv_get_aio_context(aio_cb
->common
.bs
);
315 aio_context_acquire(ctx
);
316 aio_cb
->common
.cb(aio_cb
->common
.opaque
, aio_cb
->ret
);
317 aio_context_release(ctx
);
320 qemu_aio_unref(aio_cb
);
324 static void xseg_find_port(char *pstr
, const char *needle
, xport
*aport
)
329 if (strstart(pstr
, needle
, &a
)) {
331 port
= strtoul(a
, &endptr
, 10);
332 if (strlen(endptr
)) {
336 *aport
= (xport
) port
;
341 static void xseg_find_segment(char *pstr
, const char *needle
,
345 if (strstart(pstr
, needle
, &a
)) {
347 *segment_name
= g_strdup(a
);
352 static void parse_filename_opts(const char *filename
, Error
**errp
,
353 char **volume
, char **segment_name
,
354 xport
*mport
, xport
*vport
)
357 char *tokens
[4], *ds
;
359 xport lmport
= NoPort
, lvport
= NoPort
;
361 strstart(filename
, "archipelago:", &start
);
363 ds
= g_strdup(start
);
364 tokens
[0] = strtok(ds
, "/");
365 tokens
[1] = strtok(NULL
, ":");
366 tokens
[2] = strtok(NULL
, ":");
367 tokens
[3] = strtok(NULL
, "\0");
369 if (!strlen(tokens
[0])) {
370 error_setg(errp
, "volume name must be specified first");
375 for (idx
= 1; idx
< 4; idx
++) {
376 if (tokens
[idx
] != NULL
) {
377 if (strstart(tokens
[idx
], "mport=", NULL
)) {
378 xseg_find_port(tokens
[idx
], "mport=", &lmport
);
380 if (strstart(tokens
[idx
], "vport=", NULL
)) {
381 xseg_find_port(tokens
[idx
], "vport=", &lvport
);
383 if (strstart(tokens
[idx
], "segment=", NULL
)) {
384 xseg_find_segment(tokens
[idx
], "segment=", segment_name
);
389 if ((lmport
== -2) || (lvport
== -2)) {
390 error_setg(errp
, "mport and/or vport must be set");
394 *volume
= g_strdup(tokens
[0]);
400 static void archipelago_parse_filename(const char *filename
, QDict
*options
,
404 char *volume
= NULL
, *segment_name
= NULL
;
405 xport mport
= NoPort
, vport
= NoPort
;
407 if (qdict_haskey(options
, ARCHIPELAGO_OPT_VOLUME
)
408 || qdict_haskey(options
, ARCHIPELAGO_OPT_SEGMENT
)
409 || qdict_haskey(options
, ARCHIPELAGO_OPT_MPORT
)
410 || qdict_haskey(options
, ARCHIPELAGO_OPT_VPORT
)) {
411 error_setg(errp
, "volume/mport/vport/segment and a file name may not"
412 " be specified at the same time");
416 if (!strstart(filename
, "archipelago:", &start
)) {
417 error_setg(errp
, "File name must start with 'archipelago:'");
421 if (!strlen(start
) || strstart(start
, "/", NULL
)) {
422 error_setg(errp
, "volume name must be specified");
426 parse_filename_opts(filename
, errp
, &volume
, &segment_name
, &mport
, &vport
);
429 qdict_put(options
, ARCHIPELAGO_OPT_VOLUME
, qstring_from_str(volume
));
433 qdict_put(options
, ARCHIPELAGO_OPT_SEGMENT
,
434 qstring_from_str(segment_name
));
435 g_free(segment_name
);
437 if (mport
!= NoPort
) {
438 qdict_put(options
, ARCHIPELAGO_OPT_MPORT
, qint_from_int(mport
));
440 if (vport
!= NoPort
) {
441 qdict_put(options
, ARCHIPELAGO_OPT_VPORT
, qint_from_int(vport
));
445 static QemuOptsList archipelago_runtime_opts
= {
446 .name
= "archipelago",
447 .head
= QTAILQ_HEAD_INITIALIZER(archipelago_runtime_opts
.head
),
450 .name
= ARCHIPELAGO_OPT_VOLUME
,
451 .type
= QEMU_OPT_STRING
,
452 .help
= "Name of the volume image",
455 .name
= ARCHIPELAGO_OPT_SEGMENT
,
456 .type
= QEMU_OPT_STRING
,
457 .help
= "Name of the Archipelago shared memory segment",
460 .name
= ARCHIPELAGO_OPT_MPORT
,
461 .type
= QEMU_OPT_NUMBER
,
462 .help
= "Archipelago mapperd port number"
465 .name
= ARCHIPELAGO_OPT_VPORT
,
466 .type
= QEMU_OPT_NUMBER
,
467 .help
= "Archipelago vlmcd port number"
470 { /* end of list */ }
474 static int qemu_archipelago_open(BlockDriverState
*bs
,
480 const char *volume
, *segment_name
;
482 Error
*local_err
= NULL
;
483 BDRVArchipelagoState
*s
= bs
->opaque
;
485 opts
= qemu_opts_create(&archipelago_runtime_opts
, NULL
, 0, &error_abort
);
486 qemu_opts_absorb_qdict(opts
, options
, &local_err
);
488 error_propagate(errp
, local_err
);
493 s
->mportno
= qemu_opt_get_number(opts
, ARCHIPELAGO_OPT_MPORT
,
494 ARCHIPELAGO_DFL_MPORT
);
495 s
->vportno
= qemu_opt_get_number(opts
, ARCHIPELAGO_OPT_VPORT
,
496 ARCHIPELAGO_DFL_VPORT
);
498 segment_name
= qemu_opt_get(opts
, ARCHIPELAGO_OPT_SEGMENT
);
499 if (segment_name
== NULL
) {
500 s
->segment_name
= g_strdup("archipelago");
502 s
->segment_name
= g_strdup(segment_name
);
505 volume
= qemu_opt_get(opts
, ARCHIPELAGO_OPT_VOLUME
);
506 if (volume
== NULL
) {
507 error_setg(errp
, "archipelago block driver requires the 'volume'"
512 s
->volname
= g_strdup(volume
);
514 /* Initialize XSEG, join shared memory segment */
515 ret
= qemu_archipelago_init(s
);
517 error_setg(errp
, "cannot initialize XSEG and join shared "
527 g_free(s
->segment_name
);
532 static void qemu_archipelago_close(BlockDriverState
*bs
)
536 struct xseg_request
*req
;
537 BDRVArchipelagoState
*s
= bs
->opaque
;
541 qemu_mutex_lock(&s
->request_mutex
);
542 while (!s
->th_is_signaled
) {
543 qemu_cond_wait(&s
->request_cond
,
546 qemu_mutex_unlock(&s
->request_mutex
);
547 qemu_thread_join(&s
->request_th
);
548 qemu_cond_destroy(&s
->request_cond
);
549 qemu_mutex_destroy(&s
->request_mutex
);
551 qemu_cond_destroy(&s
->archip_cond
);
552 qemu_mutex_destroy(&s
->archip_mutex
);
554 targetlen
= strlen(s
->volname
);
555 req
= xseg_get_request(s
->xseg
, s
->srcport
, s
->vportno
, X_ALLOC
);
557 archipelagolog("Cannot get XSEG request\n");
560 r
= xseg_prep_request(s
->xseg
, req
, targetlen
, 0);
562 xseg_put_request(s
->xseg
, req
, s
->srcport
);
563 archipelagolog("Cannot prepare XSEG close request\n");
567 target
= xseg_get_target(s
->xseg
, req
);
568 memcpy(target
, s
->volname
, targetlen
);
569 req
->size
= req
->datalen
;
573 xport p
= xseg_submit(s
->xseg
, req
, s
->srcport
, X_ALLOC
);
575 xseg_put_request(s
->xseg
, req
, s
->srcport
);
576 archipelagolog("Cannot submit XSEG close request\n");
580 xseg_signal(s
->xseg
, p
);
581 wait_reply(s
->xseg
, s
->srcport
, s
->port
, req
);
583 xseg_put_request(s
->xseg
, req
, s
->srcport
);
587 g_free(s
->segment_name
);
588 xseg_quit_local_signal(s
->xseg
, s
->srcport
);
589 xseg_leave_dynport(s
->xseg
, s
->port
);
593 static int qemu_archipelago_create_volume(Error
**errp
, const char *volname
,
595 uint64_t size
, xport mportno
,
599 struct xseg
*xseg
= NULL
;
600 struct xseg_request
*req
;
601 struct xseg_request_clone
*xclone
;
602 struct xseg_port
*port
;
603 xport srcport
= NoPort
, sport
= NoPort
;
606 /* Try default values if none has been set */
607 if (mportno
== (xport
) -1) {
608 mportno
= ARCHIPELAGO_DFL_MPORT
;
611 if (vportno
== (xport
) -1) {
612 vportno
= ARCHIPELAGO_DFL_VPORT
;
615 if (xseg_initialize()) {
616 error_setg(errp
, "Cannot initialize XSEG");
620 xseg
= xseg_join("posix", segment_name
,
624 error_setg(errp
, "Cannot join XSEG shared memory segment");
628 port
= xseg_bind_dynport(xseg
);
629 srcport
= port
->portno
;
630 init_local_signal(xseg
, sport
, srcport
);
632 req
= xseg_get_request(xseg
, srcport
, mportno
, X_ALLOC
);
634 error_setg(errp
, "Cannot get XSEG request");
638 targetlen
= strlen(volname
);
639 ret
= xseg_prep_request(xseg
, req
, targetlen
,
640 sizeof(struct xseg_request_clone
));
642 error_setg(errp
, "Cannot prepare XSEG request");
646 target
= xseg_get_target(xseg
, req
);
648 error_setg(errp
, "Cannot get XSEG target.");
651 memcpy(target
, volname
, targetlen
);
652 xclone
= (struct xseg_request_clone
*) xseg_get_data(xseg
, req
);
653 memset(xclone
->target
, 0 , XSEG_MAX_TARGETLEN
);
654 xclone
->targetlen
= 0;
657 req
->size
= req
->datalen
;
660 xport p
= xseg_submit(xseg
, req
, srcport
, X_ALLOC
);
662 error_setg(errp
, "Could not submit XSEG request");
665 xseg_signal(xseg
, p
);
667 ret
= wait_reply(xseg
, srcport
, port
, req
);
669 error_setg(errp
, "wait_reply() error.");
672 xseg_put_request(xseg
, req
, srcport
);
673 xseg_quit_local_signal(xseg
, srcport
);
674 xseg_leave_dynport(xseg
, port
);
679 xseg_put_request(xseg
, req
, srcport
);
680 xseg_quit_local_signal(xseg
, srcport
);
681 xseg_leave_dynport(xseg
, port
);
686 static int qemu_archipelago_create(const char *filename
,
691 uint64_t total_size
= 0;
692 char *volname
= NULL
, *segment_name
= NULL
;
694 xport mport
= NoPort
, vport
= NoPort
;
696 if (!strstart(filename
, "archipelago:", &start
)) {
697 error_setg(errp
, "File name must start with 'archipelago:'");
701 if (!strlen(start
) || strstart(start
, "/", NULL
)) {
702 error_setg(errp
, "volume name must be specified");
706 parse_filename_opts(filename
, errp
, &volname
, &segment_name
, &mport
,
708 total_size
= ROUND_UP(qemu_opt_get_size_del(options
, BLOCK_OPT_SIZE
, 0),
711 if (segment_name
== NULL
) {
712 segment_name
= g_strdup("archipelago");
715 /* Create an Archipelago volume */
716 ret
= qemu_archipelago_create_volume(errp
, volname
, segment_name
,
721 g_free(segment_name
);
725 static const AIOCBInfo archipelago_aiocb_info
= {
726 .aiocb_size
= sizeof(ArchipelagoAIOCB
),
729 static int archipelago_submit_request(BDRVArchipelagoState
*s
,
733 ArchipelagoAIOCB
*aio_cb
,
734 ArchipelagoSegmentedRequest
*segreq
,
740 struct xseg_request
*req
;
741 AIORequestData
*reqdata
= g_new(AIORequestData
, 1);
743 targetlen
= strlen(s
->volname
);
744 req
= xseg_get_request(s
->xseg
, s
->srcport
, s
->vportno
, X_ALLOC
);
746 archipelagolog("Cannot get XSEG request\n");
749 ret
= xseg_prep_request(s
->xseg
, req
, targetlen
, count
);
751 archipelagolog("Cannot prepare XSEG request\n");
754 target
= xseg_get_target(s
->xseg
, req
);
756 archipelagolog("Cannot get XSEG target\n");
759 memcpy(target
, s
->volname
, targetlen
);
761 req
->offset
= offset
;
767 case ARCHIP_OP_WRITE
:
770 case ARCHIP_OP_FLUSH
:
774 reqdata
->volname
= s
->volname
;
775 reqdata
->offset
= offset
;
776 reqdata
->size
= count
;
777 reqdata
->bufidx
= bufidx
;
778 reqdata
->aio_cb
= aio_cb
;
779 reqdata
->segreq
= segreq
;
782 xseg_set_req_data(s
->xseg
, req
, reqdata
);
783 if (op
== ARCHIP_OP_WRITE
) {
784 data
= xseg_get_data(s
->xseg
, req
);
786 archipelagolog("Cannot get XSEG data\n");
789 qemu_iovec_to_buf(aio_cb
->qiov
, bufidx
, data
, count
);
792 xport p
= xseg_submit(s
->xseg
, req
, s
->srcport
, X_ALLOC
);
794 archipelagolog("Could not submit XSEG request\n");
797 xseg_signal(s
->xseg
, p
);
802 xseg_put_request(s
->xseg
, req
, s
->srcport
);
809 static int archipelago_aio_segmented_rw(BDRVArchipelagoState
*s
,
812 ArchipelagoAIOCB
*aio_cb
,
815 int ret
, segments_nr
;
817 ArchipelagoSegmentedRequest
*segreq
;
819 segreq
= g_new0(ArchipelagoSegmentedRequest
, 1);
821 if (op
== ARCHIP_OP_FLUSH
) {
824 segments_nr
= (int)(count
/ MAX_REQUEST_SIZE
) + \
825 ((count
% MAX_REQUEST_SIZE
) ? 1 : 0);
827 segreq
->total
= count
;
828 atomic_mb_set(&segreq
->ref
, segments_nr
);
830 while (segments_nr
> 1) {
831 ret
= archipelago_submit_request(s
, pos
,
839 count
-= MAX_REQUEST_SIZE
;
840 pos
+= MAX_REQUEST_SIZE
;
843 ret
= archipelago_submit_request(s
, pos
, count
, offset
+ pos
,
853 if (atomic_fetch_sub(&segreq
->ref
, segments_nr
) == segments_nr
) {
859 static BlockAIOCB
*qemu_archipelago_aio_rw(BlockDriverState
*bs
,
863 BlockCompletionFunc
*cb
,
867 ArchipelagoAIOCB
*aio_cb
;
868 BDRVArchipelagoState
*s
= bs
->opaque
;
872 aio_cb
= qemu_aio_get(&archipelago_aiocb_info
, bs
, cb
, opaque
);
878 aio_cb
->status
= -EINPROGRESS
;
880 off
= sector_num
* BDRV_SECTOR_SIZE
;
881 size
= nb_sectors
* BDRV_SECTOR_SIZE
;
884 ret
= archipelago_aio_segmented_rw(s
, size
, off
,
889 return &aio_cb
->common
;
892 error_report("qemu_archipelago_aio_rw(): I/O Error");
893 qemu_aio_unref(aio_cb
);
897 static BlockAIOCB
*qemu_archipelago_aio_readv(BlockDriverState
*bs
,
898 int64_t sector_num
, QEMUIOVector
*qiov
, int nb_sectors
,
899 BlockCompletionFunc
*cb
, void *opaque
)
901 return qemu_archipelago_aio_rw(bs
, sector_num
, qiov
, nb_sectors
, cb
,
902 opaque
, ARCHIP_OP_READ
);
905 static BlockAIOCB
*qemu_archipelago_aio_writev(BlockDriverState
*bs
,
906 int64_t sector_num
, QEMUIOVector
*qiov
, int nb_sectors
,
907 BlockCompletionFunc
*cb
, void *opaque
)
909 return qemu_archipelago_aio_rw(bs
, sector_num
, qiov
, nb_sectors
, cb
,
910 opaque
, ARCHIP_OP_WRITE
);
913 static int64_t archipelago_volume_info(BDRVArchipelagoState
*s
)
917 struct xseg_request
*req
;
918 struct xseg_reply_info
*xinfo
;
919 AIORequestData
*reqdata
= g_new(AIORequestData
, 1);
921 const char *volname
= s
->volname
;
922 targetlen
= strlen(volname
);
923 req
= xseg_get_request(s
->xseg
, s
->srcport
, s
->mportno
, X_ALLOC
);
925 archipelagolog("Cannot get XSEG request\n");
928 ret
= xseg_prep_request(s
->xseg
, req
, targetlen
,
929 sizeof(struct xseg_reply_info
));
931 archipelagolog("Cannot prepare XSEG request\n");
934 char *target
= xseg_get_target(s
->xseg
, req
);
936 archipelagolog("Cannot get XSEG target\n");
939 memcpy(target
, volname
, targetlen
);
940 req
->size
= req
->datalen
;
944 reqdata
->op
= ARCHIP_OP_VOLINFO
;
945 reqdata
->volname
= volname
;
946 xseg_set_req_data(s
->xseg
, req
, reqdata
);
948 xport p
= xseg_submit(s
->xseg
, req
, s
->srcport
, X_ALLOC
);
950 archipelagolog("Cannot submit XSEG request\n");
953 xseg_signal(s
->xseg
, p
);
954 qemu_mutex_lock(&s
->archip_mutex
);
955 while (!s
->is_signaled
) {
956 qemu_cond_wait(&s
->archip_cond
, &s
->archip_mutex
);
958 s
->is_signaled
= false;
959 qemu_mutex_unlock(&s
->archip_mutex
);
961 xinfo
= (struct xseg_reply_info
*) xseg_get_data(s
->xseg
, req
);
963 xseg_put_request(s
->xseg
, req
, s
->srcport
);
969 xseg_put_request(s
->xseg
, req
, s
->srcport
);
975 static int64_t qemu_archipelago_getlength(BlockDriverState
*bs
)
977 BDRVArchipelagoState
*s
= bs
->opaque
;
979 return archipelago_volume_info(s
);
982 static int qemu_archipelago_truncate(BlockDriverState
*bs
, int64_t offset
)
985 struct xseg_request
*req
;
986 BDRVArchipelagoState
*s
= bs
->opaque
;
987 AIORequestData
*reqdata
= g_new(AIORequestData
, 1);
989 const char *volname
= s
->volname
;
990 targetlen
= strlen(volname
);
991 req
= xseg_get_request(s
->xseg
, s
->srcport
, s
->mportno
, X_ALLOC
);
993 archipelagolog("Cannot get XSEG request\n");
997 ret
= xseg_prep_request(s
->xseg
, req
, targetlen
, 0);
999 archipelagolog("Cannot prepare XSEG request\n");
1002 char *target
= xseg_get_target(s
->xseg
, req
);
1004 archipelagolog("Cannot get XSEG target\n");
1007 memcpy(target
, volname
, targetlen
);
1008 req
->offset
= offset
;
1009 req
->op
= X_TRUNCATE
;
1011 reqdata
->op
= ARCHIP_OP_TRUNCATE
;
1012 reqdata
->volname
= volname
;
1014 xseg_set_req_data(s
->xseg
, req
, reqdata
);
1016 xport p
= xseg_submit(s
->xseg
, req
, s
->srcport
, X_ALLOC
);
1018 archipelagolog("Cannot submit XSEG request\n");
1022 xseg_signal(s
->xseg
, p
);
1023 qemu_mutex_lock(&s
->archip_mutex
);
1024 while (!s
->is_signaled
) {
1025 qemu_cond_wait(&s
->archip_cond
, &s
->archip_mutex
);
1027 s
->is_signaled
= false;
1028 qemu_mutex_unlock(&s
->archip_mutex
);
1029 xseg_put_request(s
->xseg
, req
, s
->srcport
);
1034 xseg_put_request(s
->xseg
, req
, s
->srcport
);
1040 static QemuOptsList qemu_archipelago_create_opts
= {
1041 .name
= "archipelago-create-opts",
1042 .head
= QTAILQ_HEAD_INITIALIZER(qemu_archipelago_create_opts
.head
),
1045 .name
= BLOCK_OPT_SIZE
,
1046 .type
= QEMU_OPT_SIZE
,
1047 .help
= "Virtual disk size"
1049 { /* end of list */ }
1053 static BlockAIOCB
*qemu_archipelago_aio_flush(BlockDriverState
*bs
,
1054 BlockCompletionFunc
*cb
, void *opaque
)
1056 return qemu_archipelago_aio_rw(bs
, 0, NULL
, 0, cb
, opaque
,
1060 static BlockDriver bdrv_archipelago
= {
1061 .format_name
= "archipelago",
1062 .protocol_name
= "archipelago",
1063 .instance_size
= sizeof(BDRVArchipelagoState
),
1064 .bdrv_parse_filename
= archipelago_parse_filename
,
1065 .bdrv_file_open
= qemu_archipelago_open
,
1066 .bdrv_close
= qemu_archipelago_close
,
1067 .bdrv_create
= qemu_archipelago_create
,
1068 .bdrv_getlength
= qemu_archipelago_getlength
,
1069 .bdrv_truncate
= qemu_archipelago_truncate
,
1070 .bdrv_aio_readv
= qemu_archipelago_aio_readv
,
1071 .bdrv_aio_writev
= qemu_archipelago_aio_writev
,
1072 .bdrv_aio_flush
= qemu_archipelago_aio_flush
,
1073 .bdrv_has_zero_init
= bdrv_has_zero_init_1
,
1074 .create_opts
= &qemu_archipelago_create_opts
,
1077 static void bdrv_archipelago_init(void)
1079 bdrv_register(&bdrv_archipelago
);
1082 block_init(bdrv_archipelago_init
);