|
@@ -1031,6 +1031,37 @@ static void remove_session_caps(struct ceph_mds_session *session)
|
|
|
{
|
|
|
dout("remove_session_caps on %p\n", session);
|
|
|
iterate_session_caps(session, remove_session_caps_cb, NULL);
|
|
|
+
|
|
|
+ spin_lock(&session->s_cap_lock);
|
|
|
+ if (session->s_nr_caps > 0) {
|
|
|
+ struct super_block *sb = session->s_mdsc->fsc->sb;
|
|
|
+ struct inode *inode;
|
|
|
+ struct ceph_cap *cap, *prev = NULL;
|
|
|
+ struct ceph_vino vino;
|
|
|
+ /*
|
|
|
+ * iterate_session_caps() skips inodes that are being
|
|
|
+ * deleted, we need to wait until deletions are complete.
|
|
|
+ * __wait_on_freeing_inode() is designed for the job,
|
|
|
+ * but it is not exported, so use lookup inode function
|
|
|
+ * to access it.
|
|
|
+ */
|
|
|
+ while (!list_empty(&session->s_caps)) {
|
|
|
+ cap = list_entry(session->s_caps.next,
|
|
|
+ struct ceph_cap, session_caps);
|
|
|
+ if (cap == prev)
|
|
|
+ break;
|
|
|
+ prev = cap;
|
|
|
+ vino = cap->ci->i_vino;
|
|
|
+ spin_unlock(&session->s_cap_lock);
|
|
|
+
|
|
|
+ inode = ceph_lookup_inode(sb, vino);
|
|
|
+ iput(inode);
|
|
|
+
|
|
|
+ spin_lock(&session->s_cap_lock);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ spin_unlock(&session->s_cap_lock);
|
|
|
+
|
|
|
BUG_ON(session->s_nr_caps > 0);
|
|
|
BUG_ON(!list_empty(&session->s_cap_flushing));
|
|
|
cleanup_cap_releases(session);
|