Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 938aaa4f authored by Eric W. Biederman's avatar Eric W. Biederman
Browse files

sysctl: Initial support for auto-unregistering sysctl tables.



Add nreg to ctl_table_header.  When nreg drops to 0 the ctl_table_header
will be unregistered.

Factor out drop_sysctl_table from unregister_sysctl_table, and add
the logic for decrementing nreg.

Signed-off-by: default avatarEric W. Biederman <ebiederm@xmission.com>
parent 3cc3e046
Loading
Loading
Loading
Loading
+19 −9
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@ static struct ctl_table root_table[1];
static struct ctl_table_root sysctl_table_root;
static struct ctl_table_root sysctl_table_root;
static struct ctl_table_header root_table_header = {
static struct ctl_table_header root_table_header = {
	{{.count = 1,
	{{.count = 1,
	  .nreg = 1,
	  .ctl_table = root_table,
	  .ctl_table = root_table,
	  .ctl_entry = LIST_HEAD_INIT(sysctl_table_root.default_set.list),}},
	  .ctl_entry = LIST_HEAD_INIT(sysctl_table_root.default_set.list),}},
	.root = &sysctl_table_root,
	.root = &sysctl_table_root,
@@ -938,6 +939,7 @@ struct ctl_table_header *__register_sysctl_table(
	header->unregistering = NULL;
	header->unregistering = NULL;
	header->root = root;
	header->root = root;
	header->count = 1;
	header->count = 1;
	header->nreg = 1;
	if (sysctl_check_table(path, table))
	if (sysctl_check_table(path, table))
		goto fail;
		goto fail;


@@ -1192,6 +1194,20 @@ struct ctl_table_header *register_sysctl_table(struct ctl_table *table)
}
}
EXPORT_SYMBOL(register_sysctl_table);
EXPORT_SYMBOL(register_sysctl_table);


static void drop_sysctl_table(struct ctl_table_header *header)
{
	if (--header->nreg)
		return;

	start_unregistering(header);
	if (!--header->parent->count) {
		WARN_ON(1);
		kfree_rcu(header->parent, rcu);
	}
	if (!--header->count)
		kfree_rcu(header, rcu);
}

/**
/**
 * unregister_sysctl_table - unregister a sysctl table hierarchy
 * unregister_sysctl_table - unregister a sysctl table hierarchy
 * @header: the header returned from register_sysctl_table
 * @header: the header returned from register_sysctl_table
@@ -1224,13 +1240,7 @@ void unregister_sysctl_table(struct ctl_table_header * header)
	}
	}


	spin_lock(&sysctl_lock);
	spin_lock(&sysctl_lock);
	start_unregistering(header);
	drop_sysctl_table(header);
	if (!--header->parent->count) {
		WARN_ON(1);
		kfree_rcu(header->parent, rcu);
	}
	if (!--header->count)
		kfree_rcu(header, rcu);
	spin_unlock(&sysctl_lock);
	spin_unlock(&sysctl_lock);
}
}
EXPORT_SYMBOL(unregister_sysctl_table);
EXPORT_SYMBOL(unregister_sysctl_table);
+1 −0
Original line number Original line Diff line number Diff line
@@ -1032,6 +1032,7 @@ struct ctl_table_header
			struct list_head ctl_entry;
			struct list_head ctl_entry;
			int used;
			int used;
			int count;
			int count;
			int nreg;
		};
		};
		struct rcu_head rcu;
		struct rcu_head rcu;
	};
	};