follow_dotdot{,_rcu}(): lift switching nd->path to parent out of loop
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
a6a7eb7628
commit
abc2c632e0
20
fs/namei.c
20
fs/namei.c
|
@ -1365,7 +1365,9 @@ static inline int handle_mounts(struct nameidata *nd, struct dentry *dentry,
|
||||||
|
|
||||||
static int follow_dotdot_rcu(struct nameidata *nd)
|
static int follow_dotdot_rcu(struct nameidata *nd)
|
||||||
{
|
{
|
||||||
|
struct dentry *parent = NULL;
|
||||||
struct inode *inode = nd->inode;
|
struct inode *inode = nd->inode;
|
||||||
|
unsigned seq;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (path_equal(&nd->path, &nd->root)) {
|
if (path_equal(&nd->path, &nd->root)) {
|
||||||
|
@ -1375,15 +1377,12 @@ static int follow_dotdot_rcu(struct nameidata *nd)
|
||||||
}
|
}
|
||||||
if (nd->path.dentry != nd->path.mnt->mnt_root) {
|
if (nd->path.dentry != nd->path.mnt->mnt_root) {
|
||||||
struct dentry *old = nd->path.dentry;
|
struct dentry *old = nd->path.dentry;
|
||||||
struct dentry *parent = old->d_parent;
|
|
||||||
unsigned seq;
|
|
||||||
|
|
||||||
|
parent = old->d_parent;
|
||||||
inode = parent->d_inode;
|
inode = parent->d_inode;
|
||||||
seq = read_seqcount_begin(&parent->d_seq);
|
seq = read_seqcount_begin(&parent->d_seq);
|
||||||
if (unlikely(read_seqcount_retry(&old->d_seq, nd->seq)))
|
if (unlikely(read_seqcount_retry(&old->d_seq, nd->seq)))
|
||||||
return -ECHILD;
|
return -ECHILD;
|
||||||
nd->path.dentry = parent;
|
|
||||||
nd->seq = seq;
|
|
||||||
if (unlikely(!path_connected(nd->path.mnt, parent)))
|
if (unlikely(!path_connected(nd->path.mnt, parent)))
|
||||||
return -ECHILD;
|
return -ECHILD;
|
||||||
break;
|
break;
|
||||||
|
@ -1406,6 +1405,10 @@ static int follow_dotdot_rcu(struct nameidata *nd)
|
||||||
nd->seq = seq;
|
nd->seq = seq;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (likely(parent)) {
|
||||||
|
nd->path.dentry = parent;
|
||||||
|
nd->seq = seq;
|
||||||
|
}
|
||||||
while (unlikely(d_mountpoint(nd->path.dentry))) {
|
while (unlikely(d_mountpoint(nd->path.dentry))) {
|
||||||
struct mount *mounted;
|
struct mount *mounted;
|
||||||
mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry);
|
mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry);
|
||||||
|
@ -1442,7 +1445,7 @@ static void follow_mount(struct path *path)
|
||||||
|
|
||||||
static int follow_dotdot(struct nameidata *nd)
|
static int follow_dotdot(struct nameidata *nd)
|
||||||
{
|
{
|
||||||
struct dentry *parent;
|
struct dentry *parent = NULL;
|
||||||
while (1) {
|
while (1) {
|
||||||
if (path_equal(&nd->path, &nd->root)) {
|
if (path_equal(&nd->path, &nd->root)) {
|
||||||
if (unlikely(nd->flags & LOOKUP_BENEATH))
|
if (unlikely(nd->flags & LOOKUP_BENEATH))
|
||||||
|
@ -1452,13 +1455,10 @@ static int follow_dotdot(struct nameidata *nd)
|
||||||
if (nd->path.dentry != nd->path.mnt->mnt_root) {
|
if (nd->path.dentry != nd->path.mnt->mnt_root) {
|
||||||
/* rare case of legitimate dget_parent()... */
|
/* rare case of legitimate dget_parent()... */
|
||||||
parent = dget_parent(nd->path.dentry);
|
parent = dget_parent(nd->path.dentry);
|
||||||
|
|
||||||
if (unlikely(!path_connected(nd->path.mnt, parent))) {
|
if (unlikely(!path_connected(nd->path.mnt, parent))) {
|
||||||
dput(parent);
|
dput(parent);
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
dput(nd->path.dentry);
|
|
||||||
nd->path.dentry = parent;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!follow_up(&nd->path))
|
if (!follow_up(&nd->path))
|
||||||
|
@ -1466,6 +1466,10 @@ static int follow_dotdot(struct nameidata *nd)
|
||||||
if (unlikely(nd->flags & LOOKUP_NO_XDEV))
|
if (unlikely(nd->flags & LOOKUP_NO_XDEV))
|
||||||
return -EXDEV;
|
return -EXDEV;
|
||||||
}
|
}
|
||||||
|
if (likely(parent)) {
|
||||||
|
dput(nd->path.dentry);
|
||||||
|
nd->path.dentry = parent;
|
||||||
|
}
|
||||||
follow_mount(&nd->path);
|
follow_mount(&nd->path);
|
||||||
nd->inode = nd->path.dentry->d_inode;
|
nd->inode = nd->path.dentry->d_inode;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue