From 165200d6cb88a3cc1fdeb12e11e97fb96bf685d9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 28 Feb 2020 10:17:52 -0500 Subject: follow_dotdot(): be lazy about changing nd->path Change nd->path only after the loop is done and only in case we hadn't ended up finding ourselves in root. Same for NO_XDEV check. That separates the "check how far back do we need to go through the mount stack" logics from the rest of .. traversal. NOTE: path_get/path_put introduced here are temporary. They will go away later in the series. Signed-off-by: Al Viro --- fs/namei.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'fs/namei.c') diff --git a/fs/namei.c b/fs/namei.c index af18ede95e2d..9cfb7096e307 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1748,16 +1748,24 @@ static struct dentry *follow_dotdot(struct nameidata *nd, if (path_equal(&nd->path, &nd->root)) goto in_root; if (unlikely(nd->path.dentry == nd->path.mnt->mnt_root)) { + struct path path = nd->path; + path_get(&path); while (1) { - if (!follow_up(&nd->path)) + if (!follow_up(&path)) { + path_put(&path); goto in_root; - if (unlikely(nd->flags & LOOKUP_NO_XDEV)) - return ERR_PTR(-EXDEV); - if (path_equal(&nd->path, &nd->root)) + } + if (path_equal(&path, &nd->root)) { + path_put(&path); goto in_root; - if (nd->path.dentry != nd->path.mnt->mnt_root) + } + if (path.dentry != nd->path.mnt->mnt_root) break; } + path_put(&nd->path); + nd->path = path; + if (unlikely(nd->flags & LOOKUP_NO_XDEV)) + return ERR_PTR(-EXDEV); } /* rare case of legitimate dget_parent()... */ parent = dget_parent(nd->path.dentry); -- cgit