diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-23 21:08:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-23 21:08:58 -0400 |
commit | f1d38e423a697b7aa06e12d3ca4753bcc1aa3531 (patch) | |
tree | 1cbfd86070f724d5ffe53146d4c67edf14cccf98 /include/linux | |
parent | dae430c6f6e5d0b98c238c340a41a39e221e8940 (diff) | |
parent | 4e474a00d7ff746ed177ddae14fa8b2d4bad7a00 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/sysctl
Pull sysctl updates from Eric Biederman:
- Rewrite of sysctl for speed and clarity.
Insert/remove/Lookup in sysctl are all now O(NlogN) operations, and
are no longer bottlenecks in the process of adding and removing
network devices.
sysctl is now focused on being a filesystem instead of system call
and the code can all be found in fs/proc/proc_sysctl.c. Hopefully
this means the code is now approachable.
Much thanks is owed to Lucian Grinjincu for keeping at this until
something was found that was usable.
- The recent proc_sys_poll oops found by the fuzzer during hibernation
is fixed.
* git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/sysctl: (36 commits)
sysctl: protect poll() in entries that may go away
sysctl: Don't call sysctl_follow_link unless we are a link.
sysctl: Comments to make the code clearer.
sysctl: Correct error return from get_subdir
sysctl: An easier to read version of find_subdir
sysctl: fix memset parameters in setup_sysctl_set()
sysctl: remove an unused variable
sysctl: Add register_sysctl for normal sysctl users
sysctl: Index sysctl directories with rbtrees.
sysctl: Make the header lists per directory.
sysctl: Move sysctl_check_dups into insert_header
sysctl: Modify __register_sysctl_paths to take a set instead of a root and an nsproxy
sysctl: Replace root_list with links between sysctl_table_sets.
sysctl: Add sysctl_print_dir and use it in get_subdir
sysctl: Stop requiring explicit management of sysctl directories
sysctl: Add a root pointer to ctl_table_set
sysctl: Rewrite proc_sys_readdir in terms of first_entry and next_entry
sysctl: Rewrite proc_sys_lookup introducing find_entry and lookup_entry.
sysctl: Normalize the root_table data structure.
sysctl: Factor out insert_header and erase_header
...
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/sysctl.h | 106 |
1 files changed, 67 insertions, 39 deletions
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index bb9127dd814b..c34b4c82b0dc 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h | |||
@@ -932,34 +932,14 @@ enum | |||
932 | #include <linux/list.h> | 932 | #include <linux/list.h> |
933 | #include <linux/rcupdate.h> | 933 | #include <linux/rcupdate.h> |
934 | #include <linux/wait.h> | 934 | #include <linux/wait.h> |
935 | #include <linux/rbtree.h> | ||
935 | 936 | ||
936 | /* For the /proc/sys support */ | 937 | /* For the /proc/sys support */ |
937 | struct ctl_table; | 938 | struct ctl_table; |
938 | struct nsproxy; | 939 | struct nsproxy; |
939 | struct ctl_table_root; | 940 | struct ctl_table_root; |
940 | |||
941 | struct ctl_table_set { | ||
942 | struct list_head list; | ||
943 | struct ctl_table_set *parent; | ||
944 | int (*is_seen)(struct ctl_table_set *); | ||
945 | }; | ||
946 | |||
947 | extern void setup_sysctl_set(struct ctl_table_set *p, | ||
948 | struct ctl_table_set *parent, | ||
949 | int (*is_seen)(struct ctl_table_set *)); | ||
950 | |||
951 | struct ctl_table_header; | 941 | struct ctl_table_header; |
952 | 942 | struct ctl_dir; | |
953 | extern void sysctl_head_get(struct ctl_table_header *); | ||
954 | extern void sysctl_head_put(struct ctl_table_header *); | ||
955 | extern int sysctl_is_seen(struct ctl_table_header *); | ||
956 | extern struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *); | ||
957 | extern struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev); | ||
958 | extern struct ctl_table_header *__sysctl_head_next(struct nsproxy *namespaces, | ||
959 | struct ctl_table_header *prev); | ||
960 | extern void sysctl_head_finish(struct ctl_table_header *prev); | ||
961 | extern int sysctl_perm(struct ctl_table_root *root, | ||
962 | struct ctl_table *table, int op); | ||
963 | 943 | ||
964 | typedef struct ctl_table ctl_table; | 944 | typedef struct ctl_table ctl_table; |
965 | 945 | ||
@@ -1023,8 +1003,6 @@ static inline void *proc_sys_poll_event(struct ctl_table_poll *poll) | |||
1023 | return (void *)(unsigned long)atomic_read(&poll->event); | 1003 | return (void *)(unsigned long)atomic_read(&poll->event); |
1024 | } | 1004 | } |
1025 | 1005 | ||
1026 | void proc_sys_poll_notify(struct ctl_table_poll *poll); | ||
1027 | |||
1028 | #define __CTL_TABLE_POLL_INITIALIZER(name) { \ | 1006 | #define __CTL_TABLE_POLL_INITIALIZER(name) { \ |
1029 | .event = ATOMIC_INIT(0), \ | 1007 | .event = ATOMIC_INIT(0), \ |
1030 | .wait = __WAIT_QUEUE_HEAD_INITIALIZER(name.wait) } | 1008 | .wait = __WAIT_QUEUE_HEAD_INITIALIZER(name.wait) } |
@@ -1039,21 +1017,16 @@ struct ctl_table | |||
1039 | void *data; | 1017 | void *data; |
1040 | int maxlen; | 1018 | int maxlen; |
1041 | umode_t mode; | 1019 | umode_t mode; |
1042 | struct ctl_table *child; | 1020 | struct ctl_table *child; /* Deprecated */ |
1043 | struct ctl_table *parent; /* Automatically set */ | ||
1044 | proc_handler *proc_handler; /* Callback for text formatting */ | 1021 | proc_handler *proc_handler; /* Callback for text formatting */ |
1045 | struct ctl_table_poll *poll; | 1022 | struct ctl_table_poll *poll; |
1046 | void *extra1; | 1023 | void *extra1; |
1047 | void *extra2; | 1024 | void *extra2; |
1048 | }; | 1025 | }; |
1049 | 1026 | ||
1050 | struct ctl_table_root { | 1027 | struct ctl_node { |
1051 | struct list_head root_list; | 1028 | struct rb_node node; |
1052 | struct ctl_table_set default_set; | 1029 | struct ctl_table_header *header; |
1053 | struct ctl_table_set *(*lookup)(struct ctl_table_root *root, | ||
1054 | struct nsproxy *namespaces); | ||
1055 | int (*permissions)(struct ctl_table_root *root, | ||
1056 | struct nsproxy *namespaces, struct ctl_table *table); | ||
1057 | }; | 1030 | }; |
1058 | 1031 | ||
1059 | /* struct ctl_table_header is used to maintain dynamic lists of | 1032 | /* struct ctl_table_header is used to maintain dynamic lists of |
@@ -1063,9 +1036,9 @@ struct ctl_table_header | |||
1063 | union { | 1036 | union { |
1064 | struct { | 1037 | struct { |
1065 | struct ctl_table *ctl_table; | 1038 | struct ctl_table *ctl_table; |
1066 | struct list_head ctl_entry; | ||
1067 | int used; | 1039 | int used; |
1068 | int count; | 1040 | int count; |
1041 | int nreg; | ||
1069 | }; | 1042 | }; |
1070 | struct rcu_head rcu; | 1043 | struct rcu_head rcu; |
1071 | }; | 1044 | }; |
@@ -1073,9 +1046,27 @@ struct ctl_table_header | |||
1073 | struct ctl_table *ctl_table_arg; | 1046 | struct ctl_table *ctl_table_arg; |
1074 | struct ctl_table_root *root; | 1047 | struct ctl_table_root *root; |
1075 | struct ctl_table_set *set; | 1048 | struct ctl_table_set *set; |
1076 | struct ctl_table *attached_by; | 1049 | struct ctl_dir *parent; |
1077 | struct ctl_table *attached_to; | 1050 | struct ctl_node *node; |
1078 | struct ctl_table_header *parent; | 1051 | }; |
1052 | |||
1053 | struct ctl_dir { | ||
1054 | /* Header must be at the start of ctl_dir */ | ||
1055 | struct ctl_table_header header; | ||
1056 | struct rb_root root; | ||
1057 | }; | ||
1058 | |||
1059 | struct ctl_table_set { | ||
1060 | int (*is_seen)(struct ctl_table_set *); | ||
1061 | struct ctl_dir dir; | ||
1062 | }; | ||
1063 | |||
1064 | struct ctl_table_root { | ||
1065 | struct ctl_table_set default_set; | ||
1066 | struct ctl_table_set *(*lookup)(struct ctl_table_root *root, | ||
1067 | struct nsproxy *namespaces); | ||
1068 | int (*permissions)(struct ctl_table_root *root, | ||
1069 | struct nsproxy *namespaces, struct ctl_table *table); | ||
1079 | }; | 1070 | }; |
1080 | 1071 | ||
1081 | /* struct ctl_path describes where in the hierarchy a table is added */ | 1072 | /* struct ctl_path describes where in the hierarchy a table is added */ |
@@ -1083,16 +1074,53 @@ struct ctl_path { | |||
1083 | const char *procname; | 1074 | const char *procname; |
1084 | }; | 1075 | }; |
1085 | 1076 | ||
1077 | #ifdef CONFIG_SYSCTL | ||
1078 | |||
1079 | void proc_sys_poll_notify(struct ctl_table_poll *poll); | ||
1080 | |||
1081 | extern void setup_sysctl_set(struct ctl_table_set *p, | ||
1082 | struct ctl_table_root *root, | ||
1083 | int (*is_seen)(struct ctl_table_set *)); | ||
1084 | extern void retire_sysctl_set(struct ctl_table_set *set); | ||
1085 | |||
1086 | void register_sysctl_root(struct ctl_table_root *root); | 1086 | void register_sysctl_root(struct ctl_table_root *root); |
1087 | struct ctl_table_header *__register_sysctl_table( | ||
1088 | struct ctl_table_set *set, | ||
1089 | const char *path, struct ctl_table *table); | ||
1087 | struct ctl_table_header *__register_sysctl_paths( | 1090 | struct ctl_table_header *__register_sysctl_paths( |
1088 | struct ctl_table_root *root, struct nsproxy *namespaces, | 1091 | struct ctl_table_set *set, |
1089 | const struct ctl_path *path, struct ctl_table *table); | 1092 | const struct ctl_path *path, struct ctl_table *table); |
1093 | struct ctl_table_header *register_sysctl(const char *path, struct ctl_table *table); | ||
1090 | struct ctl_table_header *register_sysctl_table(struct ctl_table * table); | 1094 | struct ctl_table_header *register_sysctl_table(struct ctl_table * table); |
1091 | struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path, | 1095 | struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path, |
1092 | struct ctl_table *table); | 1096 | struct ctl_table *table); |
1093 | 1097 | ||
1094 | void unregister_sysctl_table(struct ctl_table_header * table); | 1098 | void unregister_sysctl_table(struct ctl_table_header * table); |
1095 | int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *table); | 1099 | |
1100 | extern int sysctl_init(void); | ||
1101 | #else /* CONFIG_SYSCTL */ | ||
1102 | static inline struct ctl_table_header *register_sysctl_table(struct ctl_table * table) | ||
1103 | { | ||
1104 | return NULL; | ||
1105 | } | ||
1106 | |||
1107 | static inline struct ctl_table_header *register_sysctl_paths( | ||
1108 | const struct ctl_path *path, struct ctl_table *table) | ||
1109 | { | ||
1110 | return NULL; | ||
1111 | } | ||
1112 | |||
1113 | static inline void unregister_sysctl_table(struct ctl_table_header * table) | ||
1114 | { | ||
1115 | } | ||
1116 | |||
1117 | static inline void setup_sysctl_set(struct ctl_table_set *p, | ||
1118 | struct ctl_table_root *root, | ||
1119 | int (*is_seen)(struct ctl_table_set *)) | ||
1120 | { | ||
1121 | } | ||
1122 | |||
1123 | #endif /* CONFIG_SYSCTL */ | ||
1096 | 1124 | ||
1097 | #endif /* __KERNEL__ */ | 1125 | #endif /* __KERNEL__ */ |
1098 | 1126 | ||