Commit a03e283b authored by Eric W. Biederman's avatar Eric W. Biederman Committed by Al Viro

dcache: Reduce the scope of i_lock in d_splice_alias

i_lock is only needed until __d_find_any_alias calls dget on the alias
dentry.  After that the reference to new ensures that dentry_kill and
d_delete will not remove the inode from the dentry, and remove the
dentry from the inode->d_entry list.

The inode i_lock came to be held over the the __d_move calls in
d_splice_alias through a series of introduction of locks with
increasing smaller scope.  First it was the dcache_lock, then
it was the dcache_inode_lock, and finally inode->i_lock.

Furthermore inode->i_lock is not held over any other calls
to d_move or __d_move so it can not provide any meaningful
rename protection.
Signed-off-by: default avatar"Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent cde93be4
...@@ -2718,7 +2718,7 @@ struct dentry *d_ancestor(struct dentry *p1, struct dentry *p2) ...@@ -2718,7 +2718,7 @@ struct dentry *d_ancestor(struct dentry *p1, struct dentry *p2)
* This helper attempts to cope with remotely renamed directories * This helper attempts to cope with remotely renamed directories
* *
* It assumes that the caller is already holding * It assumes that the caller is already holding
* dentry->d_parent->d_inode->i_mutex, inode->i_lock and rename_lock * dentry->d_parent->d_inode->i_mutex, and rename_lock
* *
* Note: If ever the locking in lock_rename() changes, then please * Note: If ever the locking in lock_rename() changes, then please
* remember to update this too... * remember to update this too...
...@@ -2744,7 +2744,6 @@ static int __d_unalias(struct inode *inode, ...@@ -2744,7 +2744,6 @@ static int __d_unalias(struct inode *inode,
__d_move(alias, dentry, false); __d_move(alias, dentry, false);
ret = 0; ret = 0;
out_err: out_err:
spin_unlock(&inode->i_lock);
if (m2) if (m2)
mutex_unlock(m2); mutex_unlock(m2);
if (m1) if (m1)
...@@ -2790,10 +2789,11 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) ...@@ -2790,10 +2789,11 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
if (S_ISDIR(inode->i_mode)) { if (S_ISDIR(inode->i_mode)) {
struct dentry *new = __d_find_any_alias(inode); struct dentry *new = __d_find_any_alias(inode);
if (unlikely(new)) { if (unlikely(new)) {
/* The reference to new ensures it remains an alias */
spin_unlock(&inode->i_lock);
write_seqlock(&rename_lock); write_seqlock(&rename_lock);
if (unlikely(d_ancestor(new, dentry))) { if (unlikely(d_ancestor(new, dentry))) {
write_sequnlock(&rename_lock); write_sequnlock(&rename_lock);
spin_unlock(&inode->i_lock);
dput(new); dput(new);
new = ERR_PTR(-ELOOP); new = ERR_PTR(-ELOOP);
pr_warn_ratelimited( pr_warn_ratelimited(
...@@ -2812,7 +2812,6 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry) ...@@ -2812,7 +2812,6 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
} else { } else {
__d_move(new, dentry, false); __d_move(new, dentry, false);
write_sequnlock(&rename_lock); write_sequnlock(&rename_lock);
spin_unlock(&inode->i_lock);
security_d_instantiate(new, inode); security_d_instantiate(new, inode);
} }
iput(inode); iput(inode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment