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

Konstantin Khorenko khorenko at virtuozzo.com
Fri Jun 8 19:10:12 MSK 2018


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 at 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 at virtuozzo.com>
---
 fs/fuse/kio/pcs/pcs_map.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

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)


More information about the Devel mailing list