summaryrefslogtreecommitdiffstats
path: root/fs/ceph/mds_client.c
diff options
context:
space:
mode:
authorSage Weil2009-12-22 05:40:34 +0100
committerSage Weil2009-12-23 17:17:14 +0100
commit5dacf09121ffb2e5fc7d15b78cae0b77042a1935 (patch)
tree8a4ec2fde459f93936a91644d024673d37347408 /fs/ceph/mds_client.c
parentceph: fix incremental osdmap pg_temp decoding bug (diff)
downloadkernel-qcow2-linux-5dacf09121ffb2e5fc7d15b78cae0b77042a1935.tar.gz
kernel-qcow2-linux-5dacf09121ffb2e5fc7d15b78cae0b77042a1935.tar.xz
kernel-qcow2-linux-5dacf09121ffb2e5fc7d15b78cae0b77042a1935.zip
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.c14
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,
s->s_renew_seq = 0;
INIT_LIST_HEAD(&s->s_caps);
s->s_nr_caps = 0;
+ s->s_trim_caps = 0;
atomic_set(&s->s_ref, 1);
INIT_LIST_HEAD(&s->s_waiting);
INIT_LIST_HEAD(&s->s_unsafe);
s->s_num_cap_releases = 0;
+ s->s_iterating_caps = false;
INIT_LIST_HEAD(&s->s_cap_releases);
INIT_LIST_HEAD(&s->s_cap_releases_done);
INIT_LIST_HEAD(&s->s_cap_flushing);
@@ -699,6 +701,7 @@ static int iterate_session_caps(struct ceph_mds_session *session,
dout("iterate_session_caps %p mds%d\n", session, session->s_mds);
spin_lock(&session->s_cap_lock);
+ session->s_iterating_caps = true;
list_for_each_entry_safe(cap, ncap, &session->s_caps, session_caps) {
inode = igrab(&cap->ci->vfs_inode);
if (!inode)
@@ -706,13 +709,15 @@ static int iterate_session_caps(struct ceph_mds_session *session,
spin_unlock(&session->s_cap_lock);
ret = cb(inode, cap, arg);
iput(inode);
- if (ret < 0)
- return ret;
spin_lock(&session->s_cap_lock);
+ if (ret < 0)
+ goto out;
}
+ ret = 0;
+out:
+ session->s_iterating_caps = false;
spin_unlock(&session->s_cap_lock);
-
- return 0;
+ return ret;
}
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,
dout("trim_caps mds%d done: %d / %d, trimmed %d\n",
session->s_mds, session->s_nr_caps, max_caps,
trim_caps - session->s_trim_caps);
+ session->s_trim_caps = 0;
}
return 0;
}