aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ceph/mds_client.c
diff options
context:
space:
mode:
authorAlex Elder <elder@dreamhost.com>2012-01-12 20:48:10 -0500
committerSage Weil <sage@newdream.net>2012-02-02 15:49:19 -0500
commitd8fb02abdc39f92a1066313e2b17047876afa8f9 (patch)
tree32f8126683dd185411b701b79d23900cf6c02035 /fs/ceph/mds_client.c
parent32852a81bccd9e3d1953b894966393d1b546576d (diff)
ceph: create a new session lock to avoid lock inversion
Lockdep was reporting a possible circular lock dependency in dentry_lease_is_valid(). That function needs to sample the session's s_cap_gen and and s_cap_ttl fields coherently, but needs to do so while holding a dentry lock. The s_cap_lock field was being used to protect the two fields, but that can't be taken while holding a lock on a dentry within the session. In most cases, the s_cap_gen and s_cap_ttl fields only get operated on separately. But in three cases they need to be updated together. Implement a new lock to protect the spots updating both fields atomically is required. Signed-off-by: Alex Elder <elder@dreamhost.com> Reviewed-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs/ceph/mds_client.c')
-rw-r--r--fs/ceph/mds_client.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index be1415fcaac8..a4fdf9397a90 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -400,9 +400,11 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
400 s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS; 400 s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS;
401 s->s_con.peer_name.num = cpu_to_le64(mds); 401 s->s_con.peer_name.num = cpu_to_le64(mds);
402 402
403 spin_lock_init(&s->s_cap_lock); 403 spin_lock_init(&s->s_gen_ttl_lock);
404 s->s_cap_gen = 0; 404 s->s_cap_gen = 0;
405 s->s_cap_ttl = 0; 405 s->s_cap_ttl = 0;
406
407 spin_lock_init(&s->s_cap_lock);
406 s->s_renew_requested = 0; 408 s->s_renew_requested = 0;
407 s->s_renew_seq = 0; 409 s->s_renew_seq = 0;
408 INIT_LIST_HEAD(&s->s_caps); 410 INIT_LIST_HEAD(&s->s_caps);
@@ -2328,10 +2330,10 @@ static void handle_session(struct ceph_mds_session *session,
2328 case CEPH_SESSION_STALE: 2330 case CEPH_SESSION_STALE:
2329 pr_info("mds%d caps went stale, renewing\n", 2331 pr_info("mds%d caps went stale, renewing\n",
2330 session->s_mds); 2332 session->s_mds);
2331 spin_lock(&session->s_cap_lock); 2333 spin_lock(&session->s_gen_ttl_lock);
2332 session->s_cap_gen++; 2334 session->s_cap_gen++;
2333 session->s_cap_ttl = 0; 2335 session->s_cap_ttl = 0;
2334 spin_unlock(&session->s_cap_lock); 2336 spin_unlock(&session->s_gen_ttl_lock);
2335 send_renew_caps(mdsc, session); 2337 send_renew_caps(mdsc, session);
2336 break; 2338 break;
2337 2339