Merge branch 'freezer'
* freezer: af_unix: use freezable blocking calls in read sigtimedwait: use freezable blocking call nanosleep: use freezable blocking call futex: use freezable blocking call select: use freezable blocking call epoll: use freezable blocking call binder: use freezable blocking calls freezer: add new freezable helpers using freezer_do_not_count() freezer: convert freezable helpers to static inline where possible freezer: convert freezable helpers to freezer_do_not_count() freezer: skip waking up tasks with PF_FREEZER_SKIP set freezer: shorten freezer sleep time using exponential backoff lockdep: check that no locks held at freeze time lockdep: remove task argument from debug_check_no_locks_held freezer: add unsafe versions of freezable helpers for CIFS freezer: add unsafe versions of freezable helpers for NFS
This commit is contained in:
@@ -835,7 +835,7 @@ void do_exit(long code)
|
||||
/*
|
||||
* Make sure we are holding no locks:
|
||||
*/
|
||||
debug_check_no_locks_held(tsk);
|
||||
debug_check_no_locks_held();
|
||||
/*
|
||||
* We can do this unlocked here. The futex code uses this flag
|
||||
* just to verify whether the pi state cleanup has been done
|
||||
|
@@ -110,6 +110,18 @@ bool freeze_task(struct task_struct *p)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* This check can race with freezer_do_not_count, but worst case that
|
||||
* will result in an extra wakeup being sent to the task. It does not
|
||||
* race with freezer_count(), the barriers in freezer_count() and
|
||||
* freezer_should_skip() ensure that either freezer_count() sees
|
||||
* freezing == true in try_to_freeze() and freezes, or
|
||||
* freezer_should_skip() sees !PF_FREEZE_SKIP and freezes the task
|
||||
* normally.
|
||||
*/
|
||||
if (freezer_should_skip(p))
|
||||
return false;
|
||||
|
||||
spin_lock_irqsave(&freezer_lock, flags);
|
||||
if (!freezing(p) || frozen(p)) {
|
||||
spin_unlock_irqrestore(&freezer_lock, flags);
|
||||
|
@@ -61,6 +61,7 @@
|
||||
#include <linux/nsproxy.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/sched/rt.h>
|
||||
#include <linux/freezer.h>
|
||||
|
||||
#include <asm/futex.h>
|
||||
|
||||
@@ -1807,7 +1808,7 @@ static void futex_wait_queue_me(struct futex_hash_bucket *hb, struct futex_q *q,
|
||||
* is no timeout, or if it has yet to expire.
|
||||
*/
|
||||
if (!timeout || timeout->task)
|
||||
schedule();
|
||||
freezable_schedule();
|
||||
}
|
||||
__set_current_state(TASK_RUNNING);
|
||||
}
|
||||
|
@@ -47,6 +47,7 @@
|
||||
#include <linux/sched/sysctl.h>
|
||||
#include <linux/sched/rt.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/freezer.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
@@ -1545,7 +1546,7 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
|
||||
t->task = NULL;
|
||||
|
||||
if (likely(t->task))
|
||||
schedule();
|
||||
freezable_schedule();
|
||||
|
||||
hrtimer_cancel(&t->timer);
|
||||
mode = HRTIMER_MODE_ABS;
|
||||
|
@@ -4090,7 +4090,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(debug_check_no_locks_freed);
|
||||
|
||||
static void print_held_locks_bug(struct task_struct *curr)
|
||||
static void print_held_locks_bug(void)
|
||||
{
|
||||
if (!debug_locks_off())
|
||||
return;
|
||||
@@ -4099,22 +4099,21 @@ static void print_held_locks_bug(struct task_struct *curr)
|
||||
|
||||
printk("\n");
|
||||
printk("=====================================\n");
|
||||
printk("[ BUG: lock held at task exit time! ]\n");
|
||||
printk("[ BUG: %s/%d still has locks held! ]\n",
|
||||
current->comm, task_pid_nr(current));
|
||||
print_kernel_ident();
|
||||
printk("-------------------------------------\n");
|
||||
printk("%s/%d is exiting with locks still held!\n",
|
||||
curr->comm, task_pid_nr(curr));
|
||||
lockdep_print_held_locks(curr);
|
||||
|
||||
lockdep_print_held_locks(current);
|
||||
printk("\nstack backtrace:\n");
|
||||
dump_stack();
|
||||
}
|
||||
|
||||
void debug_check_no_locks_held(struct task_struct *task)
|
||||
void debug_check_no_locks_held(void)
|
||||
{
|
||||
if (unlikely(task->lockdep_depth > 0))
|
||||
print_held_locks_bug(task);
|
||||
if (unlikely(current->lockdep_depth > 0))
|
||||
print_held_locks_bug();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(debug_check_no_locks_held);
|
||||
|
||||
void debug_show_all_locks(void)
|
||||
{
|
||||
|
@@ -30,9 +30,10 @@ static int try_to_freeze_tasks(bool user_only)
|
||||
unsigned int todo;
|
||||
bool wq_busy = false;
|
||||
struct timeval start, end;
|
||||
u64 elapsed_csecs64;
|
||||
unsigned int elapsed_csecs;
|
||||
u64 elapsed_msecs64;
|
||||
unsigned int elapsed_msecs;
|
||||
bool wakeup = false;
|
||||
int sleep_usecs = USEC_PER_MSEC;
|
||||
|
||||
do_gettimeofday(&start);
|
||||
|
||||
@@ -68,22 +69,25 @@ static int try_to_freeze_tasks(bool user_only)
|
||||
|
||||
/*
|
||||
* We need to retry, but first give the freezing tasks some
|
||||
* time to enter the refrigerator.
|
||||
* time to enter the refrigerator. Start with an initial
|
||||
* 1 ms sleep followed by exponential backoff until 8 ms.
|
||||
*/
|
||||
msleep(10);
|
||||
usleep_range(sleep_usecs / 2, sleep_usecs);
|
||||
if (sleep_usecs < 8 * USEC_PER_MSEC)
|
||||
sleep_usecs *= 2;
|
||||
}
|
||||
|
||||
do_gettimeofday(&end);
|
||||
elapsed_csecs64 = timeval_to_ns(&end) - timeval_to_ns(&start);
|
||||
do_div(elapsed_csecs64, NSEC_PER_SEC / 100);
|
||||
elapsed_csecs = elapsed_csecs64;
|
||||
elapsed_msecs64 = timeval_to_ns(&end) - timeval_to_ns(&start);
|
||||
do_div(elapsed_msecs64, NSEC_PER_MSEC);
|
||||
elapsed_msecs = elapsed_msecs64;
|
||||
|
||||
if (todo) {
|
||||
printk("\n");
|
||||
printk(KERN_ERR "Freezing of tasks %s after %d.%02d seconds "
|
||||
printk(KERN_ERR "Freezing of tasks %s after %d.%03d seconds "
|
||||
"(%d tasks refusing to freeze, wq_busy=%d):\n",
|
||||
wakeup ? "aborted" : "failed",
|
||||
elapsed_csecs / 100, elapsed_csecs % 100,
|
||||
elapsed_msecs / 1000, elapsed_msecs % 1000,
|
||||
todo - wq_busy, wq_busy);
|
||||
|
||||
if (!wakeup) {
|
||||
@@ -96,8 +100,8 @@ static int try_to_freeze_tasks(bool user_only)
|
||||
read_unlock(&tasklist_lock);
|
||||
}
|
||||
} else {
|
||||
printk("(elapsed %d.%02d seconds) ", elapsed_csecs / 100,
|
||||
elapsed_csecs % 100);
|
||||
printk("(elapsed %d.%03d seconds) ", elapsed_msecs / 1000,
|
||||
elapsed_msecs % 1000);
|
||||
}
|
||||
|
||||
return todo ? -EBUSY : 0;
|
||||
|
@@ -2848,7 +2848,7 @@ int do_sigtimedwait(const sigset_t *which, siginfo_t *info,
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(&tsk->sighand->siglock);
|
||||
|
||||
timeout = schedule_timeout_interruptible(timeout);
|
||||
timeout = freezable_schedule_timeout_interruptible(timeout);
|
||||
|
||||
spin_lock_irq(&tsk->sighand->siglock);
|
||||
__set_task_blocked(tsk, &tsk->real_blocked);
|
||||
|
Reference in New Issue
Block a user