提交 6847da38 编写于 作者: K Kevin Wolf

quorum: Implement .bdrv_co_preadv/pwritev()

This enables byte granularity requests on quorum nodes.

Note that the QMP events emitted by the driver are an external API that
we were careless enough to define as sector based. The offset and length
of requests reported in events are rounded therefore.
Signed-off-by: NKevin Wolf <kwolf@redhat.com>
Reviewed-by: NEric Blake <eblake@redhat.com>
Reviewed-by: NAlberto Garcia <berto@igalia.com>
上级 dee66e28
...@@ -114,8 +114,8 @@ struct QuorumAIOCB { ...@@ -114,8 +114,8 @@ struct QuorumAIOCB {
Coroutine *co; Coroutine *co;
/* Request metadata */ /* Request metadata */
uint64_t sector_num; uint64_t offset;
int nb_sectors; uint64_t bytes;
QEMUIOVector *qiov; /* calling IOV */ QEMUIOVector *qiov; /* calling IOV */
...@@ -157,8 +157,8 @@ static bool quorum_64bits_compare(QuorumVoteValue *a, QuorumVoteValue *b) ...@@ -157,8 +157,8 @@ static bool quorum_64bits_compare(QuorumVoteValue *a, QuorumVoteValue *b)
static QuorumAIOCB *quorum_aio_get(BlockDriverState *bs, static QuorumAIOCB *quorum_aio_get(BlockDriverState *bs,
QEMUIOVector *qiov, QEMUIOVector *qiov,
uint64_t sector_num, uint64_t offset,
int nb_sectors) uint64_t bytes)
{ {
BDRVQuorumState *s = bs->opaque; BDRVQuorumState *s = bs->opaque;
QuorumAIOCB *acb = g_new(QuorumAIOCB, 1); QuorumAIOCB *acb = g_new(QuorumAIOCB, 1);
...@@ -166,8 +166,8 @@ static QuorumAIOCB *quorum_aio_get(BlockDriverState *bs, ...@@ -166,8 +166,8 @@ static QuorumAIOCB *quorum_aio_get(BlockDriverState *bs,
acb->co = qemu_coroutine_self(); acb->co = qemu_coroutine_self();
acb->bs = bs; acb->bs = bs;
acb->sector_num = sector_num; acb->offset = offset;
acb->nb_sectors = nb_sectors; acb->bytes = bytes;
acb->qiov = qiov; acb->qiov = qiov;
acb->qcrs = g_new0(QuorumChildRequest, s->num_children); acb->qcrs = g_new0(QuorumChildRequest, s->num_children);
acb->count = 0; acb->count = 0;
...@@ -187,23 +187,30 @@ static QuorumAIOCB *quorum_aio_get(BlockDriverState *bs, ...@@ -187,23 +187,30 @@ static QuorumAIOCB *quorum_aio_get(BlockDriverState *bs,
return acb; return acb;
} }
static void quorum_report_bad(QuorumOpType type, uint64_t sector_num, static void quorum_report_bad(QuorumOpType type, uint64_t offset,
int nb_sectors, char *node_name, int ret) uint64_t bytes, char *node_name, int ret)
{ {
const char *msg = NULL; const char *msg = NULL;
int64_t start_sector = offset / BDRV_SECTOR_SIZE;
int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);
if (ret < 0) { if (ret < 0) {
msg = strerror(-ret); msg = strerror(-ret);
} }
qapi_event_send_quorum_report_bad(type, !!msg, msg, node_name, qapi_event_send_quorum_report_bad(type, !!msg, msg, node_name, start_sector,
sector_num, nb_sectors, &error_abort); end_sector - start_sector, &error_abort);
} }
static void quorum_report_failure(QuorumAIOCB *acb) static void quorum_report_failure(QuorumAIOCB *acb)
{ {
const char *reference = bdrv_get_device_or_node_name(acb->bs); const char *reference = bdrv_get_device_or_node_name(acb->bs);
qapi_event_send_quorum_failure(reference, acb->sector_num, int64_t start_sector = acb->offset / BDRV_SECTOR_SIZE;
acb->nb_sectors, &error_abort); int64_t end_sector = DIV_ROUND_UP(acb->offset + acb->bytes,
BDRV_SECTOR_SIZE);
qapi_event_send_quorum_failure(reference, start_sector,
end_sector - start_sector, &error_abort);
} }
static int quorum_vote_error(QuorumAIOCB *acb); static int quorum_vote_error(QuorumAIOCB *acb);
...@@ -240,8 +247,7 @@ static void quorum_report_bad_acb(QuorumChildRequest *sacb, int ret) ...@@ -240,8 +247,7 @@ static void quorum_report_bad_acb(QuorumChildRequest *sacb, int ret)
{ {
QuorumAIOCB *acb = sacb->parent; QuorumAIOCB *acb = sacb->parent;
QuorumOpType type = acb->is_read ? QUORUM_OP_TYPE_READ : QUORUM_OP_TYPE_WRITE; QuorumOpType type = acb->is_read ? QUORUM_OP_TYPE_READ : QUORUM_OP_TYPE_WRITE;
quorum_report_bad(type, acb->sector_num, acb->nb_sectors, quorum_report_bad(type, acb->offset, acb->bytes, sacb->bs->node_name, ret);
sacb->bs->node_name, ret);
} }
static int quorum_fifo_aio_cb(void *opaque, int ret) static int quorum_fifo_aio_cb(void *opaque, int ret)
...@@ -280,8 +286,7 @@ static void quorum_report_bad_versions(BDRVQuorumState *s, ...@@ -280,8 +286,7 @@ static void quorum_report_bad_versions(BDRVQuorumState *s,
continue; continue;
} }
QLIST_FOREACH(item, &version->items, next) { QLIST_FOREACH(item, &version->items, next) {
quorum_report_bad(QUORUM_OP_TYPE_READ, acb->sector_num, quorum_report_bad(QUORUM_OP_TYPE_READ, acb->offset, acb->bytes,
acb->nb_sectors,
s->children[item->index]->bs->node_name, 0); s->children[item->index]->bs->node_name, 0);
} }
} }
...@@ -295,9 +300,7 @@ static void quorum_rewrite_entry(void *opaque) ...@@ -295,9 +300,7 @@ static void quorum_rewrite_entry(void *opaque)
/* Ignore any errors, it's just a correction attempt for already /* Ignore any errors, it's just a correction attempt for already
* corrupted data. */ * corrupted data. */
bdrv_co_pwritev(s->children[co->idx], bdrv_co_pwritev(s->children[co->idx], acb->offset, acb->bytes,
acb->sector_num * BDRV_SECTOR_SIZE,
acb->nb_sectors * BDRV_SECTOR_SIZE,
acb->qiov, 0); acb->qiov, 0);
/* Wake up the caller after the last rewrite */ /* Wake up the caller after the last rewrite */
...@@ -462,8 +465,8 @@ static void GCC_FMT_ATTR(2, 3) quorum_err(QuorumAIOCB *acb, ...@@ -462,8 +465,8 @@ static void GCC_FMT_ATTR(2, 3) quorum_err(QuorumAIOCB *acb,
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
fprintf(stderr, "quorum: sector_num=%" PRId64 " nb_sectors=%d ", fprintf(stderr, "quorum: offset=%" PRIu64 " bytes=%" PRIu64 " ",
acb->sector_num, acb->nb_sectors); acb->offset, acb->bytes);
vfprintf(stderr, fmt, ap); vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
va_end(ap); va_end(ap);
...@@ -481,9 +484,8 @@ static bool quorum_compare(QuorumAIOCB *acb, ...@@ -481,9 +484,8 @@ static bool quorum_compare(QuorumAIOCB *acb,
if (s->is_blkverify) { if (s->is_blkverify) {
offset = qemu_iovec_compare(a, b); offset = qemu_iovec_compare(a, b);
if (offset != -1) { if (offset != -1) {
quorum_err(acb, "contents mismatch in sector %" PRId64, quorum_err(acb, "contents mismatch at offset %" PRIu64,
acb->sector_num + acb->offset + offset);
(uint64_t)(offset / BDRV_SECTOR_SIZE));
} }
return true; return true;
} }
...@@ -612,9 +614,7 @@ static void read_quorum_children_entry(void *opaque) ...@@ -612,9 +614,7 @@ static void read_quorum_children_entry(void *opaque)
QuorumChildRequest *sacb = &acb->qcrs[i]; QuorumChildRequest *sacb = &acb->qcrs[i];
sacb->bs = s->children[i]->bs; sacb->bs = s->children[i]->bs;
sacb->ret = bdrv_co_preadv(s->children[i], sacb->ret = bdrv_co_preadv(s->children[i], acb->offset, acb->bytes,
acb->sector_num * BDRV_SECTOR_SIZE,
acb->nb_sectors * BDRV_SECTOR_SIZE,
&acb->qcrs[i].qiov, 0); &acb->qcrs[i].qiov, 0);
if (sacb->ret == 0) { if (sacb->ret == 0) {
...@@ -683,19 +683,17 @@ static int read_fifo_child(QuorumAIOCB *acb) ...@@ -683,19 +683,17 @@ static int read_fifo_child(QuorumAIOCB *acb)
int ret; int ret;
acb->qcrs[n].bs = s->children[n]->bs; acb->qcrs[n].bs = s->children[n]->bs;
ret = bdrv_co_preadv(s->children[n], acb->sector_num * BDRV_SECTOR_SIZE, ret = bdrv_co_preadv(s->children[n], acb->offset, acb->bytes, acb->qiov, 0);
acb->nb_sectors * BDRV_SECTOR_SIZE, acb->qiov, 0);
ret = quorum_fifo_aio_cb(&acb->qcrs[n], ret); ret = quorum_fifo_aio_cb(&acb->qcrs[n], ret);
return ret; return ret;
} }
static int quorum_co_readv(BlockDriverState *bs, static int quorum_co_preadv(BlockDriverState *bs, uint64_t offset,
int64_t sector_num, int nb_sectors, uint64_t bytes, QEMUIOVector *qiov, int flags)
QEMUIOVector *qiov)
{ {
BDRVQuorumState *s = bs->opaque; BDRVQuorumState *s = bs->opaque;
QuorumAIOCB *acb = quorum_aio_get(bs, qiov, sector_num, nb_sectors); QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes);
int ret; int ret;
acb->is_read = true; acb->is_read = true;
...@@ -720,9 +718,7 @@ static void write_quorum_entry(void *opaque) ...@@ -720,9 +718,7 @@ static void write_quorum_entry(void *opaque)
QuorumChildRequest *sacb = &acb->qcrs[i]; QuorumChildRequest *sacb = &acb->qcrs[i];
sacb->bs = s->children[i]->bs; sacb->bs = s->children[i]->bs;
sacb->ret = bdrv_co_pwritev(s->children[i], sacb->ret = bdrv_co_pwritev(s->children[i], acb->offset, acb->bytes,
acb->sector_num * BDRV_SECTOR_SIZE,
acb->nb_sectors * BDRV_SECTOR_SIZE,
acb->qiov, 0); acb->qiov, 0);
if (sacb->ret == 0) { if (sacb->ret == 0) {
acb->success_count++; acb->success_count++;
...@@ -739,12 +735,11 @@ static void write_quorum_entry(void *opaque) ...@@ -739,12 +735,11 @@ static void write_quorum_entry(void *opaque)
} }
} }
static int quorum_co_writev(BlockDriverState *bs, static int quorum_co_pwritev(BlockDriverState *bs, uint64_t offset,
int64_t sector_num, int nb_sectors, uint64_t bytes, QEMUIOVector *qiov, int flags)
QEMUIOVector *qiov)
{ {
BDRVQuorumState *s = bs->opaque; BDRVQuorumState *s = bs->opaque;
QuorumAIOCB *acb = quorum_aio_get(bs, qiov, sector_num, nb_sectors); QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes);
int i, ret; int i, ret;
for (i = 0; i < s->num_children; i++) { for (i = 0; i < s->num_children; i++) {
...@@ -811,7 +806,7 @@ static coroutine_fn int quorum_co_flush(BlockDriverState *bs) ...@@ -811,7 +806,7 @@ static coroutine_fn int quorum_co_flush(BlockDriverState *bs)
result = bdrv_co_flush(s->children[i]->bs); result = bdrv_co_flush(s->children[i]->bs);
if (result) { if (result) {
quorum_report_bad(QUORUM_OP_TYPE_FLUSH, 0, quorum_report_bad(QUORUM_OP_TYPE_FLUSH, 0,
bdrv_nb_sectors(s->children[i]->bs), bdrv_getlength(s->children[i]->bs),
s->children[i]->bs->node_name, result); s->children[i]->bs->node_name, result);
result_value.l = result; result_value.l = result;
quorum_count_vote(&error_votes, &result_value, i); quorum_count_vote(&error_votes, &result_value, i);
...@@ -1144,8 +1139,8 @@ static BlockDriver bdrv_quorum = { ...@@ -1144,8 +1139,8 @@ static BlockDriver bdrv_quorum = {
.bdrv_getlength = quorum_getlength, .bdrv_getlength = quorum_getlength,
.bdrv_co_readv = quorum_co_readv, .bdrv_co_preadv = quorum_co_preadv,
.bdrv_co_writev = quorum_co_writev, .bdrv_co_pwritev = quorum_co_pwritev,
.bdrv_add_child = quorum_add_child, .bdrv_add_child = quorum_add_child,
.bdrv_del_child = quorum_del_child, .bdrv_del_child = quorum_del_child,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册