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

Commit 5dacf091 authored by Sage Weil's avatar Sage Weil
Browse files

ceph: do not touch_caps while iterating over caps list



Avoid confusing iterate_session_caps(), flag the session while we are
iterating so that __touch_cap does not rearrange items on the list.

All other modifiers of session->s_caps do so under the protection of
s_mutex.

Signed-off-by: default avatarSage Weil <sage@newdream.net>
parent 7067f797
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -697,10 +697,15 @@ static void __touch_cap(struct ceph_cap *cap)
{
	struct ceph_mds_session *s = cap->session;

	spin_lock(&s->s_cap_lock);
	if (!s->s_iterating_caps) {
		dout("__touch_cap %p cap %p mds%d\n", &cap->ci->vfs_inode, cap,
		     s->s_mds);
	spin_lock(&s->s_cap_lock);
		list_move_tail(&cap->session_caps, &s->s_caps);
	} else {
		dout("__touch_cap %p cap %p mds%d NOP, iterating over caps\n",
		     &cap->ci->vfs_inode, cap, s->s_mds);
	}
	spin_unlock(&s->s_cap_lock);
}

+10 −4
Original line number Diff line number Diff line
@@ -337,10 +337,12 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
	s->s_renew_seq = 0;
	INIT_LIST_HEAD(&s->s_caps);
	s->s_nr_caps = 0;
	s->s_trim_caps = 0;
	atomic_set(&s->s_ref, 1);
	INIT_LIST_HEAD(&s->s_waiting);
	INIT_LIST_HEAD(&s->s_unsafe);
	s->s_num_cap_releases = 0;
	s->s_iterating_caps = false;
	INIT_LIST_HEAD(&s->s_cap_releases);
	INIT_LIST_HEAD(&s->s_cap_releases_done);
	INIT_LIST_HEAD(&s->s_cap_flushing);
@@ -699,6 +701,7 @@ static int iterate_session_caps(struct ceph_mds_session *session,

	dout("iterate_session_caps %p mds%d\n", session, session->s_mds);
	spin_lock(&session->s_cap_lock);
	session->s_iterating_caps = true;
	list_for_each_entry_safe(cap, ncap, &session->s_caps, session_caps) {
		inode = igrab(&cap->ci->vfs_inode);
		if (!inode)
@@ -706,13 +709,15 @@ static int iterate_session_caps(struct ceph_mds_session *session,
		spin_unlock(&session->s_cap_lock);
		ret = cb(inode, cap, arg);
		iput(inode);
		if (ret < 0)
			return ret;
		spin_lock(&session->s_cap_lock);
		if (ret < 0)
			goto out;
	}
	ret = 0;
out:
	session->s_iterating_caps = false;
	spin_unlock(&session->s_cap_lock);

	return 0;
	return ret;
}

static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
@@ -935,6 +940,7 @@ static int trim_caps(struct ceph_mds_client *mdsc,
		dout("trim_caps mds%d done: %d / %d, trimmed %d\n",
		     session->s_mds, session->s_nr_caps, max_caps,
			trim_caps - session->s_trim_caps);
		session->s_trim_caps = 0;
	}
	return 0;
}
+1 −0
Original line number Diff line number Diff line
@@ -114,6 +114,7 @@ struct ceph_mds_session {
	int               s_num_cap_releases;
	struct list_head  s_cap_releases; /* waiting cap_release messages */
	struct list_head  s_cap_releases_done; /* ready to send */
	bool              s_iterating_caps;

	/* protected by mutex */
	struct list_head  s_cap_flushing;     /* inodes w/ flushing caps */