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

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

ceph: don't assume frag tree splits in mds reply are sorted



The algorithm that updates i_fragtree relies on that the frag tree
splits in mds reply are of the same order of i_fragtree. This is not
true because current MDS encodes frag tree splits in ascending order
of (unsigned)frag_t. But nodes in i_fragtree are sorted according to
ceph_frag_compare().

The fix is sort the frag tree splits first, then updates i_fragtree.

Signed-off-by: default avatarYan, Zheng <zyan@redhat.com>
parent 209ae762
Loading
Loading
Loading
Loading
+13 −0
Original line number Original line Diff line number Diff line
@@ -10,6 +10,7 @@
#include <linux/vmalloc.h>
#include <linux/vmalloc.h>
#include <linux/posix_acl.h>
#include <linux/posix_acl.h>
#include <linux/random.h>
#include <linux/random.h>
#include <linux/sort.h>


#include "super.h"
#include "super.h"
#include "mds_client.h"
#include "mds_client.h"
@@ -299,6 +300,13 @@ static int ceph_fill_dirfrag(struct inode *inode,
	return err;
	return err;
}
}


static int frag_tree_split_cmp(const void *l, const void *r)
{
	struct ceph_frag_tree_split *ls = (struct ceph_frag_tree_split*)l;
	struct ceph_frag_tree_split *rs = (struct ceph_frag_tree_split*)r;
	return ceph_frag_compare(ls->frag, rs->frag);
}

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)
@@ -331,6 +339,11 @@ static int ceph_fill_fragtree(struct inode *inode,
	if (!update)
	if (!update)
		goto out_unlock;
		goto out_unlock;


	if (nsplits > 1) {
		sort(fragtree->splits, nsplits, sizeof(fragtree->splits[0]),
		     frag_tree_split_cmp, NULL);
	}

	dout("fill_fragtree %llx.%llx\n", ceph_vinop(inode));
	dout("fill_fragtree %llx.%llx\n", ceph_vinop(inode));
	rb_node = rb_first(&ci->i_fragtree);
	rb_node = rb_first(&ci->i_fragtree);
	for (i = 0; i < nsplits; i++) {
	for (i = 0; i < nsplits; i++) {