ceph: use d_invalidate() to invalidate aliases
[firefly-linux-kernel-4.4.55.git] / fs / ceph / mds_client.c
index 74fd2898b2ab43012ab1c3fbf25f619fbd7df3b2..b7bda5d9611da031aaf6f104ece9fa6351993070 100644 (file)
@@ -414,6 +414,9 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
 {
        struct ceph_mds_session *s;
 
+       if (mds >= mdsc->mdsmap->m_max_mds)
+               return ERR_PTR(-EINVAL);
+
        s = kzalloc(sizeof(*s), GFP_NOFS);
        if (!s)
                return ERR_PTR(-ENOMEM);
@@ -1028,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_find_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);
@@ -1391,6 +1425,7 @@ static void discard_cap_releases(struct ceph_mds_client *mdsc,
        num = le32_to_cpu(head->num);
        dout("discard_cap_releases mds%d %p %u\n", session->s_mds, msg, num);
        head->num = cpu_to_le32(0);
+       msg->front.iov_len = sizeof(*head);
        session->s_num_cap_releases += num;
 
        /* requeue completed messages */
@@ -1553,7 +1588,7 @@ retry:
        *base = ceph_ino(temp->d_inode);
        *plen = len;
        dout("build_path on %p %d built %llx '%.*s'\n",
-            dentry, dentry->d_count, *base, len, path);
+            dentry, d_count(dentry), *base, len, path);
        return path;
 }
 
@@ -2454,6 +2489,7 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap,
        spin_lock(&ci->i_ceph_lock);
        cap->seq = 0;        /* reset cap seq */
        cap->issue_seq = 0;  /* and issue_seq */
+       cap->mseq = 0;       /* and migrate_seq */
 
        if (recon_state->flock) {
                rec.v2.cap_id = cpu_to_le64(cap->cap_id);
@@ -3040,8 +3076,10 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc)
        fsc->mdsc = mdsc;
        mutex_init(&mdsc->mutex);
        mdsc->mdsmap = kzalloc(sizeof(*mdsc->mdsmap), GFP_NOFS);
-       if (mdsc->mdsmap == NULL)
+       if (mdsc->mdsmap == NULL) {
+               kfree(mdsc);
                return -ENOMEM;
+       }
 
        init_completion(&mdsc->safe_umount_waiters);
        init_waitqueue_head(&mdsc->session_close_wq);