Commit 3e7fbe9c authored by Yan, Zheng's avatar Yan, Zheng

ceph: introduce ceph_fill_fragtree()

Move the code that update the i_fragtree into a separate function.
Also add simple probabilistic test to decide whether the i_fragtree
should be updated
Signed-off-by: default avatarYan, Zheng <zheng.z.yan@intel.com>
parent 2cd698be
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/posix_acl.h> #include <linux/posix_acl.h>
#include <linux/random.h>
#include "super.h" #include "super.h"
#include "mds_client.h" #include "mds_client.h"
...@@ -179,9 +180,8 @@ struct ceph_inode_frag *__ceph_find_frag(struct ceph_inode_info *ci, u32 f) ...@@ -179,9 +180,8 @@ struct ceph_inode_frag *__ceph_find_frag(struct ceph_inode_info *ci, u32 f)
* specified, copy the frag delegation info to the caller if * specified, copy the frag delegation info to the caller if
* it is present. * it is present.
*/ */
u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v, static u32 __ceph_choose_frag(struct ceph_inode_info *ci, u32 v,
struct ceph_inode_frag *pfrag, struct ceph_inode_frag *pfrag, int *found)
int *found)
{ {
u32 t = ceph_frag_make(0, 0); u32 t = ceph_frag_make(0, 0);
struct ceph_inode_frag *frag; struct ceph_inode_frag *frag;
...@@ -191,7 +191,6 @@ u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v, ...@@ -191,7 +191,6 @@ u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v,
if (found) if (found)
*found = 0; *found = 0;
mutex_lock(&ci->i_fragtree_mutex);
while (1) { while (1) {
WARN_ON(!ceph_frag_contains_value(t, v)); WARN_ON(!ceph_frag_contains_value(t, v));
frag = __ceph_find_frag(ci, t); frag = __ceph_find_frag(ci, t);
...@@ -220,10 +219,19 @@ u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v, ...@@ -220,10 +219,19 @@ u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v,
} }
dout("choose_frag(%x) = %x\n", v, t); dout("choose_frag(%x) = %x\n", v, t);
mutex_unlock(&ci->i_fragtree_mutex);
return t; return t;
} }
u32 ceph_choose_frag(struct ceph_inode_info *ci, u32 v,
struct ceph_inode_frag *pfrag, int *found)
{
u32 ret;
mutex_lock(&ci->i_fragtree_mutex);
ret = __ceph_choose_frag(ci, v, pfrag, found);
mutex_unlock(&ci->i_fragtree_mutex);
return ret;
}
/* /*
* Process dirfrag (delegation) info from the mds. Include leaf * Process dirfrag (delegation) info from the mds. Include leaf
* fragment in tree ONLY if ndist > 0. Otherwise, only * fragment in tree ONLY if ndist > 0. Otherwise, only
...@@ -286,6 +294,75 @@ static int ceph_fill_dirfrag(struct inode *inode, ...@@ -286,6 +294,75 @@ static int ceph_fill_dirfrag(struct inode *inode,
return err; return err;
} }
static int ceph_fill_fragtree(struct inode *inode,
struct ceph_frag_tree_head *fragtree,
struct ceph_mds_reply_dirfrag *dirinfo)
{
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_inode_frag *frag;
struct rb_node *rb_node;
int i;
u32 id, nsplits;
bool update = false;
mutex_lock(&ci->i_fragtree_mutex);
nsplits = le32_to_cpu(fragtree->nsplits);
if (nsplits) {
i = prandom_u32() % nsplits;
id = le32_to_cpu(fragtree->splits[i].frag);
if (!__ceph_find_frag(ci, id))
update = true;
} else if (!RB_EMPTY_ROOT(&ci->i_fragtree)) {
rb_node = rb_first(&ci->i_fragtree);
frag = rb_entry(rb_node, struct ceph_inode_frag, node);
if (frag->frag != ceph_frag_make(0, 0) || rb_next(rb_node))
update = true;
}
if (!update && dirinfo) {
id = le32_to_cpu(dirinfo->frag);
if (id != __ceph_choose_frag(ci, id, NULL, NULL))
update = true;
}
if (!update)
goto out_unlock;
dout("fill_fragtree %llx.%llx\n", ceph_vinop(inode));
rb_node = rb_first(&ci->i_fragtree);
for (i = 0; i < nsplits; i++) {
id = le32_to_cpu(fragtree->splits[i].frag);
frag = NULL;
while (rb_node) {
frag = rb_entry(rb_node, struct ceph_inode_frag, node);
if (ceph_frag_compare(frag->frag, id) >= 0) {
if (frag->frag != id)
frag = NULL;
else
rb_node = rb_next(rb_node);
break;
}
rb_node = rb_next(rb_node);
rb_erase(&frag->node, &ci->i_fragtree);
kfree(frag);
frag = NULL;
}
if (!frag) {
frag = __get_or_create_frag(ci, id);
if (IS_ERR(frag))
continue;
}
frag->split_by = le32_to_cpu(fragtree->splits[i].by);
dout(" frag %x split by %d\n", frag->frag, frag->split_by);
}
while (rb_node) {
frag = rb_entry(rb_node, struct ceph_inode_frag, node);
rb_node = rb_next(rb_node);
rb_erase(&frag->node, &ci->i_fragtree);
kfree(frag);
}
out_unlock:
mutex_unlock(&ci->i_fragtree_mutex);
return 0;
}
/* /*
* initialize a newly allocated inode. * initialize a newly allocated inode.
...@@ -584,12 +661,8 @@ static int fill_inode(struct inode *inode, ...@@ -584,12 +661,8 @@ static int fill_inode(struct inode *inode,
struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
struct ceph_mds_reply_inode *info = iinfo->in; struct ceph_mds_reply_inode *info = iinfo->in;
struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_inode_info *ci = ceph_inode(inode);
int i;
int issued = 0, implemented, new_issued; int issued = 0, implemented, new_issued;
struct timespec mtime, atime, ctime; struct timespec mtime, atime, ctime;
u32 nsplits;
struct ceph_inode_frag *frag;
struct rb_node *rb_node;
struct ceph_buffer *xattr_blob = NULL; struct ceph_buffer *xattr_blob = NULL;
struct ceph_cap *new_cap = NULL; struct ceph_cap *new_cap = NULL;
int err = 0; int err = 0;
...@@ -804,42 +877,8 @@ static int fill_inode(struct inode *inode, ...@@ -804,42 +877,8 @@ static int fill_inode(struct inode *inode,
ceph_queue_vmtruncate(inode); ceph_queue_vmtruncate(inode);
/* populate frag tree */ /* populate frag tree */
/* FIXME: move me up, if/when version reflects fragtree changes */ if (S_ISDIR(inode->i_mode))
nsplits = le32_to_cpu(info->fragtree.nsplits); ceph_fill_fragtree(inode, &info->fragtree, dirinfo);
mutex_lock(&ci->i_fragtree_mutex);
rb_node = rb_first(&ci->i_fragtree);
for (i = 0; i < nsplits; i++) {
u32 id = le32_to_cpu(info->fragtree.splits[i].frag);
frag = NULL;
while (rb_node) {
frag = rb_entry(rb_node, struct ceph_inode_frag, node);
if (ceph_frag_compare(frag->frag, id) >= 0) {
if (frag->frag != id)
frag = NULL;
else
rb_node = rb_next(rb_node);
break;
}
rb_node = rb_next(rb_node);
rb_erase(&frag->node, &ci->i_fragtree);
kfree(frag);
frag = NULL;
}
if (!frag) {
frag = __get_or_create_frag(ci, id);
if (IS_ERR(frag))
continue;
}
frag->split_by = le32_to_cpu(info->fragtree.splits[i].by);
dout(" frag %x split by %d\n", frag->frag, frag->split_by);
}
while (rb_node) {
frag = rb_entry(rb_node, struct ceph_inode_frag, node);
rb_node = rb_next(rb_node);
rb_erase(&frag->node, &ci->i_fragtree);
kfree(frag);
}
mutex_unlock(&ci->i_fragtree_mutex);
/* update delegation info? */ /* update delegation info? */
if (dirinfo) if (dirinfo)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment