| From 4a1afbc8eeca464832fd2c8c2524ea19831593fc Mon Sep 17 00:00:00 2001 |
| From: Jeff Layton <jlayton@kernel.org> |
| Date: Mon, 22 Jul 2019 13:12:01 -0400 |
| Subject: [PATCH] ceph: fetch cap_gen under spinlock in ceph_add_cap |
| |
| commit 606d102327a45a49d293557527802ee7fbfd7af1 upstream. |
| |
| 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> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c |
| index 622467e47cde..07ac2de542eb 100644 |
| --- a/fs/ceph/caps.c |
| +++ b/fs/ceph/caps.c |
| @@ -644,6 +644,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); |
| @@ -655,6 +656,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; |
| @@ -680,7 +685,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; |
| |
| /* |
| @@ -774,7 +779,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); |
| -- |
| 2.7.4 |
| |