Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933520AbbHJX0o (ORCPT ); Mon, 10 Aug 2015 19:26:44 -0400 Received: from mail-pd0-f180.google.com ([209.85.192.180]:34502 "EHLO mail-pd0-f180.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933302AbbHJX0n (ORCPT ); Mon, 10 Aug 2015 19:26:43 -0400 Date: Tue, 11 Aug 2015 08:26:33 +0900 From: Minchan Kim To: Joonsoo Kim Cc: Sergey Senozhatsky , Andrew Morton , Nitin Gupta , linux-kernel@vger.kernel.org, paulmck@linux.vnet.ibm.com, peterz@infradead.org Subject: Re: [PATCH] zram: fix possible race when checking idle_strm Message-ID: <20150810232633.GA7197@bgram> References: <1438934609-16924-1-git-send-email-iamjoonsoo.kim@lge.com> <20150807091457.GL1891@swordfish> <20150807095816.GP1891@swordfish> <20150810003229.GA26074@js1304-P5Q-DELUXE> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20150810003229.GA26074@js1304-P5Q-DELUXE> User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3632 Lines: 103 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. > > check if idle_strm is empty or not with holding the lock > It is empty so do spin_unlock and run wait_event macro > check if idle_strm is empty or not > It is still empty > > do strm release > call wake_up > > add T1 to wait queue > check if idle_strm is empty or not > compiler reuse '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. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/