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>
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,
* @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);
#include <linux/vmalloc.h>
#include <linux/sched/xacct.h>
#include <linux/crc32c.h>
-#include <linux/namei.h>
#include <linux/splice.h>
#include "glob.h"
{
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') {
}
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) {
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))
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;
#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 */
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 *);