When simdisk support is built as a loadable module,
simdisk_param_set_filename() receives a pointer into module::args and
stores each filename pointer as is.

In preparation for removing module::args, update the simdisk.filename
parameter code to copy the provided string. This is somewhat complicated by
the fact that simdisk support can also be built-in, in which case the
parameters are parsed during early boot before slab is available. In that
case, the command line itself is preserved for the lifetime of the kernel,
so continue storing the incoming pointer directly.

Signed-off-by: Petr Pavlu <[email protected]>
---
 arch/xtensa/platforms/iss/simdisk.c | 38 +++++++++++++++++++++++++----
 1 file changed, 33 insertions(+), 5 deletions(-)

diff --git a/arch/xtensa/platforms/iss/simdisk.c 
b/arch/xtensa/platforms/iss/simdisk.c
index 7c7a2aa749f8..a2ddb49c269d 100644
--- a/arch/xtensa/platforms/iss/simdisk.c
+++ b/arch/xtensa/platforms/iss/simdisk.c
@@ -41,7 +41,7 @@ module_param(simdisk_count, int, S_IRUGO);
 MODULE_PARM_DESC(simdisk_count, "Number of simdisk units.");
 
 static int n_files;
-static const char *filename[MAX_SIMDISK_COUNT] = {
+static char *filename[MAX_SIMDISK_COUNT] = {
 #ifdef CONFIG_SIMDISK0_FILENAME
        CONFIG_SIMDISK0_FILENAME,
 #ifdef CONFIG_SIMDISK1_FILENAME
@@ -50,20 +50,48 @@ static const char *filename[MAX_SIMDISK_COUNT] = {
 #endif
 };
 
+/*
+ * The simdisk code can be built either into the kernel or as a loadable 
module.
+ * When built-in, CONFIG_SIMDISK{0,1}_FILENAME can be used to specify the
+ * initial simdisk filenames and additional filenames can be provided on the
+ * kernel command line. These arguments are parsed during early boot when slab
+ * is not yet available, but the command line itself is preserved for the
+ * lifetime of the kernel, so the incoming pointer is stored directly.
+ * When built as a loadable module, each value is copied with kstrdup() and all
+ * allocated memory is freed in simdisk_param_free_filename() when the module 
is
+ * unloaded.
+ */
 static int simdisk_param_set_filename(const char *val,
                const struct kernel_param *kp)
 {
-       if (n_files < ARRAY_SIZE(filename))
-               filename[n_files++] = val;
-       else
+       char *str;
+
+       if (n_files >= ARRAY_SIZE(filename))
                return -EINVAL;
+
+#ifdef MODULE
+       str = kstrdup(val, GFP_KERNEL);
+       if (!str)
+               return -ENOMEM;
+#else
+       str = (char *)val;
+#endif
+
+       filename[n_files++] = str;
        return 0;
 }
 
+static void simdisk_param_free_filename(void *arg)
+{
+       for (int i = 0; i < n_files; i++)
+               kfree(filename[i]);
+}
+
 static const struct kernel_param_ops simdisk_param_ops_filename = {
        .set = simdisk_param_set_filename,
+       .free = simdisk_param_free_filename,
 };
-module_param_cb(filename, &simdisk_param_ops_filename, &n_files, 0);
+module_param_cb(filename, &simdisk_param_ops_filename, NULL, 0);
 MODULE_PARM_DESC(filename, "Backing storage filename.");
 
 static int simdisk_major = SIMDISK_MAJOR;
-- 
2.54.0


Reply via email to