vfs: make LAST_XXX private to fs/namei.c

The only user of LAST_XXX outside of fs/namei.c is fs/smb/server/vfs.c;
ksmbd_vfs_path_lookup() calls vfs_path_parent_lookup() and expects a
LAST_NORM last type (or it will be ENOENT). ksmbd_vfs_rename() also calls
vfs_path_parent_lookup() but forgets the LAST_NORM check.

It does not really make sense to have vfs_path_parent_lookup() expose
the last_type because it is only needed to ensure it is LAST_NORM. So
let's do this check in vfs_path_parent_lookup() instead and keep the
LAST_XXX internal to fs/namei.c. This changes the ENOENT errno in
ksmbd_vfs_path_lookup() to EINVAL, which matches better with how this is
handled by callers of filename_parentat().

Signed-off-by: Jori Koolstra <jkoolstra@xs4all.nl>
Link: https://patch.msgid.link/20260528175854.57626-1-jkoolstra@xs4all.nl
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Reviewed-by: NeilBrown <neil@brown.name>
Reviewed-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
This commit is contained in:
Jori Koolstra 2026-05-28 17:58:46 +00:00 committed by Christian Brauner
parent 8c47b5e9b9
commit f2f1dddcca
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2
3 changed files with 20 additions and 22 deletions

View File

@ -129,6 +129,11 @@
static struct kmem_cache *__names_cache __ro_after_init;
#define names_cache runtime_const_ptr(__names_cache)
/*
* Type of the last component on LOOKUP_PARENT
*/
enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT};
void __init filename_init(void)
{
__names_cache = kmem_cache_create_usercopy("names_cache", sizeof(struct filename), 0,
@ -3051,15 +3056,22 @@ EXPORT_SYMBOL(kern_path);
* @flags: lookup flags
* @parent: pointer to struct path to fill
* @last: last component
* @type: type of the last component
* @root: pointer to struct path of the base directory
*/
int vfs_path_parent_lookup(struct filename *filename, unsigned int flags,
struct path *parent, struct qstr *last, int *type,
struct path *parent, struct qstr *last,
const struct path *root)
{
return __filename_parentat(AT_FDCWD, filename, flags, parent, last,
type, root);
int type;
int err = __filename_parentat(AT_FDCWD, filename, flags, parent, last,
&type, root);
if (err)
return err;
if (unlikely(type != LAST_NORM)) {
path_put(parent);
return -EINVAL;
}
return 0;
}
EXPORT_SYMBOL(vfs_path_parent_lookup);

View File

@ -19,7 +19,6 @@
#include <linux/vmalloc.h>
#include <linux/sched/xacct.h>
#include <linux/crc32c.h>
#include <linux/namei.h>
#include <linux/splice.h>
#include "glob.h"
@ -56,7 +55,7 @@ static int ksmbd_vfs_path_lookup(struct ksmbd_share_config *share_conf,
{
struct qstr last;
const struct path *root_share_path = &share_conf->vfs_path;
int err, type;
int err;
struct dentry *d;
if (pathname[0] == '\0') {
@ -67,17 +66,11 @@ static int ksmbd_vfs_path_lookup(struct ksmbd_share_config *share_conf,
}
CLASS(filename_kernel, filename)(pathname);
err = vfs_path_parent_lookup(filename, flags,
path, &last, &type,
err = vfs_path_parent_lookup(filename, flags, path, &last,
root_share_path);
if (err)
return err;
if (unlikely(type != LAST_NORM)) {
path_put(path);
return -ENOENT;
}
if (for_remove) {
err = mnt_want_write(path->mnt);
if (err) {
@ -668,7 +661,6 @@ int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path,
struct renamedata rd;
struct ksmbd_share_config *share_conf = work->tcon->share_conf;
struct ksmbd_file *parent_fp;
int new_type;
int err, lookup_flags = LOOKUP_NO_SYMLINKS;
if (ksmbd_override_fsids(work))
@ -678,8 +670,7 @@ int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path,
retry:
err = vfs_path_parent_lookup(to, lookup_flags | LOOKUP_BENEATH,
&new_path, &new_last, &new_type,
&share_conf->vfs_path);
&new_path, &new_last, &share_conf->vfs_path);
if (err)
goto out1;

View File

@ -13,11 +13,6 @@ enum { MAX_NESTED_LINKS = 8 };
#define MAXSYMLINKS 40
/*
* Type of the last component on LOOKUP_PARENT
*/
enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT};
/* pathwalk mode */
#define LOOKUP_FOLLOW BIT(0) /* follow links at the end */
#define LOOKUP_DIRECTORY BIT(1) /* require a directory */
@ -67,7 +62,7 @@ static inline void end_removing_path(const struct path *path , struct dentry *de
end_creating_path(path, dentry);
}
int vfs_path_parent_lookup(struct filename *filename, unsigned int flags,
struct path *parent, struct qstr *last, int *type,
struct path *parent, struct qstr *last,
const struct path *root);
int vfs_path_lookup(struct dentry *, struct vfsmount *, const char *,
unsigned int, struct path *);