sysctl: move sysctl type to ctl_table_header
authorThomas Weißschuh <linux@weissschuh.net>
Fri, 22 Mar 2024 17:05:57 +0000 (18:05 +0100)
committerJoel Granados <j.granados@samsung.com>
Wed, 24 Apr 2024 07:43:54 +0000 (09:43 +0200)
Move the SYSCTL_TABLE_TYPE_{DEFAULT,PERMANENTLY_EMPTY} enums from
ctl_table to ctl_table_header.
Removing the mutable member is necessary to constify static instances
of struct ctl_table.

Move the initialization of the sysctl_mount_point type into
init_header() where all the other header fields are also initialized.

As a side-effect the memory usage of the sysctl core is reduced.
Each ctl_table_header instance can manage multiple ctl_table instances
and is only allocated when the table is actually registered.
This saves 8 bytes of memory per ctl_table on 64bit, 4 due to the enum
field itself and 4 due to padding.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Signed-off-by: Joel Granados <j.granados@samsung.com>
fs/proc/proc_sysctl.c
include/linux/sysctl.h

index 3f8abb6d2ad5477b4cc193ae3cda7843aadb4a7b..a847b0bc63c457bad7b4a7966b9983787be21eca 100644 (file)
@@ -31,7 +31,7 @@ static const struct inode_operations proc_sys_dir_operations;
 
 /* Support for permanently empty directories */
 static struct ctl_table sysctl_mount_point[] = {
-       {.type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY }
+       { }
 };
 
 /**
@@ -49,11 +49,11 @@ struct ctl_table_header *register_sysctl_mount_point(const char *path)
 EXPORT_SYMBOL(register_sysctl_mount_point);
 
 #define sysctl_is_perm_empty_ctl_header(hptr)          \
-       (hptr->ctl_table[0].type == SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
+       (hptr->type == SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
 #define sysctl_set_perm_empty_ctl_header(hptr)         \
-       (hptr->ctl_table[0].type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
+       (hptr->type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
 #define sysctl_clear_perm_empty_ctl_header(hptr)       \
-       (hptr->ctl_table[0].type = SYSCTL_TABLE_TYPE_DEFAULT)
+       (hptr->type = SYSCTL_TABLE_TYPE_DEFAULT)
 
 void proc_sys_poll_notify(struct ctl_table_poll *poll)
 {
@@ -208,6 +208,8 @@ static void init_header(struct ctl_table_header *head,
                        node++;
                }
        }
+       if (table == sysctl_mount_point)
+               sysctl_set_perm_empty_ctl_header(head);
 }
 
 static void erase_header(struct ctl_table_header *head)
index f9214de0490c41d4fb06ff68264105d8b3841a1f..47bd28ffa88f47648873f115a63f66188acbf6d6 100644 (file)
@@ -137,17 +137,6 @@ struct ctl_table {
        void *data;
        int maxlen;
        umode_t mode;
-       /**
-        * enum type - Enumeration to differentiate between ctl target types
-        * @SYSCTL_TABLE_TYPE_DEFAULT: ctl target with no special considerations
-        * @SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY: Used to identify a permanently
-        *                                       empty directory target to serve
-        *                                       as mount point.
-        */
-       enum {
-               SYSCTL_TABLE_TYPE_DEFAULT,
-               SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY
-       } type;
        proc_handler *proc_handler;     /* Callback for text formatting */
        struct ctl_table_poll *poll;
        void *extra1;
@@ -188,6 +177,17 @@ struct ctl_table_header {
        struct ctl_dir *parent;
        struct ctl_node *node;
        struct hlist_head inodes; /* head for proc_inode->sysctl_inodes */
+       /**
+        * enum type - Enumeration to differentiate between ctl target types
+        * @SYSCTL_TABLE_TYPE_DEFAULT: ctl target with no special considerations
+        * @SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY: Used to identify a permanently
+        *                                       empty directory target to serve
+        *                                       as mount point.
+        */
+       enum {
+               SYSCTL_TABLE_TYPE_DEFAULT,
+               SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY,
+       } type;
 };
 
 struct ctl_dir {