quorum: Add quorum_aio_writev and its dependencies.
Writes are mirrored num_children times on num_children devices. Signed-off-by: Benoit Canet <benoit@irqsave.net> Reviewed-by: Max Reitz <mreitz@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
		
							
								
								
									
										103
									
								
								block/quorum.c
									
									
									
									
									
								
							
							
						
						
									
										103
									
								
								block/quorum.c
									
									
									
									
									
								
							| @@ -69,11 +69,114 @@ struct QuorumAIOCB { | ||||
|     int vote_ret; | ||||
| }; | ||||
|  | ||||
| static void quorum_aio_cancel(BlockDriverAIOCB *blockacb) | ||||
| { | ||||
|     QuorumAIOCB *acb = container_of(blockacb, QuorumAIOCB, common); | ||||
|     BDRVQuorumState *s = acb->common.bs->opaque; | ||||
|     int i; | ||||
|  | ||||
|     /* cancel all callbacks */ | ||||
|     for (i = 0; i < s->num_children; i++) { | ||||
|         bdrv_aio_cancel(acb->qcrs[i].aiocb); | ||||
|     } | ||||
|  | ||||
|     g_free(acb->qcrs); | ||||
|     qemu_aio_release(acb); | ||||
| } | ||||
|  | ||||
| static AIOCBInfo quorum_aiocb_info = { | ||||
|     .aiocb_size         = sizeof(QuorumAIOCB), | ||||
|     .cancel             = quorum_aio_cancel, | ||||
| }; | ||||
|  | ||||
| static void quorum_aio_finalize(QuorumAIOCB *acb) | ||||
| { | ||||
|     int ret = 0; | ||||
|  | ||||
|     acb->common.cb(acb->common.opaque, ret); | ||||
|  | ||||
|     g_free(acb->qcrs); | ||||
|     qemu_aio_release(acb); | ||||
| } | ||||
|  | ||||
| static QuorumAIOCB *quorum_aio_get(BDRVQuorumState *s, | ||||
|                                    BlockDriverState *bs, | ||||
|                                    QEMUIOVector *qiov, | ||||
|                                    uint64_t sector_num, | ||||
|                                    int nb_sectors, | ||||
|                                    BlockDriverCompletionFunc *cb, | ||||
|                                    void *opaque) | ||||
| { | ||||
|     QuorumAIOCB *acb = qemu_aio_get(&quorum_aiocb_info, bs, cb, opaque); | ||||
|     int i; | ||||
|  | ||||
|     acb->common.bs->opaque = s; | ||||
|     acb->sector_num = sector_num; | ||||
|     acb->nb_sectors = nb_sectors; | ||||
|     acb->qiov = qiov; | ||||
|     acb->qcrs = g_new0(QuorumChildRequest, s->num_children); | ||||
|     acb->count = 0; | ||||
|     acb->success_count = 0; | ||||
|     acb->is_read = false; | ||||
|     acb->vote_ret = 0; | ||||
|  | ||||
|     for (i = 0; i < s->num_children; i++) { | ||||
|         acb->qcrs[i].buf = NULL; | ||||
|         acb->qcrs[i].ret = 0; | ||||
|         acb->qcrs[i].parent = acb; | ||||
|     } | ||||
|  | ||||
|     return acb; | ||||
| } | ||||
|  | ||||
| static void quorum_aio_cb(void *opaque, int ret) | ||||
| { | ||||
|     QuorumChildRequest *sacb = opaque; | ||||
|     QuorumAIOCB *acb = sacb->parent; | ||||
|     BDRVQuorumState *s = acb->common.bs->opaque; | ||||
|  | ||||
|     sacb->ret = ret; | ||||
|     acb->count++; | ||||
|     if (ret == 0) { | ||||
|         acb->success_count++; | ||||
|     } | ||||
|     assert(acb->count <= s->num_children); | ||||
|     assert(acb->success_count <= s->num_children); | ||||
|     if (acb->count < s->num_children) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     quorum_aio_finalize(acb); | ||||
| } | ||||
|  | ||||
| static BlockDriverAIOCB *quorum_aio_writev(BlockDriverState *bs, | ||||
|                                           int64_t sector_num, | ||||
|                                           QEMUIOVector *qiov, | ||||
|                                           int nb_sectors, | ||||
|                                           BlockDriverCompletionFunc *cb, | ||||
|                                           void *opaque) | ||||
| { | ||||
|     BDRVQuorumState *s = bs->opaque; | ||||
|     QuorumAIOCB *acb = quorum_aio_get(s, bs, qiov, sector_num, nb_sectors, | ||||
|                                       cb, opaque); | ||||
|     int i; | ||||
|  | ||||
|     for (i = 0; i < s->num_children; i++) { | ||||
|         acb->qcrs[i].aiocb = bdrv_aio_writev(s->bs[i], sector_num, qiov, | ||||
|                                              nb_sectors, &quorum_aio_cb, | ||||
|                                              &acb->qcrs[i]); | ||||
|     } | ||||
|  | ||||
|     return &acb->common; | ||||
| } | ||||
|  | ||||
| static BlockDriver bdrv_quorum = { | ||||
|     .format_name        = "quorum", | ||||
|     .protocol_name      = "quorum", | ||||
|  | ||||
|     .instance_size      = sizeof(BDRVQuorumState), | ||||
|  | ||||
|     .bdrv_aio_writev    = quorum_aio_writev, | ||||
| }; | ||||
|  | ||||
| static void bdrv_quorum_init(void) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user