Merge tag 'v3.12' into core/locking to pick up mutex upates
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
+3
-2
@@ -1117,9 +1117,10 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
|
||||
|
||||
sleep_time = timeout_start + audit_backlog_wait_time -
|
||||
jiffies;
|
||||
if ((long)sleep_time > 0)
|
||||
if ((long)sleep_time > 0) {
|
||||
wait_for_auditd(sleep_time);
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (audit_rate_check() && printk_ratelimit())
|
||||
printk(KERN_WARNING
|
||||
|
||||
+6
-8
@@ -2039,7 +2039,7 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
|
||||
|
||||
/* @tsk either already exited or can't exit until the end */
|
||||
if (tsk->flags & PF_EXITING)
|
||||
continue;
|
||||
goto next;
|
||||
|
||||
/* as per above, nr_threads may decrease, but not increase. */
|
||||
BUG_ON(i >= group_size);
|
||||
@@ -2047,7 +2047,7 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
|
||||
ent.cgrp = task_cgroup_from_root(tsk, root);
|
||||
/* nothing to do if this task is already in the cgroup */
|
||||
if (ent.cgrp == cgrp)
|
||||
continue;
|
||||
goto next;
|
||||
/*
|
||||
* saying GFP_ATOMIC has no effect here because we did prealloc
|
||||
* earlier, but it's good form to communicate our expectations.
|
||||
@@ -2055,7 +2055,7 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk,
|
||||
retval = flex_array_put(group, i, &ent, GFP_ATOMIC);
|
||||
BUG_ON(retval != 0);
|
||||
i++;
|
||||
|
||||
next:
|
||||
if (!threadgroup)
|
||||
break;
|
||||
} while_each_thread(leader, tsk);
|
||||
@@ -3188,11 +3188,9 @@ css_next_descendant_post(struct cgroup_subsys_state *pos,
|
||||
|
||||
WARN_ON_ONCE(!rcu_read_lock_held());
|
||||
|
||||
/* if first iteration, visit the leftmost descendant */
|
||||
if (!pos) {
|
||||
next = css_leftmost_descendant(root);
|
||||
return next != root ? next : NULL;
|
||||
}
|
||||
/* if first iteration, visit leftmost descendant which may be @root */
|
||||
if (!pos)
|
||||
return css_leftmost_descendant(root);
|
||||
|
||||
/* if we visited @root, we're done */
|
||||
if (pos == root)
|
||||
|
||||
@@ -50,6 +50,15 @@ void context_tracking_user_enter(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* Repeat the user_enter() check here because some archs may be calling
|
||||
* this from asm and if no CPU needs context tracking, they shouldn't
|
||||
* go further. Repeat the check here until they support the static key
|
||||
* check.
|
||||
*/
|
||||
if (!static_key_false(&context_tracking_enabled))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Some contexts may involve an exception occuring in an irq,
|
||||
* leading to that nesting:
|
||||
@@ -151,6 +160,9 @@ void context_tracking_user_exit(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (!static_key_false(&context_tracking_enabled))
|
||||
return;
|
||||
|
||||
if (in_interrupt())
|
||||
return;
|
||||
|
||||
|
||||
+28
-3
@@ -3660,6 +3660,26 @@ static void calc_timer_values(struct perf_event *event,
|
||||
*running = ctx_time - event->tstamp_running;
|
||||
}
|
||||
|
||||
static void perf_event_init_userpage(struct perf_event *event)
|
||||
{
|
||||
struct perf_event_mmap_page *userpg;
|
||||
struct ring_buffer *rb;
|
||||
|
||||
rcu_read_lock();
|
||||
rb = rcu_dereference(event->rb);
|
||||
if (!rb)
|
||||
goto unlock;
|
||||
|
||||
userpg = rb->user_page;
|
||||
|
||||
/* Allow new userspace to detect that bit 0 is deprecated */
|
||||
userpg->cap_bit0_is_deprecated = 1;
|
||||
userpg->size = offsetof(struct perf_event_mmap_page, __reserved);
|
||||
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void __weak arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now)
|
||||
{
|
||||
}
|
||||
@@ -4044,6 +4064,7 @@ again:
|
||||
ring_buffer_attach(event, rb);
|
||||
rcu_assign_pointer(event->rb, rb);
|
||||
|
||||
perf_event_init_userpage(event);
|
||||
perf_event_update_userpage(event);
|
||||
|
||||
unlock:
|
||||
@@ -6746,6 +6767,10 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr,
|
||||
if (ret)
|
||||
return -EFAULT;
|
||||
|
||||
/* disabled for now */
|
||||
if (attr->mmap2)
|
||||
return -EINVAL;
|
||||
|
||||
if (attr->__reserved_1)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -7213,15 +7238,15 @@ void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu)
|
||||
perf_remove_from_context(event);
|
||||
unaccount_event_cpu(event, src_cpu);
|
||||
put_ctx(src_ctx);
|
||||
list_add(&event->event_entry, &events);
|
||||
list_add(&event->migrate_entry, &events);
|
||||
}
|
||||
mutex_unlock(&src_ctx->mutex);
|
||||
|
||||
synchronize_rcu();
|
||||
|
||||
mutex_lock(&dst_ctx->mutex);
|
||||
list_for_each_entry_safe(event, tmp, &events, event_entry) {
|
||||
list_del(&event->event_entry);
|
||||
list_for_each_entry_safe(event, tmp, &events, migrate_entry) {
|
||||
list_del(&event->migrate_entry);
|
||||
if (event->state >= PERF_EVENT_STATE_OFF)
|
||||
event->state = PERF_EVENT_STATE_INACTIVE;
|
||||
account_event_cpu(event, dst_cpu);
|
||||
|
||||
@@ -87,10 +87,31 @@ again:
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Publish the known good head. Rely on the full barrier implied
|
||||
* by atomic_dec_and_test() order the rb->head read and this
|
||||
* write.
|
||||
* Since the mmap() consumer (userspace) can run on a different CPU:
|
||||
*
|
||||
* kernel user
|
||||
*
|
||||
* READ ->data_tail READ ->data_head
|
||||
* smp_mb() (A) smp_rmb() (C)
|
||||
* WRITE $data READ $data
|
||||
* smp_wmb() (B) smp_mb() (D)
|
||||
* STORE ->data_head WRITE ->data_tail
|
||||
*
|
||||
* Where A pairs with D, and B pairs with C.
|
||||
*
|
||||
* I don't think A needs to be a full barrier because we won't in fact
|
||||
* write data until we see the store from userspace. So we simply don't
|
||||
* issue the data WRITE until we observe it. Be conservative for now.
|
||||
*
|
||||
* OTOH, D needs to be a full barrier since it separates the data READ
|
||||
* from the tail WRITE.
|
||||
*
|
||||
* For B a WMB is sufficient since it separates two WRITEs, and for C
|
||||
* an RMB is sufficient since it separates two READs.
|
||||
*
|
||||
* See perf_output_begin().
|
||||
*/
|
||||
smp_wmb();
|
||||
rb->user_page->data_head = head;
|
||||
|
||||
/*
|
||||
@@ -154,9 +175,11 @@ int perf_output_begin(struct perf_output_handle *handle,
|
||||
* Userspace could choose to issue a mb() before updating the
|
||||
* tail pointer. So that all reads will be completed before the
|
||||
* write is issued.
|
||||
*
|
||||
* See perf_output_put_handle().
|
||||
*/
|
||||
tail = ACCESS_ONCE(rb->user_page->data_tail);
|
||||
smp_rmb();
|
||||
smp_mb();
|
||||
offset = head = local_read(&rb->head);
|
||||
head += size;
|
||||
if (unlikely(!perf_output_space(rb, tail, offset, head)))
|
||||
|
||||
@@ -571,6 +571,10 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait)
|
||||
DECLARE_COMPLETION_ONSTACK(done);
|
||||
int retval = 0;
|
||||
|
||||
if (!sub_info->path) {
|
||||
call_usermodehelper_freeinfo(sub_info);
|
||||
return -EINVAL;
|
||||
}
|
||||
helper_lock();
|
||||
if (!khelper_wq || usermodehelper_disabled) {
|
||||
retval = -EBUSY;
|
||||
|
||||
+16
-16
@@ -410,7 +410,7 @@ ww_mutex_set_context_fastpath(struct ww_mutex *lock,
|
||||
static __always_inline int __sched
|
||||
__mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
|
||||
struct lockdep_map *nest_lock, unsigned long ip,
|
||||
struct ww_acquire_ctx *ww_ctx)
|
||||
struct ww_acquire_ctx *ww_ctx, const bool use_ww_ctx)
|
||||
{
|
||||
struct task_struct *task = current;
|
||||
struct mutex_waiter waiter;
|
||||
@@ -450,7 +450,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
|
||||
struct task_struct *owner;
|
||||
struct mspin_node node;
|
||||
|
||||
if (!__builtin_constant_p(ww_ctx == NULL) && ww_ctx->acquired > 0) {
|
||||
if (use_ww_ctx && ww_ctx->acquired > 0) {
|
||||
struct ww_mutex *ww;
|
||||
|
||||
ww = container_of(lock, struct ww_mutex, base);
|
||||
@@ -480,7 +480,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
|
||||
if ((atomic_read(&lock->count) == 1) &&
|
||||
(atomic_cmpxchg(&lock->count, 1, 0) == 1)) {
|
||||
lock_acquired(&lock->dep_map, ip);
|
||||
if (!__builtin_constant_p(ww_ctx == NULL)) {
|
||||
if (use_ww_ctx) {
|
||||
struct ww_mutex *ww;
|
||||
ww = container_of(lock, struct ww_mutex, base);
|
||||
|
||||
@@ -551,7 +551,7 @@ slowpath:
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!__builtin_constant_p(ww_ctx == NULL) && ww_ctx->acquired > 0) {
|
||||
if (use_ww_ctx && ww_ctx->acquired > 0) {
|
||||
ret = __mutex_lock_check_stamp(lock, ww_ctx);
|
||||
if (ret)
|
||||
goto err;
|
||||
@@ -575,7 +575,7 @@ skip_wait:
|
||||
lock_acquired(&lock->dep_map, ip);
|
||||
mutex_set_owner(lock);
|
||||
|
||||
if (!__builtin_constant_p(ww_ctx == NULL)) {
|
||||
if (use_ww_ctx) {
|
||||
struct ww_mutex *ww = container_of(lock, struct ww_mutex, base);
|
||||
struct mutex_waiter *cur;
|
||||
|
||||
@@ -615,7 +615,7 @@ mutex_lock_nested(struct mutex *lock, unsigned int subclass)
|
||||
{
|
||||
might_sleep();
|
||||
__mutex_lock_common(lock, TASK_UNINTERRUPTIBLE,
|
||||
subclass, NULL, _RET_IP_, NULL);
|
||||
subclass, NULL, _RET_IP_, NULL, 0);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(mutex_lock_nested);
|
||||
@@ -625,7 +625,7 @@ _mutex_lock_nest_lock(struct mutex *lock, struct lockdep_map *nest)
|
||||
{
|
||||
might_sleep();
|
||||
__mutex_lock_common(lock, TASK_UNINTERRUPTIBLE,
|
||||
0, nest, _RET_IP_, NULL);
|
||||
0, nest, _RET_IP_, NULL, 0);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(_mutex_lock_nest_lock);
|
||||
@@ -635,7 +635,7 @@ mutex_lock_killable_nested(struct mutex *lock, unsigned int subclass)
|
||||
{
|
||||
might_sleep();
|
||||
return __mutex_lock_common(lock, TASK_KILLABLE,
|
||||
subclass, NULL, _RET_IP_, NULL);
|
||||
subclass, NULL, _RET_IP_, NULL, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mutex_lock_killable_nested);
|
||||
|
||||
@@ -644,7 +644,7 @@ mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass)
|
||||
{
|
||||
might_sleep();
|
||||
return __mutex_lock_common(lock, TASK_INTERRUPTIBLE,
|
||||
subclass, NULL, _RET_IP_, NULL);
|
||||
subclass, NULL, _RET_IP_, NULL, 0);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(mutex_lock_interruptible_nested);
|
||||
@@ -682,7 +682,7 @@ __ww_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
|
||||
|
||||
might_sleep();
|
||||
ret = __mutex_lock_common(&lock->base, TASK_UNINTERRUPTIBLE,
|
||||
0, &ctx->dep_map, _RET_IP_, ctx);
|
||||
0, &ctx->dep_map, _RET_IP_, ctx, 1);
|
||||
if (!ret && ctx->acquired > 1)
|
||||
return ww_mutex_deadlock_injection(lock, ctx);
|
||||
|
||||
@@ -697,7 +697,7 @@ __ww_mutex_lock_interruptible(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
|
||||
|
||||
might_sleep();
|
||||
ret = __mutex_lock_common(&lock->base, TASK_INTERRUPTIBLE,
|
||||
0, &ctx->dep_map, _RET_IP_, ctx);
|
||||
0, &ctx->dep_map, _RET_IP_, ctx, 1);
|
||||
|
||||
if (!ret && ctx->acquired > 1)
|
||||
return ww_mutex_deadlock_injection(lock, ctx);
|
||||
@@ -809,28 +809,28 @@ __mutex_lock_slowpath(atomic_t *lock_count)
|
||||
struct mutex *lock = container_of(lock_count, struct mutex, count);
|
||||
|
||||
__mutex_lock_common(lock, TASK_UNINTERRUPTIBLE, 0,
|
||||
NULL, _RET_IP_, NULL);
|
||||
NULL, _RET_IP_, NULL, 0);
|
||||
}
|
||||
|
||||
static noinline int __sched
|
||||
__mutex_lock_killable_slowpath(struct mutex *lock)
|
||||
{
|
||||
return __mutex_lock_common(lock, TASK_KILLABLE, 0,
|
||||
NULL, _RET_IP_, NULL);
|
||||
NULL, _RET_IP_, NULL, 0);
|
||||
}
|
||||
|
||||
static noinline int __sched
|
||||
__mutex_lock_interruptible_slowpath(struct mutex *lock)
|
||||
{
|
||||
return __mutex_lock_common(lock, TASK_INTERRUPTIBLE, 0,
|
||||
NULL, _RET_IP_, NULL);
|
||||
NULL, _RET_IP_, NULL, 0);
|
||||
}
|
||||
|
||||
static noinline int __sched
|
||||
__ww_mutex_lock_slowpath(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
|
||||
{
|
||||
return __mutex_lock_common(&lock->base, TASK_UNINTERRUPTIBLE, 0,
|
||||
NULL, _RET_IP_, ctx);
|
||||
NULL, _RET_IP_, ctx, 1);
|
||||
}
|
||||
|
||||
static noinline int __sched
|
||||
@@ -838,7 +838,7 @@ __ww_mutex_lock_interruptible_slowpath(struct ww_mutex *lock,
|
||||
struct ww_acquire_ctx *ctx)
|
||||
{
|
||||
return __mutex_lock_common(&lock->base, TASK_INTERRUPTIBLE, 0,
|
||||
NULL, _RET_IP_, ctx);
|
||||
NULL, _RET_IP_, ctx, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+3
-3
@@ -254,11 +254,11 @@ int parse_args(const char *doing,
|
||||
|
||||
|
||||
STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", unsigned long, kstrtoul);
|
||||
STANDARD_PARAM_DEF(short, short, "%hi", long, kstrtoul);
|
||||
STANDARD_PARAM_DEF(short, short, "%hi", long, kstrtol);
|
||||
STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", unsigned long, kstrtoul);
|
||||
STANDARD_PARAM_DEF(int, int, "%i", long, kstrtoul);
|
||||
STANDARD_PARAM_DEF(int, int, "%i", long, kstrtol);
|
||||
STANDARD_PARAM_DEF(uint, unsigned int, "%u", unsigned long, kstrtoul);
|
||||
STANDARD_PARAM_DEF(long, long, "%li", long, kstrtoul);
|
||||
STANDARD_PARAM_DEF(long, long, "%li", long, kstrtol);
|
||||
STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", unsigned long, kstrtoul);
|
||||
|
||||
int param_set_charp(const char *val, const struct kernel_param *kp)
|
||||
|
||||
@@ -273,6 +273,11 @@ void free_pid(struct pid *pid)
|
||||
*/
|
||||
wake_up_process(ns->child_reaper);
|
||||
break;
|
||||
case PIDNS_HASH_ADDING:
|
||||
/* Handle a fork failure of the first process */
|
||||
WARN_ON(ns->child_reaper);
|
||||
ns->nr_hashed = 0;
|
||||
/* fall through */
|
||||
case 0:
|
||||
schedule_work(&ns->proc_work);
|
||||
break;
|
||||
|
||||
@@ -846,7 +846,7 @@ static int software_resume(void)
|
||||
goto Finish;
|
||||
}
|
||||
|
||||
late_initcall(software_resume);
|
||||
late_initcall_sync(software_resume);
|
||||
|
||||
|
||||
static const char * const hibernation_modes[] = {
|
||||
|
||||
@@ -743,7 +743,10 @@ int create_basic_memory_bitmaps(void)
|
||||
struct memory_bitmap *bm1, *bm2;
|
||||
int error = 0;
|
||||
|
||||
BUG_ON(forbidden_pages_map || free_pages_map);
|
||||
if (forbidden_pages_map && free_pages_map)
|
||||
return 0;
|
||||
else
|
||||
BUG_ON(forbidden_pages_map || free_pages_map);
|
||||
|
||||
bm1 = kzalloc(sizeof(struct memory_bitmap), GFP_KERNEL);
|
||||
if (!bm1)
|
||||
|
||||
@@ -39,6 +39,7 @@ static struct snapshot_data {
|
||||
char frozen;
|
||||
char ready;
|
||||
char platform_support;
|
||||
bool free_bitmaps;
|
||||
} snapshot_state;
|
||||
|
||||
atomic_t snapshot_device_available = ATOMIC_INIT(1);
|
||||
@@ -82,6 +83,10 @@ static int snapshot_open(struct inode *inode, struct file *filp)
|
||||
data->swap = -1;
|
||||
data->mode = O_WRONLY;
|
||||
error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
|
||||
if (!error) {
|
||||
error = create_basic_memory_bitmaps();
|
||||
data->free_bitmaps = !error;
|
||||
}
|
||||
if (error)
|
||||
pm_notifier_call_chain(PM_POST_RESTORE);
|
||||
}
|
||||
@@ -111,6 +116,8 @@ static int snapshot_release(struct inode *inode, struct file *filp)
|
||||
pm_restore_gfp_mask();
|
||||
free_basic_memory_bitmaps();
|
||||
thaw_processes();
|
||||
} else if (data->free_bitmaps) {
|
||||
free_basic_memory_bitmaps();
|
||||
}
|
||||
pm_notifier_call_chain(data->mode == O_RDONLY ?
|
||||
PM_POST_HIBERNATION : PM_POST_RESTORE);
|
||||
@@ -231,6 +238,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
|
||||
break;
|
||||
pm_restore_gfp_mask();
|
||||
free_basic_memory_bitmaps();
|
||||
data->free_bitmaps = false;
|
||||
thaw_processes();
|
||||
data->frozen = 0;
|
||||
break;
|
||||
|
||||
+8
-1
@@ -32,7 +32,14 @@ EXPORT_SYMBOL(cad_pid);
|
||||
#endif
|
||||
enum reboot_mode reboot_mode DEFAULT_REBOOT_MODE;
|
||||
|
||||
int reboot_default;
|
||||
/*
|
||||
* This variable is used privately to keep track of whether or not
|
||||
* reboot_type is still set to its default value (i.e., reboot= hasn't
|
||||
* been set on the command line). This is needed so that we can
|
||||
* suppress DMI scanning for reboot quirks. Without it, it's
|
||||
* impossible to override a faulty reboot quirk without recompiling.
|
||||
*/
|
||||
int reboot_default = 1;
|
||||
int reboot_cpu;
|
||||
enum reboot_type reboot_type = BOOT_ACPI;
|
||||
int reboot_force;
|
||||
|
||||
+5
-4
@@ -4242,7 +4242,7 @@ static void update_cfs_rq_h_load(struct cfs_rq *cfs_rq)
|
||||
}
|
||||
|
||||
if (!se) {
|
||||
cfs_rq->h_load = rq->avg.load_avg_contrib;
|
||||
cfs_rq->h_load = cfs_rq->runnable_load_avg;
|
||||
cfs_rq->last_h_load_update = now;
|
||||
}
|
||||
|
||||
@@ -4823,8 +4823,8 @@ void fix_small_imbalance(struct lb_env *env, struct sd_lb_stats *sds)
|
||||
(busiest->load_per_task * SCHED_POWER_SCALE) /
|
||||
busiest->group_power;
|
||||
|
||||
if (busiest->avg_load - local->avg_load + scaled_busy_load_per_task >=
|
||||
(scaled_busy_load_per_task * imbn)) {
|
||||
if (busiest->avg_load + scaled_busy_load_per_task >=
|
||||
local->avg_load + (scaled_busy_load_per_task * imbn)) {
|
||||
env->imbalance = busiest->load_per_task;
|
||||
return;
|
||||
}
|
||||
@@ -4896,7 +4896,8 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s
|
||||
* max load less than avg load(as we skip the groups at or below
|
||||
* its cpu_power, while calculating max_load..)
|
||||
*/
|
||||
if (busiest->avg_load < sds->avg_load) {
|
||||
if (busiest->avg_load <= sds->avg_load ||
|
||||
local->avg_load >= sds->avg_load) {
|
||||
env->imbalance = 0;
|
||||
return fix_small_imbalance(env, sds);
|
||||
}
|
||||
|
||||
+12
-3
@@ -328,10 +328,19 @@ void irq_enter(void)
|
||||
|
||||
static inline void invoke_softirq(void)
|
||||
{
|
||||
if (!force_irqthreads)
|
||||
__do_softirq();
|
||||
else
|
||||
if (!force_irqthreads) {
|
||||
/*
|
||||
* We can safely execute softirq on the current stack if
|
||||
* it is the irq stack, because it should be near empty
|
||||
* at this stage. But we have no way to know if the arch
|
||||
* calls irq_exit() on the irq stack. So call softirq
|
||||
* in its own stack to prevent from any overrun on top
|
||||
* of a potentially deep task stack.
|
||||
*/
|
||||
do_softirq();
|
||||
} else {
|
||||
wakeup_softirqd();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void tick_irq_exit(void)
|
||||
|
||||
+51
-16
@@ -33,6 +33,54 @@ struct ce_unbind {
|
||||
int res;
|
||||
};
|
||||
|
||||
static u64 cev_delta2ns(unsigned long latch, struct clock_event_device *evt,
|
||||
bool ismax)
|
||||
{
|
||||
u64 clc = (u64) latch << evt->shift;
|
||||
u64 rnd;
|
||||
|
||||
if (unlikely(!evt->mult)) {
|
||||
evt->mult = 1;
|
||||
WARN_ON(1);
|
||||
}
|
||||
rnd = (u64) evt->mult - 1;
|
||||
|
||||
/*
|
||||
* Upper bound sanity check. If the backwards conversion is
|
||||
* not equal latch, we know that the above shift overflowed.
|
||||
*/
|
||||
if ((clc >> evt->shift) != (u64)latch)
|
||||
clc = ~0ULL;
|
||||
|
||||
/*
|
||||
* Scaled math oddities:
|
||||
*
|
||||
* For mult <= (1 << shift) we can safely add mult - 1 to
|
||||
* prevent integer rounding loss. So the backwards conversion
|
||||
* from nsec to device ticks will be correct.
|
||||
*
|
||||
* For mult > (1 << shift), i.e. device frequency is > 1GHz we
|
||||
* need to be careful. Adding mult - 1 will result in a value
|
||||
* which when converted back to device ticks can be larger
|
||||
* than latch by up to (mult - 1) >> shift. For the min_delta
|
||||
* calculation we still want to apply this in order to stay
|
||||
* above the minimum device ticks limit. For the upper limit
|
||||
* we would end up with a latch value larger than the upper
|
||||
* limit of the device, so we omit the add to stay below the
|
||||
* device upper boundary.
|
||||
*
|
||||
* Also omit the add if it would overflow the u64 boundary.
|
||||
*/
|
||||
if ((~0ULL - clc > rnd) &&
|
||||
(!ismax || evt->mult <= (1U << evt->shift)))
|
||||
clc += rnd;
|
||||
|
||||
do_div(clc, evt->mult);
|
||||
|
||||
/* Deltas less than 1usec are pointless noise */
|
||||
return clc > 1000 ? clc : 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* clockevents_delta2ns - Convert a latch value (device ticks) to nanoseconds
|
||||
* @latch: value to convert
|
||||
@@ -42,20 +90,7 @@ struct ce_unbind {
|
||||
*/
|
||||
u64 clockevent_delta2ns(unsigned long latch, struct clock_event_device *evt)
|
||||
{
|
||||
u64 clc = (u64) latch << evt->shift;
|
||||
|
||||
if (unlikely(!evt->mult)) {
|
||||
evt->mult = 1;
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
do_div(clc, evt->mult);
|
||||
if (clc < 1000)
|
||||
clc = 1000;
|
||||
if (clc > KTIME_MAX)
|
||||
clc = KTIME_MAX;
|
||||
|
||||
return clc;
|
||||
return cev_delta2ns(latch, evt, false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(clockevent_delta2ns);
|
||||
|
||||
@@ -380,8 +415,8 @@ void clockevents_config(struct clock_event_device *dev, u32 freq)
|
||||
sec = 600;
|
||||
|
||||
clockevents_calc_mult_shift(dev, freq, sec);
|
||||
dev->min_delta_ns = clockevent_delta2ns(dev->min_delta_ticks, dev);
|
||||
dev->max_delta_ns = clockevent_delta2ns(dev->max_delta_ticks, dev);
|
||||
dev->min_delta_ns = cev_delta2ns(dev->min_delta_ticks, dev, false);
|
||||
dev->max_delta_ns = cev_delta2ns(dev->max_delta_ticks, dev, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+55
-5
@@ -486,7 +486,52 @@ static struct smp_hotplug_thread watchdog_threads = {
|
||||
.unpark = watchdog_enable,
|
||||
};
|
||||
|
||||
static int watchdog_enable_all_cpus(void)
|
||||
static void restart_watchdog_hrtimer(void *info)
|
||||
{
|
||||
struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* No need to cancel and restart hrtimer if it is currently executing
|
||||
* because it will reprogram itself with the new period now.
|
||||
* We should never see it unqueued here because we are running per-cpu
|
||||
* with interrupts disabled.
|
||||
*/
|
||||
ret = hrtimer_try_to_cancel(hrtimer);
|
||||
if (ret == 1)
|
||||
hrtimer_start(hrtimer, ns_to_ktime(sample_period),
|
||||
HRTIMER_MODE_REL_PINNED);
|
||||
}
|
||||
|
||||
static void update_timers(int cpu)
|
||||
{
|
||||
struct call_single_data data = {.func = restart_watchdog_hrtimer};
|
||||
/*
|
||||
* Make sure that perf event counter will adopt to a new
|
||||
* sampling period. Updating the sampling period directly would
|
||||
* be much nicer but we do not have an API for that now so
|
||||
* let's use a big hammer.
|
||||
* Hrtimer will adopt the new period on the next tick but this
|
||||
* might be late already so we have to restart the timer as well.
|
||||
*/
|
||||
watchdog_nmi_disable(cpu);
|
||||
__smp_call_function_single(cpu, &data, 1);
|
||||
watchdog_nmi_enable(cpu);
|
||||
}
|
||||
|
||||
static void update_timers_all_cpus(void)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
get_online_cpus();
|
||||
preempt_disable();
|
||||
for_each_online_cpu(cpu)
|
||||
update_timers(cpu);
|
||||
preempt_enable();
|
||||
put_online_cpus();
|
||||
}
|
||||
|
||||
static int watchdog_enable_all_cpus(bool sample_period_changed)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
@@ -496,6 +541,8 @@ static int watchdog_enable_all_cpus(void)
|
||||
pr_err("Failed to create watchdog threads, disabled\n");
|
||||
else
|
||||
watchdog_running = 1;
|
||||
} else if (sample_period_changed) {
|
||||
update_timers_all_cpus();
|
||||
}
|
||||
|
||||
return err;
|
||||
@@ -520,13 +567,15 @@ int proc_dowatchdog(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
int err, old_thresh, old_enabled;
|
||||
static DEFINE_MUTEX(watchdog_proc_mutex);
|
||||
|
||||
mutex_lock(&watchdog_proc_mutex);
|
||||
old_thresh = ACCESS_ONCE(watchdog_thresh);
|
||||
old_enabled = ACCESS_ONCE(watchdog_user_enabled);
|
||||
|
||||
err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
|
||||
if (err || !write)
|
||||
return err;
|
||||
goto out;
|
||||
|
||||
set_sample_period();
|
||||
/*
|
||||
@@ -535,7 +584,7 @@ int proc_dowatchdog(struct ctl_table *table, int write,
|
||||
* watchdog_*_all_cpus() function takes care of this.
|
||||
*/
|
||||
if (watchdog_user_enabled && watchdog_thresh)
|
||||
err = watchdog_enable_all_cpus();
|
||||
err = watchdog_enable_all_cpus(old_thresh != watchdog_thresh);
|
||||
else
|
||||
watchdog_disable_all_cpus();
|
||||
|
||||
@@ -544,7 +593,8 @@ int proc_dowatchdog(struct ctl_table *table, int write,
|
||||
watchdog_thresh = old_thresh;
|
||||
watchdog_user_enabled = old_enabled;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&watchdog_proc_mutex);
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
@@ -554,5 +604,5 @@ void __init lockup_detector_init(void)
|
||||
set_sample_period();
|
||||
|
||||
if (watchdog_user_enabled)
|
||||
watchdog_enable_all_cpus();
|
||||
watchdog_enable_all_cpus(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user