Linux-mtd Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Zhihao Cheng <chengzhihao1@huawei.com>
To: Richard Weinberger <richard.weinberger@gmail.com>
Cc: Richard Weinberger <richard@nod.at>,
	linux-mtd@lists.infradead.org,
	LKML <linux-kernel@vger.kernel.org>,
	"zhangyi \(F\)" <yi.zhang@huawei.com>
Subject: Re: [PATCH] ubi: check kthread_should_stop() after the setting of task state
Date: Wed, 5 Aug 2020 10:23:17 +0800	[thread overview]
Message-ID: <2086f822-e67a-43e4-76d8-5339eaccd3ac@huawei.com> (raw)
In-Reply-To: <CAFLxGvycs7DNu5o5QY1WwTPfS6cTTykTh-91n9TQZ7yP_ADr4A@mail.gmail.com>

在 2020/8/5 5:56, Richard Weinberger 写道:
> On Tue, Aug 4, 2020 at 4:58 AM Zhihao Cheng <chengzhihao1@huawei.com> wrote:
>> Oh, you're thinking about influence by schedule(), I get it. But I think
>> it still works. Because the ubi_thread is still on runqueue, it will be
>> scheduled to execute later anyway.
> It will not get woken. This is the problem.
>
>> op                                                    state of
>> ubi_thread           on runqueue
>> set_current_state(TASK_INTERRUPTIBLE) TASK_INTERRUPTIBLE              Yes
>> if (kthread_should_stop()) // not satisfy
>> TASK_INTERRUPTIBLE              Yes
>> kthread_stop:
>>     wake_up_process
>>       ttwu_queue
>>         ttwu_do_activate
>>           ttwu_do_wakeup TASK_RUNNING                       Yes
>> schedule
>>     __schedule(false)
>>
>>    // prev->state is TASK_RUNNING, so we cannot move it from runqueue by
>> deactivate_task(). So just pick next task to execute, ubi_thread is
>> still on runqueue and will be scheduled to execute later.
> It will be in state TASK_RUNNING only if your check is reached.
>
> If kthread_stop() is called *before* your code:
> +                       if (kthread_should_stop()) {
> +                               set_current_state(TASK_RUNNING);
> +                               break;
> +                       }
>
> ...everything is fine.
> But there is still a race window between your if
> (kthread_should_stop()) and schedule() in the next line.
> So if kthread_stop() is called right *after* the if and *before*
> schedule(), the task state is still TASK_INTERRUPTIBLE
> --> schedule() will not return unless the task is explicitly woken,
> which does not happen.
Er, I can't get the point. I can list two possible situations, did I 
miss other situations?

P1:ubi_thread
   set_current_state(TASK_INTERRUPTIBLE)
   if (kthread_should_stop()) {
     set_current_state(TASK_RUNNING)
     break
   }
   schedule()                            -> don't *remove* task from 
runqueue if *TASK_RUNNING*, removing operation is protected by rq_lock

P2:kthread_stop
   set_bit(KTHREAD_SHOULD_STOP, &kthread->flags)
   wake_up_process(k)             -> enqueue task & set *TASK_RUNNING*, 
these two operations are protected by rq_lock
   wait_for_completion(&kthread->exited)


Situation 1:
P1_set_current_state               on-rq, TASK_RUNNING -> TASK_INTERRUPTIBLE
P1_kthread_should_stop        on-rq, TASK_INTERRUPTIBLE
P2_set_bit                               on-rq, TASK_INTERRUPTIBLE , 
KTHREAD_SHOULD_STOP
P2_wake_up_process             on-rq, TASK_INTERRUPTIBLE -> TASK_RUNNING 
, KTHREAD_SHOULD_STOP
P1_schedule                           on-rq, TASK_RUNNING , 
KTHREAD_SHOULD_STOP
P2_wait_for_completion        // wait for P1 exit

Situation 2:
P1_set_current_state             on-rq, TASK_RUNNING -> TASK_INTERRUPTIBLE
P1_kthread_should_stop       on-rq, TASK_INTERRUPTIBLE
P2_set_bit                             on-rq, TASK_INTERRUPTIBLE , 
KTHREAD_SHOULD_STOP
P1_schedule                          off-rq, TASK_INTERRUPTIBLE , 
KTHREAD_SHOULD_STOP
P2_wake_up_process             on-rq, TASK_INTERRUPTIBLE -> TASK_RUNNING 
, KTHREAD_SHOULD_STOP
P2_wait_for_completion       // wait for P1 exit
> Before your patch, the race window was much larger, I fully agree, but
> your patch does not cure the problem
> it just makes it harder to hit.
>
> And using mdelay() to verify such a thing is also tricky because
> mdelay() will influence the task state.
>



______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

  reply	other threads:[~2020-08-05  2:24 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-01  9:12 [PATCH] ubi: check kthread_should_stop() after the setting of task state Zhihao Cheng
2020-08-02 21:25 ` Richard Weinberger
2020-08-03  2:01   ` Zhihao Cheng
2020-08-03 22:11     ` Richard Weinberger
2020-08-04  2:58       ` Zhihao Cheng
2020-08-04 21:56         ` Richard Weinberger
2020-08-05  2:23           ` Zhihao Cheng [this message]
2020-08-06 20:15             ` Richard Weinberger
2020-08-07  2:18               ` Zhihao Cheng
2020-08-07 19:29                 ` Richard Weinberger
2020-08-08  3:26                   ` Zhihao Cheng
2020-09-13 18:48                     ` Richard Weinberger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2086f822-e67a-43e4-76d8-5339eaccd3ac@huawei.com \
    --to=chengzhihao1@huawei.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=richard.weinberger@gmail.com \
    --cc=richard@nod.at \
    --cc=yi.zhang@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox