فهرست منبع

radix tree test suite: iteration test misuses RCU

Each thread needs to register itself with RCU, otherwise the reading
thread's read lock has no effect and the freeing thread will free the
memory in the tree without waiting for the read lock to be dropped.

Link: http://lkml.kernel.org/r/1480369871-5271-42-git-send-email-mawilcox@linuxonhyperv.com
Signed-off-by: Matthew Wilcox <mawilcox@microsoft.com>
Tested-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Konstantin Khlebnikov <koct9i@gmail.com>
Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
Cc: Matthew Wilcox <mawilcox@microsoft.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Matthew Wilcox 8 سال پیش
والد
کامیت
ba20cd60c9
1فایلهای تغییر یافته به همراه26 افزوده شده و 2 حذف شده
  1. 26 2
      tools/testing/radix-tree/iteration_check.c

+ 26 - 2
tools/testing/radix-tree/iteration_check.c

@@ -29,6 +29,8 @@ static void *add_entries_fn(void *arg)
 {
 {
 	int pgoff;
 	int pgoff;
 
 
+	rcu_register_thread();
+
 	while (!test_complete) {
 	while (!test_complete) {
 		for (pgoff = 0; pgoff < 100; pgoff++) {
 		for (pgoff = 0; pgoff < 100; pgoff++) {
 			pthread_mutex_lock(&tree_lock);
 			pthread_mutex_lock(&tree_lock);
@@ -38,6 +40,8 @@ static void *add_entries_fn(void *arg)
 		}
 		}
 	}
 	}
 
 
+	rcu_unregister_thread();
+
 	return NULL;
 	return NULL;
 }
 }
 
 
@@ -53,6 +57,8 @@ static void *tagged_iteration_fn(void *arg)
 	struct radix_tree_iter iter;
 	struct radix_tree_iter iter;
 	void **slot;
 	void **slot;
 
 
+	rcu_register_thread();
+
 	while (!test_complete) {
 	while (!test_complete) {
 		rcu_read_lock();
 		rcu_read_lock();
 		radix_tree_for_each_tagged(slot, &tree, &iter, 0, TAG) {
 		radix_tree_for_each_tagged(slot, &tree, &iter, 0, TAG) {
@@ -72,12 +78,18 @@ static void *tagged_iteration_fn(void *arg)
 				continue;
 				continue;
 			}
 			}
 
 
-			if (rand_r(&seeds[0]) % 50 == 0)
+			if (rand_r(&seeds[0]) % 50 == 0) {
 				slot = radix_tree_iter_next(&iter);
 				slot = radix_tree_iter_next(&iter);
+				rcu_read_unlock();
+				rcu_barrier();
+				rcu_read_lock();
+			}
 		}
 		}
 		rcu_read_unlock();
 		rcu_read_unlock();
 	}
 	}
 
 
+	rcu_unregister_thread();
+
 	return NULL;
 	return NULL;
 }
 }
 
 
@@ -93,6 +105,8 @@ static void *untagged_iteration_fn(void *arg)
 	struct radix_tree_iter iter;
 	struct radix_tree_iter iter;
 	void **slot;
 	void **slot;
 
 
+	rcu_register_thread();
+
 	while (!test_complete) {
 	while (!test_complete) {
 		rcu_read_lock();
 		rcu_read_lock();
 		radix_tree_for_each_slot(slot, &tree, &iter, 0) {
 		radix_tree_for_each_slot(slot, &tree, &iter, 0) {
@@ -112,12 +126,18 @@ static void *untagged_iteration_fn(void *arg)
 				continue;
 				continue;
 			}
 			}
 
 
-			if (rand_r(&seeds[1]) % 50 == 0)
+			if (rand_r(&seeds[1]) % 50 == 0) {
 				slot = radix_tree_iter_next(&iter);
 				slot = radix_tree_iter_next(&iter);
+				rcu_read_unlock();
+				rcu_barrier();
+				rcu_read_lock();
+			}
 		}
 		}
 		rcu_read_unlock();
 		rcu_read_unlock();
 	}
 	}
 
 
+	rcu_unregister_thread();
+
 	return NULL;
 	return NULL;
 }
 }
 
 
@@ -127,6 +147,8 @@ static void *untagged_iteration_fn(void *arg)
  */
  */
 static void *remove_entries_fn(void *arg)
 static void *remove_entries_fn(void *arg)
 {
 {
+	rcu_register_thread();
+
 	while (!test_complete) {
 	while (!test_complete) {
 		int pgoff;
 		int pgoff;
 
 
@@ -137,6 +159,8 @@ static void *remove_entries_fn(void *arg)
 		pthread_mutex_unlock(&tree_lock);
 		pthread_mutex_unlock(&tree_lock);
 	}
 	}
 
 
+	rcu_unregister_thread();
+
 	return NULL;
 	return NULL;
 }
 }