forked from Minki/linux
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: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: <linux-fsdevel@vger.kernel.org>
This commit is contained in:
parent
cb7e125e03
commit
7088efa913
10
fs/dcache.c
10
fs/dcache.c
@ -1636,8 +1636,7 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
|
||||
dname[name->len] = 0;
|
||||
|
||||
/* Make sure we always see the terminating NUL character */
|
||||
smp_wmb();
|
||||
dentry->d_name.name = dname;
|
||||
smp_store_release(&dentry->d_name.name, dname); /* ^^^ */
|
||||
|
||||
dentry->d_lockref.count = 1;
|
||||
dentry->d_flags = 0;
|
||||
@ -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
|
||||
* due to mismatched pointer and length will be discarded.
|
||||
*
|
||||
* Data dependency barrier is needed to make sure that we see that terminating
|
||||
* NUL. Alpha strikes again, film at 11...
|
||||
* Load acquire is needed to make sure that we see that terminating NUL.
|
||||
*/
|
||||
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);
|
||||
char *p;
|
||||
|
||||
smp_read_barrier_depends();
|
||||
|
||||
*buflen -= dlen + 1;
|
||||
if (*buflen < 0)
|
||||
return -ENAMETOOLONG;
|
||||
|
Loading…
Reference in New Issue
Block a user