/*
* /proc/sys support
*/
#include <linux/init.h>
#include <linux/sysctl.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/security.h>
#include <linux/namei.h>
#include <linux/module.h>
#include "internal.h"
static const struct dentry_operations proc_sys_dentry_operations;
static const struct file_operations proc_sys_file_operations;
static const struct inode_operations proc_sys_inode_operations;
static const struct file_operations proc_sys_dir_file_operations;
static const struct inode_operations proc_sys_dir_operations;
void proc_sys_poll_notify(struct ctl_table_poll *poll)
{
if (!poll)
return;
atomic_inc(&poll->event);
wake_up_interruptible(&poll->wait);
}
static struct ctl_table root_table[1];
static struct ctl_table_root sysctl_table_root;
static struct ctl_table_header root_table_header = {
{{.count = 1,
.nreg = 1,
.ctl_table = root_table,
.ctl_entry = LIST_HEAD_INIT(sysctl_table_root.default_set.list),}},
.root = &sysctl_table_root,
.set = &sysctl_table_root.default_set,
};
static struct ctl_table_root sysctl_table_root = {
.root_list = LIST_HEAD_INIT(sysctl_table_root.root_list),
.default_set.list = LIST_HEAD_INIT(root_table_header.ctl_entry),
};
static DEFINE_SPINLOCK(sysctl_lock);
static void init_header(struct ctl_table_header *head,
struct ctl_table_root *root, struct ctl_table_set *set,
struct ctl_table *table)
{
head->ctl_table_arg = table;
INIT_LIST_HEAD(&head->ctl_entry);
head->used = 0;
head->count = 1;
head->nreg = 1;
head->unregistering = NULL;
head->root = root;
head->set = set;
head->parent = NULL;
}
static void erase_header(struct ctl_table_header *head)
{
list_del_init(&head->ctl_entry);
}
static void insert_header(struct ctl_table_header *header)
{
header->parent->count++;
list_add_tail(&header->ctl_entry, &header->set->list);
}
/* called under sysctl_lock */
static int use_table(struct ctl_table_header *p)
{
if (unlikely(p->unregistering