All of lore.kernel.org
 help / color / mirror / Atom feed
From: Al Viro <viro@ZenIV.linux.org.uk>
To: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Cc: Miklos Szeredi <miklos@szeredi.hu>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Linux-Fsdevel <linux-fsdevel@vger.kernel.org>,
	Kernel Mailing List <linux-kernel@vger.kernel.org>,
	linux-unionfs@vger.kernel.org
Subject: Re: [GIT PULL] overlay filesystem v25
Date: Mon, 27 Oct 2014 17:28:01 +0000	[thread overview]
Message-ID: <20141027172800.GW7996@ZenIV.linux.org.uk> (raw)
In-Reply-To: <20141027155901.GE5718@linux.vnet.ibm.com>

On Mon, Oct 27, 2014 at 08:59:01AM -0700, Paul E. McKenney wrote:

> Indeed, life is hard here.  Keep in mind that lock acquisition is not
> guaranteed to prevent prior operations from being reordered into the
> critical section, possibly as follows:
> 
> 	CPU1:
> 	  grab lock
> 	  if (!global)
> 	      global = p;
> 	  /* Assume all of CPU2's accesses happen here. */
> 	  p->foo = 1;

A bit of context: p is a local pointer to struct file here and alloc is
opening it...

> This clearly allows CPU2 to execute as follows:
> 
> 	CPU2:
> 	  p = global; /* gets p */
> 	  if (p) /* non-NULL */
> 	  	q = p->foo; /* might not be 1 */
> 
> Not only that, on DEC Alpha, even if CPU1's accesses are ordered, CPU2's
> accesses can be misordered.  You need rcu_dereference() or the combination
> of ACCESS_ONCE() and smp_read_barrier_depends() to avoid this issue.
> As always, see http://www.openvms.compaq.com/wizard/wiz_2637.html for
> more info.
> 
> So no, there is no guarantee.  I am assuming that the lock grabbed by
> CPU1 guards all assignments to "global", otherwise the code needs further
> help.  I am further assuming that the memory pointed to by CPU1's "p"
> is inaccessible to any other CPU, as in CPU1 just allocated the memory.
> Otherwise, the assignment "p->foo = 1" is questionable.  And finally,
> I am assuming that p->foo stays constant once it has been made
> accessible to readers.
> 
> But the following should work:
> 
> 	CPU1:
> 	  p->foo = 1;  /* Assumes p is local. */
> 	  smp_mb__before_spinlock();
> 	  grab lock
> 	  if (!global)  /* Assumes lock protects all assignments to global. */
> 	      global = p;
> 
> 	CPU2:
> 	  p = rcu_dereference(global);
> 	  if (p)
> 	     q = p->foo; /* Assumes p->foo constant once visible to readers. */
> 	     		 /* Also assumes p and q are local. */
> 
> If the assumptions called out in the comments do not hold, you at least
> need ACCESS_ONCE(), and perhaps even more synchronization.  For more info
> on ACCESS_ONCE(), Jon's LWN article is at http://lwn.net/Articles/508991/.

First of all, this "p->foo = 1" is a shorthand for initialization of
struct file done by opening a file.  What you are saying is that it
can leak past the point where we stick a pointer to freshly opened
file into a place where another CPU can see it, but not past the
barrier in dropping the lock, right?

And you are suggesting rcu_dereference() as a way to bring the required
barriers in.  Ouch...  The names are really bad, but there's another
fun issue - rcu_dereference brings in sparse noise.  Wouldn't direct use
of smp_read_barrier_depends() be cleaner, anyway?

  reply	other threads:[~2014-10-27 17:28 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-23 23:25 [GIT PULL] overlay filesystem v25 Miklos Szeredi
2014-10-24  2:20 ` Al Viro
2014-10-24  3:24   ` Al Viro
2014-10-24  7:24     ` Miklos Szeredi
2014-10-25  8:18       ` Al Viro
2014-10-25  9:53         ` Miklos Szeredi
2014-10-25 17:06           ` Al Viro
2014-10-27  8:06             ` Miklos Szeredi
2014-10-27 15:59               ` Paul E. McKenney
2014-10-27 17:28                 ` Al Viro [this message]
2014-10-27 17:36                   ` Paul E. McKenney
2014-10-28  1:12                     ` Al Viro
2014-10-28  4:11                       ` Paul E. McKenney
2014-10-28 22:55                         ` Al Viro
2014-10-28 23:25                           ` Paul E. McKenney
2014-10-24  7:28     ` Geert Uytterhoeven

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=20141027172800.GW7996@ZenIV.linux.org.uk \
    --to=viro@zeniv.linux.org.uk \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-unionfs@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=paulmck@linux.vnet.ibm.com \
    --cc=torvalds@linux-foundation.org \
    /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.