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 ...
This commit is contained in:
@@ -932,34 +932,14 @@ enum
|
||||
#include <linux/list.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/rbtree.h>
|
||||
|
||||
/* For the /proc/sys support */
|
||||
struct ctl_table;
|
||||
struct nsproxy;
|
||||
struct ctl_table_root;
|
||||
|
||||
struct ctl_table_set {
|
||||
struct list_head list;
|
||||
struct ctl_table_set *parent;
|
||||
int (*is_seen)(struct ctl_table_set *);
|
||||
};
|
||||
|
||||
extern void setup_sysctl_set(struct ctl_table_set *p,
|
||||
struct ctl_table_set *parent,
|
||||
int (*is_seen)(struct ctl_table_set *));
|
||||
|
||||
struct ctl_table_header;
|
||||
|
||||
extern void sysctl_head_get(struct ctl_table_header *);
|
||||
extern void sysctl_head_put(struct ctl_table_header *);
|
||||
extern int sysctl_is_seen(struct ctl_table_header *);
|
||||
extern struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *);
|
||||
extern struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev);
|
||||
extern struct ctl_table_header *__sysctl_head_next(struct nsproxy *namespaces,
|
||||
struct ctl_table_header *prev);
|
||||
extern void sysctl_head_finish(struct ctl_table_header *prev);
|
||||
extern int sysctl_perm(struct ctl_table_root *root,
|
||||
struct ctl_table *table, int op);
|
||||
struct ctl_dir;
|
||||
|
||||
typedef struct ctl_table ctl_table;
|
||||
|
||||
@@ -1023,8 +1003,6 @@ static inline void *proc_sys_poll_event(struct ctl_table_poll *poll)
|
||||
return (void *)(unsigned long)atomic_read(&poll->event);
|
||||
}
|
||||
|
||||
void proc_sys_poll_notify(struct ctl_table_poll *poll);
|
||||
|
||||
#define __CTL_TABLE_POLL_INITIALIZER(name) { \
|
||||
.event = ATOMIC_INIT(0), \
|
||||
.wait = __WAIT_QUEUE_HEAD_INITIALIZER(name.wait) }
|
||||
@@ -1039,21 +1017,16 @@ struct ctl_table
|
||||
void *data;
|
||||
int maxlen;
|
||||
umode_t mode;
|
||||
struct ctl_table *child;
|
||||
struct ctl_table *parent; /* Automatically set */
|
||||
struct ctl_table *child; /* Deprecated */
|
||||
proc_handler *proc_handler; /* Callback for text formatting */
|
||||
struct ctl_table_poll *poll;
|
||||
void *extra1;
|
||||
void *extra2;
|
||||
};
|
||||
|
||||
struct ctl_table_root {
|
||||
struct list_head root_list;
|
||||
struct ctl_table_set default_set;
|
||||
struct ctl_table_set *(*lookup)(struct ctl_table_root *root,
|
||||
struct nsproxy *namespaces);
|
||||
int (*permissions)(struct ctl_table_root *root,
|
||||
struct nsproxy *namespaces, struct ctl_table *table);
|
||||
struct ctl_node {
|
||||
struct rb_node node;
|
||||
struct ctl_table_header *header;
|
||||
};
|
||||
|
||||
/* struct ctl_table_header is used to maintain dynamic lists of
|
||||
@@ -1063,9 +1036,9 @@ struct ctl_table_header
|
||||
union {
|
||||
struct {
|
||||
struct ctl_table *ctl_table;
|
||||
struct list_head ctl_entry;
|
||||
int used;
|
||||
int count;
|
||||
int nreg;
|
||||
};
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
@@ -1073,9 +1046,27 @@ struct ctl_table_header
|
||||
struct ctl_table *ctl_table_arg;
|
||||
struct ctl_table_root *root;
|
||||
struct ctl_table_set *set;
|
||||
struct ctl_table *attached_by;
|
||||
struct ctl_table *attached_to;
|
||||
struct ctl_table_header *parent;
|
||||
struct ctl_dir *parent;
|
||||
struct ctl_node *node;
|
||||
};
|
||||
|
||||
struct ctl_dir {
|
||||
/* Header must be at the start of ctl_dir */
|
||||
struct ctl_table_header header;
|
||||
struct rb_root root;
|
||||
};
|
||||
|
||||
struct ctl_table_set {
|
||||
int (*is_seen)(struct ctl_table_set *);
|
||||
struct ctl_dir dir;
|
||||
};
|
||||
|
||||
struct ctl_table_root {
|
||||
struct ctl_table_set default_set;
|
||||
struct ctl_table_set *(*lookup)(struct ctl_table_root *root,
|
||||
struct nsproxy *namespaces);
|
||||
int (*permissions)(struct ctl_table_root *root,
|
||||
struct nsproxy *namespaces, struct ctl_table *table);
|
||||
};
|
||||
|
||||
/* struct ctl_path describes where in the hierarchy a table is added */
|
||||
@@ -1083,16 +1074,53 @@ struct ctl_path {
|
||||
const char *procname;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
|
||||
void proc_sys_poll_notify(struct ctl_table_poll *poll);
|
||||
|
||||
extern void setup_sysctl_set(struct ctl_table_set *p,
|
||||
struct ctl_table_root *root,
|
||||
int (*is_seen)(struct ctl_table_set *));
|
||||
extern void retire_sysctl_set(struct ctl_table_set *set);
|
||||
|
||||
void register_sysctl_root(struct ctl_table_root *root);
|
||||
struct ctl_table_header *__register_sysctl_table(
|
||||
struct ctl_table_set *set,
|
||||
const char *path, struct ctl_table *table);
|
||||
struct ctl_table_header *__register_sysctl_paths(
|
||||
struct ctl_table_root *root, struct nsproxy *namespaces,
|
||||
struct ctl_table_set *set,
|
||||
const struct ctl_path *path, struct ctl_table *table);
|
||||
struct ctl_table_header *register_sysctl(const char *path, struct ctl_table *table);
|
||||
struct ctl_table_header *register_sysctl_table(struct ctl_table * table);
|
||||
struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path,
|
||||
struct ctl_table *table);
|
||||
|
||||
void unregister_sysctl_table(struct ctl_table_header * table);
|
||||
int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *table);
|
||||
|
||||
extern int sysctl_init(void);
|
||||
#else /* CONFIG_SYSCTL */
|
||||
static inline struct ctl_table_header *register_sysctl_table(struct ctl_table * table)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct ctl_table_header *register_sysctl_paths(
|
||||
const struct ctl_path *path, struct ctl_table *table)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void unregister_sysctl_table(struct ctl_table_header * table)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void setup_sysctl_set(struct ctl_table_set *p,
|
||||
struct ctl_table_root *root,
|
||||
int (*is_seen)(struct ctl_table_set *))
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
|
Reference in New Issue
Block a user