Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+23 −5
Original line number Diff line number Diff line
@@ -310,12 +310,21 @@ static int frag_tree_split_cmp(const void *l, const void *r)
	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,
			      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 ceph_inode_frag *frag, *prev_frag = NULL;
	struct rb_node *rb_node;
	int i;
	u32 id, nsplits;
@@ -362,8 +371,12 @@ static int ceph_fill_fragtree(struct inode *inode,
				break;
			}
			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);
				kfree(frag);
			}
			frag = NULL;
		}
		if (!frag) {
@@ -373,13 +386,18 @@ static int ceph_fill_fragtree(struct inode *inode,
		}
		frag->split_by = le32_to_cpu(fragtree->splits[i].by);
		dout(" frag %x split by %d\n", frag->frag, frag->split_by);
		prev_frag = frag;
	}
	while (rb_node) {
		frag = rb_entry(rb_node, struct ceph_inode_frag, 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);
			kfree(frag);
		}
	}
out_unlock:
	mutex_unlock(&ci->i_fragtree_mutex);
	return 0;