aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2009-12-21 23:40:34 -0500
committerSage Weil <sage@newdream.net>2009-12-23 11:17:14 -0500
commit5dacf09121ffb2e5fc7d15b78cae0b77042a1935 (patch)
tree8a4ec2fde459f93936a91644d024673d37347408 /fs
parent7067f797b8409f1e10ec95ac2c1e17a200173d13 (diff)
ceph: do not touch_caps while iterating over caps list
Avoid confusing iterate_session_caps(), flag the session while we are iterating so that __touch_cap does not rearrange items on the list. All other modifiers of session->s_caps do so under the protection of s_mutex. Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs')
-rw-r--r--fs/ceph/caps.c11
-rw-r--r--fs/ceph/mds_client.c14
-rw-r--r--fs/ceph/mds_client.h1
3 files changed, 19 insertions, 7 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index dfb509f53542..93c1afe3f0b3 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -697,10 +697,15 @@ static void __touch_cap(struct ceph_cap *cap)
697{ 697{
698 struct ceph_mds_session *s = cap->session; 698 struct ceph_mds_session *s = cap->session;
699 699
700 dout("__touch_cap %p cap %p mds%d\n", &cap->ci->vfs_inode, cap,
701 s->s_mds);
702 spin_lock(&s->s_cap_lock); 700 spin_lock(&s->s_cap_lock);
703 list_move_tail(&cap->session_caps, &s->s_caps); 701 if (!s->s_iterating_caps) {
702 dout("__touch_cap %p cap %p mds%d\n", &cap->ci->vfs_inode, cap,
703 s->s_mds);
704 list_move_tail(&cap->session_caps, &s->s_caps);
705 } else {
706 dout("__touch_cap %p cap %p mds%d NOP, iterating over caps\n",
707 &cap->ci->vfs_inode, cap, s->s_mds);
708 }
704 spin_unlock(&s->s_cap_lock); 709 spin_unlock(&s->s_cap_lock);
705} 710}
706 711
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index d7cecc3366da..63ca3b1ad45f 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -337,10 +337,12 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
337 s->s_renew_seq = 0; 337 s->s_renew_seq = 0;
338 INIT_LIST_HEAD(&s->s_caps); 338 INIT_LIST_HEAD(&s->s_caps);
339 s->s_nr_caps = 0; 339 s->s_nr_caps = 0;
340 s->s_trim_caps = 0;
340 atomic_set(&s->s_ref, 1); 341 atomic_set(&s->s_ref, 1);
341 INIT_LIST_HEAD(&s->s_waiting); 342 INIT_LIST_HEAD(&s->s_waiting);
342 INIT_LIST_HEAD(&s->s_unsafe); 343 INIT_LIST_HEAD(&s->s_unsafe);
343 s->s_num_cap_releases = 0; 344 s->s_num_cap_releases = 0;
345 s->s_iterating_caps = false;
344 INIT_LIST_HEAD(&s->s_cap_releases); 346 INIT_LIST_HEAD(&s->s_cap_releases);
345 INIT_LIST_HEAD(&s->s_cap_releases_done); 347 INIT_LIST_HEAD(&s->s_cap_releases_done);
346 INIT_LIST_HEAD(&s->s_cap_flushing); 348 INIT_LIST_HEAD(&s->s_cap_flushing);
@@ -699,6 +701,7 @@ static int iterate_session_caps(struct ceph_mds_session *session,
699 701
700 dout("iterate_session_caps %p mds%d\n", session, session->s_mds); 702 dout("iterate_session_caps %p mds%d\n", session, session->s_mds);
701 spin_lock(&session->s_cap_lock); 703 spin_lock(&session->s_cap_lock);
704 session->s_iterating_caps = true;
702 list_for_each_entry_safe(cap, ncap, &session->s_caps, session_caps) { 705 list_for_each_entry_safe(cap, ncap, &session->s_caps, session_caps) {
703 inode = igrab(&cap->ci->vfs_inode); 706 inode = igrab(&cap->ci->vfs_inode);
704 if (!inode) 707 if (!inode)
@@ -706,13 +709,15 @@ static int iterate_session_caps(struct ceph_mds_session *session,
706 spin_unlock(&session->s_cap_lock); 709 spin_unlock(&session->s_cap_lock);
707 ret = cb(inode, cap, arg); 710 ret = cb(inode, cap, arg);
708 iput(inode); 711 iput(inode);
709 if (ret < 0)
710 return ret;
711 spin_lock(&session->s_cap_lock); 712 spin_lock(&session->s_cap_lock);
713 if (ret < 0)
714 goto out;
712 } 715 }
716 ret = 0;
717out:
718 session->s_iterating_caps = false;
713 spin_unlock(&session->s_cap_lock); 719 spin_unlock(&session->s_cap_lock);
714 720 return ret;
715 return 0;
716} 721}
717 722
718static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap, 723static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
@@ -935,6 +940,7 @@ static int trim_caps(struct ceph_mds_client *mdsc,
935 dout("trim_caps mds%d done: %d / %d, trimmed %d\n", 940 dout("trim_caps mds%d done: %d / %d, trimmed %d\n",
936 session->s_mds, session->s_nr_caps, max_caps, 941 session->s_mds, session->s_nr_caps, max_caps,
937 trim_caps - session->s_trim_caps); 942 trim_caps - session->s_trim_caps);
943 session->s_trim_caps = 0;
938 } 944 }
939 return 0; 945 return 0;
940} 946}
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index 41af5ca316e6..b1c2025227c5 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -114,6 +114,7 @@ struct ceph_mds_session {
114 int s_num_cap_releases; 114 int s_num_cap_releases;
115 struct list_head s_cap_releases; /* waiting cap_release messages */ 115 struct list_head s_cap_releases; /* waiting cap_release messages */
116 struct list_head s_cap_releases_done; /* ready to send */ 116 struct list_head s_cap_releases_done; /* ready to send */
117 bool s_iterating_caps;
117 118
118 /* protected by mutex */ 119 /* protected by mutex */
119 struct list_head s_cap_flushing; /* inodes w/ flushing caps */ 120 struct list_head s_cap_flushing; /* inodes w/ flushing caps */