summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/ksysfs.c22
-rw-r--r--kernel/rcu/srcu.c2
-rw-r--r--kernel/rcu/tree.c6
-rw-r--r--kernel/rcu/tree_plugin.h6
-rw-r--r--kernel/rcu/update.c12
5 files changed, 45 insertions, 3 deletions
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
index e83b26464061..b4e2fa52d8bc 100644
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -20,7 +20,7 @@
20#include <linux/capability.h> 20#include <linux/capability.h>
21#include <linux/compiler.h> 21#include <linux/compiler.h>
22 22
23#include <linux/rcupdate.h> /* rcu_expedited */ 23#include <linux/rcupdate.h> /* rcu_expedited and rcu_normal */
24 24
25#define KERNEL_ATTR_RO(_name) \ 25#define KERNEL_ATTR_RO(_name) \
26static struct kobj_attribute _name##_attr = __ATTR_RO(_name) 26static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
@@ -148,7 +148,7 @@ int rcu_expedited;
148static ssize_t rcu_expedited_show(struct kobject *kobj, 148static ssize_t rcu_expedited_show(struct kobject *kobj,
149 struct kobj_attribute *attr, char *buf) 149 struct kobj_attribute *attr, char *buf)
150{ 150{
151 return sprintf(buf, "%d\n", rcu_expedited); 151 return sprintf(buf, "%d\n", READ_ONCE(rcu_expedited));
152} 152}
153static ssize_t rcu_expedited_store(struct kobject *kobj, 153static ssize_t rcu_expedited_store(struct kobject *kobj,
154 struct kobj_attribute *attr, 154 struct kobj_attribute *attr,
@@ -161,6 +161,23 @@ static ssize_t rcu_expedited_store(struct kobject *kobj,
161} 161}
162KERNEL_ATTR_RW(rcu_expedited); 162KERNEL_ATTR_RW(rcu_expedited);
163 163
164int rcu_normal;
165static ssize_t rcu_normal_show(struct kobject *kobj,
166 struct kobj_attribute *attr, char *buf)
167{
168 return sprintf(buf, "%d\n", READ_ONCE(rcu_normal));
169}
170static ssize_t rcu_normal_store(struct kobject *kobj,
171 struct kobj_attribute *attr,
172 const char *buf, size_t count)
173{
174 if (kstrtoint(buf, 0, &rcu_normal))
175 return -EINVAL;
176
177 return count;
178}
179KERNEL_ATTR_RW(rcu_normal);
180
164/* 181/*
165 * Make /sys/kernel/notes give the raw contents of our kernel .notes section. 182 * Make /sys/kernel/notes give the raw contents of our kernel .notes section.
166 */ 183 */
@@ -203,6 +220,7 @@ static struct attribute * kernel_attrs[] = {
203 &vmcoreinfo_attr.attr, 220 &vmcoreinfo_attr.attr,
204#endif 221#endif
205 &rcu_expedited_attr.attr, 222 &rcu_expedited_attr.attr,
223 &rcu_normal_attr.attr,
206 NULL 224 NULL
207}; 225};
208 226
diff --git a/kernel/rcu/srcu.c b/kernel/rcu/srcu.c
index a63a1ea5a41b..9b9cdd549caa 100644
--- a/kernel/rcu/srcu.c
+++ b/kernel/rcu/srcu.c
@@ -489,7 +489,7 @@ static void __synchronize_srcu(struct srcu_struct *sp, int trycount)
489 */ 489 */
490void synchronize_srcu(struct srcu_struct *sp) 490void synchronize_srcu(struct srcu_struct *sp)
491{ 491{
492 __synchronize_srcu(sp, rcu_gp_is_expedited() 492 __synchronize_srcu(sp, (rcu_gp_is_expedited() && !rcu_gp_is_normal())
493 ? SYNCHRONIZE_SRCU_EXP_TRYCOUNT 493 ? SYNCHRONIZE_SRCU_EXP_TRYCOUNT
494 : SYNCHRONIZE_SRCU_TRYCOUNT); 494 : SYNCHRONIZE_SRCU_TRYCOUNT);
495} 495}
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 6a652d1f3d7f..489992997c06 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -3841,6 +3841,12 @@ void synchronize_sched_expedited(void)
3841 if (rcu_blocking_is_gp()) 3841 if (rcu_blocking_is_gp())
3842 return; 3842 return;
3843 3843
3844 /* If expedited grace periods are prohibited, fall back to normal. */
3845 if (rcu_gp_is_normal()) {
3846 wait_rcu_gp(call_rcu_sched);
3847 return;
3848 }
3849
3844 /* Take a snapshot of the sequence number. */ 3850 /* Take a snapshot of the sequence number. */
3845 s = rcu_exp_gp_seq_snap(rsp); 3851 s = rcu_exp_gp_seq_snap(rsp);
3846 3852
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 57ba873d2f18..d45df3781551 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -746,6 +746,12 @@ void synchronize_rcu_expedited(void)
746 struct rcu_state *rsp = rcu_state_p; 746 struct rcu_state *rsp = rcu_state_p;
747 unsigned long s; 747 unsigned long s;
748 748
749 /* If expedited grace periods are prohibited, fall back to normal. */
750 if (rcu_gp_is_normal()) {
751 wait_rcu_gp(call_rcu);
752 return;
753 }
754
749 s = rcu_exp_gp_seq_snap(rsp); 755 s = rcu_exp_gp_seq_snap(rsp);
750 756
751 rnp_unlock = exp_funnel_lock(rsp, s); 757 rnp_unlock = exp_funnel_lock(rsp, s);
diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c
index 5f748c5a40f0..8fccda3a794d 100644
--- a/kernel/rcu/update.c
+++ b/kernel/rcu/update.c
@@ -61,6 +61,7 @@ MODULE_ALIAS("rcupdate");
61#define MODULE_PARAM_PREFIX "rcupdate." 61#define MODULE_PARAM_PREFIX "rcupdate."
62 62
63module_param(rcu_expedited, int, 0); 63module_param(rcu_expedited, int, 0);
64module_param(rcu_normal, int, 0);
64 65
65#if defined(CONFIG_DEBUG_LOCK_ALLOC) && defined(CONFIG_PREEMPT_COUNT) 66#if defined(CONFIG_DEBUG_LOCK_ALLOC) && defined(CONFIG_PREEMPT_COUNT)
66/** 67/**
@@ -113,6 +114,17 @@ EXPORT_SYMBOL(rcu_read_lock_sched_held);
113 114
114#ifndef CONFIG_TINY_RCU 115#ifndef CONFIG_TINY_RCU
115 116
117/*
118 * Should expedited grace-period primitives always fall back to their
119 * non-expedited counterparts? Intended for use within RCU. Note
120 * that if the user specifies both rcu_expedited and rcu_normal, then
121 * rcu_normal wins.
122 */
123bool rcu_gp_is_normal(void)
124{
125 return READ_ONCE(rcu_normal);
126}
127
116static atomic_t rcu_expedited_nesting = 128static atomic_t rcu_expedited_nesting =
117 ATOMIC_INIT(IS_ENABLED(CONFIG_RCU_EXPEDITE_BOOT) ? 1 : 0); 129 ATOMIC_INIT(IS_ENABLED(CONFIG_RCU_EXPEDITE_BOOT) ? 1 : 0);
118 130