Commit a4b7431f authored by Yan, Zheng's avatar Yan, Zheng Committed by Ilya Dryomov

ceph: keep leaf frag when updating fragtree

Nodes in i_fragtree are sorted according to ceph_compare_frag().
It means frag node in i_fragtree always follow its direct parent
node. To check if a leaf node is valid, we just need to check if
it's child of previous split node.
Signed-off-by: default avatarYan, Zheng <zyan@redhat.com>
parent 42172119
...@@ -310,12 +310,21 @@ static int frag_tree_split_cmp(const void *l, const void *r) ...@@ -310,12 +310,21 @@ static int frag_tree_split_cmp(const void *l, const void *r)
return ceph_frag_compare(ls->frag, rs->frag); return ceph_frag_compare(ls->frag, rs->frag);
} }
static bool is_frag_child(u32 f, struct ceph_inode_frag *frag)
{
if (!frag)
return f == ceph_frag_make(0, 0);
if (ceph_frag_bits(f) != ceph_frag_bits(frag->frag) + frag->split_by)
return false;
return ceph_frag_contains_value(frag->frag, ceph_frag_value(f));
}
static int ceph_fill_fragtree(struct inode *inode, static int ceph_fill_fragtree(struct inode *inode,
struct ceph_frag_tree_head *fragtree, struct ceph_frag_tree_head *fragtree,
struct ceph_mds_reply_dirfrag *dirinfo) struct ceph_mds_reply_dirfrag *dirinfo)
{ {
struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_inode_frag *frag; struct ceph_inode_frag *frag, *prev_frag = NULL;
struct rb_node *rb_node; struct rb_node *rb_node;
int i; int i;
u32 id, nsplits; u32 id, nsplits;
...@@ -362,8 +371,12 @@ static int ceph_fill_fragtree(struct inode *inode, ...@@ -362,8 +371,12 @@ static int ceph_fill_fragtree(struct inode *inode,
break; break;
} }
rb_node = rb_next(rb_node); rb_node = rb_next(rb_node);
/* delete stale split/leaf node */
if (frag->split_by > 0 ||
!is_frag_child(frag->frag, prev_frag)) {
rb_erase(&frag->node, &ci->i_fragtree); rb_erase(&frag->node, &ci->i_fragtree);
kfree(frag); kfree(frag);
}
frag = NULL; frag = NULL;
} }
if (!frag) { if (!frag) {
...@@ -373,13 +386,18 @@ static int ceph_fill_fragtree(struct inode *inode, ...@@ -373,13 +386,18 @@ static int ceph_fill_fragtree(struct inode *inode,
} }
frag->split_by = le32_to_cpu(fragtree->splits[i].by); frag->split_by = le32_to_cpu(fragtree->splits[i].by);
dout(" frag %x split by %d\n", frag->frag, frag->split_by); dout(" frag %x split by %d\n", frag->frag, frag->split_by);
prev_frag = frag;
} }
while (rb_node) { while (rb_node) {
frag = rb_entry(rb_node, struct ceph_inode_frag, node); frag = rb_entry(rb_node, struct ceph_inode_frag, node);
rb_node = rb_next(rb_node); rb_node = rb_next(rb_node);
/* delete stale split/leaf node */
if (frag->split_by > 0 ||
!is_frag_child(frag->frag, prev_frag)) {
rb_erase(&frag->node, &ci->i_fragtree); rb_erase(&frag->node, &ci->i_fragtree);
kfree(frag); kfree(frag);
} }
}
out_unlock: out_unlock:
mutex_unlock(&ci->i_fragtree_mutex); mutex_unlock(&ci->i_fragtree_mutex);
return 0; return 0;
......
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