diff options
author | Sage Weil <sage@newdream.net> | 2009-12-21 23:40:34 -0500 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2009-12-23 11:17:14 -0500 |
commit | 5dacf09121ffb2e5fc7d15b78cae0b77042a1935 (patch) | |
tree | 8a4ec2fde459f93936a91644d024673d37347408 /fs | |
parent | 7067f797b8409f1e10ec95ac2c1e17a200173d13 (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.c | 11 | ||||
-rw-r--r-- | fs/ceph/mds_client.c | 14 | ||||
-rw-r--r-- | fs/ceph/mds_client.h | 1 |
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; | ||
717 | out: | ||
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 | ||
718 | static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap, | 723 | static 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 */ |