#include "qemu/osdep.h"
#include "qemu/cutils.h"
+#include "qemu/option.h"
#include "block/block_int.h"
-#include "qapi/qmp/qbool.h"
+#include "qapi/error.h"
+#include "qapi/qapi-events-block.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qerror.h"
-#include "qapi/qmp/qint.h"
-#include "qapi/qmp/qjson.h"
#include "qapi/qmp/qlist.h"
#include "qapi/qmp/qstring.h"
-#include "qapi-event.h"
#include "crypto/hash.h"
#define HASH_LENGTH 32
/* Request metadata */
uint64_t offset;
uint64_t bytes;
+ int flags;
QEMUIOVector *qiov; /* calling IOV */
static QuorumAIOCB *quorum_aio_get(BlockDriverState *bs,
QEMUIOVector *qiov,
uint64_t offset,
- uint64_t bytes)
+ uint64_t bytes,
+ int flags)
{
BDRVQuorumState *s = bs->opaque;
QuorumAIOCB *acb = g_new(QuorumAIOCB, 1);
.bs = bs,
.offset = offset,
.bytes = bytes,
+ .flags = flags,
.qiov = qiov,
.votes.compare = quorum_sha256_compare,
.votes.vote_list = QLIST_HEAD_INITIALIZER(acb.votes.vote_list),
BDRVQuorumState *s = acb->bs->opaque;
/* Ignore any errors, it's just a correction attempt for already
- * corrupted data. */
+ * corrupted data.
+ * Mask out BDRV_REQ_WRITE_UNCHANGED because this overwrites the
+ * area with different data from the other children. */
bdrv_co_pwritev(s->children[co->idx], acb->offset, acb->bytes,
- acb->qiov, 0);
+ acb->qiov, acb->flags & ~BDRV_REQ_WRITE_UNCHANGED);
/* Wake up the caller after the last rewrite */
acb->rewrite_count--;
uint64_t bytes, QEMUIOVector *qiov, int flags)
{
BDRVQuorumState *s = bs->opaque;
- QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes);
+ QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags);
int ret;
acb->is_read = true;
sacb->bs = s->children[i]->bs;
sacb->ret = bdrv_co_pwritev(s->children[i], acb->offset, acb->bytes,
- acb->qiov, 0);
+ acb->qiov, acb->flags);
if (sacb->ret == 0) {
acb->success_count++;
} else {
uint64_t bytes, QEMUIOVector *qiov, int flags)
{
BDRVQuorumState *s = bs->opaque;
- QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes);
+ QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags);
int i, ret;
for (i = 0; i < s->num_children; i++) {
for (i = 0; i < s->num_children; i++) {
result = bdrv_co_flush(s->children[i]->bs);
if (result) {
- quorum_report_bad(QUORUM_OP_TYPE_FLUSH, 0,
- bdrv_getlength(s->children[i]->bs),
+ quorum_report_bad(QUORUM_OP_TYPE_FLUSH, 0, 0,
s->children[i]->bs->node_name, result);
result_value.l = result;
quorum_count_vote(&error_votes, &result_value, i);
},
};
-static int parse_read_pattern(const char *opt)
-{
- int i;
-
- if (!opt) {
- /* Set quorum as default */
- return QUORUM_READ_PATTERN_QUORUM;
- }
-
- for (i = 0; i < QUORUM_READ_PATTERN__MAX; i++) {
- if (!strcmp(opt, QuorumReadPattern_lookup[i])) {
- return i;
- }
- }
-
- return -EINVAL;
-}
-
static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
BDRVQuorumState *s = bs->opaque;
Error *local_err = NULL;
QemuOpts *opts = NULL;
+ const char *pattern_str;
bool *opened;
int i;
int ret = 0;
goto exit;
}
- ret = parse_read_pattern(qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN));
+ pattern_str = qemu_opt_get(opts, QUORUM_OPT_READ_PATTERN);
+ if (!pattern_str) {
+ ret = QUORUM_READ_PATTERN_QUORUM;
+ } else {
+ ret = qapi_enum_parse(&QuorumReadPattern_lookup, pattern_str,
+ -EINVAL, NULL);
+ }
if (ret < 0) {
error_setg(&local_err, "Please set read-pattern as fifo or quorum");
goto exit;
}
s->next_child_index = s->num_children;
+ bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED;
+
g_free(opened);
goto exit;
children = qlist_new();
for (i = 0; i < s->num_children; i++) {
- QINCREF(s->children[i]->bs->full_open_options);
- qlist_append_obj(children,
- QOBJECT(s->children[i]->bs->full_open_options));
+ qlist_append(children,
+ qobject_ref(s->children[i]->bs->full_open_options));
}
opts = qdict_new();
- qdict_put_obj(opts, "driver", QOBJECT(qstring_from_str("quorum")));
- qdict_put_obj(opts, QUORUM_OPT_VOTE_THRESHOLD,
- QOBJECT(qint_from_int(s->threshold)));
- qdict_put_obj(opts, QUORUM_OPT_BLKVERIFY,
- QOBJECT(qbool_from_bool(s->is_blkverify)));
- qdict_put_obj(opts, QUORUM_OPT_REWRITE,
- QOBJECT(qbool_from_bool(s->rewrite_corrupted)));
- qdict_put_obj(opts, "children", QOBJECT(children));
+ qdict_put_str(opts, "driver", "quorum");
+ qdict_put_int(opts, QUORUM_OPT_VOTE_THRESHOLD, s->threshold);
+ qdict_put_bool(opts, QUORUM_OPT_BLKVERIFY, s->is_blkverify);
+ qdict_put_bool(opts, QUORUM_OPT_REWRITE, s->rewrite_corrupted);
+ qdict_put(opts, "children", children);
bs->full_open_options = opts;
}
static BlockDriver bdrv_quorum = {
.format_name = "quorum",
- .protocol_name = "quorum",
.instance_size = sizeof(BDRVQuorumState),
- .bdrv_file_open = quorum_open,
+ .bdrv_open = quorum_open,
.bdrv_close = quorum_close,
.bdrv_refresh_filename = quorum_refresh_filename,