From: Minchan Kim <minchan@kernel.org>
To: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>,
Andrew Morton <akpm@linux-foundation.org>,
Nitin Gupta <ngupta@vflare.org>,
linux-kernel@vger.kernel.org, paulmck@linux.vnet.ibm.com,
peterz@infradead.org
Subject: Re: [PATCH] zram: fix possible race when checking idle_strm
Date: Tue, 11 Aug 2015 08:26:33 +0900 [thread overview]
Message-ID: <20150810232633.GA7197@bgram> (raw)
In-Reply-To: <20150810003229.GA26074@js1304-P5Q-DELUXE>
Hi Joonsoo,
On Mon, Aug 10, 2015 at 09:32:30AM +0900, Joonsoo Kim wrote:
> On Fri, Aug 07, 2015 at 06:58:16PM +0900, Sergey Senozhatsky wrote:
> > On (08/07/15 18:14), Sergey Senozhatsky wrote:
> > > hm... I need to think about it more.
> > >
> > > we do wake_up every time we put stream back to the list
> > >
> > > zcomp_strm_multi_release():
> > >
> > > spin_lock(&zs->strm_lock);
> > > if (zs->avail_strm <= zs->max_strm) {
> > > list_add(&zstrm->list, &zs->idle_strm);
> > > spin_unlock(&zs->strm_lock);
> > > wake_up(&zs->strm_wait);
> > > return;
> > > }
> > >
> > >
> > > but I can probably see what you mean... in some very extreme case,
> > > though. I can't even formulate it... eh... we use a multi stream
> > > backend with ->max_strm == 1 and there are two processes, one
> > > just falsely passed the wait_event() `if (condition)' check, the
> > > other one just put stream back to ->idle_strm and called wake_up(),
> > > but the first process hasn't yet executed prepare_to_wait_event()
> > > so it might miss a wakeup. and there should be no other process
> > > doing read or write operation. otherwise, there will be wakeup
> > > eventually.
> > >
> > > is this the case you were thinking of?... then yes, this spinlock
> > > may help.
> > >
> >
> > on the other hand... it's actually
> >
> > wait_event() is
> >
> > if (condition)
> > break;
> > prepare_to_wait_event(&wq, &__wait, state)
> > if (condition)
> > break;
> > schedule();
> >
> > if first condition check was false and we missed a wakeup call between
> > first condition and prepare_to_wait_event(), then second condition
> > check should do the trick I think (or you expect that second condition
> > check may be wrongly pre-fetched or something).
>
> Hello, Sergey.
>
> This is what I thought.
> I expected that second condition can be false if compiler reuse result
> of first check for optimization. I guess that there is no prevention
> for this kind of optimization.
>
> So, following is the problem sequence I thought.
> T1 means thread 1, T2 means another thread, 2.
>
> <T1-1> check if idle_strm is empty or not with holding the lock
> <T1-2> It is empty so do spin_unlock and run wait_event macro
> <T1-3> check if idle_strm is empty or not
> <T1-4> It is still empty
>
> <T2-1> do strm release
> <T2-2> call wake_up
>
> <T1-5> add T1 to wait queue
> <T1-6> check if idle_strm is empty or not
> <T1-7> compiler reuse <T1-4>'s result or CPU just fetch cached
> result so T1 starts waiting
>
> In this case, T1 can be sleep permanently. To prevent compiler
> optimization or fetching cached value, we need a lock here.
When I read Documentation/memory-barrier.txt, it shouldn't happen.
"All memory barriers except the data dependency barriers imply a compiler
barrier. Data dependencies do not impose any additional compiler ordering."
"SLEEP AND WAKE-UP FUNCTIONS
---------------------------
Sleeping and waking on an event flagged in global data ...
...
...
...
A general memory barrier is interpolated automatically by set_current_state()
after it has altered the task state:"
So I think your T1-7 assumption is not true.
As well, there are many examples under drivers/ to use the global data
as event flag without locking or atomic.
Just in case, Ccing Paul and Peter.
next prev parent reply other threads:[~2015-08-10 23:26 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-08-07 8:03 [PATCH] zram: fix possible race when checking idle_strm Joonsoo Kim
2015-08-07 9:14 ` Sergey Senozhatsky
2015-08-07 9:19 ` Sergey Senozhatsky
2015-08-07 9:38 ` Sergey Senozhatsky
2015-08-07 9:58 ` Sergey Senozhatsky
2015-08-10 0:32 ` Joonsoo Kim
2015-08-10 2:16 ` Sergey Senozhatsky
2015-08-11 8:26 ` Joonsoo Kim
2015-08-10 23:26 ` Minchan Kim [this message]
2015-08-11 8:25 ` Joonsoo Kim
2015-08-11 8:25 ` Sergey Senozhatsky
2015-08-07 9:37 ` Sergey Senozhatsky
2015-08-07 10:16 ` Sergey Senozhatsky
2015-08-07 14:49 ` Minchan Kim
2015-08-10 0:35 ` Joonsoo Kim
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=20150810232633.GA7197@bgram \
--to=minchan@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=iamjoonsoo.kim@lge.com \
--cc=linux-kernel@vger.kernel.org \
--cc=ngupta@vflare.org \
--cc=paulmck@linux.vnet.ibm.com \
--cc=peterz@infradead.org \
--cc=sergey.senozhatsky.work@gmail.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.