diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-09-29 20:54:27 +0200 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-10-09 08:38:41 +0200 |
commit | 8d85b4845a668d9a72649005c5aa932657311bd4 (patch) | |
tree | 47d8ce0b4836404030837c8ad3abb28e047ad594 /fs/cifs/smb2transport.c | |
parent | missing data dependency barrier in prepend_name() (diff) | |
download | linux-8d85b4845a668d9a72649005c5aa932657311bd4.tar.xz linux-8d85b4845a668d9a72649005c5aa932657311bd4.zip |
Allow sharing external names after __d_move()
* external dentry names get a small structure prepended to them
(struct external_name).
* it contains an atomic refcount, matching the number of struct dentry
instances that have ->d_name.name pointing to that external name. The
first thing free_dentry() does is decrementing refcount of external name,
so the instances that are between the call of free_dentry() and
RCU-delayed actual freeing do not contribute.
* __d_move(x, y, false) makes the name of x equal to the name of y,
external or not. If y has an external name, extra reference is grabbed
and put into x->d_name.name. If x used to have an external name, the
reference to the old name is dropped and, should it reach zero, freeing
is scheduled via kfree_rcu().
* free_dentry() in dentry with external name decrements the refcount of
that name and, should it reach zero, does RCU-delayed call that will
free both the dentry and external name. Otherwise it does what it
used to do, except that __d_free() doesn't even look at ->d_name.name;
it simply frees the dentry.
All non-RCU accesses to dentry external name are safe wrt freeing since they
all should happen before free_dentry() is called. RCU accesses might run
into a dentry seen by free_dentry() or into an old name that got already
dropped by __d_move(); however, in both cases dentry must have been
alive and refer to that name at some point after we'd done rcu_read_lock(),
which means that any freeing must be still pending.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/cifs/smb2transport.c')
0 files changed, 0 insertions, 0 deletions