Merge tag 'mm-nonmm-stable-2023-04-27-16-01' of git://git.kernel.org/pub/scm/linux...
[platform/kernel/linux-starfive.git] / fs / proc / proc_sysctl.c
index 875771b..81dbb17 100644 (file)
@@ -1282,11 +1282,43 @@ out:
        return err;
 }
 
+/* Find the directory for the ctl_table. If one is not found create it. */
+static struct ctl_dir *sysctl_mkdir_p(struct ctl_dir *dir, const char *path)
+{
+       const char *name, *nextname;
+
+       for (name = path; name; name = nextname) {
+               int namelen;
+               nextname = strchr(name, '/');
+               if (nextname) {
+                       namelen = nextname - name;
+                       nextname++;
+               } else {
+                       namelen = strlen(name);
+               }
+               if (namelen == 0)
+                       continue;
+
+               /*
+                * namelen ensures if name is "foo/bar/yay" only foo is
+                * registered first. We traverse as if using mkdir -p and
+                * return a ctl_dir for the last directory entry.
+                */
+               dir = get_subdir(dir, name, namelen);
+               if (IS_ERR(dir))
+                       break;
+       }
+       return dir;
+}
+
 /**
  * __register_sysctl_table - register a leaf sysctl table
  * @set: Sysctl tree to register on
  * @path: The path to the directory the sysctl table is in.
- * @table: the top-level table structure
+ * @table: the top-level table structure without any child. This table
+ *      should not be free'd after registration. So it should not be
+ *      used on stack. It can either be a global or dynamically allocated
+ *      by the caller and free'd later after sysctl unregistration.
  *
  * Register a sysctl table hierarchy. @table should be a filled in ctl_table
  * array. A completely 0 filled entry terminates the table.
@@ -1307,9 +1339,12 @@ out:
  * proc_handler - the text handler routine (described below)
  *
  * extra1, extra2 - extra pointers usable by the proc handler routines
+ * XXX: we should eventually modify these to use long min / max [0]
+ * [0] https://lkml.kernel.org/87zgpte9o4.fsf@email.froward.int.ebiederm.org
  *
  * Leaf nodes in the sysctl tree will be represented by a single file
- * under /proc; non-leaf nodes will be represented by directories.
+ * under /proc; non-leaf nodes (where child is not NULL) are not allowed,
+ * sysctl_check_table() verifies this.
  *
  * There must be a proc_handler routine for any terminal nodes.
  * Several default handlers are available to cover common cases -
@@ -1330,7 +1365,6 @@ struct ctl_table_header *__register_sysctl_table(
 {
        struct ctl_table_root *root = set->dir.header.root;
        struct ctl_table_header *header;
-       const char *name, *nextname;
        struct ctl_dir *dir;
        struct ctl_table *entry;
        struct ctl_node *node;
@@ -1351,28 +1385,13 @@ struct ctl_table_header *__register_sysctl_table(
 
        spin_lock(&sysctl_lock);
        dir = &set->dir;
-       /* Reference moved down the diretory tree get_subdir */
+       /* Reference moved down the directory tree get_subdir */
        dir->header.nreg++;
        spin_unlock(&sysctl_lock);
 
-       /* Find the directory for the ctl_table */
-       for (name = path; name; name = nextname) {
-               int namelen;
-               nextname = strchr(name, '/');
-               if (nextname) {
-                       namelen = nextname - name;
-                       nextname++;
-               } else {
-                       namelen = strlen(name);
-               }
-               if (namelen == 0)
-                       continue;
-
-               dir = get_subdir(dir, name, namelen);
-               if (IS_ERR(dir))
-                       goto fail;
-       }
-
+       dir = sysctl_mkdir_p(dir, path);
+       if (IS_ERR(dir))
+               goto fail;
        spin_lock(&sysctl_lock);
        if (insert_header(dir, header))
                goto fail_put_dir_locked;
@@ -1393,8 +1412,15 @@ fail:
 
 /**
  * register_sysctl - register a sysctl table
- * @path: The path to the directory the sysctl table is in.
- * @table: the table structure
+ * @path: The path to the directory the sysctl table is in. If the path
+ *     doesn't exist we will create it for you.
+ * @table: the table structure. The calller must ensure the life of the @table
+ *     will be kept during the lifetime use of the syctl. It must not be freed
+ *     until unregister_sysctl_table() is called with the given returned table
+ *     with this registration. If your code is non modular then you don't need
+ *     to call unregister_sysctl_table() and can instead use something like
+ *     register_sysctl_init() which does not care for the result of the syctl
+ *     registration.
  *
  * Register a sysctl table. @table should be a filled in ctl_table
  * array. A completely 0 filled entry terminates the table.
@@ -1410,8 +1436,11 @@ EXPORT_SYMBOL(register_sysctl);
 
 /**
  * __register_sysctl_init() - register sysctl table to path
- * @path: path name for sysctl base
- * @table: This is the sysctl table that needs to be registered to the path
+ * @path: path name for sysctl base. If that path doesn't exist we will create
+ *     it for you.
+ * @table: This is the sysctl table that needs to be registered to the path.
+ *     The caller must ensure the life of the @table will be kept during the
+ *     lifetime use of the sysctl.
  * @table_name: The name of sysctl table, only used for log printing when
  *              registration fails
  *
@@ -1423,10 +1452,7 @@ EXPORT_SYMBOL(register_sysctl);
  * register_sysctl() failing on init are extremely low, and so for both reasons
  * this function does not return any error as it is used by initialization code.
  *
- * Context: Can only be called after your respective sysctl base path has been
- * registered. So for instance, most base directories are registered early on
- * init before init levels are processed through proc_sys_init() and
- * sysctl_init_bases().
+ * Context: if your base directory does not exist it will be created for you.
  */
 void __init __register_sysctl_init(const char *path, struct ctl_table *table,
                                 const char *table_name)
@@ -1556,6 +1582,7 @@ out:
  *
  * Register a sysctl table hierarchy. @table should be a filled in ctl_table
  * array. A completely 0 filled entry terminates the table.
+ * We are slowly deprecating this call so avoid its use.
  *
  * See __register_sysctl_table for more details.
  */
@@ -1627,6 +1654,7 @@ err_register_leaves:
  *
  * Register a sysctl table hierarchy. @table should be a filled in ctl_table
  * array. A completely 0 filled entry terminates the table.
+ * We are slowly deprecating this caller so avoid future uses of it.
  *
  * See __register_sysctl_paths for more details.
  */