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 |