ceph: fetch cap_gen under spinlock in ceph_add_cap
authorJeff Layton <jlayton@kernel.org>
Mon, 22 Jul 2019 17:12:01 +0000 (13:12 -0400)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 16 Sep 2019 10:06:24 +0000 (12:06 +0200)
It's protected by the s_gen_ttl_lock, so we should fetch under it
and ensure that we're using the same generation in both places.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: "Yan, Zheng" <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/ceph/caps.c

index 4615f2501e1503581f57b0f31551b2bfacf4ffdf..bdfec8978479a0b0f00638f38b7595640e7f72c4 100644 (file)
@@ -614,6 +614,7 @@ void ceph_add_cap(struct inode *inode,
        struct ceph_cap *cap;
        int mds = session->s_mds;
        int actual_wanted;
+       u32 gen;
 
        dout("add_cap %p mds%d cap %llx %s seq %d\n", inode,
             session->s_mds, cap_id, ceph_cap_string(issued), seq);
@@ -625,6 +626,10 @@ void ceph_add_cap(struct inode *inode,
        if (fmode >= 0)
                wanted |= ceph_caps_for_mode(fmode);
 
+       spin_lock(&session->s_gen_ttl_lock);
+       gen = session->s_cap_gen;
+       spin_unlock(&session->s_gen_ttl_lock);
+
        cap = __get_cap_for_mds(ci, mds);
        if (!cap) {
                cap = *new_cap;
@@ -650,7 +655,7 @@ void ceph_add_cap(struct inode *inode,
                list_move_tail(&cap->session_caps, &session->s_caps);
                spin_unlock(&session->s_cap_lock);
 
-               if (cap->cap_gen < session->s_cap_gen)
+               if (cap->cap_gen < gen)
                        cap->issued = cap->implemented = CEPH_CAP_PIN;
 
                /*
@@ -744,7 +749,7 @@ void ceph_add_cap(struct inode *inode,
        cap->seq = seq;
        cap->issue_seq = seq;
        cap->mseq = mseq;
-       cap->cap_gen = session->s_cap_gen;
+       cap->cap_gen = gen;
 
        if (fmode >= 0)
                __ceph_get_fmode(ci, fmode);