[sheepdog] [PATCH v2 7/8] shared lib: implement vdi_{open, read, write, close}
Liu Yuan
namei.unix at gmail.com
Wed Apr 8 04:19:38 CEST 2015
From: Liu Yuan <liuyuan at cmss.chinamobile.com>
Nothing intersting, these functions are basically wrappers of sheep.c.
Signed-off-by: Liu Yuan <liuyuan at cmss.chinamobile.com>
---
lib/shared/sheep.c | 3 +-
lib/shared/sheepdog.h | 10 ++-
lib/shared/vdi.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 195 insertions(+), 3 deletions(-)
create mode 100644 lib/shared/vdi.c
diff --git a/lib/shared/sheep.c b/lib/shared/sheep.c
index 3afe6f5..4c1b1f1 100644
--- a/lib/shared/sheep.c
+++ b/lib/shared/sheep.c
@@ -112,7 +112,8 @@ int sd_run_sdreq(struct sd_cluster *c, struct sd_req *hdr, void *data)
static void aio_end_request(struct sd_request *req, int ret)
{
-
+ req->ret = ret;
+ eventfd_xwrite(req->efd, 1);
}
static void aio_rw_done(struct sheep_aiocb *aiocb)
diff --git a/lib/shared/sheepdog.h b/lib/shared/sheepdog.h
index c2c072c..f0be852 100644
--- a/lib/shared/sheepdog.h
+++ b/lib/shared/sheepdog.h
@@ -23,6 +23,7 @@
#include "util.h"
#include <arpa/inet.h>
+#include <sys/eventfd.h>
struct sd_cluster {
int sockfd;
@@ -50,6 +51,8 @@ struct sd_request {
size_t length;
off_t offset;
bool write;
+ int efd;
+ int ret;
};
struct sd_vdi {
@@ -57,12 +60,15 @@ struct sd_vdi {
struct sd_inode *inode;
uint32_t vid;
struct sd_rw_lock lock;
+ char *name;
};
-int sd_init(void);
-void sd_free(void);
struct sd_cluster *sd_connect(char *host);
int sd_disconnect(struct sd_cluster *sd);
int sd_run_sdreq(struct sd_cluster *c, struct sd_req *hdr, void *data);
+struct sd_vdi *sd_vdi_open(struct sd_cluster *sd, char *name);
+int sd_vdi_read(struct sd_vdi *vdi, void *buf, size_t count, off_t offset);
+int sd_vdi_write(struct sd_vdi *vdi, void *buf, size_t count, off_t offset);
+int sd_vdi_close(struct sd_vdi *vdi);
#endif
diff --git a/lib/shared/vdi.c b/lib/shared/vdi.c
new file mode 100644
index 0000000..d40bd4b
--- /dev/null
+++ b/lib/shared/vdi.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2015 China Mobile Inc.
+ *
+ * Liu Yuan <liuyuan at cmss.chinamobile.com>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "sheepdog.h"
+
+static int lock_vdi(struct sd_vdi *vdi)
+{
+ struct sd_req hdr = {};
+ struct sd_rsp *rsp = (struct sd_rsp *)&hdr;
+ int ret;
+
+ 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);
+ if (ret < 0)
+ return ret;
+
+ vdi->vid = rsp->vdi.vdi_id;
+
+ return 0;
+}
+
+static int unlock_vdi(struct sd_vdi *vdi)
+{
+ struct sd_req hdr = {};
+ int ret;
+
+ 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);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+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);
+
+ return new;
+}
+
+static void free_vdi(struct sd_vdi *vdi)
+{
+ sd_destroy_rw_lock(&vdi->lock);
+ free(vdi->inode);
+ free(vdi);
+}
+
+struct sd_vdi *sd_vdi_open(struct sd_cluster *c, char *name)
+{
+ struct sd_req hdr = {};
+ struct sd_vdi *new = alloc_vdi(c, name);
+ int ret;
+
+ ret = lock_vdi(new);
+ if (ret < 0) {
+ errno = -ret;
+ goto out_free;
+ }
+
+ hdr.opcode = SD_OP_READ_OBJ;
+ hdr.data_length = SD_INODE_SIZE;
+ hdr.obj.oid = vid_to_vdi_oid(new->vid);
+ hdr.obj.offset = 0;
+ ret = sd_run_sdreq(c, &hdr, new->inode);
+ if (ret < 0) {
+ errno = -ret;
+ goto out_unlock;
+ }
+
+ if (vdi_is_snapshot(new->inode)) {
+ errno = EINVAL;
+ goto out_unlock;
+ }
+
+ return new;
+out_unlock:
+ unlock_vdi(new);
+out_free:
+ free_vdi(new);
+ return NULL;
+}
+
+static void queue_request(struct sd_request *req)
+{
+ struct sd_cluster *c = req->vdi->cluster;
+
+ sd_write_lock(&c->request_lock);
+ list_add_tail(&req->list, &c->request_list);
+ sd_rw_unlock(&c->request_lock);
+
+ eventfd_xwrite(c->request_fd, 1);
+}
+
+static 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 write)
+{
+ struct sd_request *req;
+ int fd;
+
+ fd = eventfd(0, 0);
+ if (fd < 0)
+ return ERR_PTR(-errno);
+ req = xzalloc(sizeof(*req));
+ req->efd = fd;
+ req->data = buf;
+ req->length = count;
+ req->offset = offset;
+ req->write = write;
+ 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)
+{
+ struct sd_request *req = alloc_request(vdi, buf, count, offset, false);
+ int ret;
+
+ if (IS_ERR(req))
+ return PTR_ERR(req);
+
+ queue_request(req);
+
+ eventfd_xread(req->efd);
+ ret = req->ret;
+ free_request(req);
+
+ return ret;
+}
+
+int sd_vdi_write(struct sd_vdi *vdi, void *buf, size_t count, off_t offset)
+{
+ struct sd_request *req = alloc_request(vdi, buf, count, offset, true);
+ int ret;
+
+ if (IS_ERR(req))
+ return PTR_ERR(req);
+
+ queue_request(req);
+
+ eventfd_xread(req->efd);
+ ret = req->ret;
+ free_request(req);
+
+ return ret;
+}
+
+int sd_vdi_close(struct sd_vdi *vdi)
+{
+ int ret;
+
+ ret = unlock_vdi(vdi);
+ if (ret < 0) {
+ fprintf(stderr, "failed to unlock %s\n", vdi->name);
+ return ret;
+ }
+ free_vdi(vdi);
+ return 0;
+}
--
1.9.1
More information about the sheepdog
mailing list