diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index dfb509f53542a19ead1fea327a60db05e2921470..93c1afe3f0b3ecb395af080bdef0b7f046eadf1a 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -697,10 +697,15 @@ static void __touch_cap(struct ceph_cap *cap)
 {
 	struct ceph_mds_session *s = cap->session;
 
-	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);
+	if (!s->s_iterating_caps) {
+		dout("__touch_cap %p cap %p mds%d\n", &cap->ci->vfs_inode, cap,
+		     s->s_mds);
+		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);
 }
 
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index d7cecc3366daf555b8cab465a67f81834cc1b09b..63ca3b1ad45fc69feb0c87d1b7598c9264239466 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -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;
 }
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index 41af5ca316e6ee0142d5481b4209b90d4c03eabf..b1c2025227c5d45c9b74e2238fe1dbe84a7dabd5 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -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 */