diff options
author | Niels Dossche <dossche.niels@gmail.com> | 2022-03-15 16:29:47 +0100 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2022-04-25 10:45:15 +0200 |
commit | 7f47f7f3b3c33fd2b4a662cd43cd1af96e1a297e (patch) | |
tree | 90a305f1eeff65d108133db4cb7dcd0766a8e580 /fs/ceph/caps.c | |
parent | dc9b0dc4561dedd44b2bf4b8e5ef1a8a040b2424 (diff) |
ceph: get snap_rwsem read lock in handle_cap_export for ceph_add_cap
ceph_add_cap says in its function documentation that the caller should
hold the read lock on the session snap_rwsem. Furthermore, not only
ceph_add_cap needs that lock, when it calls to ceph_lookup_snap_realm it
eventually calls ceph_get_snap_realm which states via lockdep that
snap_rwsem needs to be held. handle_cap_export calls ceph_add_cap
without that mdsc->snap_rwsem held. Thus, since ceph_get_snap_realm
and ceph_add_cap both need the lock, the common place to acquire that
lock is inside handle_cap_export.
Signed-off-by: Niels Dossche <dossche.niels@gmail.com>
Reviewed-by: Xiubo Li <xiubli@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs/ceph/caps.c')
-rw-r--r-- | fs/ceph/caps.c | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index f1ad6884d4da..31204cdc2fbf 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -3870,6 +3870,7 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex, dout("handle_cap_export inode %p ci %p mds%d mseq %d target %d\n", inode, ci, mds, mseq, target); retry: + down_read(&mdsc->snap_rwsem); spin_lock(&ci->i_ceph_lock); cap = __get_cap_for_mds(ci, mds); if (!cap || cap->cap_id != le64_to_cpu(ex->cap_id)) @@ -3933,6 +3934,7 @@ retry: } spin_unlock(&ci->i_ceph_lock); + up_read(&mdsc->snap_rwsem); mutex_unlock(&session->s_mutex); /* open target session */ @@ -3958,6 +3960,7 @@ retry: out_unlock: spin_unlock(&ci->i_ceph_lock); + up_read(&mdsc->snap_rwsem); mutex_unlock(&session->s_mutex); if (tsession) { mutex_unlock(&tsession->s_mutex); |