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/ceph/mds_client.c | |
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/ceph/mds_client.c')
-rw-r--r-- | fs/ceph/mds_client.c | 14 |
1 files changed, 10 insertions, 4 deletions
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 | } |