md/raid1,raid10: silence warning about wait-within-wait

If you prepare_to_wait() after a previous prepare_to_wait(),
but before calling schedule(), you get warning:

  do not call blocking ops when !TASK_RUNNING; state=2

This is appropriate as it is often a bug.  The event that the
first prepare_to_wait() expects might wake up the schedule following
the second prepare_to_wait(), which could be confusing.

However if both prepare_to_wait()s are part of simple wait_event()
loops, and if the inner one is rarely called, then there is
no problem.  The inner loop is too simple to get confused by
a stray wakeup, and the outer loop won't spin unduly because the
inner doesnt affect it often.

This pattern occurs in both raid1.c and raid10.c in the use of
flush_pending_writes().

The warning can be silenced by setting current->state to TASK_RUNNING.

Signed-off-by: NeilBrown <neilb@suse.com>
Signed-off-by: Shaohua Li <shli@fb.com>
This commit is contained in:
NeilBrown 2017-12-04 08:21:04 +11:00 коммит произвёл Shaohua Li
Родитель d5d885fd51
Коммит 474beb575c
2 изменённых файлов: 23 добавлений и 0 удалений

Просмотреть файл

@ -815,6 +815,17 @@ static void flush_pending_writes(struct r1conf *conf)
bio = bio_list_get(&conf->pending_bio_list); bio = bio_list_get(&conf->pending_bio_list);
conf->pending_count = 0; conf->pending_count = 0;
spin_unlock_irq(&conf->device_lock); spin_unlock_irq(&conf->device_lock);
/*
* As this is called in a wait_event() loop (see freeze_array),
* current->state might be TASK_UNINTERRUPTIBLE which will
* cause a warning when we prepare to wait again. As it is
* rare that this path is taken, it is perfectly safe to force
* us to go around the wait_event() loop again, so the warning
* is a false-positive. Silence the warning by resetting
* thread state
*/
__set_current_state(TASK_RUNNING);
blk_start_plug(&plug); blk_start_plug(&plug);
flush_bio_list(conf, bio); flush_bio_list(conf, bio);
blk_finish_plug(&plug); blk_finish_plug(&plug);

Просмотреть файл

@ -900,6 +900,18 @@ static void flush_pending_writes(struct r10conf *conf)
bio = bio_list_get(&conf->pending_bio_list); bio = bio_list_get(&conf->pending_bio_list);
conf->pending_count = 0; conf->pending_count = 0;
spin_unlock_irq(&conf->device_lock); spin_unlock_irq(&conf->device_lock);
/*
* As this is called in a wait_event() loop (see freeze_array),
* current->state might be TASK_UNINTERRUPTIBLE which will
* cause a warning when we prepare to wait again. As it is
* rare that this path is taken, it is perfectly safe to force
* us to go around the wait_event() loop again, so the warning
* is a false-positive. Silence the warning by resetting
* thread state
*/
__set_current_state(TASK_RUNNING);
blk_start_plug(&plug); blk_start_plug(&plug);
/* flush any pending bitmap writes to disk /* flush any pending bitmap writes to disk
* before proceeding w/ I/O */ * before proceeding w/ I/O */