Skip to content

Commit 3bd8bc8

Browse files
author
Al Viro
committed
step_into(): move fetching ->d_inode past handle_mounts()
... and lose messing with it in __follow_mount_rcu() Signed-off-by: Al Viro <[email protected]>
1 parent 4cb6402 commit 3bd8bc8

File tree

1 file changed

+11
-20
lines changed

1 file changed

+11
-20
lines changed

fs/namei.c

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,8 +1474,7 @@ EXPORT_SYMBOL(follow_down);
14741474
* Try to skip to top of mountpoint pile in rcuwalk mode. Fail if
14751475
* we meet a managed dentry that would need blocking.
14761476
*/
1477-
static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
1478-
struct inode **inode)
1477+
static bool __follow_mount_rcu(struct nameidata *nd, struct path *path)
14791478
{
14801479
struct dentry *dentry = path->dentry;
14811480
unsigned int flags = dentry->d_flags;
@@ -1505,13 +1504,6 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
15051504
dentry = path->dentry = mounted->mnt.mnt_root;
15061505
nd->state |= ND_JUMPED;
15071506
nd->next_seq = read_seqcount_begin(&dentry->d_seq);
1508-
*inode = dentry->d_inode;
1509-
/*
1510-
* We don't need to re-check ->d_seq after this
1511-
* ->d_inode read - there will be an RCU delay
1512-
* between mount hash removal and ->mnt_root
1513-
* becoming unpinned.
1514-
*/
15151507
flags = dentry->d_flags;
15161508
// makes sure that non-RCU pathwalk could reach
15171509
// this state.
@@ -1527,7 +1519,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
15271519
}
15281520

15291521
static inline int handle_mounts(struct nameidata *nd, struct dentry *dentry,
1530-
struct path *path, struct inode **inode)
1522+
struct path *path)
15311523
{
15321524
bool jumped;
15331525
int ret;
@@ -1536,12 +1528,7 @@ static inline int handle_mounts(struct nameidata *nd, struct dentry *dentry,
15361528
path->dentry = dentry;
15371529
if (nd->flags & LOOKUP_RCU) {
15381530
unsigned int seq = nd->next_seq;
1539-
*inode = dentry->d_inode;
1540-
if (read_seqcount_retry(&dentry->d_seq, seq))
1541-
return -ECHILD;
1542-
if (unlikely(!*inode))
1543-
return -ENOENT;
1544-
if (likely(__follow_mount_rcu(nd, path, inode)))
1531+
if (likely(__follow_mount_rcu(nd, path)))
15451532
return 0;
15461533
// *path and nd->next_seq might've been clobbered
15471534
path->mnt = nd->path.mnt;
@@ -1561,8 +1548,6 @@ static inline int handle_mounts(struct nameidata *nd, struct dentry *dentry,
15611548
dput(path->dentry);
15621549
if (path->mnt != nd->path.mnt)
15631550
mntput(path->mnt);
1564-
} else {
1565-
*inode = d_backing_inode(path->dentry);
15661551
}
15671552
return ret;
15681553
}
@@ -1843,15 +1828,21 @@ static const char *step_into(struct nameidata *nd, int flags,
18431828
{
18441829
struct path path;
18451830
struct inode *inode;
1846-
int err = handle_mounts(nd, dentry, &path, &inode);
1831+
int err = handle_mounts(nd, dentry, &path);
18471832

18481833
if (err < 0)
18491834
return ERR_PTR(err);
1835+
inode = path.dentry->d_inode;
18501836
if (likely(!d_is_symlink(path.dentry)) ||
18511837
((flags & WALK_TRAILING) && !(nd->flags & LOOKUP_FOLLOW)) ||
18521838
(flags & WALK_NOFOLLOW)) {
18531839
/* not a symlink or should not follow */
1854-
if (!(nd->flags & LOOKUP_RCU)) {
1840+
if (nd->flags & LOOKUP_RCU) {
1841+
if (read_seqcount_retry(&path.dentry->d_seq, nd->next_seq))
1842+
return ERR_PTR(-ECHILD);
1843+
if (unlikely(!inode))
1844+
return ERR_PTR(-ENOENT);
1845+
} else {
18551846
dput(nd->path.dentry);
18561847
if (nd->path.mnt != path.mnt)
18571848
mntput(nd->path.mnt);

0 commit comments

Comments
 (0)