Merge tag 'pull-fs_context' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull fs_context updates from Al Viro:
 "Change vfs_parse_fs_string() calling conventions

  Get rid of the length argument (almost all callers pass strlen() of
  the string argument there), add vfs_parse_fs_qstr() for the cases that
  do want separate length"

* tag 'pull-fs_context' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  do_nfs4_mount(): switch to vfs_parse_fs_string()
  change the calling conventions for vfs_parse_fs_string()
This commit is contained in:
Linus Torvalds
2025-10-03 10:51:44 -07:00
13 changed files with 60 additions and 74 deletions

View File

@@ -504,10 +504,18 @@ returned.
clear the pointer, but then becomes responsible for disposing of the
object.
* ::
int vfs_parse_fs_qstr(struct fs_context *fc, const char *key,
const struct qstr *value);
A wrapper around vfs_parse_fs_param() that copies the value string it is
passed.
* ::
int vfs_parse_fs_string(struct fs_context *fc, const char *key,
const char *value, size_t v_size);
const char *value);
A wrapper around vfs_parse_fs_param() that copies the value string it is
passed.

View File

@@ -1297,3 +1297,15 @@ Several functions are renamed:
- user_path_create -> start_creating_user_path
- user_path_locked_at -> start_removing_user_path_at
- done_path_create -> end_creating_path
---
**mandatory**
Calling conventions for vfs_parse_fs_string() have changed; it does *not*
take length anymore (value ? strlen(value) : 0 is used). If you want
a different length, use
vfs_parse_fs_qstr(fc, key, &QSTR_LEN(value, len))
instead.

View File

@@ -11,11 +11,6 @@
#include "i915_gemfs.h"
#include "i915_utils.h"
static int add_param(struct fs_context *fc, const char *key, const char *val)
{
return vfs_parse_fs_string(fc, key, val, strlen(val));
}
void i915_gemfs_init(struct drm_i915_private *i915)
{
struct file_system_type *type;
@@ -48,9 +43,9 @@ void i915_gemfs_init(struct drm_i915_private *i915)
fc = fs_context_for_mount(type, SB_KERNMOUNT);
if (IS_ERR(fc))
goto err;
ret = add_param(fc, "source", "tmpfs");
ret = vfs_parse_fs_string(fc, "source", "tmpfs");
if (!ret)
ret = add_param(fc, "huge", "within_size");
ret = vfs_parse_fs_string(fc, "huge", "within_size");
if (!ret)
gemfs = fc_mount_longterm(fc);
put_fs_context(fc);

View File

@@ -7,11 +7,6 @@
#include "v3d_drv.h"
static int add_param(struct fs_context *fc, const char *key, const char *val)
{
return vfs_parse_fs_string(fc, key, val, strlen(val));
}
void v3d_gemfs_init(struct v3d_dev *v3d)
{
struct file_system_type *type;
@@ -38,9 +33,9 @@ void v3d_gemfs_init(struct v3d_dev *v3d)
fc = fs_context_for_mount(type, SB_KERNMOUNT);
if (IS_ERR(fc))
goto err;
ret = add_param(fc, "source", "tmpfs");
ret = vfs_parse_fs_string(fc, "source", "tmpfs");
if (!ret)
ret = add_param(fc, "huge", "within_size");
ret = vfs_parse_fs_string(fc, "huge", "within_size");
if (!ret)
gemfs = fc_mount_longterm(fc);
put_fs_context(fc);

View File

@@ -137,7 +137,8 @@ static int afs_mntpt_set_params(struct fs_context *fc, struct dentry *mntpt)
ret = -EINVAL;
if (content[size - 1] == '.')
ret = vfs_parse_fs_string(fc, "source", content, size - 1);
ret = vfs_parse_fs_qstr(fc, "source",
&QSTR_LEN(content, size - 1));
do_delayed_call(&cleanup);
if (ret < 0)
return ret;

View File

@@ -161,25 +161,24 @@ int vfs_parse_fs_param(struct fs_context *fc, struct fs_parameter *param)
EXPORT_SYMBOL(vfs_parse_fs_param);
/**
* vfs_parse_fs_string - Convenience function to just parse a string.
* vfs_parse_fs_qstr - Convenience function to just parse a string.
* @fc: Filesystem context.
* @key: Parameter name.
* @value: Default value.
* @v_size: Maximum number of bytes in the value.
*/
int vfs_parse_fs_string(struct fs_context *fc, const char *key,
const char *value, size_t v_size)
int vfs_parse_fs_qstr(struct fs_context *fc, const char *key,
const struct qstr *value)
{
int ret;
struct fs_parameter param = {
.key = key,
.type = fs_value_is_flag,
.size = v_size,
.size = value ? value->len : 0,
};
if (value) {
param.string = kmemdup_nul(value, v_size, GFP_KERNEL);
param.string = kmemdup_nul(value->name, value->len, GFP_KERNEL);
if (!param.string)
return -ENOMEM;
param.type = fs_value_is_string;
@@ -189,7 +188,7 @@ int vfs_parse_fs_string(struct fs_context *fc, const char *key,
kfree(param.string);
return ret;
}
EXPORT_SYMBOL(vfs_parse_fs_string);
EXPORT_SYMBOL(vfs_parse_fs_qstr);
/**
* vfs_parse_monolithic_sep - Parse key[=val][,key[=val]]* mount data
@@ -218,16 +217,14 @@ int vfs_parse_monolithic_sep(struct fs_context *fc, void *data,
while ((key = sep(&options)) != NULL) {
if (*key) {
size_t v_len = 0;
char *value = strchr(key, '=');
if (value) {
if (unlikely(value == key))
continue;
*value++ = 0;
v_len = strlen(value);
}
ret = vfs_parse_fs_string(fc, key, value, v_len);
ret = vfs_parse_fs_string(fc, key, value);
if (ret < 0)
break;
}

View File

@@ -1239,8 +1239,7 @@ struct vfsmount *vfs_kern_mount(struct file_system_type *type,
return ERR_CAST(fc);
if (name)
ret = vfs_parse_fs_string(fc, "source",
name, strlen(name));
ret = vfs_parse_fs_string(fc, "source", name);
if (!ret)
ret = parse_monolithic_mount_data(fc, data);
if (!ret)
@@ -3717,10 +3716,9 @@ static int do_new_mount(const struct path *path, const char *fstype,
fc->oldapi = true;
if (subtype)
err = vfs_parse_fs_string(fc, "subtype",
subtype, strlen(subtype));
err = vfs_parse_fs_string(fc, "subtype", subtype);
if (!err && name)
err = vfs_parse_fs_string(fc, "source", name, strlen(name));
err = vfs_parse_fs_string(fc, "source", name);
if (!err)
err = parse_monolithic_mount_data(fc, data);
if (!err && !mount_capable(fc))

View File

@@ -1269,8 +1269,7 @@ static int nfs23_parse_monolithic(struct fs_context *fc,
int ret;
data->context[NFS_MAX_CONTEXT_LEN] = '\0';
ret = vfs_parse_fs_string(fc, "context",
data->context, strlen(data->context));
ret = vfs_parse_fs_string(fc, "context", data->context);
if (ret < 0)
return ret;
#else

View File

@@ -290,7 +290,8 @@ int nfs_do_submount(struct fs_context *fc)
nfs_errorf(fc, "NFS: Couldn't determine submount pathname");
ret = PTR_ERR(p);
} else {
ret = vfs_parse_fs_string(fc, "source", p, buffer + 4096 - p);
ret = vfs_parse_fs_qstr(fc, "source",
&QSTR_LEN(p, buffer + 4096 - p));
if (!ret)
ret = vfs_get_tree(fc);
}

View File

@@ -149,21 +149,9 @@ static int do_nfs4_mount(struct nfs_server *server,
struct fs_context *root_fc;
struct vfsmount *root_mnt;
struct dentry *dentry;
size_t len;
char *source;
int ret;
struct fs_parameter param = {
.key = "source",
.type = fs_value_is_string,
.dirfd = -1,
};
struct fs_parameter param_fsc = {
.key = "fsc",
.type = fs_value_is_string,
.dirfd = -1,
};
if (IS_ERR(server))
return PTR_ERR(server);
@@ -181,15 +169,7 @@ static int do_nfs4_mount(struct nfs_server *server,
root_ctx->server = server;
if (ctx->fscache_uniq) {
len = strlen(ctx->fscache_uniq);
param_fsc.size = len;
param_fsc.string = kmemdup_nul(ctx->fscache_uniq, len, GFP_KERNEL);
if (param_fsc.string == NULL) {
put_fs_context(root_fc);
return -ENOMEM;
}
ret = vfs_parse_fs_param(root_fc, &param_fsc);
kfree(param_fsc.string);
ret = vfs_parse_fs_string(root_fc, "fsc", ctx->fscache_uniq);
if (ret < 0) {
put_fs_context(root_fc);
return ret;
@@ -197,20 +177,18 @@ static int do_nfs4_mount(struct nfs_server *server,
}
/* We leave export_path unset as it's not used to find the root. */
len = strlen(hostname) + 5;
param.string = kmalloc(len, GFP_KERNEL);
if (param.string == NULL) {
/* Does hostname needs to be enclosed in brackets? */
if (strchr(hostname, ':'))
source = kasprintf(GFP_KERNEL, "[%s]:/", hostname);
else
source = kasprintf(GFP_KERNEL, "%s:/", hostname);
if (!source) {
put_fs_context(root_fc);
return -ENOMEM;
}
/* Does hostname needs to be enclosed in brackets? */
if (strchr(hostname, ':'))
param.size = snprintf(param.string, len, "[%s]:/", hostname);
else
param.size = snprintf(param.string, len, "%s:/", hostname);
ret = vfs_parse_fs_param(root_fc, &param);
kfree(param.string);
ret = vfs_parse_fs_string(root_fc, "source", source);
kfree(source);
if (ret < 0) {
put_fs_context(root_fc);
return ret;

View File

@@ -773,16 +773,14 @@ static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
}
len = 0;
value = strchr(key, '=');
if (value) {
if (value == key)
continue;
*value++ = 0;
len = strlen(value);
}
ret = vfs_parse_fs_string(fc, key, value, len);
ret = vfs_parse_fs_string(fc, key, value);
if (ret < 0)
break;
}

View File

@@ -134,8 +134,13 @@ extern struct fs_context *fs_context_for_submount(struct file_system_type *fs_ty
extern struct fs_context *vfs_dup_fs_context(struct fs_context *fc);
extern int vfs_parse_fs_param(struct fs_context *fc, struct fs_parameter *param);
extern int vfs_parse_fs_string(struct fs_context *fc, const char *key,
const char *value, size_t v_size);
extern int vfs_parse_fs_qstr(struct fs_context *fc, const char *key,
const struct qstr *value);
static inline int vfs_parse_fs_string(struct fs_context *fc, const char *key,
const char *value)
{
return vfs_parse_fs_qstr(fc, key, value ? &QSTR(value) : NULL);
}
int vfs_parse_monolithic_sep(struct fs_context *fc, void *data,
char *(*sep)(char **));
extern int generic_parse_monolithic(struct fs_context *fc, void *data);

View File

@@ -10211,8 +10211,7 @@ static struct vfsmount *trace_automount(struct dentry *mntpt, void *ingore)
pr_warn("NOTICE: Automounting of tracing to debugfs is deprecated and will be removed in 2030\n");
ret = vfs_parse_fs_string(fc, "source",
"tracefs", strlen("tracefs"));
ret = vfs_parse_fs_string(fc, "source", "tracefs");
if (!ret)
mnt = fc_mount(fc);
else