Skip to content

Commit

Permalink
freezer: unexport refrigerator() and update try_to_freeze() slightly
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
htejun committed Nov 21, 2011
1 parent 3a7cbd5 commit a0acae0
Show file tree
Hide file tree
Showing 15 changed files with 37 additions and 39 deletions.
12 changes: 6 additions & 6 deletions Documentation/power/freezing-of-tasks.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@ 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
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
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
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
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).
User space processes are generally frozen before kernel threads.

It is not recommended to call refrigerator() directly. Instead, it is
recommended to use the try_to_freeze() function (defined in
include/linux/freezer.h), that checks the task's TIF_FREEZE flag and makes the
task enter refrigerator() if the flag is set.
__refrigerator() must not be called directly. Instead, use the
try_to_freeze() function (defined in include/linux/freezer.h), that checks
the task's TIF_FREEZE flag and makes the task enter __refrigerator() if the
flag is set.

For user space processes try_to_freeze() is called automatically from the
signal-handling code, but the freezable kernel threads need to call it
Expand Down Expand Up @@ -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
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
have been frozen leave refrigerator() and continue running.
have been frozen leave __refrigerator() and continue running.

III. Which kernel threads are freezable?

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/irda/stir4200.c
Original file line number Diff line number Diff line change
Expand Up @@ -750,7 +750,7 @@ static int stir_transmit_thread(void *arg)

write_reg(stir, REG_CTRL1, CTRL1_TXPWD|CTRL1_RXPWD);

refrigerator();
try_to_freeze();

if (change_speed(stir, stir->speed))
break;
Expand Down
2 changes: 1 addition & 1 deletion fs/btrfs/async-thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ static int worker_loop(void *arg)
if (freezing(current)) {
worker->working = 0;
spin_unlock_irq(&worker->lock);
refrigerator();
try_to_freeze();
} else {
spin_unlock_irq(&worker->lock);
if (!kthread_should_stop()) {
Expand Down
8 changes: 2 additions & 6 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -1579,9 +1579,7 @@ static int cleaner_kthread(void *arg)
btrfs_run_defrag_inodes(root->fs_info);
}

if (freezing(current)) {
refrigerator();
} else {
if (!try_to_freeze()) {
set_current_state(TASK_INTERRUPTIBLE);
if (!kthread_should_stop())
schedule();
Expand Down Expand Up @@ -1635,9 +1633,7 @@ static int transaction_kthread(void *arg)
wake_up_process(root->fs_info->cleaner_kthread);
mutex_unlock(&root->fs_info->transaction_kthread_mutex);

if (freezing(current)) {
refrigerator();
} else {
if (!try_to_freeze()) {
set_current_state(TASK_INTERRUPTIBLE);
if (!kthread_should_stop() &&
!btrfs_transaction_blocked(root->fs_info))
Expand Down
3 changes: 1 addition & 2 deletions fs/ext4/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -2882,8 +2882,7 @@ static int ext4_lazyinit_thread(void *arg)
}
mutex_unlock(&eli->li_list_mtx);

if (freezing(current))
refrigerator();
try_to_freeze();

cur = jiffies;
if ((time_after_eq(cur, next_wakeup)) ||
Expand Down
4 changes: 2 additions & 2 deletions fs/gfs2/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -951,8 +951,8 @@ int gfs2_logd(void *data)
wake_up(&sdp->sd_log_waitq);

t = gfs2_tune_get(sdp, gt_logd_secs) * HZ;
if (freezing(current))
refrigerator();

try_to_freeze();

do {
prepare_to_wait(&sdp->sd_logd_waitq, &wait,
Expand Down
4 changes: 2 additions & 2 deletions fs/gfs2/quota.c
Original file line number Diff line number Diff line change
Expand Up @@ -1427,8 +1427,8 @@ int gfs2_quotad(void *data)
/* Check for & recover partially truncated inodes */
quotad_check_trunc_list(sdp);

if (freezing(current))
refrigerator();
try_to_freeze();

t = min(quotad_timeo, statfs_timeo);

prepare_to_wait(&sdp->sd_quota_wait, &wait, TASK_INTERRUPTIBLE);
Expand Down
2 changes: 1 addition & 1 deletion fs/jbd/journal.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ static int kjournald(void *arg)
*/
jbd_debug(1, "Now suspending kjournald\n");
spin_unlock(&journal->j_state_lock);
refrigerator();
try_to_freeze();
spin_lock(&journal->j_state_lock);
} else {
/*
Expand Down
2 changes: 1 addition & 1 deletion fs/jbd2/journal.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ static int kjournald2(void *arg)
*/
jbd_debug(1, "Now suspending kjournald2\n");
write_unlock(&journal->j_state_lock);
refrigerator();
try_to_freeze();
write_lock(&journal->j_state_lock);
} else {
/*
Expand Down
2 changes: 1 addition & 1 deletion fs/jfs/jfs_logmgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2349,7 +2349,7 @@ int jfsIOWait(void *arg)

if (freezing(current)) {
spin_unlock_irq(&log_redrive_lock);
refrigerator();
try_to_freeze();
} else {
set_current_state(TASK_INTERRUPTIBLE);
spin_unlock_irq(&log_redrive_lock);
Expand Down
4 changes: 2 additions & 2 deletions fs/jfs/jfs_txnmgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2800,7 +2800,7 @@ int jfs_lazycommit(void *arg)

if (freezing(current)) {
LAZY_UNLOCK(flags);
refrigerator();
try_to_freeze();
} else {
DECLARE_WAITQUEUE(wq, current);

Expand Down Expand Up @@ -2994,7 +2994,7 @@ int jfs_sync(void *arg)

if (freezing(current)) {
TXN_UNLOCK();
refrigerator();
try_to_freeze();
} else {
set_current_state(TASK_INTERRUPTIBLE);
TXN_UNLOCK();
Expand Down
2 changes: 1 addition & 1 deletion fs/nilfs2/segment.c
Original file line number Diff line number Diff line change
Expand Up @@ -2470,7 +2470,7 @@ static int nilfs_segctor_thread(void *arg)

if (freezing(current)) {
spin_unlock(&sci->sc_state_lock);
refrigerator();
try_to_freeze();
spin_lock(&sci->sc_state_lock);
} else {
DEFINE_WAIT(wait);
Expand Down
2 changes: 1 addition & 1 deletion fs/xfs/xfs_buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1703,7 +1703,7 @@ xfsbufd(

if (unlikely(freezing(current))) {
set_bit(XBT_FORCE_SLEEP, &target->bt_flags);
refrigerator();
try_to_freeze();
} else {
clear_bit(XBT_FORCE_SLEEP, &target->bt_flags);
}
Expand Down
17 changes: 8 additions & 9 deletions include/linux/freezer.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,17 @@ static inline bool should_send_signal(struct task_struct *p)
/* Takes and releases task alloc lock using task_lock() */
extern int thaw_process(struct task_struct *p);

extern void refrigerator(void);
extern bool __refrigerator(void);
extern int freeze_processes(void);
extern int freeze_kernel_threads(void);
extern void thaw_processes(void);

static inline int try_to_freeze(void)
static inline bool try_to_freeze(void)
{
if (freezing(current)) {
refrigerator();
return 1;
} else
return 0;
might_sleep();
if (likely(!freezing(current)))
return false;
return __refrigerator();
}

extern bool freeze_task(struct task_struct *p, bool sig_only);
Expand Down Expand Up @@ -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 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_kernel_threads(void) { return -ENOSYS; }
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_count(void) {}
Expand Down
10 changes: 7 additions & 3 deletions kernel/freezer.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ static inline void frozen_process(void)
}

/* 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
processes around? */
bool was_frozen = false;
long save;

task_lock(current);
Expand All @@ -35,7 +36,7 @@ void refrigerator(void)
task_unlock(current);
} else {
task_unlock(current);
return;
return was_frozen;
}
save = current->state;
pr_debug("%s entered refrigerator\n", current->comm);
Expand All @@ -51,6 +52,7 @@ void refrigerator(void)
set_current_state(TASK_UNINTERRUPTIBLE);
if (!frozen(current))
break;
was_frozen = true;
schedule();
}

Expand All @@ -65,8 +67,10 @@ void refrigerator(void)
* synchronization which depends on ordered task state change.
*/
set_current_state(save);

return was_frozen;
}
EXPORT_SYMBOL(refrigerator);
EXPORT_SYMBOL(__refrigerator);

static void fake_signal_wake_up(struct task_struct *p)
{
Expand Down

0 comments on commit a0acae0

Please sign in to comment.