[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