Skip to content

Commit 2f2665c

Browse files
Joelgranadosmcgrof
authored andcommitted
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 <[email protected]> Signed-off-by: Luis Chamberlain <[email protected]>
1 parent 94a6490 commit 2f2665c

File tree

3 files changed

+30
-66
lines changed

3 files changed

+30
-66
lines changed

drivers/parport/procfs.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,6 @@ parport_device_sysctl_template = {
387387
.data = NULL,
388388
.maxlen = 0,
389389
.mode = 0555,
390-
.child = NULL
391390
},
392391
{}
393392
}

fs/proc/proc_sysctl.c

Lines changed: 18 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@ static const struct file_operations proc_sys_dir_file_operations;
2929
static const struct inode_operations proc_sys_dir_operations;
3030

3131
/* Support for permanently empty directories */
32-
3332
struct ctl_table sysctl_mount_point[] = {
34-
{ }
33+
{.type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY }
3534
};
3635

3736
/**
@@ -48,21 +47,14 @@ struct ctl_table_header *register_sysctl_mount_point(const char *path)
4847
}
4948
EXPORT_SYMBOL(register_sysctl_mount_point);
5049

51-
static bool is_empty_dir(struct ctl_table_header *head)
52-
{
53-
return head->ctl_table[0].child == sysctl_mount_point;
54-
}
55-
56-
static void set_empty_dir(struct ctl_dir *dir)
57-
{
58-
dir->header.ctl_table[0].child = sysctl_mount_point;
59-
}
60-
61-
static void clear_empty_dir(struct ctl_dir *dir)
62-
63-
{
64-
dir->header.ctl_table[0].child = NULL;
65-
}
50+
#define sysctl_is_perm_empty_ctl_table(tptr) \
51+
(tptr[0].type == SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
52+
#define sysctl_is_perm_empty_ctl_header(hptr) \
53+
(sysctl_is_perm_empty_ctl_table(hptr->ctl_table))
54+
#define sysctl_set_perm_empty_ctl_header(hptr) \
55+
(hptr->ctl_table[0].type = SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY)
56+
#define sysctl_clear_perm_empty_ctl_header(hptr) \
57+
(hptr->ctl_table[0].type = SYSCTL_TABLE_TYPE_DEFAULT)
6658

6759
void proc_sys_poll_notify(struct ctl_table_poll *poll)
6860
{
@@ -230,20 +222,22 @@ static void erase_header(struct ctl_table_header *head)
230222
static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
231223
{
232224
struct ctl_table *entry;
225+
struct ctl_table_header *dir_h = &dir->header;
233226
int err;
234227

228+
235229
/* Is this a permanently empty directory? */
236-
if (is_empty_dir(&dir->header))
230+
if (sysctl_is_perm_empty_ctl_header(dir_h))
237231
return -EROFS;
238232

239233
/* Am I creating a permanently empty directory? */
240-
if (header->ctl_table == sysctl_mount_point) {
234+
if (sysctl_is_perm_empty_ctl_table(header->ctl_table)) {
241235
if (!RB_EMPTY_ROOT(&dir->root))
242236
return -EINVAL;
243-
set_empty_dir(dir);
237+
sysctl_set_perm_empty_ctl_header(dir_h);
244238
}
245239

246-
dir->header.nreg++;
240+
dir_h->nreg++;
247241
header->parent = dir;
248242
err = insert_links(header);
249243
if (err)
@@ -259,9 +253,9 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
259253
put_links(header);
260254
fail_links:
261255
if (header->ctl_table == sysctl_mount_point)
262-
clear_empty_dir(dir);
256+
sysctl_clear_perm_empty_ctl_header(dir_h);
263257
header->parent = NULL;
264-
drop_sysctl_table(&dir->header);
258+
drop_sysctl_table(dir_h);
265259
return err;
266260
}
267261

@@ -479,7 +473,7 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
479473
inode->i_mode |= S_IFDIR;
480474
inode->i_op = &proc_sys_dir_operations;
481475
inode->i_fop = &proc_sys_dir_file_operations;
482-
if (is_empty_dir(head))
476+
if (sysctl_is_perm_empty_ctl_header(head))
483477
make_empty_dir_inode(inode);
484478
}
485479

@@ -1136,9 +1130,6 @@ static int sysctl_check_table(const char *path, struct ctl_table *table)
11361130
struct ctl_table *entry;
11371131
int err = 0;
11381132
list_for_each_table_entry(entry, table) {
1139-
if (entry->child)
1140-
err |= sysctl_err(path, entry, "Not a file");
1141-
11421133
if ((entry->proc_handler == proc_dostring) ||
11431134
(entry->proc_handler == proc_dobool) ||
11441135
(entry->proc_handler == proc_dointvec) ||
@@ -1465,25 +1456,6 @@ void __init __register_sysctl_init(const char *path, struct ctl_table *table,
14651456
kmemleak_not_leak(hdr);
14661457
}
14671458

1468-
static int count_subheaders(struct ctl_table *table)
1469-
{
1470-
int has_files = 0;
1471-
int nr_subheaders = 0;
1472-
struct ctl_table *entry;
1473-
1474-
/* special case: no directory and empty directory */
1475-
if (!table || !table->procname)
1476-
return 1;
1477-
1478-
list_for_each_table_entry(entry, table) {
1479-
if (entry->child)
1480-
nr_subheaders += count_subheaders(entry->child);
1481-
else
1482-
has_files = 1;
1483-
}
1484-
return nr_subheaders + has_files;
1485-
}
1486-
14871459
static void put_links(struct ctl_table_header *header)
14881460
{
14891461
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)
15461518
*/
15471519
void unregister_sysctl_table(struct ctl_table_header * header)
15481520
{
1549-
int nr_subheaders;
15501521
might_sleep();
15511522

15521523
if (header == NULL)
15531524
return;
15541525

1555-
nr_subheaders = count_subheaders(header->ctl_table_arg);
1556-
if (unlikely(nr_subheaders > 1)) {
1557-
struct ctl_table_header **subheaders;
1558-
int i;
1559-
1560-
subheaders = (struct ctl_table_header **)(header + 1);
1561-
for (i = nr_subheaders -1; i >= 0; i--) {
1562-
struct ctl_table_header *subh = subheaders[i];
1563-
struct ctl_table *table = subh->ctl_table_arg;
1564-
unregister_sysctl_table(subh);
1565-
kfree(table);
1566-
}
1567-
kfree(header);
1568-
return;
1569-
}
1570-
15711526
spin_lock(&sysctl_lock);
15721527
drop_sysctl_table(header);
15731528
spin_unlock(&sysctl_lock);

include/linux/sysctl.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,17 @@ struct ctl_table {
137137
void *data;
138138
int maxlen;
139139
umode_t mode;
140-
struct ctl_table *child; /* Deprecated */
140+
/**
141+
* enum type - Enumeration to differentiate between ctl target types
142+
* @SYSCTL_TABLE_TYPE_DEFAULT: ctl target with no special considerations
143+
* @SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY: Used to identify a permanently
144+
* empty directory target to serve
145+
* as mount point.
146+
*/
147+
enum {
148+
SYSCTL_TABLE_TYPE_DEFAULT,
149+
SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY
150+
} type;
141151
proc_handler *proc_handler; /* Callback for text formatting */
142152
struct ctl_table_poll *poll;
143153
void *extra1;
@@ -229,7 +239,7 @@ extern int unaligned_enabled;
229239
extern int unaligned_dump_stack;
230240
extern int no_unaligned_warning;
231241

232-
extern struct ctl_table sysctl_mount_point[];
242+
#define SYSCTL_PERM_EMPTY_DIR (1 << 0)
233243

234244
#else /* CONFIG_SYSCTL */
235245

0 commit comments

Comments
 (0)