From: Christian Brauner <christian.brauner@xxxxxxxxxx> Various filesystems use the try_lookup_one_len() helper to lookup a single path component relative to a well-known starting point. Allow such filesystems to support idmapped mounts by enabling try_lookup_one_len() to take the idmap into account when calling inode_permission(). This change is a required to let btrfs (and other filesystems) support idmapped mounts. Cc: Christoph Hellwig <hch@xxxxxxxxxxxxx> Cc: Al Viro <viro@xxxxxxxxxxxxxxxxxx> Cc: linux-fsdevel@xxxxxxxxxxxxxxx Signed-off-by: Christian Brauner <christian.brauner@xxxxxxxxxx> --- fs/afs/dynroot.c | 2 +- fs/namei.c | 7 +++++-- include/linux/namei.h | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/fs/afs/dynroot.c b/fs/afs/dynroot.c index 6b89d68c8e44..9e96840e6952 100644 --- a/fs/afs/dynroot.c +++ b/fs/afs/dynroot.c @@ -315,7 +315,7 @@ void afs_dynroot_rmdir(struct afs_net *net, struct afs_cell *cell) inode_lock(root->d_inode); /* Don't want to trigger a lookup call, which will re-add the cell */ - subdir = try_lookup_one_len(cell->name, root, cell->name_len); + subdir = try_lookup_one_len(&init_user_ns, cell->name, root, cell->name_len); if (IS_ERR_OR_NULL(subdir)) { _debug("lookup %ld", PTR_ERR(subdir)); goto no_dentry; diff --git a/fs/namei.c b/fs/namei.c index 68489c23bc44..0866b88628b9 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2610,6 +2610,7 @@ static int lookup_one_len_common(struct user_namespace *mnt_userns, /** * try_lookup_one_len - filesystem helper to lookup single pathname component + * @mnt_userns: user namespace of the mount the lookup is performed from * @name: pathname component to lookup * @base: base directory to lookup from * @len: maximum length @len should be interpreted to @@ -2622,14 +2623,16 @@ static int lookup_one_len_common(struct user_namespace *mnt_userns, * * The caller must hold base->i_mutex. */ -struct dentry *try_lookup_one_len(const char *name, struct dentry *base, int len) +struct dentry *try_lookup_one_len(struct user_namespace *mnt_userns, + const char *name, struct dentry *base, + int len) { struct qstr this; int err; WARN_ON_ONCE(!inode_is_locked(base->d_inode)); - err = lookup_one_len_common(&init_user_ns, name, base, len, &this); + err = lookup_one_len_common(mnt_userns, name, base, len, &this); if (err) return ERR_PTR(err); diff --git a/include/linux/namei.h b/include/linux/namei.h index c177edfb2364..206ea4702d62 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -64,7 +64,8 @@ extern struct dentry *user_path_create(int, const char __user *, struct path *, extern void done_path_create(struct path *, struct dentry *); extern struct dentry *kern_path_locked(const char *, struct path *); -extern struct dentry *try_lookup_one_len(const char *, struct dentry *, int); +extern struct dentry *try_lookup_one_len(struct user_namespace *, const char *, + struct dentry *, int); extern struct dentry *lookup_one_len(struct user_namespace *mnt_userns, const char *, struct dentry *, int); extern struct dentry *lookup_one_len_unlocked(struct user_namespace *, -- 2.30.2