Commit 829ad4db authored by Jeff Layton's avatar Jeff Layton Committed by Ilya Dryomov
Browse files

ceph: ceph_kick_flushing_caps needs the s_mutex



The mdsc->cap_dirty_lock is not held while walking the list in
ceph_kick_flushing_caps, which is not safe.

ceph_early_kick_flushing_caps does something similar, but the
s_mutex is held while it's called and I think that guards against
changes to the list.

Ensure we hold the s_mutex when calling ceph_kick_flushing_caps,
and add some clarifying comments.

Signed-off-by: default avatarJeff Layton <jlayton@kernel.org>
Reviewed-by: default avatar"Yan, Zheng" <zyan@redhat.com>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
parent d67c72e6
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -2518,6 +2518,8 @@ void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc,
	struct ceph_cap *cap;
	u64 oldest_flush_tid;

	lockdep_assert_held(&session->s_mutex);

	dout("kick_flushing_caps mds%d\n", session->s_mds);

	spin_lock(&mdsc->cap_dirty_lock);
+2 −0
Original line number Diff line number Diff line
@@ -4024,7 +4024,9 @@ static void check_new_map(struct ceph_mds_client *mdsc,
			    oldstate != CEPH_MDS_STATE_STARTING)
				pr_info("mds%d recovery completed\n", s->s_mds);
			kick_requests(mdsc, i);
			mutex_lock(&s->s_mutex);
			ceph_kick_flushing_caps(mdsc, s);
			mutex_unlock(&s->s_mutex);
			wake_up_session_caps(s, RECONNECT);
		}
	}
+3 −1
Original line number Diff line number Diff line
@@ -199,8 +199,10 @@ struct ceph_mds_session {
	struct list_head  s_cap_releases; /* waiting cap_release messages */
	struct work_struct s_cap_release_work;

	/* both protected by s_mdsc->cap_dirty_lock */
	/* See ceph_inode_info->i_dirty_item. */
	struct list_head  s_cap_dirty;	      /* inodes w/ dirty caps */

	/* See ceph_inode_info->i_flushing_item. */
	struct list_head  s_cap_flushing;     /* inodes w/ flushing caps */

	unsigned long     s_renew_requested; /* last time we sent a renew req */
+5 −2
Original line number Diff line number Diff line
@@ -362,8 +362,11 @@ struct ceph_inode_info {
	struct list_head i_dirty_item;

	/*
	 * Link to session's s_cap_flushing list. Protected by
	 * mdsc->cap_dirty_lock.
	 * Link to session's s_cap_flushing list. Protected in a similar
	 * fashion to i_dirty_item, but also by the s_mutex for changes. The
	 * s_cap_flushing list can be walked while holding either the s_mutex
	 * or msdc->cap_dirty_lock. List presence can also be checked while
	 * holding the i_ceph_lock for this inode.
	 */
	struct list_head i_flushing_item;