[sheepdog] [PATCH] sheep: rework get_vdis_from to reduce network overhead
Ruoyu
liangry at ucweb.com
Fri Jul 4 12:30:30 CEST 2014
Current get_vdis_from function prepare a buffer large enough (4M)
to get vdi state. It is not elegant and transfers too much between
sheep nodes.
Signed-off-by: Ruoyu <liangry at ucweb.com>
---
sheep/group.c | 18 ++++++++++++++----
sheep/ops.c | 4 +---
sheep/sheep_priv.h | 3 ++-
sheep/vdi.c | 35 ++++++++++++++++++++++++-----------
4 files changed, 41 insertions(+), 19 deletions(-)
diff --git a/sheep/group.c b/sheep/group.c
index adfd798..6b1ec5d 100644
--- a/sheep/group.c
+++ b/sheep/group.c
@@ -471,21 +471,31 @@ static int get_vdis_from(struct sd_node *node)
struct sd_req hdr;
struct sd_rsp *rsp = (struct sd_rsp *)&hdr;
struct vdi_state *vs = NULL;
- int i, ret = SD_RES_SUCCESS;
+ int i, ret;
unsigned int rlen;
int count;
if (node_is_local(node))
- goto out;
+ return SD_RES_SUCCESS;
- rlen = SD_DATA_OBJ_SIZE; /* FIXME */
+#define DEFAULT_VDI_STATE_COUNT 512
+ rlen = DEFAULT_VDI_STATE_COUNT * sizeof(struct vdi_state);
vs = xzalloc(rlen);
+retry:
sd_init_req(&hdr, SD_OP_GET_VDI_COPIES);
hdr.data_length = rlen;
hdr.epoch = sys_epoch();
ret = sheep_exec_req(&node->nid, &hdr, (char *)vs);
- if (ret != SD_RES_SUCCESS)
+ switch (ret) {
+ case SD_RES_SUCCESS:
+ break;
+ case SD_RES_BUFFER_SMALL:
+ rlen *= 2;
+ vs = xrealloc(vs, rlen);
+ goto retry;
+ default:
goto out;
+ }
count = rsp->data_length / sizeof(*vs);
for (i = 0; i < count; i++) {
diff --git a/sheep/ops.c b/sheep/ops.c
index fb26077..d76a0bb 100644
--- a/sheep/ops.c
+++ b/sheep/ops.c
@@ -412,9 +412,7 @@ static int local_read_vdis(const struct sd_req *req, struct sd_rsp *rsp,
static int local_get_vdi_copies(const struct sd_req *req, struct sd_rsp *rsp,
void *data)
{
- rsp->data_length = fill_vdi_state_list(data);
-
- return SD_RES_SUCCESS;
+ return fill_vdi_state_list(req, rsp, data);
}
static int local_stat_sheep(struct request *req)
diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h
index 02f75ad..3f25bec 100644
--- a/sheep/sheep_priv.h
+++ b/sheep/sheep_priv.h
@@ -327,7 +327,8 @@ int init_base_path(const char *dir);
int init_disk_space(const char *d);
int lock_base_dir(const char *d);
-int fill_vdi_state_list(void *data);
+int fill_vdi_state_list(const struct sd_req *hdr,
+ struct sd_rsp *rsp, void *data);
bool oid_is_readonly(uint64_t oid);
int get_vdi_copy_number(uint32_t vid);
int get_vdi_copy_policy(uint32_t vid);
diff --git a/sheep/vdi.c b/sheep/vdi.c
index b58b538..747c810 100644
--- a/sheep/vdi.c
+++ b/sheep/vdi.c
@@ -172,25 +172,38 @@ int add_vdi_state(uint32_t vid, int nr_copies, bool snapshot, uint8_t cp)
return SD_RES_SUCCESS;
}
-int fill_vdi_state_list(void *data)
+int fill_vdi_state_list(const struct sd_req *hdr,
+ struct sd_rsp *rsp, void *data)
{
- int nr = 0;
- struct vdi_state *vs = data;
+#define DEFAULT_VDI_STATE_COUNT 512
+ int last = 0, end = DEFAULT_VDI_STATE_COUNT;
struct vdi_state_entry *entry;
+ struct vdi_state *vs = xzalloc(end * sizeof(struct vdi_state));
sd_read_lock(&vdi_state_lock);
rb_for_each_entry(entry, &vdi_state_root, node) {
- memset(vs, 0, sizeof(*vs));
- vs->vid = entry->vid;
- vs->nr_copies = entry->nr_copies;
- vs->snapshot = entry->snapshot;
- vs->copy_policy = entry->copy_policy;
- vs++;
- nr++;
+ if (last >= end) {
+ end *= 2;
+ vs = xrealloc(vs, end * sizeof(struct vdi_state));
+ }
+
+ vs[last].vid = entry->vid;
+ vs[last].nr_copies = entry->nr_copies;
+ vs[last].snapshot = entry->snapshot;
+ vs[last].copy_policy = entry->copy_policy;
+ last++;
}
sd_rw_unlock(&vdi_state_lock);
- return nr * sizeof(*vs);
+ if (hdr->data_length < last * sizeof(struct vdi_state)) {
+ free(vs);
+ return SD_RES_BUFFER_SMALL;
+ }
+
+ rsp->data_length = last * sizeof(struct vdi_state);
+ memcpy(data, vs, rsp->data_length);
+ free(vs);
+ return SD_RES_SUCCESS;
}
static inline bool vdi_is_deleted(struct sd_inode *inode)
--
1.8.3.2
More information about the sheepdog
mailing list