aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorYan, Zheng <zheng.z.yan@intel.com>2013-09-21 23:08:14 -0400
committerSage Weil <sage@inktank.com>2013-11-23 14:01:02 -0500
commit99a9c273b94a087f8feaec6c5ffbe3205a2dbe51 (patch)
treec02a8c512356b2a9ae76e18558e5b59a75458868 /fs
parent44c99757fae80e9db058e1f1d7419cf6472e9af1 (diff)
ceph: handle race between cap reconnect and cap release
When a cap get released while composing the cap reconnect message. We should skip queuing the release message if the cap hasn't been added to the cap reconnect message. Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com> Reviewed-by: Sage Weil <sage@inktank.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/ceph/caps.c8
-rw-r--r--fs/ceph/mds_client.c21
-rw-r--r--fs/ceph/mds_client.h1
3 files changed, 26 insertions, 4 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index d2d6e40e7345..3c0a4bd74996 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -909,7 +909,13 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
909 909
910 /* remove from session list */ 910 /* remove from session list */
911 spin_lock(&session->s_cap_lock); 911 spin_lock(&session->s_cap_lock);
912 if (queue_release) 912 /*
913 * s_cap_reconnect is protected by s_cap_lock. no one changes
914 * s_cap_gen while session is in the reconnect state.
915 */
916 if (queue_release &&
917 (!session->s_cap_reconnect ||
918 cap->cap_gen == session->s_cap_gen))
913 __queue_cap_release(session, ci->i_vino.ino, cap->cap_id, 919 __queue_cap_release(session, ci->i_vino.ino, cap->cap_id,
914 cap->mseq, cap->issue_seq); 920 cap->mseq, cap->issue_seq);
915 921
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 4a93d69abc8b..6d953ab0ac06 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -444,6 +444,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
444 INIT_LIST_HEAD(&s->s_waiting); 444 INIT_LIST_HEAD(&s->s_waiting);
445 INIT_LIST_HEAD(&s->s_unsafe); 445 INIT_LIST_HEAD(&s->s_unsafe);
446 s->s_num_cap_releases = 0; 446 s->s_num_cap_releases = 0;
447 s->s_cap_reconnect = 0;
447 s->s_cap_iterator = NULL; 448 s->s_cap_iterator = NULL;
448 INIT_LIST_HEAD(&s->s_cap_releases); 449 INIT_LIST_HEAD(&s->s_cap_releases);
449 INIT_LIST_HEAD(&s->s_cap_releases_done); 450 INIT_LIST_HEAD(&s->s_cap_releases_done);
@@ -1415,7 +1416,6 @@ static void discard_cap_releases(struct ceph_mds_client *mdsc,
1415 unsigned num; 1416 unsigned num;
1416 1417
1417 dout("discard_cap_releases mds%d\n", session->s_mds); 1418 dout("discard_cap_releases mds%d\n", session->s_mds);
1418 spin_lock(&session->s_cap_lock);
1419 1419
1420 /* zero out the in-progress message */ 1420 /* zero out the in-progress message */
1421 msg = list_first_entry(&session->s_cap_releases, 1421 msg = list_first_entry(&session->s_cap_releases,
@@ -1442,8 +1442,6 @@ static void discard_cap_releases(struct ceph_mds_client *mdsc,
1442 msg->front.iov_len = sizeof(*head); 1442 msg->front.iov_len = sizeof(*head);
1443 list_add(&msg->list_head, &session->s_cap_releases); 1443 list_add(&msg->list_head, &session->s_cap_releases);
1444 } 1444 }
1445
1446 spin_unlock(&session->s_cap_lock);
1447} 1445}
1448 1446
1449/* 1447/*
@@ -2488,6 +2486,7 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap,
2488 cap->seq = 0; /* reset cap seq */ 2486 cap->seq = 0; /* reset cap seq */
2489 cap->issue_seq = 0; /* and issue_seq */ 2487 cap->issue_seq = 0; /* and issue_seq */
2490 cap->mseq = 0; /* and migrate_seq */ 2488 cap->mseq = 0; /* and migrate_seq */
2489 cap->cap_gen = cap->session->s_cap_gen;
2491 2490
2492 if (recon_state->flock) { 2491 if (recon_state->flock) {
2493 rec.v2.cap_id = cpu_to_le64(cap->cap_id); 2492 rec.v2.cap_id = cpu_to_le64(cap->cap_id);
@@ -2611,8 +2610,20 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc,
2611 dout("session %p state %s\n", session, 2610 dout("session %p state %s\n", session,
2612 session_state_name(session->s_state)); 2611 session_state_name(session->s_state));
2613 2612
2613 spin_lock(&session->s_gen_ttl_lock);
2614 session->s_cap_gen++;
2615 spin_unlock(&session->s_gen_ttl_lock);
2616
2617 spin_lock(&session->s_cap_lock);
2618 /*
2619 * notify __ceph_remove_cap() that we are composing cap reconnect.
2620 * If a cap get released before being added to the cap reconnect,
2621 * __ceph_remove_cap() should skip queuing cap release.
2622 */
2623 session->s_cap_reconnect = 1;
2614 /* drop old cap expires; we're about to reestablish that state */ 2624 /* drop old cap expires; we're about to reestablish that state */
2615 discard_cap_releases(mdsc, session); 2625 discard_cap_releases(mdsc, session);
2626 spin_unlock(&session->s_cap_lock);
2616 2627
2617 /* traverse this session's caps */ 2628 /* traverse this session's caps */
2618 s_nr_caps = session->s_nr_caps; 2629 s_nr_caps = session->s_nr_caps;
@@ -2627,6 +2638,10 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc,
2627 if (err < 0) 2638 if (err < 0)
2628 goto fail; 2639 goto fail;
2629 2640
2641 spin_lock(&session->s_cap_lock);
2642 session->s_cap_reconnect = 0;
2643 spin_unlock(&session->s_cap_lock);
2644
2630 /* 2645 /*
2631 * snaprealms. we provide mds with the ino, seq (version), and 2646 * snaprealms. we provide mds with the ino, seq (version), and
2632 * parent for all of our realms. If the mds has any newer info, 2647 * parent for all of our realms. If the mds has any newer info,
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index c2a19fbbe517..4c053d099ae4 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -132,6 +132,7 @@ struct ceph_mds_session {
132 struct list_head s_caps; /* all caps issued by this session */ 132 struct list_head s_caps; /* all caps issued by this session */
133 int s_nr_caps, s_trim_caps; 133 int s_nr_caps, s_trim_caps;
134 int s_num_cap_releases; 134 int s_num_cap_releases;
135 int s_cap_reconnect;
135 struct list_head s_cap_releases; /* waiting cap_release messages */ 136 struct list_head s_cap_releases; /* waiting cap_release messages */
136 struct list_head s_cap_releases_done; /* ready to send */ 137 struct list_head s_cap_releases_done; /* ready to send */
137 struct ceph_cap *s_cap_iterator; 138 struct ceph_cap *s_cap_iterator;