|
@@ -1561,11 +1561,12 @@ static __init int sysctl_init(void)
|
|
|
core_initcall(sysctl_init);
|
|
|
|
|
|
/**
|
|
|
- * register_sysctl_table - register a sysctl hierarchy
|
|
|
+ * register_sysctl_paths - register a sysctl hierarchy
|
|
|
+ * @path: The path to the directory the sysctl table is in.
|
|
|
* @table: the top-level table structure
|
|
|
*
|
|
|
* Register a sysctl table hierarchy. @table should be a filled in ctl_table
|
|
|
- * array. An entry with a ctl_name of 0 terminates the table.
|
|
|
+ * array. A completely 0 filled entry terminates the table.
|
|
|
*
|
|
|
* The members of the &struct ctl_table structure are used as follows:
|
|
|
*
|
|
@@ -1628,25 +1629,76 @@ core_initcall(sysctl_init);
|
|
|
* This routine returns %NULL on a failure to register, and a pointer
|
|
|
* to the table header on success.
|
|
|
*/
|
|
|
-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)
|
|
|
{
|
|
|
- struct ctl_table_header *tmp;
|
|
|
- tmp = kmalloc(sizeof(struct ctl_table_header), GFP_KERNEL);
|
|
|
- if (!tmp)
|
|
|
+ struct ctl_table_header *header;
|
|
|
+ struct ctl_table *new, **prevp;
|
|
|
+ unsigned int n, npath;
|
|
|
+
|
|
|
+ /* Count the path components */
|
|
|
+ for (npath = 0; path[npath].ctl_name || path[npath].procname; ++npath)
|
|
|
+ ;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * For each path component, allocate a 2-element ctl_table array.
|
|
|
+ * The first array element will be filled with the sysctl entry
|
|
|
+ * for this, the second will be the sentinel (ctl_name == 0).
|
|
|
+ *
|
|
|
+ * We allocate everything in one go so that we don't have to
|
|
|
+ * worry about freeing additional memory in unregister_sysctl_table.
|
|
|
+ */
|
|
|
+ header = kzalloc(sizeof(struct ctl_table_header) +
|
|
|
+ (2 * npath * sizeof(struct ctl_table)), GFP_KERNEL);
|
|
|
+ if (!header)
|
|
|
return NULL;
|
|
|
- tmp->ctl_table = table;
|
|
|
- INIT_LIST_HEAD(&tmp->ctl_entry);
|
|
|
- tmp->used = 0;
|
|
|
- tmp->unregistering = NULL;
|
|
|
- sysctl_set_parent(NULL, table);
|
|
|
- if (sysctl_check_table(tmp->ctl_table)) {
|
|
|
- kfree(tmp);
|
|
|
+
|
|
|
+ new = (struct ctl_table *) (header + 1);
|
|
|
+
|
|
|
+ /* Now connect the dots */
|
|
|
+ prevp = &header->ctl_table;
|
|
|
+ for (n = 0; n < npath; ++n, ++path) {
|
|
|
+ /* Copy the procname */
|
|
|
+ new->procname = path->procname;
|
|
|
+ new->ctl_name = path->ctl_name;
|
|
|
+ new->mode = 0555;
|
|
|
+
|
|
|
+ *prevp = new;
|
|
|
+ prevp = &new->child;
|
|
|
+
|
|
|
+ new += 2;
|
|
|
+ }
|
|
|
+ *prevp = table;
|
|
|
+
|
|
|
+ INIT_LIST_HEAD(&header->ctl_entry);
|
|
|
+ header->used = 0;
|
|
|
+ header->unregistering = NULL;
|
|
|
+ sysctl_set_parent(NULL, header->ctl_table);
|
|
|
+ if (sysctl_check_table(header->ctl_table)) {
|
|
|
+ kfree(header);
|
|
|
return NULL;
|
|
|
}
|
|
|
spin_lock(&sysctl_lock);
|
|
|
- list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
|
|
|
+ list_add_tail(&header->ctl_entry, &root_table_header.ctl_entry);
|
|
|
spin_unlock(&sysctl_lock);
|
|
|
- return tmp;
|
|
|
+
|
|
|
+ return header;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * register_sysctl_table - register a sysctl table hierarchy
|
|
|
+ * @table: the top-level table structure
|
|
|
+ *
|
|
|
+ * Register a sysctl table hierarchy. @table should be a filled in ctl_table
|
|
|
+ * array. A completely 0 filled entry terminates the table.
|
|
|
+ *
|
|
|
+ * See register_sysctl_paths for more details.
|
|
|
+ */
|
|
|
+struct ctl_table_header *register_sysctl_table(struct ctl_table *table)
|
|
|
+{
|
|
|
+ static const struct ctl_path null_path[] = { {} };
|
|
|
+
|
|
|
+ return register_sysctl_paths(null_path, table);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1675,6 +1727,12 @@ struct ctl_table_header *register_sysctl_table(struct ctl_table * table)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
+struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path,
|
|
|
+ struct ctl_table *table)
|
|
|
+{
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
void unregister_sysctl_table(struct ctl_table_header * table)
|
|
|
{
|
|
|
}
|
|
@@ -2733,6 +2791,7 @@ EXPORT_SYMBOL(proc_dostring);
|
|
|
EXPORT_SYMBOL(proc_doulongvec_minmax);
|
|
|
EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
|
|
|
EXPORT_SYMBOL(register_sysctl_table);
|
|
|
+EXPORT_SYMBOL(register_sysctl_paths);
|
|
|
EXPORT_SYMBOL(sysctl_intvec);
|
|
|
EXPORT_SYMBOL(sysctl_jiffies);
|
|
|
EXPORT_SYMBOL(sysctl_ms_jiffies);
|