A root directory is a directory that has itself as the parent. There is only one such directory, but for chroot support we will want to stop path resolution at a non-root directory as well.
We do this by giving struct nameidata a d_root field, which serves as a root directory for the lookup. As we initialize it to the global root directory, this introduces no functional change. Signed-off-by: Ahmad Fatoum <a.fat...@pengutronix.de> --- fs/fs.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/fs/fs.c b/fs/fs.c index 54f38aa2e63b..7fc638451f13 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -1623,6 +1623,7 @@ struct nameidata { } *stack, internal[EMBEDDED_LEVELS]; struct filename *name; struct inode *link_inode; + struct dentry *d_root; }; struct filename { @@ -1635,6 +1636,7 @@ static void set_nameidata(struct nameidata *p, struct filename *name) p->stack = p->internal; p->name = name; p->total_link_count = 0; + p->d_root = d_root; } static void path_get(const struct path *path) @@ -1820,16 +1822,16 @@ static int lookup_fast(struct nameidata *nd, struct path *path) * Return 1 if we went up a level and 0 if we were already at the * root. */ -static int follow_up(struct path *path) +static int follow_up(struct nameidata *nd) { - struct vfsmount *parent, *mnt = path->mnt; + struct path *path = &nd->path; + struct vfsmount *mnt = path->mnt; struct dentry *mountpoint; - parent = mnt->parent; - if (parent == mnt) + if (nd->d_root == path->dentry) return 0; - mntget(parent); + mntget(mnt->parent); mountpoint = dget(mnt->mountpoint); dput(path->dentry); path->dentry = mountpoint; @@ -1871,7 +1873,7 @@ static int follow_dotdot(struct nameidata *nd) break; } - if (!follow_up(&nd->path)) + if (!follow_up(nd)) break; } -- 2.39.2