[Sheepdog] [PATCH 4/4] add SD_OP_SO_READ_VDIS

FUJITA Tomonori fujita.tomonori at lab.ntt.co.jp
Mon Dec 21 09:04:17 CET 2009


It is necessary to parse vdis (shepherd).

TODO: handling many vdis.

Signed-off-by: FUJITA Tomonori <fujita.tomonori at lab.ntt.co.jp>
---
 collie/net.c             |    1 +
 collie/store.c           |   80 ++++++++++++++++++++++++++++++++++++++++++++++
 collie/vdi.c             |    6 ++--
 include/meta.h           |    9 -----
 include/net.h            |    2 +-
 include/sheepdog_proto.h |    1 +
 lib/net.c                |   26 +++++++++++----
 shepherd/shepherd.c      |   11 ++++--
 8 files changed, 113 insertions(+), 23 deletions(-)

diff --git a/collie/net.c b/collie/net.c
index be2d084..5505613 100644
--- a/collie/net.c
+++ b/collie/net.c
@@ -64,6 +64,7 @@ static void queue_request(struct request *req)
 	case SD_OP_SO:
 	case SD_OP_SO_NEW_VDI:
 	case SD_OP_SO_LOOKUP_VDI:
+	case SD_OP_SO_READ_VDIS:
 		req->work.fn = so_queue_request;
 		break;
 	default:
diff --git a/collie/store.c b/collie/store.c
index 41a8dc5..9f14d00 100644
--- a/collie/store.c
+++ b/collie/store.c
@@ -323,6 +323,83 @@ out:
 		close(fd);
 }
 
+static int so_read_vdis(struct request *req)
+{
+	struct sd_so_rsp *rsp = (struct sd_so_rsp *)&req->rp;
+	DIR *dir, *vdir;
+	struct dirent *dent, *vdent;
+	char *p;
+	int fd, ret;
+	uint64_t coid;
+	char path[1024], vpath[1024];
+	struct sheepdog_dir_entry *sde = req->data;
+
+	memset(path, 0, sizeof(path));
+	snprintf(path, sizeof(path), "%s/vdi", obj_dir);
+
+	dir = opendir(path);
+
+	while ((dent = readdir(dir))) {
+		if (!strcmp(dent->d_name, ".") ||
+		    !strcmp(dent->d_name, ".."))
+			continue;
+
+		memcpy(vpath, path, sizeof(vpath));
+		snprintf(vpath + strlen(vpath), sizeof(vpath) - strlen(vpath),
+			 "/%s", dent->d_name);
+
+		fd = open(vpath, O_RDONLY);
+		if (fd < 0) {
+			eprintf("%m\n");
+			return SD_RES_EIO;
+		}
+
+		ret = fgetxattr(fd, ANAME_CURRENT, &coid,
+				sizeof(coid));
+		if (ret != sizeof(coid)) {
+			close(fd);
+			eprintf("%s, %m\n", path);
+			return SD_RES_EIO;
+		}
+
+		dprintf("%lx\n", coid);
+
+		close(fd);
+
+		vdir = opendir(vpath);
+		while ((vdent = readdir(vdir))) {
+			if (!strcmp(vdent->d_name, ".") ||
+			    !strcmp(vdent->d_name, ".."))
+				continue;
+
+			p = strchr(vdent->d_name, '-');
+			if (!p) {
+				eprintf("bug %s\n", vdent->d_name);
+				continue;
+			}
+
+			dprintf("%s\n", vdent->d_name);
+
+			*p = '\0';
+
+			sde->oid = strtoull(vdent->d_name, NULL, 16);
+			sde->tag = strtoull(p + 1, NULL, 16);
+
+			if (sde->oid == coid)
+				sde->flags = FLAG_CURRENT;
+
+			sde->name_len = strlen(dent->d_name);
+			strcpy(sde->name, dent->d_name);
+			sde = next_entry(sde);
+		}
+	}
+
+	rsp->data_length = (char *)sde - (char *)req->data;
+	dprintf("%d\n", rsp->data_length);
+
+	return SD_RES_SUCCESS;
+}
+
 static int so_lookup_vdi(struct request *req)
 {
 	struct sd_so_req *hdr = (struct sd_so_req *)&req->rq;
@@ -519,6 +596,9 @@ void so_queue_request(struct work *work, int idx)
 	case SD_OP_SO_LOOKUP_VDI:
 		ret = so_lookup_vdi(req);
 		break;
+	case SD_OP_SO_READ_VDIS:
+		ret = so_read_vdis(req);
+		break;
 	}
 
 out:
diff --git a/collie/vdi.c b/collie/vdi.c
index cf8d9ac..b822d1d 100644
--- a/collie/vdi.c
+++ b/collie/vdi.c
@@ -109,7 +109,7 @@ int add_vdi(struct cluster_info *ci, char *name, int len, uint64_t size,
 	req.tag = tag;
 
 	ret = exec_reqs(entries, nr_nodes, ci->epoch,
-			SD_DIR_OID, (struct sd_req *)&req, name, len, copies);
+			SD_DIR_OID, (struct sd_req *)&req, name, len, 0, copies);
 
 	/* todo: error handling */
 
@@ -157,7 +157,7 @@ int lookup_vdi(struct cluster_info *ci,
 	req.tag = tag;
 
 	ret = exec_reqs(entries, nr_nodes, ci->epoch,
-			SD_DIR_OID, (struct sd_req *)&req, filename, strlen(filename), copies);
+			SD_DIR_OID, (struct sd_req *)&req, filename, strlen(filename), 0, copies);
 
 	*oid = rsp->oid;
 	if (rsp->flags & SD_VDI_RSP_FLAG_CURRENT)
@@ -187,7 +187,7 @@ int make_super_object(struct cluster_info *ci, struct sd_vdi_req *hdr)
 	nr_nodes = build_node_list(&ci->node_list, entries);
 
 	ret = exec_reqs(entries, nr_nodes, ci->epoch,
-			SD_DIR_OID, (struct sd_req *)&req, NULL, 0, req.copies);
+			SD_DIR_OID, (struct sd_req *)&req, NULL, 0, 0, req.copies);
 
 	return ret;
 }
diff --git a/include/meta.h b/include/meta.h
index 73b63de..e0b05cd 100644
--- a/include/meta.h
+++ b/include/meta.h
@@ -48,15 +48,6 @@ static inline int is_data_obj(uint64_t oid)
 
 #define SHEEPDOG_SUPER_OBJ_SIZE (UINT64_C(1) << 12)
 
-struct sheepdog_super_block {
-	uint64_t ctime;
-	uint8_t default_nr_copies;
-	uint8_t pad1[7];
-
-	uint8_t pad2[SHEEPDOG_SUPER_OBJ_SIZE - 16];
-	uint8_t pad3[1 << 24];
-};
-
 #define FLAG_CURRENT 1
 
 struct sheepdog_dir_entry {
diff --git a/include/net.h b/include/net.h
index 7205f6a..b0e3df0 100644
--- a/include/net.h
+++ b/include/net.h
@@ -46,7 +46,7 @@ int read_object(struct sheepdog_node_list_entry *e,
 
 int exec_reqs(struct sheepdog_node_list_entry *e,
 	      int nodes, uint32_t node_version, uint64_t oid, struct sd_req *hdr,
-	      char *wdata, unsigned int wdatalen, int nr);
+	      char *data, unsigned int wdatalen, unsigned int rdatalen, int nr);
 
 int create_listen_ports(int port, int (*callback)(int fd, void *), void *data);
 
diff --git a/include/sheepdog_proto.h b/include/sheepdog_proto.h
index 2f3bad4..b55f2e2 100644
--- a/include/sheepdog_proto.h
+++ b/include/sheepdog_proto.h
@@ -48,6 +48,7 @@
 #define SD_OP_SO_NEW_VDI     0x61
 #define SD_OP_SO_DEL_VDI     0x62
 #define SD_OP_SO_LOOKUP_VDI  0x63
+#define SD_OP_SO_READ_VDIS   0x64
 
 #define SD_OP_STAT_SHEEP     0xB0
 
diff --git a/lib/net.c b/lib/net.c
index 4f05cb9..9c17ea7 100644
--- a/lib/net.c
+++ b/lib/net.c
@@ -433,14 +433,15 @@ int read_object(struct sheepdog_node_list_entry *e,
 /* TODO: clean up with the above functions */
 int exec_reqs(struct sheepdog_node_list_entry *e,
 	      int nodes, uint32_t node_version, uint64_t oid, struct sd_req *hdr,
-	      char *wdata, unsigned int wdatalen, int nr)
+	      char *data, unsigned int wdatalen, unsigned int rdatalen, int nr)
 {
 	char name[128];
 	int i = 0, n, fd, ret;
 	int success = 0;
+	struct sd_obj_rsp *rsp = (struct sd_obj_rsp *)&hdr;
 
 	for (i = 0; i < nr; i++) {
-		unsigned wlen = wdatalen, rlen = 0;
+		unsigned wlen = wdatalen, rlen = rdatalen;
 
 		n = obj_to_sheep(e, nodes, oid, i);
 
@@ -454,16 +455,27 @@ int exec_reqs(struct sheepdog_node_list_entry *e,
 		if (fd < 0)
 			return -1;
 
+		rsp->result = 0;
 		hdr->epoch = node_version;
-		if (wdatalen)
+		if (wdatalen) {
 			hdr->flags = SD_FLAG_CMD_WRITE;
-		hdr->data_length = wlen;
+			hdr->data_length = wdatalen;
+		} else if (rdatalen)
+			hdr->data_length = rdatalen;
+		else
+			hdr->data_length = 0;
 
-		ret = exec_req(fd, hdr, wdata, &wlen, &rlen);
+		ret = exec_req(fd, hdr, data, &wlen, &rlen);
 		close(fd);
 
-		if (!ret)
-			success++;
+		if (rdatalen) {
+			if (!ret) {
+				if (rsp->result == SD_RES_SUCCESS)
+					return rlen;
+			}
+		} else
+			if (!ret)
+				success++;
 	}
 
 	return !success;
diff --git a/shepherd/shepherd.c b/shepherd/shepherd.c
index 4ac7e4a..7cf4243 100644
--- a/shepherd/shepherd.c
+++ b/shepherd/shepherd.c
@@ -388,14 +388,19 @@ int parse_vdi(vdi_parser_func_t func, void *data)
 	char *buf;
 	int rest, ret;
 	struct sheepdog_inode i;
+	struct sd_so_req req;
+
+	memset(&req, 0, sizeof(req));
 
 	buf = zalloc(DIR_BUF_LEN);
 	if (!buf)
 		return 1;
 
-	ret = read_object(node_list_entries, nr_nodes, node_list_version,
-			  SD_DIR_OID, buf, DIR_BUF_LEN,
-			  sizeof(struct sheepdog_super_block), nr_nodes);
+	req.opcode = SD_OP_SO_READ_VDIS;
+
+	ret = exec_reqs(node_list_entries, nr_nodes, node_list_version,
+			SD_DIR_OID, (struct sd_req *)&req, buf, 0, DIR_BUF_LEN,nr_nodes);
+
 	if (ret < 0) {
 		ret = 1;
 		goto out;
-- 
1.5.6.5




More information about the sheepdog mailing list