sysctl: replace child with an enumeration
This is part of the effort to remove the empty element at the end of ctl_table structs. "child" was a deprecated elem in this struct and was being used to differentiate between two types of ctl_tables: "normal" and "permanently emtpy". What changed?: * Replace "child" with an enumeration that will have two values: the default (0) and the permanently empty (1). The latter is left at zero so when struct ctl_table is created with kzalloc or in a local context, it will have the zero value by default. We document the new enum with kdoc. * Remove the "empty child" check from sysctl_check_table * Remove count_subheaders function as there is no longer a need to calculate how many headers there are for every child * Remove the recursive call to unregister_sysctl_table as there is no need to traverse down the child tree any longer * Add a new SYSCTL_PERM_EMPTY_DIR binary flag * Remove the last remanence of child from partport/procfs.c Signed-off-by: Joel Granados <j.granados@samsung.com> Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
This commit is contained in:
parent
94a6490518
commit
2f2665c13a
3 changed files with 30 additions and 66 deletions
|
@ -387,7 +387,6 @@ parport_device_sysctl_template = {
|
||||||
.data = NULL,
|
.data = NULL,
|
||||||
.maxlen = 0,
|
.maxlen = 0,
|
||||||
.mode = 0555,
|
.mode = 0555,
|
||||||
.child = NULL
|
|
||||||
},
|
},
|
||||||
{}
|
{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,8 @@ static const struct file_operations proc_sys_dir_file_operations;
|
||||||
static const struct inode_operations proc_sys_dir_operations;
|
static const struct inode_operations proc_sys_dir_operations;
|
||||||
|
|
||||||
/* Support for permanently empty directories */
|
/* Support for permanently empty directories */
|
||||||
|
|
||||||
struct ctl_table sysctl_mount_point[] = {
|
struct ctl_table sysctl_mount_point[] = {
|
||||||
{ }
|
{.type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY }
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,21 +47,14 @@ struct ctl_table_header *register_sysctl_mount_point(const char *path)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(register_sysctl_mount_point);
|
EXPORT_SYMBOL(register_sysctl_mount_point);
|
||||||
|
|
||||||
static bool is_empty_dir(struct ctl_table_header *head)
|
#define sysctl_is_perm_empty_ctl_table(tptr) \
|
||||||
{
|
(tptr[0].type == SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
|
||||||
return head->ctl_table[0].child == sysctl_mount_point;
|
#define sysctl_is_perm_empty_ctl_header(hptr) \
|
||||||
}
|
(sysctl_is_perm_empty_ctl_table(hptr->ctl_table))
|
||||||
|
#define sysctl_set_perm_empty_ctl_header(hptr) \
|
||||||
static void set_empty_dir(struct ctl_dir *dir)
|
(hptr->ctl_table[0].type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
|
||||||
{
|
#define sysctl_clear_perm_empty_ctl_header(hptr) \
|
||||||
dir->header.ctl_table[0].child = sysctl_mount_point;
|
(hptr->ctl_table[0].type = SYSCTL_TABLE_TYPE_DEFAULT)
|
||||||
}
|
|
||||||
|
|
||||||
static void clear_empty_dir(struct ctl_dir *dir)
|
|
||||||
|
|
||||||
{
|
|
||||||
dir->header.ctl_table[0].child = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void proc_sys_poll_notify(struct ctl_table_poll *poll)
|
void proc_sys_poll_notify(struct ctl_table_poll *poll)
|
||||||
{
|
{
|
||||||
|
@ -230,20 +222,22 @@ static void erase_header(struct ctl_table_header *head)
|
||||||
static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
|
static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
|
||||||
{
|
{
|
||||||
struct ctl_table *entry;
|
struct ctl_table *entry;
|
||||||
|
struct ctl_table_header *dir_h = &dir->header;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
|
||||||
/* Is this a permanently empty directory? */
|
/* Is this a permanently empty directory? */
|
||||||
if (is_empty_dir(&dir->header))
|
if (sysctl_is_perm_empty_ctl_header(dir_h))
|
||||||
return -EROFS;
|
return -EROFS;
|
||||||
|
|
||||||
/* Am I creating a permanently empty directory? */
|
/* Am I creating a permanently empty directory? */
|
||||||
if (header->ctl_table == sysctl_mount_point) {
|
if (sysctl_is_perm_empty_ctl_table(header->ctl_table)) {
|
||||||
if (!RB_EMPTY_ROOT(&dir->root))
|
if (!RB_EMPTY_ROOT(&dir->root))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
set_empty_dir(dir);
|
sysctl_set_perm_empty_ctl_header(dir_h);
|
||||||
}
|
}
|
||||||
|
|
||||||
dir->header.nreg++;
|
dir_h->nreg++;
|
||||||
header->parent = dir;
|
header->parent = dir;
|
||||||
err = insert_links(header);
|
err = insert_links(header);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -259,9 +253,9 @@ fail:
|
||||||
put_links(header);
|
put_links(header);
|
||||||
fail_links:
|
fail_links:
|
||||||
if (header->ctl_table == sysctl_mount_point)
|
if (header->ctl_table == sysctl_mount_point)
|
||||||
clear_empty_dir(dir);
|
sysctl_clear_perm_empty_ctl_header(dir_h);
|
||||||
header->parent = NULL;
|
header->parent = NULL;
|
||||||
drop_sysctl_table(&dir->header);
|
drop_sysctl_table(dir_h);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,7 +473,7 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
|
||||||
inode->i_mode |= S_IFDIR;
|
inode->i_mode |= S_IFDIR;
|
||||||
inode->i_op = &proc_sys_dir_operations;
|
inode->i_op = &proc_sys_dir_operations;
|
||||||
inode->i_fop = &proc_sys_dir_file_operations;
|
inode->i_fop = &proc_sys_dir_file_operations;
|
||||||
if (is_empty_dir(head))
|
if (sysctl_is_perm_empty_ctl_header(head))
|
||||||
make_empty_dir_inode(inode);
|
make_empty_dir_inode(inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1136,9 +1130,6 @@ static int sysctl_check_table(const char *path, struct ctl_table *table)
|
||||||
struct ctl_table *entry;
|
struct ctl_table *entry;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
list_for_each_table_entry(entry, table) {
|
list_for_each_table_entry(entry, table) {
|
||||||
if (entry->child)
|
|
||||||
err |= sysctl_err(path, entry, "Not a file");
|
|
||||||
|
|
||||||
if ((entry->proc_handler == proc_dostring) ||
|
if ((entry->proc_handler == proc_dostring) ||
|
||||||
(entry->proc_handler == proc_dobool) ||
|
(entry->proc_handler == proc_dobool) ||
|
||||||
(entry->proc_handler == proc_dointvec) ||
|
(entry->proc_handler == proc_dointvec) ||
|
||||||
|
@ -1465,25 +1456,6 @@ void __init __register_sysctl_init(const char *path, struct ctl_table *table,
|
||||||
kmemleak_not_leak(hdr);
|
kmemleak_not_leak(hdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int count_subheaders(struct ctl_table *table)
|
|
||||||
{
|
|
||||||
int has_files = 0;
|
|
||||||
int nr_subheaders = 0;
|
|
||||||
struct ctl_table *entry;
|
|
||||||
|
|
||||||
/* special case: no directory and empty directory */
|
|
||||||
if (!table || !table->procname)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
list_for_each_table_entry(entry, table) {
|
|
||||||
if (entry->child)
|
|
||||||
nr_subheaders += count_subheaders(entry->child);
|
|
||||||
else
|
|
||||||
has_files = 1;
|
|
||||||
}
|
|
||||||
return nr_subheaders + has_files;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void put_links(struct ctl_table_header *header)
|
static void put_links(struct ctl_table_header *header)
|
||||||
{
|
{
|
||||||
struct ctl_table_set *root_set = &sysctl_table_root.default_set;
|
struct ctl_table_set *root_set = &sysctl_table_root.default_set;
|
||||||
|
@ -1546,28 +1518,11 @@ static void drop_sysctl_table(struct ctl_table_header *header)
|
||||||
*/
|
*/
|
||||||
void unregister_sysctl_table(struct ctl_table_header * header)
|
void unregister_sysctl_table(struct ctl_table_header * header)
|
||||||
{
|
{
|
||||||
int nr_subheaders;
|
|
||||||
might_sleep();
|
might_sleep();
|
||||||
|
|
||||||
if (header == NULL)
|
if (header == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
nr_subheaders = count_subheaders(header->ctl_table_arg);
|
|
||||||
if (unlikely(nr_subheaders > 1)) {
|
|
||||||
struct ctl_table_header **subheaders;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
subheaders = (struct ctl_table_header **)(header + 1);
|
|
||||||
for (i = nr_subheaders -1; i >= 0; i--) {
|
|
||||||
struct ctl_table_header *subh = subheaders[i];
|
|
||||||
struct ctl_table *table = subh->ctl_table_arg;
|
|
||||||
unregister_sysctl_table(subh);
|
|
||||||
kfree(table);
|
|
||||||
}
|
|
||||||
kfree(header);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_lock(&sysctl_lock);
|
spin_lock(&sysctl_lock);
|
||||||
drop_sysctl_table(header);
|
drop_sysctl_table(header);
|
||||||
spin_unlock(&sysctl_lock);
|
spin_unlock(&sysctl_lock);
|
||||||
|
|
|
@ -137,7 +137,17 @@ struct ctl_table {
|
||||||
void *data;
|
void *data;
|
||||||
int maxlen;
|
int maxlen;
|
||||||
umode_t mode;
|
umode_t mode;
|
||||||
struct ctl_table *child; /* Deprecated */
|
/**
|
||||||
|
* 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 */
|
proc_handler *proc_handler; /* Callback for text formatting */
|
||||||
struct ctl_table_poll *poll;
|
struct ctl_table_poll *poll;
|
||||||
void *extra1;
|
void *extra1;
|
||||||
|
@ -229,7 +239,7 @@ extern int unaligned_enabled;
|
||||||
extern int unaligned_dump_stack;
|
extern int unaligned_dump_stack;
|
||||||
extern int no_unaligned_warning;
|
extern int no_unaligned_warning;
|
||||||
|
|
||||||
extern struct ctl_table sysctl_mount_point[];
|
#define SYSCTL_PERM_EMPTY_DIR (1 << 0)
|
||||||
|
|
||||||
#else /* CONFIG_SYSCTL */
|
#else /* CONFIG_SYSCTL */
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue