summaryrefslogtreecommitdiff
path: root/fs/namei.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2022-07-06 12:40:31 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2022-07-06 12:40:31 -0400
commit6e180327153071281dbbf6a16759e49862debdca (patch)
treebb089c228824d356fc5387e601444a178812a8f3 /fs/namei.c
parent7e4745a09426b3fe63e9fbea3190e0f8500820a4 (diff)
namei: move clearing LOOKUP_RCU towards rcu_read_unlock()
try_to_unlazy()/try_to_unlazy_next() drop LOOKUP_RCU in the very beginning and do rcu_read_unlock() only at the very end. However, nothing done in between even looks at the flag in question; might as well clear it at the same time we unlock. Note that try_to_unlazy_next() used to call legitimize_mnt(), which might drop/regain rcu_read_lock() in some cases. This is no longer true, so we really have rcu_read_lock() held all along until the end. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/fs/namei.c b/fs/namei.c
index e864d5b9eeac..4b7a2147c207 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -665,6 +665,12 @@ static void drop_links(struct nameidata *nd)
}
}
+static void leave_rcu(struct nameidata *nd)
+{
+ nd->flags &= ~LOOKUP_RCU;
+ rcu_read_unlock();
+}
+
static void terminate_walk(struct nameidata *nd)
{
drop_links(nd);
@@ -678,8 +684,7 @@ static void terminate_walk(struct nameidata *nd)
nd->state &= ~ND_ROOT_GRABBED;
}
} else {
- nd->flags &= ~LOOKUP_RCU;
- rcu_read_unlock();
+ leave_rcu(nd);
}
nd->depth = 0;
nd->path.mnt = NULL;
@@ -765,14 +770,13 @@ static bool try_to_unlazy(struct nameidata *nd)
BUG_ON(!(nd->flags & LOOKUP_RCU));
- nd->flags &= ~LOOKUP_RCU;
if (unlikely(!legitimize_links(nd)))
goto out1;
if (unlikely(!legitimize_path(nd, &nd->path, nd->seq)))
goto out;
if (unlikely(!legitimize_root(nd)))
goto out;
- rcu_read_unlock();
+ leave_rcu(nd);
BUG_ON(nd->inode != parent->d_inode);
return true;
@@ -780,7 +784,7 @@ out1:
nd->path.mnt = NULL;
nd->path.dentry = NULL;
out:
- rcu_read_unlock();
+ leave_rcu(nd);
return false;
}
@@ -802,7 +806,6 @@ static bool try_to_unlazy_next(struct nameidata *nd, struct dentry *dentry, unsi
int res;
BUG_ON(!(nd->flags & LOOKUP_RCU));
- nd->flags &= ~LOOKUP_RCU;
if (unlikely(!legitimize_links(nd)))
goto out2;
res = __legitimize_mnt(nd->path.mnt, nd->m_seq);
@@ -831,7 +834,7 @@ static bool try_to_unlazy_next(struct nameidata *nd, struct dentry *dentry, unsi
*/
if (unlikely(!legitimize_root(nd)))
goto out_dput;
- rcu_read_unlock();
+ leave_rcu(nd);
return true;
out2:
@@ -839,10 +842,10 @@ out2:
out1:
nd->path.dentry = NULL;
out:
- rcu_read_unlock();
+ leave_rcu(nd);
return false;
out_dput:
- rcu_read_unlock();
+ leave_rcu(nd);
dput(dentry);
return false;
}