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: Tejun 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>
This commit is contained in:
Tejun Heo 2011-11-21 12:32:22 -08:00
parent 3a7cbd50f7
commit a0acae0e88
15 changed files with 37 additions and 39 deletions

View File

@ -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
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.
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?

View File

@ -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;

View File

@ -340,7 +340,7 @@ again:
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()) {

View File

@ -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 @@ sleep:
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))

View File

@ -2882,8 +2882,7 @@ cont_thread:
} }
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)) ||

View File

@ -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,

View File

@ -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);

View File

@ -166,7 +166,7 @@ loop:
*/ */
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 {
/* /*

View File

@ -173,7 +173,7 @@ loop:
*/ */
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 {
/* /*

View File

@ -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);

View File

@ -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)
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();

View File

@ -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);

View File

@ -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);
} }

View File

@ -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) {}
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) {}

View File

@ -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)
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)
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)
* 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)
{ {