Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Two trivial overlapping changes conflicts in MPLS and mlx5. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
+7
-11
@@ -11,7 +11,6 @@
|
||||
*/
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/filter.h>
|
||||
@@ -74,14 +73,10 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
|
||||
if (array_size >= U32_MAX - PAGE_SIZE)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
||||
/* allocate all map elements and zero-initialize them */
|
||||
array = kzalloc(array_size, GFP_USER | __GFP_NOWARN);
|
||||
if (!array) {
|
||||
array = vzalloc(array_size);
|
||||
if (!array)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
array = bpf_map_area_alloc(array_size);
|
||||
if (!array)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/* copy mandatory map attributes */
|
||||
array->map.map_type = attr->map_type;
|
||||
@@ -97,7 +92,7 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr)
|
||||
|
||||
if (array_size >= U32_MAX - PAGE_SIZE ||
|
||||
elem_size > PCPU_MIN_UNIT_SIZE || bpf_array_alloc_percpu(array)) {
|
||||
kvfree(array);
|
||||
bpf_map_area_free(array);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
out:
|
||||
@@ -262,7 +257,7 @@ static void array_map_free(struct bpf_map *map)
|
||||
if (array->map.map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
|
||||
bpf_array_free_percpu(array);
|
||||
|
||||
kvfree(array);
|
||||
bpf_map_area_free(array);
|
||||
}
|
||||
|
||||
static const struct bpf_map_ops array_ops = {
|
||||
@@ -319,7 +314,8 @@ static void fd_array_map_free(struct bpf_map *map)
|
||||
/* make sure it's empty */
|
||||
for (i = 0; i < array->map.max_entries; i++)
|
||||
BUG_ON(array->ptrs[i] != NULL);
|
||||
kvfree(array);
|
||||
|
||||
bpf_map_area_free(array);
|
||||
}
|
||||
|
||||
static void *fd_array_map_lookup_elem(struct bpf_map *map, void *key)
|
||||
|
||||
+9
-13
@@ -13,7 +13,6 @@
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include "percpu_freelist.h"
|
||||
#include "bpf_lru_list.h"
|
||||
|
||||
@@ -103,7 +102,7 @@ static void htab_free_elems(struct bpf_htab *htab)
|
||||
free_percpu(pptr);
|
||||
}
|
||||
free_elems:
|
||||
vfree(htab->elems);
|
||||
bpf_map_area_free(htab->elems);
|
||||
}
|
||||
|
||||
static struct htab_elem *prealloc_lru_pop(struct bpf_htab *htab, void *key,
|
||||
@@ -125,7 +124,8 @@ static int prealloc_init(struct bpf_htab *htab)
|
||||
{
|
||||
int err = -ENOMEM, i;
|
||||
|
||||
htab->elems = vzalloc(htab->elem_size * htab->map.max_entries);
|
||||
htab->elems = bpf_map_area_alloc(htab->elem_size *
|
||||
htab->map.max_entries);
|
||||
if (!htab->elems)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -320,14 +320,10 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
|
||||
goto free_htab;
|
||||
|
||||
err = -ENOMEM;
|
||||
htab->buckets = kmalloc_array(htab->n_buckets, sizeof(struct bucket),
|
||||
GFP_USER | __GFP_NOWARN);
|
||||
|
||||
if (!htab->buckets) {
|
||||
htab->buckets = vmalloc(htab->n_buckets * sizeof(struct bucket));
|
||||
if (!htab->buckets)
|
||||
goto free_htab;
|
||||
}
|
||||
htab->buckets = bpf_map_area_alloc(htab->n_buckets *
|
||||
sizeof(struct bucket));
|
||||
if (!htab->buckets)
|
||||
goto free_htab;
|
||||
|
||||
for (i = 0; i < htab->n_buckets; i++) {
|
||||
INIT_HLIST_HEAD(&htab->buckets[i].head);
|
||||
@@ -354,7 +350,7 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
|
||||
free_extra_elems:
|
||||
free_percpu(htab->extra_elems);
|
||||
free_buckets:
|
||||
kvfree(htab->buckets);
|
||||
bpf_map_area_free(htab->buckets);
|
||||
free_htab:
|
||||
kfree(htab);
|
||||
return ERR_PTR(err);
|
||||
@@ -1014,7 +1010,7 @@ static void htab_map_free(struct bpf_map *map)
|
||||
prealloc_destroy(htab);
|
||||
|
||||
free_percpu(htab->extra_elems);
|
||||
kvfree(htab->buckets);
|
||||
bpf_map_area_free(htab->buckets);
|
||||
kfree(htab);
|
||||
}
|
||||
|
||||
|
||||
+8
-12
@@ -7,7 +7,6 @@
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/stacktrace.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include "percpu_freelist.h"
|
||||
@@ -32,7 +31,7 @@ static int prealloc_elems_and_freelist(struct bpf_stack_map *smap)
|
||||
u32 elem_size = sizeof(struct stack_map_bucket) + smap->map.value_size;
|
||||
int err;
|
||||
|
||||
smap->elems = vzalloc(elem_size * smap->map.max_entries);
|
||||
smap->elems = bpf_map_area_alloc(elem_size * smap->map.max_entries);
|
||||
if (!smap->elems)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -45,7 +44,7 @@ static int prealloc_elems_and_freelist(struct bpf_stack_map *smap)
|
||||
return 0;
|
||||
|
||||
free_elems:
|
||||
vfree(smap->elems);
|
||||
bpf_map_area_free(smap->elems);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -76,12 +75,9 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr)
|
||||
if (cost >= U32_MAX - PAGE_SIZE)
|
||||
return ERR_PTR(-E2BIG);
|
||||
|
||||
smap = kzalloc(cost, GFP_USER | __GFP_NOWARN);
|
||||
if (!smap) {
|
||||
smap = vzalloc(cost);
|
||||
if (!smap)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
smap = bpf_map_area_alloc(cost);
|
||||
if (!smap)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
err = -E2BIG;
|
||||
cost += n_buckets * (value_size + sizeof(struct stack_map_bucket));
|
||||
@@ -112,7 +108,7 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr)
|
||||
put_buffers:
|
||||
put_callchain_buffers();
|
||||
free_smap:
|
||||
kvfree(smap);
|
||||
bpf_map_area_free(smap);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
@@ -262,9 +258,9 @@ static void stack_map_free(struct bpf_map *map)
|
||||
/* wait for bpf programs to complete before freeing stack map */
|
||||
synchronize_rcu();
|
||||
|
||||
vfree(smap->elems);
|
||||
bpf_map_area_free(smap->elems);
|
||||
pcpu_freelist_destroy(&smap->freelist);
|
||||
kvfree(smap);
|
||||
bpf_map_area_free(smap);
|
||||
put_callchain_buffers();
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <linux/bpf_trace.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/mmzone.h>
|
||||
#include <linux/anon_inodes.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/license.h>
|
||||
@@ -50,6 +52,30 @@ void bpf_register_map_type(struct bpf_map_type_list *tl)
|
||||
list_add(&tl->list_node, &bpf_map_types);
|
||||
}
|
||||
|
||||
void *bpf_map_area_alloc(size_t size)
|
||||
{
|
||||
/* We definitely need __GFP_NORETRY, so OOM killer doesn't
|
||||
* trigger under memory pressure as we really just want to
|
||||
* fail instead.
|
||||
*/
|
||||
const gfp_t flags = __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO;
|
||||
void *area;
|
||||
|
||||
if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
|
||||
area = kmalloc(size, GFP_USER | flags);
|
||||
if (area != NULL)
|
||||
return area;
|
||||
}
|
||||
|
||||
return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | flags,
|
||||
PAGE_KERNEL);
|
||||
}
|
||||
|
||||
void bpf_map_area_free(void *area)
|
||||
{
|
||||
kvfree(area);
|
||||
}
|
||||
|
||||
int bpf_map_precharge_memlock(u32 pages)
|
||||
{
|
||||
struct user_struct *user = get_current_user();
|
||||
|
||||
+18
-6
@@ -764,7 +764,6 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen,
|
||||
{
|
||||
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
|
||||
int prev_state, ret = 0;
|
||||
bool hasdied = false;
|
||||
|
||||
if (num_online_cpus() == 1)
|
||||
return -EBUSY;
|
||||
@@ -809,7 +808,6 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen,
|
||||
cpuhp_kick_ap_work(cpu);
|
||||
}
|
||||
|
||||
hasdied = prev_state != st->state && st->state == CPUHP_OFFLINE;
|
||||
out:
|
||||
cpu_hotplug_done();
|
||||
return ret;
|
||||
@@ -1302,10 +1300,24 @@ static int cpuhp_cb_check(enum cpuhp_state state)
|
||||
*/
|
||||
static int cpuhp_reserve_state(enum cpuhp_state state)
|
||||
{
|
||||
enum cpuhp_state i;
|
||||
enum cpuhp_state i, end;
|
||||
struct cpuhp_step *step;
|
||||
|
||||
for (i = CPUHP_AP_ONLINE_DYN; i <= CPUHP_AP_ONLINE_DYN_END; i++) {
|
||||
if (!cpuhp_ap_states[i].name)
|
||||
switch (state) {
|
||||
case CPUHP_AP_ONLINE_DYN:
|
||||
step = cpuhp_ap_states + CPUHP_AP_ONLINE_DYN;
|
||||
end = CPUHP_AP_ONLINE_DYN_END;
|
||||
break;
|
||||
case CPUHP_BP_PREPARE_DYN:
|
||||
step = cpuhp_bp_states + CPUHP_BP_PREPARE_DYN;
|
||||
end = CPUHP_BP_PREPARE_DYN_END;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = state; i <= end; i++, step++) {
|
||||
if (!step->name)
|
||||
return i;
|
||||
}
|
||||
WARN(1, "No more dynamic states available for CPU hotplug\n");
|
||||
@@ -1323,7 +1335,7 @@ static int cpuhp_store_callbacks(enum cpuhp_state state, const char *name,
|
||||
|
||||
mutex_lock(&cpuhp_state_mutex);
|
||||
|
||||
if (state == CPUHP_AP_ONLINE_DYN) {
|
||||
if (state == CPUHP_AP_ONLINE_DYN || state == CPUHP_BP_PREPARE_DYN) {
|
||||
ret = cpuhp_reserve_state(state);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
+1
-1
@@ -1145,7 +1145,7 @@ static size_t module_flags_taint(struct module *mod, char *buf)
|
||||
|
||||
for (i = 0; i < TAINT_FLAGS_COUNT; i++) {
|
||||
if (taint_flags[i].module && test_bit(i, &mod->taints))
|
||||
buf[l++] = taint_flags[i].true;
|
||||
buf[l++] = taint_flags[i].c_true;
|
||||
}
|
||||
|
||||
return l;
|
||||
|
||||
+2
-2
@@ -249,7 +249,7 @@ void panic(const char *fmt, ...)
|
||||
* Delay timeout seconds before rebooting the machine.
|
||||
* We can't use the "normal" timers since we just panicked.
|
||||
*/
|
||||
pr_emerg("Rebooting in %d seconds..", panic_timeout);
|
||||
pr_emerg("Rebooting in %d seconds..\n", panic_timeout);
|
||||
|
||||
for (i = 0; i < panic_timeout * 1000; i += PANIC_TIMER_STEP) {
|
||||
touch_nmi_watchdog();
|
||||
@@ -355,7 +355,7 @@ const char *print_tainted(void)
|
||||
for (i = 0; i < TAINT_FLAGS_COUNT; i++) {
|
||||
const struct taint_flag *t = &taint_flags[i];
|
||||
*s++ = test_bit(i, &tainted_mask) ?
|
||||
t->true : t->false;
|
||||
t->c_true : t->c_false;
|
||||
}
|
||||
*s = 0;
|
||||
} else
|
||||
|
||||
@@ -46,7 +46,7 @@ static const char * const mem_sleep_labels[] = {
|
||||
const char *mem_sleep_states[PM_SUSPEND_MAX];
|
||||
|
||||
suspend_state_t mem_sleep_current = PM_SUSPEND_FREEZE;
|
||||
suspend_state_t mem_sleep_default = PM_SUSPEND_MAX;
|
||||
static suspend_state_t mem_sleep_default = PM_SUSPEND_MEM;
|
||||
|
||||
unsigned int pm_suspend_global_flags;
|
||||
EXPORT_SYMBOL_GPL(pm_suspend_global_flags);
|
||||
@@ -168,7 +168,7 @@ void suspend_set_ops(const struct platform_suspend_ops *ops)
|
||||
}
|
||||
if (valid_state(PM_SUSPEND_MEM)) {
|
||||
mem_sleep_states[PM_SUSPEND_MEM] = mem_sleep_labels[PM_SUSPEND_MEM];
|
||||
if (mem_sleep_default >= PM_SUSPEND_MEM)
|
||||
if (mem_sleep_default == PM_SUSPEND_MEM)
|
||||
mem_sleep_current = PM_SUSPEND_MEM;
|
||||
}
|
||||
|
||||
|
||||
@@ -136,6 +136,7 @@ int rcu_jiffies_till_stall_check(void);
|
||||
#define TPS(x) tracepoint_string(x)
|
||||
|
||||
void rcu_early_boot_tests(void);
|
||||
void rcu_test_sync_prims(void);
|
||||
|
||||
/*
|
||||
* This function really isn't for public consumption, but RCU is special in
|
||||
|
||||
@@ -185,9 +185,6 @@ static __latent_entropy void rcu_process_callbacks(struct softirq_action *unused
|
||||
* benefits of doing might_sleep() to reduce latency.)
|
||||
*
|
||||
* Cool, huh? (Due to Josh Triplett.)
|
||||
*
|
||||
* But we want to make this a static inline later. The cond_resched()
|
||||
* currently makes this problematic.
|
||||
*/
|
||||
void synchronize_sched(void)
|
||||
{
|
||||
@@ -195,7 +192,6 @@ void synchronize_sched(void)
|
||||
lock_is_held(&rcu_lock_map) ||
|
||||
lock_is_held(&rcu_sched_lock_map),
|
||||
"Illegal synchronize_sched() in RCU read-side critical section");
|
||||
cond_resched();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(synchronize_sched);
|
||||
|
||||
|
||||
@@ -60,12 +60,17 @@ EXPORT_SYMBOL_GPL(rcu_scheduler_active);
|
||||
|
||||
/*
|
||||
* During boot, we forgive RCU lockdep issues. After this function is
|
||||
* invoked, we start taking RCU lockdep issues seriously.
|
||||
* invoked, we start taking RCU lockdep issues seriously. Note that unlike
|
||||
* Tree RCU, Tiny RCU transitions directly from RCU_SCHEDULER_INACTIVE
|
||||
* to RCU_SCHEDULER_RUNNING, skipping the RCU_SCHEDULER_INIT stage.
|
||||
* The reason for this is that Tiny RCU does not need kthreads, so does
|
||||
* not have to care about the fact that the scheduler is half-initialized
|
||||
* at a certain phase of the boot process.
|
||||
*/
|
||||
void __init rcu_scheduler_starting(void)
|
||||
{
|
||||
WARN_ON(nr_context_switches() > 0);
|
||||
rcu_scheduler_active = 1;
|
||||
rcu_scheduler_active = RCU_SCHEDULER_RUNNING;
|
||||
}
|
||||
|
||||
#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
|
||||
|
||||
+20
-13
@@ -127,13 +127,16 @@ int rcu_num_nodes __read_mostly = NUM_RCU_NODES; /* Total # rcu_nodes in use. */
|
||||
int sysctl_panic_on_rcu_stall __read_mostly;
|
||||
|
||||
/*
|
||||
* The rcu_scheduler_active variable transitions from zero to one just
|
||||
* before the first task is spawned. So when this variable is zero, RCU
|
||||
* can assume that there is but one task, allowing RCU to (for example)
|
||||
* The rcu_scheduler_active variable is initialized to the value
|
||||
* RCU_SCHEDULER_INACTIVE and transitions RCU_SCHEDULER_INIT just before the
|
||||
* first task is spawned. So when this variable is RCU_SCHEDULER_INACTIVE,
|
||||
* RCU can assume that there is but one task, allowing RCU to (for example)
|
||||
* optimize synchronize_rcu() to a simple barrier(). When this variable
|
||||
* is one, RCU must actually do all the hard work required to detect real
|
||||
* grace periods. This variable is also used to suppress boot-time false
|
||||
* positives from lockdep-RCU error checking.
|
||||
* is RCU_SCHEDULER_INIT, RCU must actually do all the hard work required
|
||||
* to detect real grace periods. This variable is also used to suppress
|
||||
* boot-time false positives from lockdep-RCU error checking. Finally, it
|
||||
* transitions from RCU_SCHEDULER_INIT to RCU_SCHEDULER_RUNNING after RCU
|
||||
* is fully initialized, including all of its kthreads having been spawned.
|
||||
*/
|
||||
int rcu_scheduler_active __read_mostly;
|
||||
EXPORT_SYMBOL_GPL(rcu_scheduler_active);
|
||||
@@ -3980,18 +3983,22 @@ static int __init rcu_spawn_gp_kthread(void)
|
||||
early_initcall(rcu_spawn_gp_kthread);
|
||||
|
||||
/*
|
||||
* This function is invoked towards the end of the scheduler's initialization
|
||||
* process. Before this is called, the idle task might contain
|
||||
* RCU read-side critical sections (during which time, this idle
|
||||
* task is booting the system). After this function is called, the
|
||||
* idle tasks are prohibited from containing RCU read-side critical
|
||||
* sections. This function also enables RCU lockdep checking.
|
||||
* This function is invoked towards the end of the scheduler's
|
||||
* initialization process. Before this is called, the idle task might
|
||||
* contain synchronous grace-period primitives (during which time, this idle
|
||||
* task is booting the system, and such primitives are no-ops). After this
|
||||
* function is called, any synchronous grace-period primitives are run as
|
||||
* expedited, with the requesting task driving the grace period forward.
|
||||
* A later core_initcall() rcu_exp_runtime_mode() will switch to full
|
||||
* runtime RCU functionality.
|
||||
*/
|
||||
void rcu_scheduler_starting(void)
|
||||
{
|
||||
WARN_ON(num_online_cpus() != 1);
|
||||
WARN_ON(nr_context_switches() > 0);
|
||||
rcu_scheduler_active = 1;
|
||||
rcu_test_sync_prims();
|
||||
rcu_scheduler_active = RCU_SCHEDULER_INIT;
|
||||
rcu_test_sync_prims();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+41
-11
@@ -531,6 +531,20 @@ struct rcu_exp_work {
|
||||
struct work_struct rew_work;
|
||||
};
|
||||
|
||||
/*
|
||||
* Common code to drive an expedited grace period forward, used by
|
||||
* workqueues and mid-boot-time tasks.
|
||||
*/
|
||||
static void rcu_exp_sel_wait_wake(struct rcu_state *rsp,
|
||||
smp_call_func_t func, unsigned long s)
|
||||
{
|
||||
/* Initialize the rcu_node tree in preparation for the wait. */
|
||||
sync_rcu_exp_select_cpus(rsp, func);
|
||||
|
||||
/* Wait and clean up, including waking everyone. */
|
||||
rcu_exp_wait_wake(rsp, s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Work-queue handler to drive an expedited grace period forward.
|
||||
*/
|
||||
@@ -538,12 +552,8 @@ static void wait_rcu_exp_gp(struct work_struct *wp)
|
||||
{
|
||||
struct rcu_exp_work *rewp;
|
||||
|
||||
/* Initialize the rcu_node tree in preparation for the wait. */
|
||||
rewp = container_of(wp, struct rcu_exp_work, rew_work);
|
||||
sync_rcu_exp_select_cpus(rewp->rew_rsp, rewp->rew_func);
|
||||
|
||||
/* Wait and clean up, including waking everyone. */
|
||||
rcu_exp_wait_wake(rewp->rew_rsp, rewp->rew_s);
|
||||
rcu_exp_sel_wait_wake(rewp->rew_rsp, rewp->rew_func, rewp->rew_s);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -569,12 +579,18 @@ static void _synchronize_rcu_expedited(struct rcu_state *rsp,
|
||||
if (exp_funnel_lock(rsp, s))
|
||||
return; /* Someone else did our work for us. */
|
||||
|
||||
/* Marshall arguments and schedule the expedited grace period. */
|
||||
rew.rew_func = func;
|
||||
rew.rew_rsp = rsp;
|
||||
rew.rew_s = s;
|
||||
INIT_WORK_ONSTACK(&rew.rew_work, wait_rcu_exp_gp);
|
||||
schedule_work(&rew.rew_work);
|
||||
/* Ensure that load happens before action based on it. */
|
||||
if (unlikely(rcu_scheduler_active == RCU_SCHEDULER_INIT)) {
|
||||
/* Direct call during scheduler init and early_initcalls(). */
|
||||
rcu_exp_sel_wait_wake(rsp, func, s);
|
||||
} else {
|
||||
/* Marshall arguments & schedule the expedited grace period. */
|
||||
rew.rew_func = func;
|
||||
rew.rew_rsp = rsp;
|
||||
rew.rew_s = s;
|
||||
INIT_WORK_ONSTACK(&rew.rew_work, wait_rcu_exp_gp);
|
||||
schedule_work(&rew.rew_work);
|
||||
}
|
||||
|
||||
/* Wait for expedited grace period to complete. */
|
||||
rdp = per_cpu_ptr(rsp->rda, raw_smp_processor_id());
|
||||
@@ -676,6 +692,8 @@ void synchronize_rcu_expedited(void)
|
||||
{
|
||||
struct rcu_state *rsp = rcu_state_p;
|
||||
|
||||
if (rcu_scheduler_active == RCU_SCHEDULER_INACTIVE)
|
||||
return;
|
||||
_synchronize_rcu_expedited(rsp, sync_rcu_exp_handler);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
|
||||
@@ -693,3 +711,15 @@ void synchronize_rcu_expedited(void)
|
||||
EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
|
||||
|
||||
#endif /* #else #ifdef CONFIG_PREEMPT_RCU */
|
||||
|
||||
/*
|
||||
* Switch to run-time mode once Tree RCU has fully initialized.
|
||||
*/
|
||||
static int __init rcu_exp_runtime_mode(void)
|
||||
{
|
||||
rcu_test_sync_prims();
|
||||
rcu_scheduler_active = RCU_SCHEDULER_RUNNING;
|
||||
rcu_test_sync_prims();
|
||||
return 0;
|
||||
}
|
||||
core_initcall(rcu_exp_runtime_mode);
|
||||
|
||||
@@ -670,7 +670,7 @@ void synchronize_rcu(void)
|
||||
lock_is_held(&rcu_lock_map) ||
|
||||
lock_is_held(&rcu_sched_lock_map),
|
||||
"Illegal synchronize_rcu() in RCU read-side critical section");
|
||||
if (!rcu_scheduler_active)
|
||||
if (rcu_scheduler_active == RCU_SCHEDULER_INACTIVE)
|
||||
return;
|
||||
if (rcu_gp_is_expedited())
|
||||
synchronize_rcu_expedited();
|
||||
|
||||
+30
-8
@@ -121,11 +121,14 @@ EXPORT_SYMBOL(rcu_read_lock_sched_held);
|
||||
* Should expedited grace-period primitives always fall back to their
|
||||
* non-expedited counterparts? Intended for use within RCU. Note
|
||||
* that if the user specifies both rcu_expedited and rcu_normal, then
|
||||
* rcu_normal wins.
|
||||
* rcu_normal wins. (Except during the time period during boot from
|
||||
* when the first task is spawned until the rcu_exp_runtime_mode()
|
||||
* core_initcall() is invoked, at which point everything is expedited.)
|
||||
*/
|
||||
bool rcu_gp_is_normal(void)
|
||||
{
|
||||
return READ_ONCE(rcu_normal);
|
||||
return READ_ONCE(rcu_normal) &&
|
||||
rcu_scheduler_active != RCU_SCHEDULER_INIT;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rcu_gp_is_normal);
|
||||
|
||||
@@ -135,13 +138,14 @@ static atomic_t rcu_expedited_nesting =
|
||||
/*
|
||||
* Should normal grace-period primitives be expedited? Intended for
|
||||
* use within RCU. Note that this function takes the rcu_expedited
|
||||
* sysfs/boot variable into account as well as the rcu_expedite_gp()
|
||||
* nesting. So looping on rcu_unexpedite_gp() until rcu_gp_is_expedited()
|
||||
* returns false is a -really- bad idea.
|
||||
* sysfs/boot variable and rcu_scheduler_active into account as well
|
||||
* as the rcu_expedite_gp() nesting. So looping on rcu_unexpedite_gp()
|
||||
* until rcu_gp_is_expedited() returns false is a -really- bad idea.
|
||||
*/
|
||||
bool rcu_gp_is_expedited(void)
|
||||
{
|
||||
return rcu_expedited || atomic_read(&rcu_expedited_nesting);
|
||||
return rcu_expedited || atomic_read(&rcu_expedited_nesting) ||
|
||||
rcu_scheduler_active == RCU_SCHEDULER_INIT;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rcu_gp_is_expedited);
|
||||
|
||||
@@ -257,7 +261,7 @@ EXPORT_SYMBOL_GPL(rcu_callback_map);
|
||||
|
||||
int notrace debug_lockdep_rcu_enabled(void)
|
||||
{
|
||||
return rcu_scheduler_active && debug_locks &&
|
||||
return rcu_scheduler_active != RCU_SCHEDULER_INACTIVE && debug_locks &&
|
||||
current->lockdep_recursion == 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(debug_lockdep_rcu_enabled);
|
||||
@@ -591,7 +595,7 @@ EXPORT_SYMBOL_GPL(call_rcu_tasks);
|
||||
void synchronize_rcu_tasks(void)
|
||||
{
|
||||
/* Complain if the scheduler has not started. */
|
||||
RCU_LOCKDEP_WARN(!rcu_scheduler_active,
|
||||
RCU_LOCKDEP_WARN(rcu_scheduler_active == RCU_SCHEDULER_INACTIVE,
|
||||
"synchronize_rcu_tasks called too soon");
|
||||
|
||||
/* Wait for the grace period. */
|
||||
@@ -813,6 +817,23 @@ static void rcu_spawn_tasks_kthread(void)
|
||||
|
||||
#endif /* #ifdef CONFIG_TASKS_RCU */
|
||||
|
||||
/*
|
||||
* Test each non-SRCU synchronous grace-period wait API. This is
|
||||
* useful just after a change in mode for these primitives, and
|
||||
* during early boot.
|
||||
*/
|
||||
void rcu_test_sync_prims(void)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_PROVE_RCU))
|
||||
return;
|
||||
synchronize_rcu();
|
||||
synchronize_rcu_bh();
|
||||
synchronize_sched();
|
||||
synchronize_rcu_expedited();
|
||||
synchronize_rcu_bh_expedited();
|
||||
synchronize_sched_expedited();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROVE_RCU
|
||||
|
||||
/*
|
||||
@@ -865,6 +886,7 @@ void rcu_early_boot_tests(void)
|
||||
early_boot_test_call_rcu_bh();
|
||||
if (rcu_self_test_sched)
|
||||
early_boot_test_call_rcu_sched();
|
||||
rcu_test_sync_prims();
|
||||
}
|
||||
|
||||
static int rcu_verify_early_boot_tests(void)
|
||||
|
||||
@@ -2475,6 +2475,7 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
|
||||
break;
|
||||
if (neg)
|
||||
continue;
|
||||
val = convmul * val / convdiv;
|
||||
if ((min && val < *min) || (max && val > *max))
|
||||
continue;
|
||||
*i = val;
|
||||
|
||||
+8
-6
@@ -128,10 +128,10 @@ static struct ucounts *get_ucounts(struct user_namespace *ns, kuid_t uid)
|
||||
struct hlist_head *hashent = ucounts_hashentry(ns, uid);
|
||||
struct ucounts *ucounts, *new;
|
||||
|
||||
spin_lock(&ucounts_lock);
|
||||
spin_lock_irq(&ucounts_lock);
|
||||
ucounts = find_ucounts(ns, uid, hashent);
|
||||
if (!ucounts) {
|
||||
spin_unlock(&ucounts_lock);
|
||||
spin_unlock_irq(&ucounts_lock);
|
||||
|
||||
new = kzalloc(sizeof(*new), GFP_KERNEL);
|
||||
if (!new)
|
||||
@@ -141,7 +141,7 @@ static struct ucounts *get_ucounts(struct user_namespace *ns, kuid_t uid)
|
||||
new->uid = uid;
|
||||
atomic_set(&new->count, 0);
|
||||
|
||||
spin_lock(&ucounts_lock);
|
||||
spin_lock_irq(&ucounts_lock);
|
||||
ucounts = find_ucounts(ns, uid, hashent);
|
||||
if (ucounts) {
|
||||
kfree(new);
|
||||
@@ -152,16 +152,18 @@ static struct ucounts *get_ucounts(struct user_namespace *ns, kuid_t uid)
|
||||
}
|
||||
if (!atomic_add_unless(&ucounts->count, 1, INT_MAX))
|
||||
ucounts = NULL;
|
||||
spin_unlock(&ucounts_lock);
|
||||
spin_unlock_irq(&ucounts_lock);
|
||||
return ucounts;
|
||||
}
|
||||
|
||||
static void put_ucounts(struct ucounts *ucounts)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (atomic_dec_and_test(&ucounts->count)) {
|
||||
spin_lock(&ucounts_lock);
|
||||
spin_lock_irqsave(&ucounts_lock, flags);
|
||||
hlist_del_init(&ucounts->node);
|
||||
spin_unlock(&ucounts_lock);
|
||||
spin_unlock_irqrestore(&ucounts_lock, flags);
|
||||
|
||||
kfree(ucounts);
|
||||
}
|
||||
|
||||
@@ -49,6 +49,8 @@ unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask);
|
||||
#define for_each_watchdog_cpu(cpu) \
|
||||
for_each_cpu_and((cpu), cpu_online_mask, &watchdog_cpumask)
|
||||
|
||||
atomic_t watchdog_park_in_progress = ATOMIC_INIT(0);
|
||||
|
||||
/*
|
||||
* The 'watchdog_running' variable is set to 1 when the watchdog threads
|
||||
* are registered/started and is set to 0 when the watchdog threads are
|
||||
@@ -260,6 +262,9 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
|
||||
int duration;
|
||||
int softlockup_all_cpu_backtrace = sysctl_softlockup_all_cpu_backtrace;
|
||||
|
||||
if (atomic_read(&watchdog_park_in_progress) != 0)
|
||||
return HRTIMER_NORESTART;
|
||||
|
||||
/* kick the hardlockup detector */
|
||||
watchdog_interrupt_count();
|
||||
|
||||
@@ -467,12 +472,16 @@ static int watchdog_park_threads(void)
|
||||
{
|
||||
int cpu, ret = 0;
|
||||
|
||||
atomic_set(&watchdog_park_in_progress, 1);
|
||||
|
||||
for_each_watchdog_cpu(cpu) {
|
||||
ret = kthread_park(per_cpu(softlockup_watchdog, cpu));
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
atomic_set(&watchdog_park_in_progress, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -84,6 +84,9 @@ static void watchdog_overflow_callback(struct perf_event *event,
|
||||
/* Ensure the watchdog never gets throttled */
|
||||
event->hw.interrupts = 0;
|
||||
|
||||
if (atomic_read(&watchdog_park_in_progress) != 0)
|
||||
return;
|
||||
|
||||
if (__this_cpu_read(watchdog_nmi_touch) == true) {
|
||||
__this_cpu_write(watchdog_nmi_touch, false);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user