diff --git a/lib/Makefile.am b/lib/Makefile.am index dfb2fb077..a777a2b2e 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -6,7 +6,7 @@ lib_LTLIBRARIES = libsheepdog.la libsheepdog_la_DEPENDENCIES = -libsheepdog_la_SOURCES = shared/sheep.c shared/vdi.c util.c +libsheepdog_la_SOURCES = shared/sheep.c shared/vdi.c shared/ops.c util.c libsheepdog_la_LDFLAGS = -avoid-version -shared -module -export-dynamic \ -export-symbols-regex 'sd_' diff --git a/lib/shared/internal.h b/lib/shared/internal.h index dd3647fd2..daf1c09de 100644 --- a/lib/shared/internal.h +++ b/lib/shared/internal.h @@ -14,15 +14,76 @@ #ifndef INTERNAL_H_ #define INTERNAL_H_ +enum sheep_request_type { + VDI_READ = 1, + VDI_WRITE, + VDI_CREATE, + SHEEP_CTL, +}; + struct sd_request { + struct sd_cluster *cluster; struct list_node list; - struct sd_vdi *vdi; + union { + struct sd_vdi *vdi; + struct sd_req *hdr; + }; void *data; size_t length; off_t offset; - bool write; + uint8_t opcode; int efd; int ret; }; +struct sheep_aiocb { + struct sd_request *request; + off_t offset; + size_t length; + int ret; + uint32_t nr_requests; + char *buf; + int buf_iter; + const struct sd_op_template *op; + void (*aio_done_func)(struct sheep_aiocb *); +}; + +struct sheep_request { + struct list_node list; + struct sheep_aiocb *aiocb; + uint64_t oid; + uint64_t cow_oid; + uint32_t seq_num; + uint8_t opcode; + uint32_t offset; + uint32_t length; + char *buf; +}; + +struct sd_op_template { + const char *name; + int (*request_process)(struct sheep_aiocb *aiocb); + int (*response_process)(struct sheep_request *req, struct sd_rsp *rsp); +}; + +struct sheep_request *find_inflight_request_oid(struct sd_cluster *c, + uint64_t oid); +struct sheep_request *alloc_sheep_request(struct sheep_aiocb *aiocb, + uint64_t oid, uint64_t cow_oid, + int len, int offset); +int end_sheep_request(struct sheep_request *req); +int sheep_submit_sdreq(struct sd_cluster *c, struct sd_req *hdr, + void *data, uint32_t wlen); +int submit_sheep_request(struct sheep_request *req); + +const struct sd_op_template *get_sd_op(uint8_t opcode); +void submit_blocking_sheep_request(struct sd_cluster *c, uint64_t oid); + +uint32_t sheep_inode_get_vid(struct sd_request *req, uint32_t idx); + +struct sd_request *alloc_request(struct sd_cluster *c, void *data, + size_t count, uint8_t op); +void queue_request(struct sd_request *req); +void free_request(struct sd_request *req); + #endif diff --git a/lib/shared/ops.c b/lib/shared/ops.c new file mode 100644 index 000000000..1fd3e69cc --- /dev/null +++ b/lib/shared/ops.c @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2015 China Mobile Inc. + * + * Wang Zhengyong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "sheepdog.h" +#include "internal.h" + +static int vdi_rw_request(struct sheep_aiocb *aiocb) +{ + struct sd_request *request = aiocb->request; + uint64_t offset = aiocb->offset; + uint64_t total = aiocb->length; + int start = offset % SD_DATA_OBJ_SIZE; + uint32_t idx = offset / SD_DATA_OBJ_SIZE; + int len = SD_DATA_OBJ_SIZE - start; + struct sd_cluster *c = request->cluster; + + if (total < len) + len = total; + + /* + * Make sure we don't free the aiocb before we are done with all + * requests.This additional reference is dropped at the end of this + * function. + */ + uatomic_inc(&aiocb->nr_requests); + + do { + struct sheep_request *req; + uint64_t oid = vid_to_data_oid(request->vdi->vid, idx), + cow_oid = 0; + uint32_t vid = sheep_inode_get_vid(request, idx); + + /* + * For read, either read cow object or end the request. + * For write, copy-on-write cow object + */ + if (vid && vid != request->vdi->vid) { + if (VDI_WRITE == request->opcode) + cow_oid = vid_to_data_oid(vid, idx); + else + oid = vid_to_data_oid(vid, idx); + } + + req = alloc_sheep_request(aiocb, oid, cow_oid, len, start); + if (vid && !cow_oid) + goto submit; + + switch (req->opcode) { + case VDI_WRITE: + /* + * Sheepdog can't handle concurrent creation on the same + * object. We send one create req first and then send + * write reqs in next. + */ + if (find_inflight_request_oid(c, oid)) { + uint32_t tmp_vid; + + sd_write_lock(&c->blocking_lock); + /* + * There are slim chance object was created + * before we grab blocking_lock + */ + tmp_vid = sheep_inode_get_vid(request, idx); + if (tmp_vid && tmp_vid == request->vdi->vid) { + sd_rw_unlock(&c->blocking_lock); + goto submit; + } + list_add_tail(&req->list, &c->blocking_list); + sd_rw_unlock(&c->blocking_lock); + goto done; + } + req->opcode = VDI_CREATE; + break; + case VDI_READ: + end_sheep_request(req); + goto done; + } +submit: + submit_sheep_request(req); +done: + idx++; + total -= len; + start = (start + len) % SD_DATA_OBJ_SIZE; + len = total > SD_DATA_OBJ_SIZE ? SD_DATA_OBJ_SIZE : total; + } while (total > 0); + + if (uatomic_sub_return(&aiocb->nr_requests, 1) <= 0) + aiocb->aio_done_func(aiocb); + + return SD_RES_SUCCESS; +} + +static int vdi_create_response(struct sheep_request *req, struct sd_rsp *rsp) +{ + struct sd_vdi *vdi; + struct sheep_request *new; + uint32_t vid, idx; + uint64_t oid; + struct sd_cluster *c = req->aiocb->request->cluster; + + vdi = req->aiocb->request->vdi; + + /* We need to update inode for create */ + new = xmalloc(sizeof(*new)); + vid = vdi->vid; + oid = vid_to_vdi_oid(vid); + idx = data_oid_to_idx(req->oid); + new->offset = SD_INODE_HEADER_SIZE + sizeof(vid) * idx; + new->length = sizeof(vid); + new->oid = oid; + new->cow_oid = 0; + new->aiocb = req->aiocb; + new->buf = (char *)&vid; + new->seq_num = uatomic_add_return(&c->seq_num, 1); + new->opcode = VDI_WRITE; + uatomic_inc(&req->aiocb->nr_requests); + INIT_LIST_NODE(&new->list); + + /* Make sure no request is queued while we update inode */ + sd_write_lock(&vdi->lock); + vdi->inode->data_vdi_id[idx] = vid; + sd_rw_unlock(&vdi->lock); + + submit_sheep_request(new); + submit_blocking_sheep_request(c, req->oid); + + return SD_RES_SUCCESS; +} + +static int sheep_ctl_request(struct sheep_aiocb *aiocb) +{ + struct sd_req *hdr = aiocb->request->hdr; + struct sd_cluster *c = aiocb->request->cluster; + struct sheep_request *request = xzalloc(sizeof(struct sheep_request)); + + INIT_LIST_NODE(&request->list); + request->offset = hdr->obj.offset; + request->length = hdr->data_length; + request->oid = hdr->obj.oid; + request->cow_oid = hdr->obj.cow_oid; + request->aiocb = aiocb; + request->buf = aiocb->buf; + request->seq_num = uatomic_add_return(&c->seq_num, 1); + request->opcode = SHEEP_CTL; + hdr->id = request->seq_num; + + sd_write_lock(&c->inflight_lock); + list_add_tail(&request->list, &c->inflight_list); + sd_rw_unlock(&c->inflight_lock); + + uint32_t wlen = 0; + + if (hdr->flags & SD_FLAG_CMD_WRITE) + wlen = hdr->data_length; + + uatomic_inc(&aiocb->nr_requests); + int ret = sheep_submit_sdreq(c, hdr, aiocb->buf, wlen); + eventfd_xwrite(c->reply_fd, 1); + + return ret; +} + +static int sheep_ctl_response(struct sheep_request *req, struct sd_rsp *rsp) +{ + memcpy(req->aiocb->request->hdr, rsp, sizeof(*rsp)); + req->aiocb->ret = rsp->result; + return SD_RES_SUCCESS; +} + +static struct sd_op_template sd_ops[] = { + [VDI_READ] = { + .name = "VDI WRITE", + .request_process = vdi_rw_request, + }, + [VDI_WRITE] = { + .name = "VDI WRITE", + .request_process = vdi_rw_request, + }, + [VDI_CREATE] = { + .name = "VDI CREATE", + /* The request is submitted by vdi_rw_request */ + .response_process = vdi_create_response, + }, + [SHEEP_CTL] = { + .name = "SHEEP CTL", + .request_process = sheep_ctl_request, + .response_process = sheep_ctl_response, + }, +}; + +const struct sd_op_template *get_sd_op(uint8_t opcode) +{ + return sd_ops + opcode; +} diff --git a/lib/shared/sheep.c b/lib/shared/sheep.c index 55fe32f9e..545eb63eb 100644 --- a/lib/shared/sheep.c +++ b/lib/shared/sheep.c @@ -20,36 +20,7 @@ #include #include -struct sheep_aiocb { - struct sd_request *request; - off_t offset; - size_t length; - int ret; - uint32_t nr_requests; - char *buf; - int buf_iter; - void (*aio_done_func)(struct sheep_aiocb *); -}; - -enum sheep_request_type { - VDI_READ, - VDI_WRITE, - VDI_CREATE, -}; - -struct sheep_request { - struct list_node list; - struct sheep_aiocb *aiocb; - uint64_t oid; - uint64_t cow_oid; - uint32_t seq_num; - int type; - uint32_t offset; - uint32_t length; - char *buf; -}; - -static int sheep_submit_sdreq(struct sd_cluster *c, struct sd_req *hdr, +int sheep_submit_sdreq(struct sd_cluster *c, struct sd_req *hdr, void *data, uint32_t wlen) { int ret; @@ -72,36 +43,21 @@ static int sheep_submit_sdreq(struct sd_cluster *c, struct sd_req *hdr, /* Run the request synchronously */ int sd_run_sdreq(struct sd_cluster *c, struct sd_req *hdr, void *data) { - struct sd_rsp *rsp = (struct sd_rsp *)hdr; - unsigned int wlen, rlen; + struct sd_request *req = alloc_request(c, data, + hdr->data_length, SHEEP_CTL); int ret; - if (hdr->flags & SD_FLAG_CMD_WRITE) { - wlen = hdr->data_length; - rlen = 0; - } else { - wlen = 0; - rlen = hdr->data_length; - } - - ret = sheep_submit_sdreq(c, hdr, data, wlen); - if (ret < 0) - return SD_RES_SYSTEM_ERROR; - - ret = xread(c->sockfd, rsp, sizeof(*rsp)); - if (ret < 0) + if (!req) return SD_RES_SYSTEM_ERROR; - if (rlen > rsp->data_length) - rlen = rsp->data_length; + req->hdr = hdr; + queue_request(req); - if (rlen) { - ret = xread(c->sockfd, data, rlen); - if (ret < 0) - return SD_RES_SYSTEM_ERROR; - } + eventfd_xread(req->efd); + ret = req->ret; + free_request(req); - return rsp->result; + return ret; } static void aio_end_request(struct sd_request *req, int ret) @@ -132,12 +88,12 @@ static struct sheep_aiocb *sheep_aiocb_setup(struct sd_request *req) return aiocb; } -static struct sheep_request *alloc_sheep_request(struct sheep_aiocb *aiocb, +struct sheep_request *alloc_sheep_request(struct sheep_aiocb *aiocb, uint64_t oid, uint64_t cow_oid, int len, int offset) { struct sheep_request *req = xzalloc(sizeof(*req)); - struct sd_cluster *c = aiocb->request->vdi->cluster; + struct sd_cluster *c = aiocb->request->cluster; req->offset = offset; req->length = len; @@ -146,31 +102,30 @@ static struct sheep_request *alloc_sheep_request(struct sheep_aiocb *aiocb, req->aiocb = aiocb; req->buf = aiocb->buf + aiocb->buf_iter; req->seq_num = uatomic_add_return(&c->seq_num, 1); - INIT_LIST_NODE(&req->list); - if (aiocb->request->write) - req->type = VDI_WRITE; - else - req->type = VDI_READ; - + req->opcode = aiocb->request->opcode; aiocb->buf_iter += len; + + INIT_LIST_NODE(&req->list); uatomic_inc(&aiocb->nr_requests); return req; } -static void end_sheep_request(struct sheep_request *req) +uint32_t sheep_inode_get_vid(struct sd_request *req, uint32_t idx) { - struct sheep_aiocb *aiocb = req->aiocb; + uint32_t vid; - if (uatomic_sub_return(&aiocb->nr_requests, 1) <= 0) - aiocb->aio_done_func(aiocb); - free(req); + sd_read_lock(&req->vdi->lock); + vid = req->vdi->inode->data_vdi_id[idx]; + sd_rw_unlock(&req->vdi->lock); + + return vid; } -static int submit_sheep_request(struct sheep_request *req) +int submit_sheep_request(struct sheep_request *req) { struct sd_req hdr = {}; - struct sd_cluster *c = req->aiocb->request->vdi->cluster; + struct sd_cluster *c = req->aiocb->request->cluster; int ret = 0; hdr.id = req->seq_num; @@ -183,10 +138,10 @@ static int submit_sheep_request(struct sheep_request *req) list_add_tail(&req->list, &c->inflight_list); sd_rw_unlock(&c->inflight_lock); - switch (req->type) { + switch (req->opcode) { case VDI_CREATE: case VDI_WRITE: - if (req->type == VDI_CREATE) + if (req->opcode == VDI_CREATE) hdr.opcode = SD_OP_CREATE_AND_WRITE_OBJ; else hdr.opcode = SD_OP_WRITE_OBJ; @@ -209,19 +164,21 @@ static int submit_sheep_request(struct sheep_request *req) return ret; } -static uint32_t sheep_inode_get_vid(struct sd_request *req, uint32_t idx) +void submit_blocking_sheep_request(struct sd_cluster *c, uint64_t oid) { - uint32_t vid; - - sd_read_lock(&req->vdi->lock); - vid = req->vdi->inode->data_vdi_id[idx]; - sd_rw_unlock(&req->vdi->lock); + struct sheep_request *req; - return vid; + sd_write_lock(&c->blocking_lock); + list_for_each_entry(req, &c->blocking_list, list) { + if (req->oid != oid) + continue; + list_del(&req->list); + submit_sheep_request(req); + } + sd_rw_unlock(&c->blocking_lock); } - -static struct sheep_request *find_inflight_request_oid(struct sd_cluster *c, +struct sheep_request *find_inflight_request_oid(struct sd_cluster *c, uint64_t oid) { struct sheep_request *req; @@ -240,87 +197,15 @@ static struct sheep_request *find_inflight_request_oid(struct sd_cluster *c, static int sheep_aiocb_submit(struct sheep_aiocb *aiocb) { struct sd_request *request = aiocb->request; - uint64_t offset = aiocb->offset; - uint64_t total = aiocb->length; - int start = offset % SD_DATA_OBJ_SIZE; - uint32_t idx = offset / SD_DATA_OBJ_SIZE; - int len = SD_DATA_OBJ_SIZE - start; - struct sd_cluster *c = request->vdi->cluster; - - if (total < len) - len = total; - - /* - * Make sure we don't free the aiocb before we are done with all - * requests.This additional reference is dropped at the end of this - * function. - */ - uatomic_inc(&aiocb->nr_requests); + uint8_t opcode = request->opcode; + int ret = -1; - do { - struct sheep_request *req; - uint64_t oid = vid_to_data_oid(request->vdi->vid, idx), - cow_oid = 0; - uint32_t vid = sheep_inode_get_vid(request, idx); - - /* - * For read, either read cow object or end the request. - * For write, copy-on-write cow object - */ - if (vid && vid != request->vdi->vid) { - if (request->write) - cow_oid = vid_to_data_oid(vid, idx); - else - oid = vid_to_data_oid(vid, idx); - } + aiocb->op = get_sd_op(opcode); - req = alloc_sheep_request(aiocb, oid, cow_oid, len, start); - if (vid && !cow_oid) - goto submit; - - switch (req->type) { - case VDI_WRITE: - /* - * Sheepdog can't handle concurrent creation on the same - * object. We send one create req first and then send - * write reqs in next. - */ - if (find_inflight_request_oid(c, oid)) { - uint32_t tmp_vid; - - sd_write_lock(&c->blocking_lock); - /* - * There are slim chance object was created - * before we grab blocking_lock - */ - tmp_vid = sheep_inode_get_vid(request, idx); - if (tmp_vid && tmp_vid == request->vdi->vid) { - sd_rw_unlock(&c->blocking_lock); - goto submit; - } - list_add_tail(&req->list, &c->blocking_list); - sd_rw_unlock(&c->blocking_lock); - goto done; - } - req->type = VDI_CREATE; - break; - case VDI_READ: - end_sheep_request(req); - goto done; - } -submit: - submit_sheep_request(req); -done: - idx++; - total -= len; - start = (start + len) % SD_DATA_OBJ_SIZE; - len = total > SD_DATA_OBJ_SIZE ? SD_DATA_OBJ_SIZE : total; - } while (total > 0); - - if (uatomic_sub_return(&aiocb->nr_requests, 1) <= 0) - aiocb->aio_done_func(aiocb); + if (aiocb->op != NULL && aiocb->op->request_process) + ret = aiocb->op->request_process(aiocb); - return 0; + return ret; } static int submit_request(struct sd_request *req) @@ -388,28 +273,25 @@ static struct sheep_request *fetch_inflight_request(struct sd_cluster *c, return req; } -static void submit_blocking_sheep_request(struct sd_cluster *c, uint64_t oid) +int end_sheep_request(struct sheep_request *req) { - struct sheep_request *req; + struct sheep_aiocb *aiocb = req->aiocb; - sd_write_lock(&c->blocking_lock); - list_for_each_entry(req, &c->blocking_list, list) { - if (req->oid != oid) - continue; - list_del(&req->list); - submit_sheep_request(req); - } - sd_rw_unlock(&c->blocking_lock); + if (uatomic_sub_return(&aiocb->nr_requests, 1) <= 0) + aiocb->aio_done_func(aiocb); + + free(req); + + return 0; } + /* FIXME: add auto-reconnect support */ static int sheep_handle_reply(struct sd_cluster *c) { struct sd_rsp rsp = {}; - struct sheep_request *req, *new; - struct sd_vdi *vdi; - uint32_t vid, idx; - uint64_t oid; + struct sheep_request *req; + struct sheep_aiocb *aiocb; int ret; ret = xread(c->sockfd, (char *)&rsp, sizeof(rsp)); @@ -425,6 +307,7 @@ static int sheep_handle_reply(struct sd_cluster *c) req = fetch_inflight_request(c, rsp.id); if (!req) return 0; + if (rsp.data_length > 0) { ret = xread(c->sockfd, req->buf, req->length); if (ret < 0) { @@ -433,37 +316,11 @@ static int sheep_handle_reply(struct sd_cluster *c) } } - vdi = req->aiocb->request->vdi; - switch (req->type) { - case VDI_CREATE: - /* We need to update inode for create */ - new = xmalloc(sizeof(*new)); - vid = vdi->vid; - oid = vid_to_vdi_oid(vid); - idx = data_oid_to_idx(req->oid); - new->offset = SD_INODE_HEADER_SIZE + sizeof(vid) * idx; - new->length = sizeof(vid); - new->oid = oid; - new->cow_oid = 0; - new->aiocb = req->aiocb; - new->buf = (char *)&vid; - new->seq_num = uatomic_add_return(&c->seq_num, 1); - new->type = VDI_WRITE; - uatomic_inc(&req->aiocb->nr_requests); - INIT_LIST_NODE(&new->list); - - /* Make sure no request is queued while we update inode */ - sd_write_lock(&vdi->lock); - vdi->inode->data_vdi_id[idx] = vid; - sd_rw_unlock(&vdi->lock); - - submit_sheep_request(new); - submit_blocking_sheep_request(c, req->oid); - /* fall thru */ - case VDI_WRITE: - case VDI_READ: - break; - } + aiocb = req->aiocb; + aiocb->op = get_sd_op(req->opcode); + if (aiocb->op != NULL && !!aiocb->op->response_process) + ret = aiocb->op->response_process(req, &rsp); + end_request: end_sheep_request(req); err: diff --git a/lib/shared/sheepdog.h b/lib/shared/sheepdog.h index 47bae6f13..57af3572e 100644 --- a/lib/shared/sheepdog.h +++ b/lib/shared/sheepdog.h @@ -45,7 +45,6 @@ struct sd_cluster { }; struct sd_vdi { - struct sd_cluster *cluster; struct sd_inode *inode; uint32_t vid; struct sd_rw_lock lock; @@ -103,7 +102,8 @@ struct sd_vdi *sd_vdi_open(struct sd_cluster *c, char *name); * * Return error code defined in sheepdog_proto.h. */ -int sd_vdi_read(struct sd_vdi *vdi, void *buf, size_t count, off_t offset); +int sd_vdi_read(struct sd_cluster *c, struct sd_vdi *vdi, void *buf, + size_t count, off_t offset); /* * Write to a vdi descriptor at a given offset. @@ -115,7 +115,8 @@ int sd_vdi_read(struct sd_vdi *vdi, void *buf, size_t count, off_t offset); * * Return error code defined in sheepdog_proto.h. */ -int sd_vdi_write(struct sd_vdi *vdi, void *buf, size_t count, off_t offset); +int sd_vdi_write(struct sd_cluster *c, struct sd_vdi *vdi, void *buf, + size_t count, off_t offset); /* * Close a vdi descriptor. @@ -124,7 +125,7 @@ int sd_vdi_write(struct sd_vdi *vdi, void *buf, size_t count, off_t offset); * * Return error code defined in sheepdog_proto.h. */ -int sd_vdi_close(struct sd_vdi *vdi); +int sd_vdi_close(struct sd_cluster *c, struct sd_vdi *vdi); /* * Create a snapshot of a VDI diff --git a/lib/shared/vdi.c b/lib/shared/vdi.c index d99685a5e..ad41173f1 100644 --- a/lib/shared/vdi.c +++ b/lib/shared/vdi.c @@ -15,17 +15,7 @@ #include "internal.h" #include "sheep.h" -static int write_object(struct sd_cluster *c, uint64_t oid, uint64_t cow_oid, - void *data, unsigned int datalen, uint64_t offset, uint32_t flags, - uint8_t copies, uint8_t copy_policy, bool create, bool direct); - -static int read_object(struct sd_cluster *c, uint64_t oid, void *data, - unsigned int datalen, uint64_t offset, bool direct); - -static int vdi_read_inode(struct sd_cluster *c, char *name, - char *tag, struct sd_inode *inode, bool header); - -static int lock_vdi(struct sd_vdi *vdi) +static int lock_vdi(struct sd_cluster *c, struct sd_vdi *vdi) { struct sd_req hdr = {}; struct sd_rsp *rsp = (struct sd_rsp *)&hdr; @@ -34,7 +24,7 @@ static int lock_vdi(struct sd_vdi *vdi) hdr.opcode = SD_OP_LOCK_VDI; hdr.data_length = SD_MAX_VDI_LEN; hdr.flags = SD_FLAG_CMD_WRITE; - ret = sd_run_sdreq(vdi->cluster, &hdr, vdi->name); + ret = sd_run_sdreq(c, &hdr, vdi->name); if (ret != SD_RES_SUCCESS) return ret; @@ -43,7 +33,7 @@ static int lock_vdi(struct sd_vdi *vdi) return SD_RES_SUCCESS; } -static int unlock_vdi(struct sd_vdi *vdi) +static int unlock_vdi(struct sd_cluster *c, struct sd_vdi *vdi) { struct sd_req hdr = {}; int ret; @@ -51,7 +41,7 @@ static int unlock_vdi(struct sd_vdi *vdi) hdr.opcode = SD_OP_RELEASE_VDI; hdr.vdi.type = LOCK_TYPE_NORMAL; hdr.vdi.base_vdi_id = vdi->vid; - ret = sd_run_sdreq(vdi->cluster, &hdr, NULL); + ret = sd_run_sdreq(c, &hdr, NULL); if (ret != SD_RES_SUCCESS) return ret; @@ -62,7 +52,6 @@ static struct sd_vdi *alloc_vdi(struct sd_cluster *c, char *name) { struct sd_vdi *new = xzalloc(sizeof(*new)); - new->cluster = c; new->name = name; new->inode = xmalloc(sizeof(struct sd_inode)); sd_init_rw_lock(&new->lock); @@ -83,7 +72,7 @@ struct sd_vdi *sd_vdi_open(struct sd_cluster *c, char *name) struct sd_vdi *new = alloc_vdi(c, name); int ret; - ret = lock_vdi(new); + ret = lock_vdi(c, new); if (ret != SD_RES_SUCCESS) { errno = ret; goto out_free; @@ -106,15 +95,15 @@ struct sd_vdi *sd_vdi_open(struct sd_cluster *c, char *name) return new; out_unlock: - unlock_vdi(new); + unlock_vdi(c, new); out_free: free_vdi(new); return NULL; } -static void queue_request(struct sd_request *req) +void queue_request(struct sd_request *req) { - struct sd_cluster *c = req->vdi->cluster; + struct sd_cluster *c = req->cluster; sd_write_lock(&c->request_lock); list_add_tail(&req->list, &c->request_list); @@ -123,14 +112,14 @@ static void queue_request(struct sd_request *req) eventfd_xwrite(c->request_fd, 1); } -static void free_request(struct sd_request *req) +void free_request(struct sd_request *req) { close(req->efd); free(req); } -static struct sd_request *alloc_request(struct sd_vdi *vdi, void *buf, - size_t count, off_t offset, bool iswrite) +struct sd_request *alloc_request(struct sd_cluster *c, + void *data, size_t count, uint8_t op) { struct sd_request *req; int fd; @@ -142,24 +131,27 @@ static struct sd_request *alloc_request(struct sd_vdi *vdi, void *buf, } req = xzalloc(sizeof(*req)); req->efd = fd; - req->data = buf; + req->cluster = c; + req->data = data; req->length = count; - req->offset = offset; - req->write = iswrite; + req->opcode = op; INIT_LIST_NODE(&req->list); - req->vdi = vdi; return req; } -int sd_vdi_read(struct sd_vdi *vdi, void *buf, size_t count, off_t offset) +int sd_vdi_read(struct sd_cluster *c, struct sd_vdi *vdi, + void *buf, size_t count, off_t offset) { - struct sd_request *req = alloc_request(vdi, buf, count, offset, false); + struct sd_request *req = alloc_request(c, buf, + count, VDI_READ); int ret; if (!req) return errno; + req->vdi = vdi; + req->offset = offset; queue_request(req); eventfd_xread(req->efd); @@ -169,14 +161,18 @@ int sd_vdi_read(struct sd_vdi *vdi, void *buf, size_t count, off_t offset) return ret; } -int sd_vdi_write(struct sd_vdi *vdi, void *buf, size_t count, off_t offset) +int sd_vdi_write(struct sd_cluster *c, struct sd_vdi *vdi, void *buf, + size_t count, off_t offset) { - struct sd_request *req = alloc_request(vdi, buf, count, offset, true); + struct sd_request *req = alloc_request(c, buf, + count, VDI_WRITE); int ret; if (!req) return errno; + req->vdi = vdi; + req->offset = offset; queue_request(req); eventfd_xread(req->efd); @@ -186,11 +182,11 @@ int sd_vdi_write(struct sd_vdi *vdi, void *buf, size_t count, off_t offset) return ret; } -int sd_vdi_close(struct sd_vdi *vdi) +int sd_vdi_close(struct sd_cluster *c, struct sd_vdi *vdi) { int ret; - ret = unlock_vdi(vdi); + ret = unlock_vdi(c, vdi); if (ret != SD_RES_SUCCESS) { fprintf(stderr, "failed to unlock %s\n", vdi->name); return ret; @@ -297,7 +293,7 @@ static int find_vdi(struct sd_cluster *c, char *name, if (vid) *vid = rsp->vdi.vdi_id; - return ret; + return SD_RES_SUCCESS; } static int vdi_read_inode(struct sd_cluster *c, char *name, @@ -589,6 +585,7 @@ int sd_vdi_rollback(struct sd_cluster *c, char *name, char *tag) fprintf(stderr, "Working VDI %s does NOT exist\n", name); return SD_RES_INVALID_PARMS; } + ret = find_vdi(c, name, tag, NULL); if (ret != SD_RES_SUCCESS) { fprintf(stderr, "Snapshot VDI %s(tag: %s) does NOT exist\n", @@ -618,5 +615,5 @@ int sd_vdi_rollback(struct sd_cluster *c, char *name, char *tag) fprintf(stderr, "Failed to rollback VDI: %s\n", sd_strerror(ret)); - return ret; + return SD_RES_SUCCESS; }