nilfs2: refactor nilfs_segctor_thread()

Simplify nilfs_segctor_thread(), the main loop function of the log writer
thread, to make the basic structure easier to understand.

In particular, the acquisition and release of the sc_state_lock spinlock
was scattered throughout the function, so extract the determination of
whether log writing is required into a helper function and make the
spinlock lock sections clearer.

Link: https://lkml.kernel.org/r/20240826174116.5008-9-konishi.ryusuke@gmail.com
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Cc: Huang Xiaojia <huangxiaojia2@huawei.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Ryusuke Konishi 2024-08-27 02:41:16 +09:00 committed by Andrew Morton
parent 3f66cc261c
commit 74b0099340

View File

@ -2627,6 +2627,32 @@ static int nilfs_segctor_flush_mode(struct nilfs_sc_info *sci)
return SC_LSEG_SR;
}
/**
* nilfs_log_write_required - determine whether log writing is required
* @sci: nilfs_sc_info struct
* @modep: location for storing log writing mode
*
* Return: true if log writing is required, false otherwise. If log writing
* is required, the mode is stored in the location pointed to by @modep.
*/
static bool nilfs_log_write_required(struct nilfs_sc_info *sci, int *modep)
{
bool timedout, ret = true;
spin_lock(&sci->sc_state_lock);
timedout = ((sci->sc_state & NILFS_SEGCTOR_COMMIT) &&
time_after_eq(jiffies, sci->sc_timer.expires));
if (timedout || sci->sc_seq_request != sci->sc_seq_done)
*modep = SC_LSEG_SR;
else if (sci->sc_flush_request)
*modep = nilfs_segctor_flush_mode(sci);
else
ret = false;
spin_unlock(&sci->sc_state_lock);
return ret;
}
/**
* nilfs_segctor_thread - main loop of the log writer thread
* @arg: pointer to a struct nilfs_sc_info.
@ -2642,70 +2668,39 @@ static int nilfs_segctor_thread(void *arg)
{
struct nilfs_sc_info *sci = (struct nilfs_sc_info *)arg;
struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
int timeout = 0;
nilfs_info(sci->sc_super,
"segctord starting. Construction interval = %lu seconds, CP frequency < %lu seconds",
sci->sc_interval / HZ, sci->sc_mjcp_freq / HZ);
set_freezable();
spin_lock(&sci->sc_state_lock);
loop:
for (;;) {
while (!kthread_should_stop()) {
DEFINE_WAIT(wait);
bool should_write;
int mode;
if (kthread_should_stop())
goto end_thread;
if (timeout || sci->sc_seq_request != sci->sc_seq_done)
mode = SC_LSEG_SR;
else if (sci->sc_flush_request)
mode = nilfs_segctor_flush_mode(sci);
else
break;
spin_unlock(&sci->sc_state_lock);
nilfs_segctor_thread_construct(sci, mode);
spin_lock(&sci->sc_state_lock);
timeout = 0;
}
if (freezing(current)) {
spin_unlock(&sci->sc_state_lock);
try_to_freeze();
spin_lock(&sci->sc_state_lock);
} else {
DEFINE_WAIT(wait);
int should_sleep = 1;
if (freezing(current)) {
try_to_freeze();
continue;
}
prepare_to_wait(&sci->sc_wait_daemon, &wait,
TASK_INTERRUPTIBLE);
if (sci->sc_seq_request != sci->sc_seq_done)
should_sleep = 0;
else if (sci->sc_flush_request)
should_sleep = 0;
else if (sci->sc_state & NILFS_SEGCTOR_COMMIT)
should_sleep = time_before(jiffies,
sci->sc_timer.expires);
if (should_sleep) {
spin_unlock(&sci->sc_state_lock);
should_write = nilfs_log_write_required(sci, &mode);
if (!should_write)
schedule();
spin_lock(&sci->sc_state_lock);
}
finish_wait(&sci->sc_wait_daemon, &wait);
timeout = ((sci->sc_state & NILFS_SEGCTOR_COMMIT) &&
time_after_eq(jiffies, sci->sc_timer.expires));
if (nilfs_sb_dirty(nilfs) && nilfs_sb_need_update(nilfs))
set_nilfs_discontinued(nilfs);
}
goto loop;
end_thread:
if (should_write)
nilfs_segctor_thread_construct(sci, mode);
}
/* end sync. */
spin_lock(&sci->sc_state_lock);
sci->sc_task = NULL;
timer_shutdown_sync(&sci->sc_timer);
spin_unlock(&sci->sc_state_lock);