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

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

ceph: queue cap snap only when snap realm's context changes



If we create capsnap when snap realm's context does not change, the
new capsnap's snapc is equal to ci->i_head_snapc. Page writeback code
can't differentiates dirty pages associated with the new capsnap from
dirty pages associated with i_head_snapc.

Signed-off-by: default avatar"Yan, Zheng" <zyan@redhat.com>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
parent c8fd0d37
Loading
Loading
Loading
Loading
+16 −21
Original line number Diff line number Diff line
@@ -299,7 +299,8 @@ static int cmpu64_rev(const void *a, const void *b)
/*
 * build the snap context for a given realm.
 */
static int build_snap_context(struct ceph_snap_realm *realm)
static int build_snap_context(struct ceph_snap_realm *realm,
			      struct list_head* dirty_realms)
{
	struct ceph_snap_realm *parent = realm->parent;
	struct ceph_snap_context *snapc;
@@ -313,7 +314,7 @@ static int build_snap_context(struct ceph_snap_realm *realm)
	 */
	if (parent) {
		if (!parent->cached_context) {
			err = build_snap_context(parent);
			err = build_snap_context(parent, dirty_realms);
			if (err)
				goto fail;
		}
@@ -373,7 +374,11 @@ static int build_snap_context(struct ceph_snap_realm *realm)
	     realm->ino, realm, snapc, snapc->seq,
	     (unsigned int) snapc->num_snaps);

	if (realm->cached_context) {
		ceph_put_snap_context(realm->cached_context);
		/* queue realm for cap_snap creation */
		list_add_tail(&realm->dirty_item, dirty_realms);
	}
	realm->cached_context = snapc;
	return 0;

@@ -394,15 +399,16 @@ static int build_snap_context(struct ceph_snap_realm *realm)
/*
 * rebuild snap context for the given realm and all of its children.
 */
static void rebuild_snap_realms(struct ceph_snap_realm *realm)
static void rebuild_snap_realms(struct ceph_snap_realm *realm,
				struct list_head *dirty_realms)
{
	struct ceph_snap_realm *child;

	dout("rebuild_snap_realms %llx %p\n", realm->ino, realm);
	build_snap_context(realm);
	build_snap_context(realm, dirty_realms);

	list_for_each_entry(child, &realm->children, child_item)
		rebuild_snap_realms(child);
		rebuild_snap_realms(child, dirty_realms);
}


@@ -624,13 +630,11 @@ static void queue_realm_cap_snaps(struct ceph_snap_realm *realm)
{
	struct ceph_inode_info *ci;
	struct inode *lastinode = NULL;
	struct ceph_snap_realm *child;

	dout("queue_realm_cap_snaps %p %llx inodes\n", realm, realm->ino);

	spin_lock(&realm->inodes_with_caps_lock);
	list_for_each_entry(ci, &realm->inodes_with_caps,
			    i_snap_realm_item) {
	list_for_each_entry(ci, &realm->inodes_with_caps, i_snap_realm_item) {
		struct inode *inode = igrab(&ci->vfs_inode);
		if (!inode)
			continue;
@@ -643,14 +647,6 @@ static void queue_realm_cap_snaps(struct ceph_snap_realm *realm)
	spin_unlock(&realm->inodes_with_caps_lock);
	iput(lastinode);

	list_for_each_entry(child, &realm->children, child_item) {
		dout("queue_realm_cap_snaps %p %llx queue child %p %llx\n",
		     realm, realm->ino, child, child->ino);
		list_del_init(&child->dirty_item);
		list_add(&child->dirty_item, &realm->dirty_item);
	}

	list_del_init(&realm->dirty_item);
	dout("queue_realm_cap_snaps %p %llx done\n", realm, realm->ino);
}

@@ -721,8 +717,6 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
		if (err < 0)
			goto fail;

		/* queue realm for cap_snap creation */
		list_add(&realm->dirty_item, &dirty_realms);
		if (realm->seq > mdsc->last_snap_seq)
			mdsc->last_snap_seq = realm->seq;

@@ -741,7 +735,7 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,

	/* invalidate when we reach the _end_ (root) of the trace */
	if (invalidate && p >= e)
		rebuild_snap_realms(realm);
		rebuild_snap_realms(realm, &dirty_realms);

	if (!first_realm)
		first_realm = realm;
@@ -758,6 +752,7 @@ int ceph_update_snap_trace(struct ceph_mds_client *mdsc,
	while (!list_empty(&dirty_realms)) {
		realm = list_first_entry(&dirty_realms, struct ceph_snap_realm,
					 dirty_item);
		list_del_init(&realm->dirty_item);
		queue_realm_cap_snaps(realm);
	}