Commit a0acae0e authored by Tejun Heo's avatar Tejun Heo

freezer: unexport refrigerator() and update try_to_freeze() slightly

There is no reason to export two functions for entering the
refrigerator.  Calling refrigerator() instead of try_to_freeze()
doesn't save anything noticeable or removes any race condition.

* Rename refrigerator() to __refrigerator() and make it return bool
  indicating whether it scheduled out for freezing.

* Update try_to_freeze() to return bool and relay the return value of
  __refrigerator() if freezing().

* Convert all refrigerator() users to try_to_freeze().

* Update documentation accordingly.

* While at it, add might_sleep() to try_to_freeze().
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Cc: Samuel Ortiz <samuel@sortiz.org>
Cc: Chris Mason <chris.mason@oracle.com>
Cc: "Theodore Ts'o" <tytso@mit.edu>
Cc: Steven Whitehouse <swhiteho@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Jan Kara <jack@suse.cz>
Cc: KONISHI Ryusuke <konishi.ryusuke@lab.ntt.co.jp>
Cc: Christoph Hellwig <hch@infradead.org>
parent 3a7cbd50
...@@ -21,7 +21,7 @@ freeze_processes() (defined in kernel/power/process.c) is called. It executes ...@@ -21,7 +21,7 @@ freeze_processes() (defined in kernel/power/process.c) is called. It executes
try_to_freeze_tasks() that sets TIF_FREEZE for all of the freezable tasks and try_to_freeze_tasks() that sets TIF_FREEZE for all of the freezable tasks and
either wakes them up, if they are kernel threads, or sends fake signals to them, either wakes them up, if they are kernel threads, or sends fake signals to them,
if they are user space processes. A task that has TIF_FREEZE set, should react if they are user space processes. A task that has TIF_FREEZE set, should react
to it by calling the function called refrigerator() (defined in to it by calling the function called __refrigerator() (defined in
kernel/freezer.c), which sets the task's PF_FROZEN flag, changes its state kernel/freezer.c), which sets the task's PF_FROZEN flag, changes its state
to TASK_UNINTERRUPTIBLE and makes it loop until PF_FROZEN is cleared for it. to TASK_UNINTERRUPTIBLE and makes it loop until PF_FROZEN is cleared for it.
Then, we say that the task is 'frozen' and therefore the set of functions Then, we say that the task is 'frozen' and therefore the set of functions
...@@ -29,10 +29,10 @@ handling this mechanism is referred to as 'the freezer' (these functions are ...@@ -29,10 +29,10 @@ handling this mechanism is referred to as 'the freezer' (these functions are
defined in kernel/power/process.c, kernel/freezer.c & include/linux/freezer.h). defined in kernel/power/process.c, kernel/freezer.c & include/linux/freezer.h).
User space processes are generally frozen before kernel threads. User space processes are generally frozen before kernel threads.
It is not recommended to call refrigerator() directly. Instead, it is __refrigerator() must not be called directly. Instead, use the
recommended to use the try_to_freeze() function (defined in try_to_freeze() function (defined in include/linux/freezer.h), that checks
include/linux/freezer.h), that checks the task's TIF_FREEZE flag and makes the the task's TIF_FREEZE flag and makes the task enter __refrigerator() if the
task enter refrigerator() if the flag is set. flag is set.
For user space processes try_to_freeze() is called automatically from the For user space processes try_to_freeze() is called automatically from the
signal-handling code, but the freezable kernel threads need to call it signal-handling code, but the freezable kernel threads need to call it
...@@ -61,7 +61,7 @@ wait_event_freezable() and wait_event_freezable_timeout() macros. ...@@ -61,7 +61,7 @@ wait_event_freezable() and wait_event_freezable_timeout() macros.
After the system memory state has been restored from a hibernation image and After the system memory state has been restored from a hibernation image and
devices have been reinitialized, the function thaw_processes() is called in devices have been reinitialized, the function thaw_processes() is called in
order to clear the PF_FROZEN flag for each frozen task. Then, the tasks that order to clear the PF_FROZEN flag for each frozen task. Then, the tasks that
have been frozen leave refrigerator() and continue running. have been frozen leave __refrigerator() and continue running.
III. Which kernel threads are freezable? III. Which kernel threads are freezable?
......
...@@ -750,7 +750,7 @@ static int stir_transmit_thread(void *arg) ...@@ -750,7 +750,7 @@ static int stir_transmit_thread(void *arg)
write_reg(stir, REG_CTRL1, CTRL1_TXPWD|CTRL1_RXPWD); write_reg(stir, REG_CTRL1, CTRL1_TXPWD|CTRL1_RXPWD);
refrigerator(); try_to_freeze();
if (change_speed(stir, stir->speed)) if (change_speed(stir, stir->speed))
break; break;
......
...@@ -340,7 +340,7 @@ static int worker_loop(void *arg) ...@@ -340,7 +340,7 @@ static int worker_loop(void *arg)
if (freezing(current)) { if (freezing(current)) {
worker->working = 0; worker->working = 0;
spin_unlock_irq(&worker->lock); spin_unlock_irq(&worker->lock);
refrigerator(); try_to_freeze();
} else { } else {
spin_unlock_irq(&worker->lock); spin_unlock_irq(&worker->lock);
if (!kthread_should_stop()) { if (!kthread_should_stop()) {
......
...@@ -1579,9 +1579,7 @@ static int cleaner_kthread(void *arg) ...@@ -1579,9 +1579,7 @@ static int cleaner_kthread(void *arg)
btrfs_run_defrag_inodes(root->fs_info); btrfs_run_defrag_inodes(root->fs_info);
} }
if (freezing(current)) { if (!try_to_freeze()) {
refrigerator();
} else {
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (!kthread_should_stop()) if (!kthread_should_stop())
schedule(); schedule();
...@@ -1635,9 +1633,7 @@ static int transaction_kthread(void *arg) ...@@ -1635,9 +1633,7 @@ static int transaction_kthread(void *arg)
wake_up_process(root->fs_info->cleaner_kthread); wake_up_process(root->fs_info->cleaner_kthread);
mutex_unlock(&root->fs_info->transaction_kthread_mutex); mutex_unlock(&root->fs_info->transaction_kthread_mutex);
if (freezing(current)) { if (!try_to_freeze()) {
refrigerator();
} else {
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (!kthread_should_stop() && if (!kthread_should_stop() &&
!btrfs_transaction_blocked(root->fs_info)) !btrfs_transaction_blocked(root->fs_info))
......
...@@ -2882,8 +2882,7 @@ static int ext4_lazyinit_thread(void *arg) ...@@ -2882,8 +2882,7 @@ static int ext4_lazyinit_thread(void *arg)
} }
mutex_unlock(&eli->li_list_mtx); mutex_unlock(&eli->li_list_mtx);
if (freezing(current)) try_to_freeze();
refrigerator();
cur = jiffies; cur = jiffies;
if ((time_after_eq(cur, next_wakeup)) || if ((time_after_eq(cur, next_wakeup)) ||
......
...@@ -951,8 +951,8 @@ int gfs2_logd(void *data) ...@@ -951,8 +951,8 @@ int gfs2_logd(void *data)
wake_up(&sdp->sd_log_waitq); wake_up(&sdp->sd_log_waitq);
t = gfs2_tune_get(sdp, gt_logd_secs) * HZ; t = gfs2_tune_get(sdp, gt_logd_secs) * HZ;
if (freezing(current))
refrigerator(); try_to_freeze();
do { do {
prepare_to_wait(&sdp->sd_logd_waitq, &wait, prepare_to_wait(&sdp->sd_logd_waitq, &wait,
......
...@@ -1427,8 +1427,8 @@ int gfs2_quotad(void *data) ...@@ -1427,8 +1427,8 @@ int gfs2_quotad(void *data)
/* Check for & recover partially truncated inodes */ /* Check for & recover partially truncated inodes */
quotad_check_trunc_list(sdp); quotad_check_trunc_list(sdp);
if (freezing(current)) try_to_freeze();
refrigerator();
t = min(quotad_timeo, statfs_timeo); t = min(quotad_timeo, statfs_timeo);
prepare_to_wait(&sdp->sd_quota_wait, &wait, TASK_INTERRUPTIBLE); prepare_to_wait(&sdp->sd_quota_wait, &wait, TASK_INTERRUPTIBLE);
......
...@@ -166,7 +166,7 @@ static int kjournald(void *arg) ...@@ -166,7 +166,7 @@ static int kjournald(void *arg)
*/ */
jbd_debug(1, "Now suspending kjournald\n"); jbd_debug(1, "Now suspending kjournald\n");
spin_unlock(&journal->j_state_lock); spin_unlock(&journal->j_state_lock);
refrigerator(); try_to_freeze();
spin_lock(&journal->j_state_lock); spin_lock(&journal->j_state_lock);
} else { } else {
/* /*
......
...@@ -173,7 +173,7 @@ static int kjournald2(void *arg) ...@@ -173,7 +173,7 @@ static int kjournald2(void *arg)
*/ */
jbd_debug(1, "Now suspending kjournald2\n"); jbd_debug(1, "Now suspending kjournald2\n");
write_unlock(&journal->j_state_lock); write_unlock(&journal->j_state_lock);
refrigerator(); try_to_freeze();
write_lock(&journal->j_state_lock); write_lock(&journal->j_state_lock);
} else { } else {
/* /*
......
...@@ -2349,7 +2349,7 @@ int jfsIOWait(void *arg) ...@@ -2349,7 +2349,7 @@ int jfsIOWait(void *arg)
if (freezing(current)) { if (freezing(current)) {
spin_unlock_irq(&log_redrive_lock); spin_unlock_irq(&log_redrive_lock);
refrigerator(); try_to_freeze();
} else { } else {
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
spin_unlock_irq(&log_redrive_lock); spin_unlock_irq(&log_redrive_lock);
......
...@@ -2800,7 +2800,7 @@ int jfs_lazycommit(void *arg) ...@@ -2800,7 +2800,7 @@ int jfs_lazycommit(void *arg)
if (freezing(current)) { if (freezing(current)) {
LAZY_UNLOCK(flags); LAZY_UNLOCK(flags);
refrigerator(); try_to_freeze();
} else { } else {
DECLARE_WAITQUEUE(wq, current); DECLARE_WAITQUEUE(wq, current);
...@@ -2994,7 +2994,7 @@ int jfs_sync(void *arg) ...@@ -2994,7 +2994,7 @@ int jfs_sync(void *arg)
if (freezing(current)) { if (freezing(current)) {
TXN_UNLOCK(); TXN_UNLOCK();
refrigerator(); try_to_freeze();
} else { } else {
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
TXN_UNLOCK(); TXN_UNLOCK();
......
...@@ -2470,7 +2470,7 @@ static int nilfs_segctor_thread(void *arg) ...@@ -2470,7 +2470,7 @@ static int nilfs_segctor_thread(void *arg)
if (freezing(current)) { if (freezing(current)) {
spin_unlock(&sci->sc_state_lock); spin_unlock(&sci->sc_state_lock);
refrigerator(); try_to_freeze();
spin_lock(&sci->sc_state_lock); spin_lock(&sci->sc_state_lock);
} else { } else {
DEFINE_WAIT(wait); DEFINE_WAIT(wait);
......
...@@ -1703,7 +1703,7 @@ xfsbufd( ...@@ -1703,7 +1703,7 @@ xfsbufd(
if (unlikely(freezing(current))) { if (unlikely(freezing(current))) {
set_bit(XBT_FORCE_SLEEP, &target->bt_flags); set_bit(XBT_FORCE_SLEEP, &target->bt_flags);
refrigerator(); try_to_freeze();
} else { } else {
clear_bit(XBT_FORCE_SLEEP, &target->bt_flags); clear_bit(XBT_FORCE_SLEEP, &target->bt_flags);
} }
......
...@@ -47,18 +47,17 @@ static inline bool should_send_signal(struct task_struct *p) ...@@ -47,18 +47,17 @@ static inline bool should_send_signal(struct task_struct *p)
/* Takes and releases task alloc lock using task_lock() */ /* Takes and releases task alloc lock using task_lock() */
extern int thaw_process(struct task_struct *p); extern int thaw_process(struct task_struct *p);
extern void refrigerator(void); extern bool __refrigerator(void);
extern int freeze_processes(void); extern int freeze_processes(void);
extern int freeze_kernel_threads(void); extern int freeze_kernel_threads(void);
extern void thaw_processes(void); extern void thaw_processes(void);
static inline int try_to_freeze(void) static inline bool try_to_freeze(void)
{ {
if (freezing(current)) { might_sleep();
refrigerator(); if (likely(!freezing(current)))
return 1; return false;
} else return __refrigerator();
return 0;
} }
extern bool freeze_task(struct task_struct *p, bool sig_only); extern bool freeze_task(struct task_struct *p, bool sig_only);
...@@ -181,12 +180,12 @@ static inline void set_freeze_flag(struct task_struct *p) {} ...@@ -181,12 +180,12 @@ static inline void set_freeze_flag(struct task_struct *p) {}
static inline void clear_freeze_flag(struct task_struct *p) {} static inline void clear_freeze_flag(struct task_struct *p) {}
static inline int thaw_process(struct task_struct *p) { return 1; } static inline int thaw_process(struct task_struct *p) { return 1; }
static inline void refrigerator(void) {} static inline bool __refrigerator(void) { return false; }
static inline int freeze_processes(void) { return -ENOSYS; } static inline int freeze_processes(void) { return -ENOSYS; }
static inline int freeze_kernel_threads(void) { return -ENOSYS; } static inline int freeze_kernel_threads(void) { return -ENOSYS; }
static inline void thaw_processes(void) {} static inline void thaw_processes(void) {}
static inline int try_to_freeze(void) { return 0; } static inline bool try_to_freeze(void) { return false; }
static inline void freezer_do_not_count(void) {} static inline void freezer_do_not_count(void) {}
static inline void freezer_count(void) {} static inline void freezer_count(void) {}
......
...@@ -23,10 +23,11 @@ static inline void frozen_process(void) ...@@ -23,10 +23,11 @@ static inline void frozen_process(void)
} }
/* Refrigerator is place where frozen processes are stored :-). */ /* Refrigerator is place where frozen processes are stored :-). */
void refrigerator(void) bool __refrigerator(void)
{ {
/* Hmm, should we be allowed to suspend when there are realtime /* Hmm, should we be allowed to suspend when there are realtime
processes around? */ processes around? */
bool was_frozen = false;
long save; long save;
task_lock(current); task_lock(current);
...@@ -35,7 +36,7 @@ void refrigerator(void) ...@@ -35,7 +36,7 @@ void refrigerator(void)
task_unlock(current); task_unlock(current);
} else { } else {
task_unlock(current); task_unlock(current);
return; return was_frozen;
} }
save = current->state; save = current->state;
pr_debug("%s entered refrigerator\n", current->comm); pr_debug("%s entered refrigerator\n", current->comm);
...@@ -51,6 +52,7 @@ void refrigerator(void) ...@@ -51,6 +52,7 @@ void refrigerator(void)
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
if (!frozen(current)) if (!frozen(current))
break; break;
was_frozen = true;
schedule(); schedule();
} }
...@@ -65,8 +67,10 @@ void refrigerator(void) ...@@ -65,8 +67,10 @@ void refrigerator(void)
* synchronization which depends on ordered task state change. * synchronization which depends on ordered task state change.
*/ */
set_current_state(save); set_current_state(save);
return was_frozen;
} }
EXPORT_SYMBOL(refrigerator); EXPORT_SYMBOL(__refrigerator);
static void fake_signal_wake_up(struct task_struct *p) static void fake_signal_wake_up(struct task_struct *p)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment