sheepdog: multiplex the rw FD to flush cache

This will reduce sockfds connected to the sheep server to one, which simply the
future hacks.

Cc: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
Cc: Kevin Wolf <kwolf@redhat.com>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Liu Yuan <tailai.ly@taobao.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Liu Yuan 2013-01-15 16:28:55 +08:00 committed by Stefan Hajnoczi
parent df702c9b4c
commit 4778307278

View File

@ -266,6 +266,7 @@ typedef struct AIOReq {
enum AIOCBState { enum AIOCBState {
AIOCB_WRITE_UDATA, AIOCB_WRITE_UDATA,
AIOCB_READ_UDATA, AIOCB_READ_UDATA,
AIOCB_FLUSH_CACHE,
}; };
struct SheepdogAIOCB { struct SheepdogAIOCB {
@ -299,7 +300,6 @@ typedef struct BDRVSheepdogState {
char *addr; char *addr;
char *port; char *port;
int fd; int fd;
int flush_fd;
CoMutex lock; CoMutex lock;
Coroutine *co_send; Coroutine *co_send;
@ -736,6 +736,13 @@ static void coroutine_fn aio_read_response(void *opaque)
goto out; goto out;
} }
break; break;
case AIOCB_FLUSH_CACHE:
if (rsp.result == SD_RES_INVALID_PARMS) {
dprintf("disable cache since the server doesn't support it\n");
s->cache_flags = SD_FLAG_CMD_DIRECT;
rsp.result = SD_RES_SUCCESS;
}
break;
} }
if (rsp.result != SD_RES_SUCCESS) { if (rsp.result != SD_RES_SUCCESS) {
@ -950,7 +957,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
{ {
int nr_copies = s->inode.nr_copies; int nr_copies = s->inode.nr_copies;
SheepdogObjReq hdr; SheepdogObjReq hdr;
unsigned int wlen; unsigned int wlen = 0;
int ret; int ret;
uint64_t oid = aio_req->oid; uint64_t oid = aio_req->oid;
unsigned int datalen = aio_req->data_len; unsigned int datalen = aio_req->data_len;
@ -964,18 +971,23 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
memset(&hdr, 0, sizeof(hdr)); memset(&hdr, 0, sizeof(hdr));
if (aiocb_type == AIOCB_READ_UDATA) { switch (aiocb_type) {
wlen = 0; case AIOCB_FLUSH_CACHE:
hdr.opcode = SD_OP_FLUSH_VDI;
break;
case AIOCB_READ_UDATA:
hdr.opcode = SD_OP_READ_OBJ; hdr.opcode = SD_OP_READ_OBJ;
hdr.flags = flags; hdr.flags = flags;
} else if (create) { break;
case AIOCB_WRITE_UDATA:
if (create) {
hdr.opcode = SD_OP_CREATE_AND_WRITE_OBJ;
} else {
hdr.opcode = SD_OP_WRITE_OBJ;
}
wlen = datalen; wlen = datalen;
hdr.opcode = SD_OP_CREATE_AND_WRITE_OBJ;
hdr.flags = SD_FLAG_CMD_WRITE | flags;
} else {
wlen = datalen;
hdr.opcode = SD_OP_WRITE_OBJ;
hdr.flags = SD_FLAG_CMD_WRITE | flags; hdr.flags = SD_FLAG_CMD_WRITE | flags;
break;
} }
if (s->cache_flags) { if (s->cache_flags) {
@ -1127,15 +1139,6 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
s->cache_flags = SD_FLAG_CMD_DIRECT; s->cache_flags = SD_FLAG_CMD_DIRECT;
} }
if (s->cache_flags == SD_FLAG_CMD_CACHE) {
s->flush_fd = connect_to_sdog(s->addr, s->port);
if (s->flush_fd < 0) {
error_report("failed to connect");
ret = s->flush_fd;
goto out;
}
}
if (snapid || tag[0] != '\0') { if (snapid || tag[0] != '\0') {
dprintf("%" PRIx32 " snapshot inode was open.\n", vid); dprintf("%" PRIx32 " snapshot inode was open.\n", vid);
s->is_snapshot = true; s->is_snapshot = true;
@ -1397,9 +1400,6 @@ static void sd_close(BlockDriverState *bs)
qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL, NULL); qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL, NULL);
closesocket(s->fd); closesocket(s->fd);
if (s->cache_flags) {
closesocket(s->flush_fd);
}
g_free(s->addr); g_free(s->addr);
} }
@ -1711,39 +1711,31 @@ static coroutine_fn int sd_co_readv(BlockDriverState *bs, int64_t sector_num,
static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs) static int coroutine_fn sd_co_flush_to_disk(BlockDriverState *bs)
{ {
BDRVSheepdogState *s = bs->opaque; BDRVSheepdogState *s = bs->opaque;
SheepdogObjReq hdr = { 0 }; SheepdogAIOCB *acb;
SheepdogObjRsp *rsp = (SheepdogObjRsp *)&hdr; AIOReq *aio_req;
SheepdogInode *inode = &s->inode;
int ret; int ret;
unsigned int wlen = 0, rlen = 0;
if (s->cache_flags != SD_FLAG_CMD_CACHE) { if (s->cache_flags != SD_FLAG_CMD_CACHE) {
return 0; return 0;
} }
hdr.opcode = SD_OP_FLUSH_VDI; acb = sd_aio_setup(bs, NULL, 0, 0, NULL, NULL);
hdr.oid = vid_to_vdi_oid(inode->vdi_id); acb->aiocb_type = AIOCB_FLUSH_CACHE;
acb->aio_done_func = sd_finish_aiocb;
ret = do_req(s->flush_fd, (SheepdogReq *)&hdr, NULL, &wlen, &rlen); aio_req = alloc_aio_req(s, acb, vid_to_vdi_oid(s->inode.vdi_id),
if (ret) { 0, 0, 0, 0, 0);
error_report("failed to send a request to the sheep"); QLIST_INSERT_HEAD(&s->inflight_aio_head, aio_req, aio_siblings);
ret = add_aio_request(s, aio_req, NULL, 0, false, acb->aiocb_type);
if (ret < 0) {
error_report("add_aio_request is failed");
free_aio_req(s, aio_req);
qemu_aio_release(acb);
return ret; return ret;
} }
if (rsp->result == SD_RES_INVALID_PARMS) { qemu_coroutine_yield();
dprintf("disable write cache since the server doesn't support it\n"); return acb->ret;
s->cache_flags = SD_FLAG_CMD_DIRECT;
closesocket(s->flush_fd);
return 0;
}
if (rsp->result != SD_RES_SUCCESS) {
error_report("%s", sd_strerror(rsp->result));
return -EIO;
}
return 0;
} }
static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info) static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)