mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
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>
This commit is contained in:
parent
7067f797b8
commit
5dacf09121
@ -697,10 +697,15 @@ static void __touch_cap(struct ceph_cap *cap)
|
|||||||
{
|
{
|
||||||
struct ceph_mds_session *s = cap->session;
|
struct ceph_mds_session *s = cap->session;
|
||||||
|
|
||||||
dout("__touch_cap %p cap %p mds%d\n", &cap->ci->vfs_inode, cap,
|
|
||||||
s->s_mds);
|
|
||||||
spin_lock(&s->s_cap_lock);
|
spin_lock(&s->s_cap_lock);
|
||||||
list_move_tail(&cap->session_caps, &s->s_caps);
|
if (!s->s_iterating_caps) {
|
||||||
|
dout("__touch_cap %p cap %p mds%d\n", &cap->ci->vfs_inode, cap,
|
||||||
|
s->s_mds);
|
||||||
|
list_move_tail(&cap->session_caps, &s->s_caps);
|
||||||
|
} else {
|
||||||
|
dout("__touch_cap %p cap %p mds%d NOP, iterating over caps\n",
|
||||||
|
&cap->ci->vfs_inode, cap, s->s_mds);
|
||||||
|
}
|
||||||
spin_unlock(&s->s_cap_lock);
|
spin_unlock(&s->s_cap_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,10 +337,12 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
|
|||||||
s->s_renew_seq = 0;
|
s->s_renew_seq = 0;
|
||||||
INIT_LIST_HEAD(&s->s_caps);
|
INIT_LIST_HEAD(&s->s_caps);
|
||||||
s->s_nr_caps = 0;
|
s->s_nr_caps = 0;
|
||||||
|
s->s_trim_caps = 0;
|
||||||
atomic_set(&s->s_ref, 1);
|
atomic_set(&s->s_ref, 1);
|
||||||
INIT_LIST_HEAD(&s->s_waiting);
|
INIT_LIST_HEAD(&s->s_waiting);
|
||||||
INIT_LIST_HEAD(&s->s_unsafe);
|
INIT_LIST_HEAD(&s->s_unsafe);
|
||||||
s->s_num_cap_releases = 0;
|
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);
|
||||||
INIT_LIST_HEAD(&s->s_cap_releases_done);
|
INIT_LIST_HEAD(&s->s_cap_releases_done);
|
||||||
INIT_LIST_HEAD(&s->s_cap_flushing);
|
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);
|
dout("iterate_session_caps %p mds%d\n", session, session->s_mds);
|
||||||
spin_lock(&session->s_cap_lock);
|
spin_lock(&session->s_cap_lock);
|
||||||
|
session->s_iterating_caps = true;
|
||||||
list_for_each_entry_safe(cap, ncap, &session->s_caps, session_caps) {
|
list_for_each_entry_safe(cap, ncap, &session->s_caps, session_caps) {
|
||||||
inode = igrab(&cap->ci->vfs_inode);
|
inode = igrab(&cap->ci->vfs_inode);
|
||||||
if (!inode)
|
if (!inode)
|
||||||
@ -706,13 +709,15 @@ static int iterate_session_caps(struct ceph_mds_session *session,
|
|||||||
spin_unlock(&session->s_cap_lock);
|
spin_unlock(&session->s_cap_lock);
|
||||||
ret = cb(inode, cap, arg);
|
ret = cb(inode, cap, arg);
|
||||||
iput(inode);
|
iput(inode);
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
spin_lock(&session->s_cap_lock);
|
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);
|
spin_unlock(&session->s_cap_lock);
|
||||||
|
return ret;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
|
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",
|
dout("trim_caps mds%d done: %d / %d, trimmed %d\n",
|
||||||
session->s_mds, session->s_nr_caps, max_caps,
|
session->s_mds, session->s_nr_caps, max_caps,
|
||||||
trim_caps - session->s_trim_caps);
|
trim_caps - session->s_trim_caps);
|
||||||
|
session->s_trim_caps = 0;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,7 @@ struct ceph_mds_session {
|
|||||||
int s_num_cap_releases;
|
int s_num_cap_releases;
|
||||||
struct list_head s_cap_releases; /* waiting cap_release messages */
|
struct list_head s_cap_releases; /* waiting cap_release messages */
|
||||||
struct list_head s_cap_releases_done; /* ready to send */
|
struct list_head s_cap_releases_done; /* ready to send */
|
||||||
|
bool s_iterating_caps;
|
||||||
|
|
||||||
/* protected by mutex */
|
/* protected by mutex */
|
||||||
struct list_head s_cap_flushing; /* inodes w/ flushing caps */
|
struct list_head s_cap_flushing; /* inodes w/ flushing caps */
|
||||||
|
Loading…
Reference in New Issue
Block a user