[sheepdog] [PATCH] util/sd_inode: add sd_inode_index_walk helper
Liu Yuan
namei.unix at gmail.com
Thu Feb 20 09:55:48 CET 2014
This is more easier for callers to understand what it does instead of calling
a internal btree walker.
Signed-off-by: Liu Yuan <namei.unix at gmail.com>
---
dog/cluster.c | 17 +++++-----
dog/vdi.c | 21 ++++++-------
include/sheepdog_proto.h | 9 +++---
lib/sd_inode.c | 76 +++++++++++++++++++++++++++++----------------
sheep/http/kv.c | 80 ++++++++++++++++++++++--------------------------
sheep/vdi.c | 16 ++++------
6 files changed, 112 insertions(+), 107 deletions(-)
diff --git a/dog/cluster.c b/dog/cluster.c
index 169e837..815ecff 100644
--- a/dog/cluster.c
+++ b/dog/cluster.c
@@ -281,19 +281,16 @@ out:
return ret;
}
-static void fill_cb(void *data, enum btree_node_type type, void *arg)
+static void fill_cb(struct sd_index *idx, void *arg,
+ enum btree_node_type ignore)
{
- struct sd_index *ext;
struct sd_inode *inode = (struct sd_inode *)arg;
uint64_t oid;
- if (type == BTREE_INDEX) {
- ext = (struct sd_index *)data;
- if (ext->vdi_id) {
- oid = vid_to_data_oid(ext->vdi_id, ext->idx);
- object_tree_insert(oid, inode->nr_copies,
- inode->copy_policy);
- }
+ if (idx->vdi_id) {
+ oid = vid_to_data_oid(idx->vdi_id, idx->idx);
+ object_tree_insert(oid, inode->nr_copies,
+ inode->copy_policy);
}
}
@@ -323,7 +320,7 @@ static void fill_object_tree(uint32_t vid, const char *name, const char *tag,
object_tree_insert(oid, i->nr_copies, i->copy_policy);
}
} else
- traverse_btree(i, fill_cb, &i);
+ sd_inode_index_walk(i, fill_cb, &i);
/* fill vmstate object id */
nr_vmstate_object = DIV_ROUND_UP(i->vm_state_size, SD_DATA_OBJ_SIZE);
diff --git a/dog/vdi.c b/dog/vdi.c
index 49add72..ed4ab54 100644
--- a/dog/vdi.c
+++ b/dog/vdi.c
@@ -1786,21 +1786,18 @@ struct check_arg {
int nr_copies;
};
-static void check_cb(void *data, enum btree_node_type type, void *arg)
+static void check_cb(struct sd_index *idx, void *arg,
+ enum btree_node_type ignore)
{
- struct sd_index *ext;
struct check_arg *carg = arg;
uint64_t oid;
- if (type == BTREE_INDEX) {
- ext = (struct sd_index *)data;
- if (ext->vdi_id) {
- oid = vid_to_data_oid(ext->vdi_id, ext->idx);
- *(carg->done) = (uint64_t)ext->idx * SD_DATA_OBJ_SIZE;
- vdi_show_progress(*(carg->done), carg->inode->vdi_size);
- queue_vdi_check_work(carg->inode, oid, NULL, carg->wq,
- carg->nr_copies);
- }
+ if (idx->vdi_id) {
+ oid = vid_to_data_oid(idx->vdi_id, idx->idx);
+ *(carg->done) = (uint64_t)idx->idx * SD_DATA_OBJ_SIZE;
+ vdi_show_progress(*(carg->done), carg->inode->vdi_size);
+ queue_vdi_check_work(carg->inode, oid, NULL, carg->wq,
+ carg->nr_copies);
}
}
@@ -1841,7 +1838,7 @@ int do_vdi_check(const struct sd_inode *inode)
}
} else {
struct check_arg arg = {inode, &done, wq, nr_copies};
- traverse_btree(inode, check_cb, &arg);
+ sd_inode_index_walk(inode, check_cb, &arg);
vdi_show_progress(inode->vdi_size, inode->vdi_size);
}
diff --git a/include/sheepdog_proto.h b/include/sheepdog_proto.h
index 9746fcc..95f316e 100644
--- a/include/sheepdog_proto.h
+++ b/include/sheepdog_proto.h
@@ -251,8 +251,8 @@ struct sd_index_header {
enum btree_node_type {
BTREE_HEAD = 1,
- BTREE_INDEX,
- BTREE_INDIRECT_IDX,
+ BTREE_INDEX = 2 ,
+ BTREE_INDIRECT_IDX = 4,
};
typedef int (*write_node_fn)(uint64_t id, void *mem, unsigned int len,
@@ -287,9 +287,8 @@ extern void sd_inode_copy_vdis(write_node_fn writer, read_node_fn reader,
uint8_t nr_copies, uint8_t copy_policy,
struct sd_inode *newi);
-typedef void (*btree_cb_fn)(void *data, enum btree_node_type type, void *arg);
-extern void traverse_btree(const struct sd_inode *inode,
- btree_cb_fn fn, void *arg);
+typedef void (*index_cb_fn)(struct sd_index *, void *arg, enum btree_node_type);
+void sd_inode_index_walk(const struct sd_inode *inode, index_cb_fn, void *);
/* 64 bit FNV-1a non-zero initial basis */
#define FNV1A_64_INIT ((uint64_t) 0xcbf29ce484222325ULL)
diff --git a/lib/sd_inode.c b/lib/sd_inode.c
index 1dd4ec2..012a425 100644
--- a/lib/sd_inode.c
+++ b/lib/sd_inode.c
@@ -125,27 +125,36 @@ static int index_compare(struct sd_indirect_idx *a, struct sd_indirect_idx *b)
return intcmp(a->idx, b->idx);
}
+typedef void (*btree_cb_fn)(void *data, void *arg, enum btree_node_type type);
+
/*
- * traverse the whole btree that include all the inode->data_vdi_id, bnode,
- * data objects and call btree_cb_fn()
+ * Traverse the whole btree that include all header, indirect_idx and index.
+ * @interest specify which objects user wants to run @fn against.
+ *
+ * If error happens when reading btree internal nodes, we simply continue to
+ * process next candidate.
*/
-void traverse_btree(const struct sd_inode *inode, btree_cb_fn fn, void *arg)
+static void traverse_btree(const struct sd_inode *inode, btree_cb_fn fn,
+ void *arg, int interest)
{
struct sd_index_header *header = INDEX_HEADER(inode->data_vdi_id);
struct sd_index_header *leaf_node = NULL;
struct sd_index *last, *iter;
struct sd_indirect_idx *last_idx, *iter_idx;
void *tmp;
+ int ret;
- fn(header, BTREE_HEAD, arg);
+ if (interest & BTREE_HEAD)
+ fn(header, arg, BTREE_HEAD);
if (header->depth == 1) {
last = LAST_INDEX(inode->data_vdi_id);
iter = FIRST_INDEX(inode->data_vdi_id);
- while (iter != last) {
- fn(iter, BTREE_INDEX, arg);
- iter++;
- }
+ if (interest & BTREE_INDEX)
+ while (iter != last) {
+ fn(iter, arg, BTREE_INDEX);
+ iter++;
+ }
} else if (header->depth == 2) {
last_idx = LAST_INDRECT_IDX(inode->data_vdi_id);
iter_idx = FIRST_INDIRECT_IDX(inode->data_vdi_id);
@@ -153,17 +162,25 @@ void traverse_btree(const struct sd_inode *inode, btree_cb_fn fn, void *arg)
tmp = (void *)leaf_node;
while (iter_idx != last_idx) {
- inode_actor.reader(iter_idx->oid, &tmp,
- SD_INODE_DATA_INDEX_SIZE, 0);
+ ret = inode_actor.reader(iter_idx->oid, &tmp,
+ SD_INODE_DATA_INDEX_SIZE, 0);
+ if (ret != SD_RES_SUCCESS) {
+ sd_err("failed to read %"PRIx64, iter_idx->oid);
+ iter_idx++;
+ continue;
+ }
- fn(iter_idx, BTREE_INDIRECT_IDX, arg);
- fn(leaf_node, BTREE_HEAD, arg);
+ if (interest & BTREE_INDIRECT_IDX)
+ fn(iter_idx, arg, BTREE_INDIRECT_IDX);
+ if (interest & BTREE_HEAD)
+ fn(leaf_node, arg, BTREE_HEAD);
last = LAST_INDEX(leaf_node);
iter = FIRST_INDEX(leaf_node);
- while (iter != last) {
- fn(iter, BTREE_INDEX, arg);
- iter++;
- }
+ if (interest & BTREE_INDEX)
+ while (iter != last) {
+ fn(iter, arg, BTREE_INDEX);
+ iter++;
+ }
iter_idx++;
}
@@ -172,6 +189,13 @@ void traverse_btree(const struct sd_inode *inode, btree_cb_fn fn, void *arg)
panic("This B-tree not support depth %u", header->depth);
}
+/* Walk the sd_inode's vdi index array and call func against each sd_index */
+void sd_inode_index_walk(const struct sd_inode *inode, index_cb_fn func,
+ void *arg)
+{
+ traverse_btree(inode, (btree_cb_fn)func, arg, BTREE_INDEX);
+}
+
#ifdef DEBUG
static void dump_cb(void *data, enum btree_node_type type, void *arg)
{
@@ -202,7 +226,8 @@ static void dump_btree(struct sd_inode *inode)
{
#ifdef DEBUG
sd_info("btree> BEGIN");
- traverse_btree(inode, dump_cb, NULL);
+ traverse_btree(inode, dump_cb, NULL,
+ BTREE_INDEX | BTREE_HEAD | BTREE_INDIRECT_IDX);
sd_info("btree> END");
#endif
}
@@ -839,27 +864,24 @@ struct stat_arg {
uint32_t vid;
};
-static void stat_cb(void *data, enum btree_node_type type, void *arg)
+static void stat_cb(struct sd_index *idx, void *arg,
+ enum btree_node_type ignore)
{
- struct sd_index *ext;
struct stat_arg *sarg = arg;
uint64_t *my = sarg->my;
uint64_t *cow = sarg->cow;
- if (type == BTREE_INDEX) {
- ext = (struct sd_index *)data;
- if (ext->vdi_id == sarg->vid)
- (*my)++;
- else if (ext->vdi_id != 0)
- (*cow)++;
- }
+ if (idx->vdi_id == sarg->vid)
+ (*my)++;
+ else if (idx->vdi_id != 0)
+ (*cow)++;
}
static void hypver_volume_stat(const struct sd_inode *inode,
uint64_t *my_objs, uint64_t *cow_objs)
{
struct stat_arg arg = {my_objs, cow_objs, inode->vdi_id};
- traverse_btree(inode, stat_cb, &arg);
+ sd_inode_index_walk(inode, stat_cb, &arg);
}
static void volume_stat(const struct sd_inode *inode, uint64_t *my_objs,
diff --git a/sheep/http/kv.c b/sheep/http/kv.c
index a54bf6c..c9868bf 100644
--- a/sheep/http/kv.c
+++ b/sheep/http/kv.c
@@ -90,34 +90,31 @@ int kv_create_account(const char *account)
return sd_create_hyper_volume(account, &vdi_id);
}
-static void bucket_iterater(void *data, enum btree_node_type type, void *arg)
+static void bucket_iterater(struct sd_index *idx, void *arg,
+ enum btree_node_type ignore)
{
- struct sd_index *ext;
struct bucket_iterater_arg *biarg = arg;
struct kv_bnode bnode;
uint64_t oid;
int ret;
- if (type == BTREE_INDEX) {
- ext = (struct sd_index *)data;
- if (!ext->vdi_id)
- return;
+ if (!idx->vdi_id)
+ return;
- oid = vid_to_data_oid(ext->vdi_id, ext->idx);
- ret = sd_read_object(oid, (char *)&bnode, sizeof(bnode), 0);
- if (ret != SD_RES_SUCCESS) {
- sd_err("Failed to read data object %"PRIx64, oid);
- return;
- }
-
- if (bnode.name[0] == 0)
- return;
- if (biarg->cb)
- biarg->cb(bnode.name, biarg->opaque);
- biarg->bucket_count++;
- biarg->object_count += bnode.object_count;
- biarg->bytes_used += bnode.bytes_used;
+ oid = vid_to_data_oid(idx->vdi_id, idx->idx);
+ ret = sd_read_object(oid, (char *)&bnode, sizeof(bnode), 0);
+ if (ret != SD_RES_SUCCESS) {
+ sd_err("Failed to read data object %"PRIx64, oid);
+ return;
}
+
+ if (bnode.name[0] == 0)
+ return;
+ if (biarg->cb)
+ biarg->cb(bnode.name, biarg->opaque);
+ biarg->bucket_count++;
+ biarg->object_count += bnode.object_count;
+ biarg->bytes_used += bnode.bytes_used;
}
static int read_account_meta(const char *account, uint64_t *bucket_count,
@@ -141,7 +138,7 @@ static int read_account_meta(const char *account, uint64_t *bucket_count,
goto out;
}
- traverse_btree(inode, bucket_iterater, &arg);
+ sd_inode_index_walk(inode, bucket_iterater, &arg);
*object_count = arg.object_count;
*bucket_count = arg.bucket_count;
*used = arg.bytes_used;
@@ -253,7 +250,7 @@ static int bnode_create(struct kv_bnode *bnode, uint32_t account_vid)
int ret;
ret = sd_read_object(vid_to_vdi_oid(account_vid), (char *)inode,
- sizeof(*inode), 0);
+ sizeof(*inode), 0);
if (ret != SD_RES_SUCCESS) {
sd_err("failed to read %" PRIx32 " %s", account_vid,
sd_strerror(ret));
@@ -430,33 +427,30 @@ struct object_iterater_arg {
uint32_t count;
};
-static void object_iterater(void *data, enum btree_node_type type, void *arg)
+static void object_iterater(struct sd_index *idx, void *arg,
+ enum btree_node_type ignore)
{
- struct sd_index *ext;
struct object_iterater_arg *oiarg = arg;
struct kv_onode *onode = NULL;
uint64_t oid;
int ret;
- if (type == BTREE_INDEX) {
- ext = (struct sd_index *)data;
- if (!ext->vdi_id)
- goto out;
-
- onode = xmalloc(SD_DATA_OBJ_SIZE);
- oid = vid_to_data_oid(ext->vdi_id, ext->idx);
- ret = sd_read_object(oid, (char *)onode, SD_DATA_OBJ_SIZE, 0);
- if (ret != SD_RES_SUCCESS) {
- sd_err("Failed to read data object %"PRIx64, oid);
- goto out;
- }
+ if (!idx->vdi_id)
+ goto out;
- if (onode->name[0] == '\0')
- goto out;
- if (oiarg->cb)
- oiarg->cb(onode->name, oiarg->opaque);
- oiarg->count++;
+ onode = xmalloc(SD_DATA_OBJ_SIZE);
+ oid = vid_to_data_oid(idx->vdi_id, idx->idx);
+ ret = sd_read_object(oid, (char *)onode, SD_DATA_OBJ_SIZE, 0);
+ if (ret != SD_RES_SUCCESS) {
+ sd_err("Failed to read data object %"PRIx64, oid);
+ goto out;
}
+
+ if (onode->name[0] == '\0')
+ goto out;
+ if (oiarg->cb)
+ oiarg->cb(onode->name, oiarg->opaque);
+ oiarg->count++;
out:
free(onode);
}
@@ -476,7 +470,7 @@ static int bucket_iterate_object(uint32_t bucket_vid, object_iter_cb cb,
goto out;
}
- traverse_btree(inode, object_iterater, &arg);
+ sd_inode_index_walk(inode, object_iterater, &arg);
out:
free(inode);
return ret;
@@ -590,7 +584,7 @@ int kv_iterate_bucket(const char *account, bucket_iter_cb cb, void *opaque)
goto out;
}
- traverse_btree(&account_inode, bucket_iterater, &arg);
+ sd_inode_index_walk(&account_inode, bucket_iterater, &arg);
out:
sys->cdrv->unlock(account_vid);
return ret;
diff --git a/sheep/vdi.c b/sheep/vdi.c
index 592636a..69599eb 100644
--- a/sheep/vdi.c
+++ b/sheep/vdi.c
@@ -824,20 +824,16 @@ struct delete_arg {
uint32_t *nr_deleted;
};
-static void delete_cb(void *data, enum btree_node_type type, void *arg)
+static void delete_cb(struct sd_index *idx, void *arg,
+ enum btree_node_type ignore)
{
- struct sd_index *ext;
struct delete_arg *darg = (struct delete_arg *)arg;
uint64_t oid;
int ret;
- if (type != BTREE_INDEX)
- return;
-
- ext = (struct sd_index *)data;
- if (ext->vdi_id) {
- oid = vid_to_data_oid(ext->vdi_id, ext->idx);
- if (ext->vdi_id != darg->inode->vdi_id)
+ if (idx->vdi_id) {
+ oid = vid_to_data_oid(idx->vdi_id, idx->idx);
+ if (idx->vdi_id != darg->inode->vdi_id)
sd_debug("object %" PRIx64 " is base's data, would"
" not be deleted.", oid);
else {
@@ -900,7 +896,7 @@ static int delete_one_vdi(uint32_t vdi_id)
}
} else {
struct delete_arg arg = {inode, &nr_deleted};
- traverse_btree(inode, delete_cb, &arg);
+ sd_inode_index_walk(inode, delete_cb, &arg);
}
if (vdi_is_deleted(inode))
--
1.8.1.2
More information about the sheepdog
mailing list