exportfs: clear DISCONNECTED on all parents sooner
Once we've found any connected parent, we know all our parents are connected--that's true even if there's a concurrent rename. May as well clear them all at once and be done with it. Reviewed-by: Cristoph Hellwig <hch@lst.de> Signed-off-by: J. Bruce Fields <bfields@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
78cee9a8e4
commit
0dbc018a49
1 changed files with 21 additions and 4 deletions
|
@ -90,6 +90,24 @@ find_disconnected_root(struct dentry *dentry)
|
||||||
return dentry;
|
return dentry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void clear_disconnected(struct dentry *dentry)
|
||||||
|
{
|
||||||
|
dget(dentry);
|
||||||
|
while (dentry->d_flags & DCACHE_DISCONNECTED) {
|
||||||
|
struct dentry *parent = dget_parent(dentry);
|
||||||
|
|
||||||
|
WARN_ON_ONCE(IS_ROOT(dentry));
|
||||||
|
|
||||||
|
spin_lock(&dentry->d_lock);
|
||||||
|
dentry->d_flags &= ~DCACHE_DISCONNECTED;
|
||||||
|
spin_unlock(&dentry->d_lock);
|
||||||
|
|
||||||
|
dput(dentry);
|
||||||
|
dentry = parent;
|
||||||
|
}
|
||||||
|
dput(dentry);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure target_dir is fully connected to the dentry tree.
|
* Make sure target_dir is fully connected to the dentry tree.
|
||||||
*
|
*
|
||||||
|
@ -128,10 +146,9 @@ reconnect_path(struct vfsmount *mnt, struct dentry *target_dir, char *nbuf)
|
||||||
|
|
||||||
if (!IS_ROOT(pd)) {
|
if (!IS_ROOT(pd)) {
|
||||||
/* must have found a connected parent - great */
|
/* must have found a connected parent - great */
|
||||||
spin_lock(&pd->d_lock);
|
clear_disconnected(target_dir);
|
||||||
pd->d_flags &= ~DCACHE_DISCONNECTED;
|
dput(pd);
|
||||||
spin_unlock(&pd->d_lock);
|
break;
|
||||||
noprogress = 0;
|
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* We have hit the top of a disconnected path, try to
|
* We have hit the top of a disconnected path, try to
|
||||||
|
|
Loading…
Add table
Reference in a new issue