[RHEL7,COMMIT] fuse kio: Arrange rcu modifiers around accesses to pcs_cs_link::cs

Submitted by Konstantin Khorenko on June 8, 2018, 4:10 p.m.

Details

Message ID 201806081610.w58GACUL019734@finist_ce7.work
State New
Series "fuse kio: Arrange rcu modifiers around accesses to pcs_cs_link::cs"
Headers show

Commit Message

Konstantin Khorenko June 8, 2018, 4:10 p.m.
The commit is pushed to "branch-rh7-3.10.0-693.21.1.vz7.50.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-693.21.1.vz7.50.7
------>
commit d5c4740d7233d04b595e6b5fb2ecd1adb8dafe94
Author: Kirill Tkhai <ktkhai@virtuozzo.com>
Date:   Fri Jun 8 19:10:12 2018 +0300

    fuse kio: Arrange rcu modifiers around accesses to pcs_cs_link::cs
    
    This sanity patch silences sparse warnings and makes the locking scheme
    better visible for reader.
    
    Note, that it does not cover all the places needed them, and this patch
    will have a continuation. I've added them, where sparse says.
    
    Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 fs/fuse/kio/pcs/pcs_map.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

Patch hide | download patch | download mbox

diff --git a/fs/fuse/kio/pcs/pcs_map.c b/fs/fuse/kio/pcs/pcs_map.c
index f48d8e30a61e..f105eae8863a 100644
--- a/fs/fuse/kio/pcs/pcs_map.c
+++ b/fs/fuse/kio/pcs/pcs_map.c
@@ -564,14 +564,17 @@  static void map_recalc_maps(struct pcs_cs * cs)
 
 	list_for_each_entry(csl, &cs->map_list, link) {
 		struct pcs_cs_list *cs_list;
+		struct pcs_cs *cur_cs;
 		int read_idx;
 
 		cs_list = cs_link_to_cs_list(csl);
 		read_idx = READ_ONCE(cs_list->read_index);
 
-		if (read_idx >= 0 && (!cs_is_blacklisted(cs) ||
-				      cs_list->cs[read_idx].cslink.cs == cs))
-		    WRITE_ONCE(cs_list->read_index, -1);
+		if (read_idx < 0)
+			continue;
+		cur_cs = rcu_access_pointer(cs_list->cs[read_idx].cslink.cs);
+		if (!cs_is_blacklisted(cs) || cur_cs == cs)
+			WRITE_ONCE(cs_list->read_index, -1);
 	}
 }
 
@@ -582,12 +585,16 @@  void pcs_map_force_reselect(struct pcs_cs * cs)
 
 	list_for_each_entry(csl, &cs->map_list, link) {
 		struct pcs_cs_list *cs_list;
+		struct pcs_cs *cur_cs;
 		int read_idx;
 
 		cs_list = cs_link_to_cs_list(csl);
 		read_idx = READ_ONCE(cs_list->read_index);
 
-		if (read_idx >= 0 && cs_list->cs[read_idx].cslink.cs == cs)
+		if (read_idx < 0)
+			continue;
+		cur_cs = rcu_access_pointer(cs_list->cs[read_idx].cslink.cs);
+		if (cur_cs == cs)
 			WRITE_ONCE(cs_list->read_index, -1);
 	}
 }
@@ -929,6 +936,7 @@  struct pcs_cs_list* cslist_alloc( struct pcs_cs_set *css, struct pcs_cs_info *re
 				     int read_tout, int write_tout, int error_clear)
 {
 	struct pcs_cs_list * cs_list = NULL;
+	struct pcs_cs * cs;
 	int i;
 
 	cs_list = kzalloc(sizeof(struct pcs_cs_list) + cs_cnt * sizeof(struct pcs_cs_record), GFP_NOFS);
@@ -947,7 +955,7 @@  struct pcs_cs_list* cslist_alloc( struct pcs_cs_set *css, struct pcs_cs_info *re
 	for (i = 0; i < cs_cnt; i++) {
 		cs_list->cs[i].info = rec[i];
 		memset(&cs_list->cs[i].sync, 0, sizeof(cs_list->cs[i].sync));
-		cs_list->cs[i].cslink.cs = NULL;
+		RCU_INIT_POINTER(cs_list->cs[i].cslink.cs, NULL);
 		INIT_LIST_HEAD(&cs_list->cs[i].cslink.link);
 		cs_list->cs[i].cslink.index = i;
 	}
@@ -955,7 +963,6 @@  struct pcs_cs_list* cslist_alloc( struct pcs_cs_set *css, struct pcs_cs_info *re
 
 	for (i = 0; i < cs_cnt; i++) {
 		struct pcs_cs_link * cslink = &cs_list->cs[i].cslink;
-		struct pcs_cs * cs;
 
 		if (cs_list->cs[i].info.flags & CS_FL_REPLICATING) {
 			__set_bit(i, &cs_list->blacklist);
@@ -1002,7 +1009,8 @@  struct pcs_cs_list* cslist_alloc( struct pcs_cs_set *css, struct pcs_cs_info *re
 	}
 
 	for (i = cs_cnt - 1; i >= 0; i--) {
-		struct pcs_cs * cs = cs_list->cs[i].cslink.cs;
+		cs = rcu_dereference_protected(cs_list->cs[i].cslink.cs,
+					       atomic_read(&cs_list->refcnt) > 0);
 		spin_lock(&cs->lock);
 		if (cs_is_blacklisted(cs) && !(test_bit(CS_SF_INACTIVE, &cs->state))) {
 			if (error_clear)