[Qemu-devel] [PATCH V9 06/11] quorum: Add quorum mechanism.
Use gnutls's SHA-256 to compare versions. Signed-off-by: Benoit Canet --- block/Makefile.objs | 2 +- block/quorum.c| 321 +- configure | 36 ++ include/monitor/monitor.h | 2 + monitor.c | 2 + 5 files changed, 361 insertions(+), 2 deletions(-) diff --git a/block/Makefile.objs b/block/Makefile.objs index 05a65c2..adcdc21 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -3,7 +3,7 @@ block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-c block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o block-obj-y += qed-check.o block-obj-y += vhdx.o -block-obj-y += quorum.o +block-obj-$(CONFIG_QUORUM) += quorum.o block-obj-y += parallels.o blkdebug.o blkverify.o block-obj-y += snapshot.o qapi.o block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o diff --git a/block/quorum.c b/block/quorum.c index f0fc0e9..e235ac1 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -13,7 +13,43 @@ * See the COPYING file in the top-level directory. */ +#include +#include #include "block/block_int.h" +#include "qapi/qmp/qjson.h" + +#define HASH_LENGTH 32 + +/* This union hold a vote hash value */ +typedef union QuorumVoteValue { +char h[HASH_LENGTH]; /* SHA-256 hash */ +int64_t l; /* simpler 64 bits hash */ +} QuorumVoteValue; + +/* A vote item */ +typedef struct QuorumVoteItem { +int index; +QLIST_ENTRY(QuorumVoteItem) next; +} QuorumVoteItem; + +/* this structure is a vote version. A version is the set of vote sharing the + * same vote value. + * The set of vote will be tracked with the items field and it's count is + * vote_count. + */ +typedef struct QuorumVoteVersion { +QuorumVoteValue value; +int index; +int vote_count; +QLIST_HEAD(, QuorumVoteItem) items; +QLIST_ENTRY(QuorumVoteVersion) next; +} QuorumVoteVersion; + +/* this structure hold a group of vote versions together */ +typedef struct QuorumVotes { +QLIST_HEAD(, QuorumVoteVersion) vote_list; +int (*compare)(QuorumVoteValue *a, QuorumVoteValue *b); +} QuorumVotes; /* the following structure hold the state of one quorum instance */ typedef struct { @@ -60,10 +96,14 @@ struct QuorumAIOCB { int success_count; /* number of successfully completed AIOCB */ bool *finished; /* completion signal for cancel */ +QuorumVotes votes; + bool is_read; int vote_ret; }; +static void quorum_vote(QuorumAIOCB *acb); + static void quorum_aio_cancel(BlockDriverAIOCB *blockacb) { QuorumAIOCB *acb = container_of(blockacb, QuorumAIOCB, common); @@ -111,6 +151,10 @@ static void quorum_aio_finalize(QuorumAIOCB *acb) acb->aios[i].ret = 0; } +if (acb->vote_ret) { +ret = acb->vote_ret; +} + acb->common.cb(acb->common.opaque, ret); if (acb->finished) { *acb->finished = true; @@ -122,6 +166,11 @@ static void quorum_aio_finalize(QuorumAIOCB *acb) qemu_aio_release(acb); } +static int quorum_sha256_compare(QuorumVoteValue *a, QuorumVoteValue *b) +{ +return memcmp(a->h, b->h, HASH_LENGTH); +} + static QuorumAIOCB *quorum_aio_get(BDRVQuorumState *s, BlockDriverState *bs, QEMUIOVector *qiov, @@ -141,6 +190,7 @@ static QuorumAIOCB *quorum_aio_get(BDRVQuorumState *s, acb->count = 0; acb->success_count = 0; acb->finished = NULL; +acb->votes.compare = quorum_sha256_compare; acb->is_read = false; acb->vote_ret = 0; @@ -170,9 +220,278 @@ static void quorum_aio_cb(void *opaque, int ret) return; } +/* Do the vote on read */ +if (acb->is_read) { +quorum_vote(acb); +} + quorum_aio_finalize(acb); } +static void quorum_report_bad(QuorumAIOCB *acb, int index) +{ +QObject *data; +data = qobject_from_jsonf("{ 'children-index': %i" + ", 'sector-num': %" PRId64 + ", 'sectors-count': %i }", + index, + acb->sector_num, + acb->nb_sectors); +monitor_protocol_event(QEVENT_QUORUM_REPORT_BAD, data); +} + +static void quorum_report_failure(QuorumAIOCB *acb) +{ +QObject *data; +data = qobject_from_jsonf("{ 'sector-num': %" PRId64 + ", 'sectors-count': %i }", + acb->sector_num, + acb->nb_sectors); +monitor_protocol_event(QEVENT_QUORUM_FAILURE, data); +} + +static void quorum_report_bad_versions(QuorumAIOCB *acb, + QuorumVoteValue *value) +{ +QuorumVoteVersion *version; +QuorumVoteItem *item; + +QLIST_FOREACH(version, &acb->votes.vote_list, next) { +if (!acb->votes.compare(&version->value, value)) { +continue;
Re: [Qemu-devel] [PATCH V9 06/11] quorum: Add quorum mechanism.
On 2013-10-02 14:39, Benoît Canet wrote: Use gnutls's SHA-256 to compare versions. Wouldn't CRC32 suffice? (I don't really oppose using SHA, but taking in gnutls as a dependency just for comparing several memory areas seems a bit much to me) Signed-off-by: Benoit Canet --- block/Makefile.objs | 2 +- block/quorum.c| 321 +- configure | 36 ++ include/monitor/monitor.h | 2 + monitor.c | 2 + 5 files changed, 361 insertions(+), 2 deletions(-) diff --git a/block/Makefile.objs b/block/Makefile.objs index 05a65c2..adcdc21 100644 --- a/block/Makefile.objs +++ b/block/Makefile.objs @@ -3,7 +3,7 @@ block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-c block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o block-obj-y += qed-check.o block-obj-y += vhdx.o -block-obj-y += quorum.o +block-obj-$(CONFIG_QUORUM) += quorum.o block-obj-y += parallels.o blkdebug.o blkverify.o block-obj-y += snapshot.o qapi.o block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o diff --git a/block/quorum.c b/block/quorum.c index f0fc0e9..e235ac1 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -13,7 +13,43 @@ * See the COPYING file in the top-level directory. */ +#include +#include #include "block/block_int.h" +#include "qapi/qmp/qjson.h" + +#define HASH_LENGTH 32 + +/* This union hold a vote hash value */ *holds +typedef union QuorumVoteValue { +char h[HASH_LENGTH]; /* SHA-256 hash */ +int64_t l; /* simpler 64 bits hash */ +} QuorumVoteValue; + +/* A vote item */ +typedef struct QuorumVoteItem { +int index; +QLIST_ENTRY(QuorumVoteItem) next; +} QuorumVoteItem; + +/* this structure is a vote version. A version is the set of vote sharing the *set of votes + * same vote value. + * The set of vote will be tracked with the items field and it's count is *set of votes or *vote set; also s/it's count/its cardinality/ or something like that + * vote_count. + */ +typedef struct QuorumVoteVersion { +QuorumVoteValue value; +int index; +int vote_count; +QLIST_HEAD(, QuorumVoteItem) items; +QLIST_ENTRY(QuorumVoteVersion) next; +} QuorumVoteVersion; + +/* this structure hold a group of vote versions together */ *holds +typedef struct QuorumVotes { +QLIST_HEAD(, QuorumVoteVersion) vote_list; +int (*compare)(QuorumVoteValue *a, QuorumVoteValue *b); +} QuorumVotes; /* the following structure hold the state of one quorum instance */ typedef struct { @@ -60,10 +96,14 @@ struct QuorumAIOCB { int success_count; /* number of successfully completed AIOCB */ bool *finished; /* completion signal for cancel */ +QuorumVotes votes; + bool is_read; int vote_ret; }; +static void quorum_vote(QuorumAIOCB *acb); + static void quorum_aio_cancel(BlockDriverAIOCB *blockacb) { QuorumAIOCB *acb = container_of(blockacb, QuorumAIOCB, common); @@ -111,6 +151,10 @@ static void quorum_aio_finalize(QuorumAIOCB *acb) acb->aios[i].ret = 0; } +if (acb->vote_ret) { +ret = acb->vote_ret; +} + acb->common.cb(acb->common.opaque, ret); if (acb->finished) { *acb->finished = true; @@ -122,6 +166,11 @@ static void quorum_aio_finalize(QuorumAIOCB *acb) qemu_aio_release(acb); } +static int quorum_sha256_compare(QuorumVoteValue *a, QuorumVoteValue *b) +{ +return memcmp(a->h, b->h, HASH_LENGTH); +} + static QuorumAIOCB *quorum_aio_get(BDRVQuorumState *s, BlockDriverState *bs, QEMUIOVector *qiov, @@ -141,6 +190,7 @@ static QuorumAIOCB *quorum_aio_get(BDRVQuorumState *s, acb->count = 0; acb->success_count = 0; acb->finished = NULL; +acb->votes.compare = quorum_sha256_compare; acb->is_read = false; acb->vote_ret = 0; @@ -170,9 +220,278 @@ static void quorum_aio_cb(void *opaque, int ret) return; } +/* Do the vote on read */ +if (acb->is_read) { +quorum_vote(acb); +} + quorum_aio_finalize(acb); } +static void quorum_report_bad(QuorumAIOCB *acb, int index) +{ +QObject *data; +data = qobject_from_jsonf("{ 'children-index': %i" I'd prefer child-index. Generally, remember that the singular of "children" is "child". + ", 'sector-num': %" PRId64 + ", 'sectors-count': %i }", + index, + acb->sector_num, + acb->nb_sectors); +monitor_protocol_event(QEVENT_QUORUM_REPORT_BAD, data); How about decrementing the refcount of data? +} + +static void quorum_report_failure(QuorumAIOCB *acb) +{ +QObject *data; +data = qobject_from_jsonf("{ 'sector-num': %" PRId64 +
Re: [Qemu-devel] [PATCH V9 06/11] quorum: Add quorum mechanism.
Le Friday 04 Oct 2013 à 16:48:12 (+0200), Max Reitz a écrit : > On 2013-10-02 14:39, Benoît Canet wrote: > >Use gnutls's SHA-256 to compare versions. > Wouldn't CRC32 suffice? (I don't really oppose using SHA, but taking > in gnutls as a dependency just for comparing several memory areas > seems a bit much to me) Initially it gzip's addler32 was used but someone was concerned with the risk of collisions. Anyway the code fallback using hashes only when something wrong is detected so it won't impact the normal case. Best regards Benoît > > >Signed-off-by: Benoit Canet > >--- > > block/Makefile.objs | 2 +- > > block/quorum.c| 321 > > +- > > configure | 36 ++ > > include/monitor/monitor.h | 2 + > > monitor.c | 2 + > > 5 files changed, 361 insertions(+), 2 deletions(-) > > > >diff --git a/block/Makefile.objs b/block/Makefile.objs > >index 05a65c2..adcdc21 100644 > >--- a/block/Makefile.objs > >+++ b/block/Makefile.objs > >@@ -3,7 +3,7 @@ block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o > >qcow2-snapshot.o qcow2-c > > block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o > > block-obj-y += qed-check.o > > block-obj-y += vhdx.o > >-block-obj-y += quorum.o > >+block-obj-$(CONFIG_QUORUM) += quorum.o > > block-obj-y += parallels.o blkdebug.o blkverify.o > > block-obj-y += snapshot.o qapi.o > > block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o > >diff --git a/block/quorum.c b/block/quorum.c > >index f0fc0e9..e235ac1 100644 > >--- a/block/quorum.c > >+++ b/block/quorum.c > >@@ -13,7 +13,43 @@ > > * See the COPYING file in the top-level directory. > > */ > >+#include > >+#include > > #include "block/block_int.h" > >+#include "qapi/qmp/qjson.h" > >+ > >+#define HASH_LENGTH 32 > >+ > >+/* This union hold a vote hash value */ > *holds > > >+typedef union QuorumVoteValue { > >+char h[HASH_LENGTH]; /* SHA-256 hash */ > >+int64_t l; /* simpler 64 bits hash */ > >+} QuorumVoteValue; > >+ > >+/* A vote item */ > >+typedef struct QuorumVoteItem { > >+int index; > >+QLIST_ENTRY(QuorumVoteItem) next; > >+} QuorumVoteItem; > >+ > >+/* this structure is a vote version. A version is the set of vote sharing > >the > *set of votes > > >+ * same vote value. > >+ * The set of vote will be tracked with the items field and it's count is > *set of votes or *vote set; also s/it's count/its cardinality/ or > something like that > > >+ * vote_count. > >+ */ > >+typedef struct QuorumVoteVersion { > >+QuorumVoteValue value; > >+int index; > >+int vote_count; > >+QLIST_HEAD(, QuorumVoteItem) items; > >+QLIST_ENTRY(QuorumVoteVersion) next; > >+} QuorumVoteVersion; > >+ > >+/* this structure hold a group of vote versions together */ > *holds > > >+typedef struct QuorumVotes { > >+QLIST_HEAD(, QuorumVoteVersion) vote_list; > >+int (*compare)(QuorumVoteValue *a, QuorumVoteValue *b); > >+} QuorumVotes; > > /* the following structure hold the state of one quorum instance */ > > typedef struct { > >@@ -60,10 +96,14 @@ struct QuorumAIOCB { > > int success_count; /* number of successfully completed AIOCB > > */ > > bool *finished; /* completion signal for cancel */ > >+QuorumVotes votes; > >+ > > bool is_read; > > int vote_ret; > > }; > >+static void quorum_vote(QuorumAIOCB *acb); > >+ > > static void quorum_aio_cancel(BlockDriverAIOCB *blockacb) > > { > > QuorumAIOCB *acb = container_of(blockacb, QuorumAIOCB, common); > >@@ -111,6 +151,10 @@ static void quorum_aio_finalize(QuorumAIOCB *acb) > > acb->aios[i].ret = 0; > > } > >+if (acb->vote_ret) { > >+ret = acb->vote_ret; > >+} > >+ > > acb->common.cb(acb->common.opaque, ret); > > if (acb->finished) { > > *acb->finished = true; > >@@ -122,6 +166,11 @@ static void quorum_aio_finalize(QuorumAIOCB *acb) > > qemu_aio_release(acb); > > } > >+static int quorum_sha256_compare(QuorumVoteValue *a, QuorumVoteValue *b) > >+{ > >+return memcmp(a->h, b->h, HASH_LENGTH); > >+} > >+ > > static QuorumAIOCB *quorum_aio_get(BDRVQuorumState *s, > > BlockDriverState *bs, > > QEMUIOVector *qiov, > >@@ -141,6 +190,7 @@ static QuorumAIOCB *quorum_aio_get(BDRVQuorumState *s, > > acb->count = 0; > > acb->success_count = 0; > > acb->finished = NULL; > >+acb->votes.compare = quorum_sha256_compare; > > acb->is_read = false; > > acb->vote_ret = 0; > >@@ -170,9 +220,278 @@ static void quorum_aio_cb(void *opaque, int ret) > > return; > > } > >+/* Do the vote on read */ > >+if (acb->is_read) { > >+quorum_vote(acb); > >+} > >+ > > quorum_aio_finalize(acb); > > } > >+static void quorum_report_bad(QuorumAIOCB *acb, int index) > >+{ > >+QObject *data; > >
Re: [Qemu-devel] [PATCH V9 06/11] quorum: Add quorum mechanism.
Le Friday 04 Oct 2013 à 16:48:12 (+0200), Max Reitz a écrit : > On 2013-10-02 14:39, Benoît Canet wrote: > >Use gnutls's SHA-256 to compare versions. > Wouldn't CRC32 suffice? (I don't really oppose using SHA, but taking > in gnutls as a dependency just for comparing several memory areas > seems a bit much to me) > > >Signed-off-by: Benoit Canet > >--- > > block/Makefile.objs | 2 +- > > block/quorum.c| 321 > > +- > > configure | 36 ++ > > include/monitor/monitor.h | 2 + > > monitor.c | 2 + > > 5 files changed, 361 insertions(+), 2 deletions(-) > > > >diff --git a/block/Makefile.objs b/block/Makefile.objs > >index 05a65c2..adcdc21 100644 > >--- a/block/Makefile.objs > >+++ b/block/Makefile.objs > >@@ -3,7 +3,7 @@ block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o > >qcow2-snapshot.o qcow2-c > > block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o > > block-obj-y += qed-check.o > > block-obj-y += vhdx.o > >-block-obj-y += quorum.o > >+block-obj-$(CONFIG_QUORUM) += quorum.o > > block-obj-y += parallels.o blkdebug.o blkverify.o > > block-obj-y += snapshot.o qapi.o > > block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o > >diff --git a/block/quorum.c b/block/quorum.c > >index f0fc0e9..e235ac1 100644 > >--- a/block/quorum.c > >+++ b/block/quorum.c > >@@ -13,7 +13,43 @@ > > * See the COPYING file in the top-level directory. > > */ > >+#include > >+#include > > #include "block/block_int.h" > >+#include "qapi/qmp/qjson.h" > >+ > >+#define HASH_LENGTH 32 > >+ > >+/* This union hold a vote hash value */ > *holds > > >+typedef union QuorumVoteValue { > >+char h[HASH_LENGTH]; /* SHA-256 hash */ > >+int64_t l; /* simpler 64 bits hash */ > >+} QuorumVoteValue; > >+ > >+/* A vote item */ > >+typedef struct QuorumVoteItem { > >+int index; > >+QLIST_ENTRY(QuorumVoteItem) next; > >+} QuorumVoteItem; > >+ > >+/* this structure is a vote version. A version is the set of vote sharing > >the > *set of votes > > >+ * same vote value. > >+ * The set of vote will be tracked with the items field and it's count is > *set of votes or *vote set; also s/it's count/its cardinality/ or > something like that > > >+ * vote_count. > >+ */ > >+typedef struct QuorumVoteVersion { > >+QuorumVoteValue value; > >+int index; > >+int vote_count; > >+QLIST_HEAD(, QuorumVoteItem) items; > >+QLIST_ENTRY(QuorumVoteVersion) next; > >+} QuorumVoteVersion; > >+ > >+/* this structure hold a group of vote versions together */ > *holds > > >+typedef struct QuorumVotes { > >+QLIST_HEAD(, QuorumVoteVersion) vote_list; > >+int (*compare)(QuorumVoteValue *a, QuorumVoteValue *b); > >+} QuorumVotes; > > /* the following structure hold the state of one quorum instance */ > > typedef struct { > >@@ -60,10 +96,14 @@ struct QuorumAIOCB { > > int success_count; /* number of successfully completed AIOCB > > */ > > bool *finished; /* completion signal for cancel */ > >+QuorumVotes votes; > >+ > > bool is_read; > > int vote_ret; > > }; > >+static void quorum_vote(QuorumAIOCB *acb); > >+ > > static void quorum_aio_cancel(BlockDriverAIOCB *blockacb) > > { > > QuorumAIOCB *acb = container_of(blockacb, QuorumAIOCB, common); > >@@ -111,6 +151,10 @@ static void quorum_aio_finalize(QuorumAIOCB *acb) > > acb->aios[i].ret = 0; > > } > >+if (acb->vote_ret) { > >+ret = acb->vote_ret; > >+} > >+ > > acb->common.cb(acb->common.opaque, ret); > > if (acb->finished) { > > *acb->finished = true; > >@@ -122,6 +166,11 @@ static void quorum_aio_finalize(QuorumAIOCB *acb) > > qemu_aio_release(acb); > > } > >+static int quorum_sha256_compare(QuorumVoteValue *a, QuorumVoteValue *b) > >+{ > >+return memcmp(a->h, b->h, HASH_LENGTH); > >+} > >+ > > static QuorumAIOCB *quorum_aio_get(BDRVQuorumState *s, > > BlockDriverState *bs, > > QEMUIOVector *qiov, > >@@ -141,6 +190,7 @@ static QuorumAIOCB *quorum_aio_get(BDRVQuorumState *s, > > acb->count = 0; > > acb->success_count = 0; > > acb->finished = NULL; > >+acb->votes.compare = quorum_sha256_compare; > > acb->is_read = false; > > acb->vote_ret = 0; > >@@ -170,9 +220,278 @@ static void quorum_aio_cb(void *opaque, int ret) > > return; > > } > >+/* Do the vote on read */ > >+if (acb->is_read) { > >+quorum_vote(acb); > >+} > >+ > > quorum_aio_finalize(acb); > > } > >+static void quorum_report_bad(QuorumAIOCB *acb, int index) > >+{ > >+QObject *data; > >+data = qobject_from_jsonf("{ 'children-index': %i" > I'd prefer child-index. Generally, remember that the singular of > "children" is "child". > > >+ ", 'sector-num': %" PRId64 > >+
Re: [Qemu-devel] [PATCH V9 06/11] quorum: Add quorum mechanism.
Am 28.10.2013 13:31, schrieb Benoît Canet: > Le Friday 04 Oct 2013 à 16:48:12 (+0200), Max Reitz a écrit : >> On 2013-10-02 14:39, Benoît Canet wrote: >>> Use gnutls's SHA-256 to compare versions. >> Wouldn't CRC32 suffice? (I don't really oppose using SHA, but taking >> in gnutls as a dependency just for comparing several memory areas >> seems a bit much to me) > Initially it gzip's addler32 was used but someone was concerned with the risk > of collisions. > Anyway the code fallback using hashes only when something wrong is detected so > it won't impact the normal case. > > Best regards > > Benoît Yes, that's correct, but it adds a new dependency to qemu. Personally, I am unable to decide whether this is better than having a higher risk of collisions with CRC, so I'll leave the decision to someone more qualified (like you). ;-) Max
Re: [Qemu-devel] [PATCH V9 06/11] quorum: Add quorum mechanism.
Am 28.10.2013 14:04, schrieb Benoît Canet: > Le Friday 04 Oct 2013 à 16:48:12 (+0200), Max Reitz a écrit : >> On 2013-10-02 14:39, Benoît Canet wrote: >>> Use gnutls's SHA-256 to compare versions. >> Wouldn't CRC32 suffice? (I don't really oppose using SHA, but taking >> in gnutls as a dependency just for comparing several memory areas >> seems a bit much to me) >> >>> Signed-off-by: Benoit Canet >>> --- >>> block/Makefile.objs | 2 +- >>> block/quorum.c| 321 >>> +- >>> configure | 36 ++ >>> include/monitor/monitor.h | 2 + >>> monitor.c | 2 + >>> 5 files changed, 361 insertions(+), 2 deletions(-) >>> >>> diff --git a/block/Makefile.objs b/block/Makefile.objs >>> index 05a65c2..adcdc21 100644 >>> --- a/block/Makefile.objs >>> +++ b/block/Makefile.objs >>> @@ -3,7 +3,7 @@ block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o >>> qcow2-snapshot.o qcow2-c >>> block-obj-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o >>> block-obj-y += qed-check.o >>> block-obj-y += vhdx.o >>> -block-obj-y += quorum.o >>> +block-obj-$(CONFIG_QUORUM) += quorum.o >>> block-obj-y += parallels.o blkdebug.o blkverify.o >>> block-obj-y += snapshot.o qapi.o >>> block-obj-$(CONFIG_WIN32) += raw-win32.o win32-aio.o >>> diff --git a/block/quorum.c b/block/quorum.c >>> index f0fc0e9..e235ac1 100644 >>> --- a/block/quorum.c >>> +++ b/block/quorum.c >>> @@ -13,7 +13,43 @@ >>> * See the COPYING file in the top-level directory. >>> */ >>> +#include >>> +#include >>> #include "block/block_int.h" >>> +#include "qapi/qmp/qjson.h" >>> + >>> +#define HASH_LENGTH 32 >>> + >>> +/* This union hold a vote hash value */ >> *holds >> >>> +typedef union QuorumVoteValue { >>> +char h[HASH_LENGTH]; /* SHA-256 hash */ >>> +int64_t l; /* simpler 64 bits hash */ >>> +} QuorumVoteValue; >>> + >>> +/* A vote item */ >>> +typedef struct QuorumVoteItem { >>> +int index; >>> +QLIST_ENTRY(QuorumVoteItem) next; >>> +} QuorumVoteItem; >>> + >>> +/* this structure is a vote version. A version is the set of vote sharing >>> the >> *set of votes >> >>> + * same vote value. >>> + * The set of vote will be tracked with the items field and it's count is >> *set of votes or *vote set; also s/it's count/its cardinality/ or >> something like that >> >>> + * vote_count. >>> + */ >>> +typedef struct QuorumVoteVersion { >>> +QuorumVoteValue value; >>> +int index; >>> +int vote_count; >>> +QLIST_HEAD(, QuorumVoteItem) items; >>> +QLIST_ENTRY(QuorumVoteVersion) next; >>> +} QuorumVoteVersion; >>> + >>> +/* this structure hold a group of vote versions together */ >> *holds >> >>> +typedef struct QuorumVotes { >>> +QLIST_HEAD(, QuorumVoteVersion) vote_list; >>> +int (*compare)(QuorumVoteValue *a, QuorumVoteValue *b); >>> +} QuorumVotes; >>> /* the following structure hold the state of one quorum instance */ >>> typedef struct { >>> @@ -60,10 +96,14 @@ struct QuorumAIOCB { >>> int success_count; /* number of successfully completed AIOCB >>> */ >>> bool *finished; /* completion signal for cancel */ >>> +QuorumVotes votes; >>> + >>> bool is_read; >>> int vote_ret; >>> }; >>> +static void quorum_vote(QuorumAIOCB *acb); >>> + >>> static void quorum_aio_cancel(BlockDriverAIOCB *blockacb) >>> { >>> QuorumAIOCB *acb = container_of(blockacb, QuorumAIOCB, common); >>> @@ -111,6 +151,10 @@ static void quorum_aio_finalize(QuorumAIOCB *acb) >>> acb->aios[i].ret = 0; >>> } >>> +if (acb->vote_ret) { >>> +ret = acb->vote_ret; >>> +} >>> + >>> acb->common.cb(acb->common.opaque, ret); >>> if (acb->finished) { >>> *acb->finished = true; >>> @@ -122,6 +166,11 @@ static void quorum_aio_finalize(QuorumAIOCB *acb) >>> qemu_aio_release(acb); >>> } >>> +static int quorum_sha256_compare(QuorumVoteValue *a, QuorumVoteValue *b) >>> +{ >>> +return memcmp(a->h, b->h, HASH_LENGTH); >>> +} >>> + >>> static QuorumAIOCB *quorum_aio_get(BDRVQuorumState *s, >>> BlockDriverState *bs, >>> QEMUIOVector *qiov, >>> @@ -141,6 +190,7 @@ static QuorumAIOCB *quorum_aio_get(BDRVQuorumState *s, >>> acb->count = 0; >>> acb->success_count = 0; >>> acb->finished = NULL; >>> +acb->votes.compare = quorum_sha256_compare; >>> acb->is_read = false; >>> acb->vote_ret = 0; >>> @@ -170,9 +220,278 @@ static void quorum_aio_cb(void *opaque, int ret) >>> return; >>> } >>> +/* Do the vote on read */ >>> +if (acb->is_read) { >>> +quorum_vote(acb); >>> +} >>> + >>> quorum_aio_finalize(acb); >>> } >>> +static void quorum_report_bad(QuorumAIOCB *acb, int index) >>> +{ >>> +QObject *data; >>> +data = qobject_from_jsonf("{ 'children-index': %i" >> I'd prefer child-index. Generally,