* [PATCH v2 1/2] libfs: Introduce tokenize_user_input()
2022-08-25 16:48 [PATCH v2 0/2] libfs: Introduce tokenize_user_input() Cezary Rojewski
@ 2022-08-25 16:48 ` Cezary Rojewski
2022-08-30 18:33 ` Matthew Wilcox
2022-08-25 16:48 ` [PATCH v2 2/2] ASoC: SOF: Remove strsplit_u32() and tokenize_input() Cezary Rojewski
1 sibling, 1 reply; 5+ messages in thread
From: Cezary Rojewski @ 2022-08-25 16:48 UTC (permalink / raw)
To: alsa-devel, broonie
Cc: tiwai, perex, amadeuszx.slawinski, pierre-louis.bossart, hdegoede,
lgirdwood, kai.vehmanen, peter.ujfalusi, ranjani.sridharan,
yung-chuan.liao, viro, linux-fsdevel, linux-kernel,
andy.shevchenko, Cezary Rojewski
Add new helper function to allow for splitting specified user string
into a sequence of integers. Internally it makes use of get_options() so
the returned sequence contains the integers extracted plus an additional
element that begins the sequence and specifies the integers count.
Suggested-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
---
fs/libfs.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/fs.h | 1 +
2 files changed, 46 insertions(+)
diff --git a/fs/libfs.c b/fs/libfs.c
index 31b0ddf01c31..078b23e26741 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -809,6 +809,51 @@ ssize_t simple_write_to_buffer(void *to, size_t available, loff_t *ppos,
}
EXPORT_SYMBOL(simple_write_to_buffer);
+/**
+ * tokenize_user_input - Split string into a sequence of integers
+ * @from: The user space buffer to read from
+ * @ppos: The current position in the buffer
+ * @count: The maximum number of bytes to read
+ * @tkns: Returned pointer to sequence of integers
+ *
+ * On success @tkns is allocated and initialized with a sequence of
+ * integers extracted from the @from plus an additional element that
+ * begins the sequence and specifies the integers count.
+ *
+ * Caller takes responsibility for freeing @tkns when it is no longer
+ * needed.
+ */
+int tokenize_user_input(const char __user *from, size_t count, int **tkns)
+{
+ int *ints, nints;
+ char *buf;
+ int ret = 0;
+
+ buf = memdup_user_nul(from, count);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+
+ get_options(buf, 0, &nints);
+ if (!nints) {
+ ret = -ENOENT;
+ goto free_buf;
+ }
+
+ ints = kcalloc(nints + 1, sizeof(*ints), GFP_KERNEL);
+ if (!ints) {
+ ret = -ENOMEM;
+ goto free_buf;
+ }
+
+ get_options(buf, nints + 1, ints);
+ *tkns = ints;
+
+free_buf:
+ kfree(buf);
+ return ret;
+}
+EXPORT_SYMBOL(tokenize_user_input);
+
/**
* memory_read_from_buffer - copy data from the buffer
* @to: the kernel space buffer to read to
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 9eced4cc286e..ab04cc7f9efa 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -3345,6 +3345,7 @@ extern ssize_t simple_read_from_buffer(void __user *to, size_t count,
loff_t *ppos, const void *from, size_t available);
extern ssize_t simple_write_to_buffer(void *to, size_t available, loff_t *ppos,
const void __user *from, size_t count);
+extern int tokenize_user_input(const char __user *from, size_t count, int **tkns);
extern int __generic_file_fsync(struct file *, loff_t, loff_t, int);
extern int generic_file_fsync(struct file *, loff_t, loff_t, int);
--
2.25.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH v2 2/2] ASoC: SOF: Remove strsplit_u32() and tokenize_input()
2022-08-25 16:48 [PATCH v2 0/2] libfs: Introduce tokenize_user_input() Cezary Rojewski
2022-08-25 16:48 ` [PATCH v2 1/2] " Cezary Rojewski
@ 2022-08-25 16:48 ` Cezary Rojewski
1 sibling, 0 replies; 5+ messages in thread
From: Cezary Rojewski @ 2022-08-25 16:48 UTC (permalink / raw)
To: alsa-devel, broonie
Cc: tiwai, perex, amadeuszx.slawinski, pierre-louis.bossart, hdegoede,
lgirdwood, kai.vehmanen, peter.ujfalusi, ranjani.sridharan,
yung-chuan.liao, viro, linux-fsdevel, linux-kernel,
andy.shevchenko, Cezary Rojewski
Make use of global user input tokenization helper instead of the
internal one as both serve same purpose. With that, both strsplit_u32()
and tokenize_input() become unused so remove them.
Signed-off-by: Cezary Rojewski <cezary.rojewski@intel.com>
---
sound/soc/sof/sof-client-probes.c | 92 ++++---------------------------
1 file changed, 11 insertions(+), 81 deletions(-)
diff --git a/sound/soc/sof/sof-client-probes.c b/sound/soc/sof/sof-client-probes.c
index eb246b823461..3bab54cac07b 100644
--- a/sound/soc/sof/sof-client-probes.c
+++ b/sound/soc/sof/sof-client-probes.c
@@ -410,79 +410,6 @@ static const struct snd_compress_ops sof_probes_compressed_ops = {
.copy = sof_probes_compr_copy,
};
-/**
- * strsplit_u32 - Split string into sequence of u32 tokens
- * @buf: String to split into tokens.
- * @delim: String containing delimiter characters.
- * @tkns: Returned u32 sequence pointer.
- * @num_tkns: Returned number of tokens obtained.
- */
-static int strsplit_u32(char *buf, const char *delim, u32 **tkns, size_t *num_tkns)
-{
- char *s;
- u32 *data, *tmp;
- size_t count = 0;
- size_t cap = 32;
- int ret = 0;
-
- *tkns = NULL;
- *num_tkns = 0;
- data = kcalloc(cap, sizeof(*data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- while ((s = strsep(&buf, delim)) != NULL) {
- ret = kstrtouint(s, 0, data + count);
- if (ret)
- goto exit;
- if (++count >= cap) {
- cap *= 2;
- tmp = krealloc(data, cap * sizeof(*data), GFP_KERNEL);
- if (!tmp) {
- ret = -ENOMEM;
- goto exit;
- }
- data = tmp;
- }
- }
-
- if (!count)
- goto exit;
- *tkns = kmemdup(data, count * sizeof(*data), GFP_KERNEL);
- if (!(*tkns)) {
- ret = -ENOMEM;
- goto exit;
- }
- *num_tkns = count;
-
-exit:
- kfree(data);
- return ret;
-}
-
-static int tokenize_input(const char __user *from, size_t count,
- loff_t *ppos, u32 **tkns, size_t *num_tkns)
-{
- char *buf;
- int ret;
-
- buf = kmalloc(count + 1, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- ret = simple_write_to_buffer(buf, count, ppos, from, count);
- if (ret != count) {
- ret = ret >= 0 ? -EIO : ret;
- goto exit;
- }
-
- buf[count] = '\0';
- ret = strsplit_u32(buf, ",", tkns, num_tkns);
-exit:
- kfree(buf);
- return ret;
-}
-
static ssize_t sof_probes_dfs_points_read(struct file *file, char __user *to,
size_t count, loff_t *ppos)
{
@@ -548,8 +475,8 @@ sof_probes_dfs_points_write(struct file *file, const char __user *from,
struct sof_probes_priv *priv = cdev->data;
struct device *dev = &cdev->auxdev.dev;
struct sof_probe_point_desc *desc;
- size_t num_tkns, bytes;
- u32 *tkns;
+ size_t bytes;
+ u32 num_tkns, *tkns;
int ret, err;
if (priv->extractor_stream_tag == SOF_PROBES_INVALID_NODE_ID) {
@@ -557,16 +484,18 @@ sof_probes_dfs_points_write(struct file *file, const char __user *from,
return -ENOENT;
}
- ret = tokenize_input(from, count, ppos, &tkns, &num_tkns);
+ ret = tokenize_user_input(from, count, (int **)&tkns);
if (ret < 0)
return ret;
+
+ num_tkns = *tkns;
bytes = sizeof(*tkns) * num_tkns;
if (!num_tkns || (bytes % sizeof(*desc))) {
ret = -EINVAL;
goto exit;
}
- desc = (struct sof_probe_point_desc *)tkns;
+ desc = (struct sof_probe_point_desc *)&tkns[1];
ret = pm_runtime_resume_and_get(dev);
if (ret < 0 && ret != -EACCES) {
@@ -603,8 +532,7 @@ sof_probes_dfs_points_remove_write(struct file *file, const char __user *from,
struct sof_client_dev *cdev = file->private_data;
struct sof_probes_priv *priv = cdev->data;
struct device *dev = &cdev->auxdev.dev;
- size_t num_tkns;
- u32 *tkns;
+ u32 num_tkns, *tkns;
int ret, err;
if (priv->extractor_stream_tag == SOF_PROBES_INVALID_NODE_ID) {
@@ -612,9 +540,11 @@ sof_probes_dfs_points_remove_write(struct file *file, const char __user *from,
return -ENOENT;
}
- ret = tokenize_input(from, count, ppos, &tkns, &num_tkns);
+ ret = tokenize_user_input(from, count, (int **)&tkns);
if (ret < 0)
return ret;
+
+ num_tkns = *tkns;
if (!num_tkns) {
ret = -EINVAL;
goto exit;
@@ -626,7 +556,7 @@ sof_probes_dfs_points_remove_write(struct file *file, const char __user *from,
goto exit;
}
- ret = sof_probes_points_remove(cdev, tkns, num_tkns);
+ ret = sof_probes_points_remove(cdev, &tkns[1], num_tkns);
if (!ret)
ret = count;
--
2.25.1
^ permalink raw reply related [flat|nested] 5+ messages in thread