提交 7088efa9 编写于 作者: P Paul E. McKenney

fs/dcache: Use release-acquire for name/length update

The code in __d_alloc() carefully orders filling in the NUL character
of the name (and the length, hash, and the name itself) with assigning
of the name itself.  However, prepend_name() does not order the accesses
to the ->name and ->len fields, other than on TSO systems.  This commit
therefore replaces prepend_name()'s READ_ONCE() of ->name with an
smp_load_acquire(), which orders against the subsequent READ_ONCE() of
->len.  Because READ_ONCE() now incorporates smp_read_barrier_depends(),
prepend_name()'s smp_read_barrier_depends() is removed.  Finally,
to save a line, the smp_wmb()/store pair in __d_alloc() is replaced
by smp_store_release().
Signed-off-by: NPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: <linux-fsdevel@vger.kernel.org>
上级 cb7e125e
...@@ -1636,8 +1636,7 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name) ...@@ -1636,8 +1636,7 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
dname[name->len] = 0; dname[name->len] = 0;
/* Make sure we always see the terminating NUL character */ /* Make sure we always see the terminating NUL character */
smp_wmb(); smp_store_release(&dentry->d_name.name, dname); /* ^^^ */
dentry->d_name.name = dname;
dentry->d_lockref.count = 1; dentry->d_lockref.count = 1;
dentry->d_flags = 0; dentry->d_flags = 0;
...@@ -3047,17 +3046,14 @@ static int prepend(char **buffer, int *buflen, const char *str, int namelen) ...@@ -3047,17 +3046,14 @@ static int prepend(char **buffer, int *buflen, const char *str, int namelen)
* retry it again when a d_move() does happen. So any garbage in the buffer * retry it again when a d_move() does happen. So any garbage in the buffer
* due to mismatched pointer and length will be discarded. * due to mismatched pointer and length will be discarded.
* *
* Data dependency barrier is needed to make sure that we see that terminating * Load acquire is needed to make sure that we see that terminating NUL.
* NUL. Alpha strikes again, film at 11...
*/ */
static int prepend_name(char **buffer, int *buflen, const struct qstr *name) static int prepend_name(char **buffer, int *buflen, const struct qstr *name)
{ {
const char *dname = READ_ONCE(name->name); const char *dname = smp_load_acquire(&name->name); /* ^^^ */
u32 dlen = READ_ONCE(name->len); u32 dlen = READ_ONCE(name->len);
char *p; char *p;
smp_read_barrier_depends();
*buflen -= dlen + 1; *buflen -= dlen + 1;
if (*buflen < 0) if (*buflen < 0)
return -ENAMETOOLONG; return -ENAMETOOLONG;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册