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; | ||||
| 
 | ||||
| 	dout("__touch_cap %p cap %p mds%d\n", &cap->ci->vfs_inode, cap, | ||||
| 	     s->s_mds); | ||||
| 	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); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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; | ||||
| } | ||||
|  | ||||
| @ -114,6 +114,7 @@ struct ceph_mds_session { | ||||
| 	int               s_num_cap_releases; | ||||
| 	struct list_head  s_cap_releases; /* waiting cap_release messages */ | ||||
| 	struct list_head  s_cap_releases_done; /* ready to send */ | ||||
| 	bool              s_iterating_caps; | ||||
| 
 | ||||
| 	/* protected by mutex */ | ||||
| 	struct list_head  s_cap_flushing;     /* inodes w/ flushing caps */ | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user