mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 06:01:57 +00:00
net: Don't register pernet_operations if only one of id or size is specified.
We can allocate per-netns memory for struct pernet_operations by specifying id and size. register_pernet_operations() assigns an id to pernet_operations and later ops_init() allocates the specified size of memory as net->gen->ptr[id]. If id is missing, no memory is allocated. If size is not specified, pernet_operations just wastes an entry of net->gen->ptr[] for every netns. net_generic is available only when both id and size are specified, so let's ensure that. While we are at it, we add const to both fields. Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
1ad001347f
commit
768e4bb6a7
@ -451,8 +451,8 @@ struct pernet_operations {
|
||||
/* Following method is called with RTNL held. */
|
||||
void (*exit_batch_rtnl)(struct list_head *net_exit_list,
|
||||
struct list_head *dev_kill_list);
|
||||
unsigned int *id;
|
||||
size_t size;
|
||||
unsigned int * const id;
|
||||
const size_t size;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -125,7 +125,7 @@ static int ops_init(const struct pernet_operations *ops, struct net *net)
|
||||
int err = -ENOMEM;
|
||||
void *data = NULL;
|
||||
|
||||
if (ops->id && ops->size) {
|
||||
if (ops->id) {
|
||||
data = kzalloc(ops->size, GFP_KERNEL);
|
||||
if (!data)
|
||||
goto out;
|
||||
@ -140,7 +140,7 @@ static int ops_init(const struct pernet_operations *ops, struct net *net)
|
||||
if (!err)
|
||||
return 0;
|
||||
|
||||
if (ops->id && ops->size) {
|
||||
if (ops->id) {
|
||||
ng = rcu_dereference_protected(net->gen,
|
||||
lockdep_is_held(&pernet_ops_rwsem));
|
||||
ng->ptr[*ops->id] = NULL;
|
||||
@ -182,7 +182,8 @@ static void ops_free_list(const struct pernet_operations *ops,
|
||||
struct list_head *net_exit_list)
|
||||
{
|
||||
struct net *net;
|
||||
if (ops->size && ops->id) {
|
||||
|
||||
if (ops->id) {
|
||||
list_for_each_entry(net, net_exit_list, exit_list)
|
||||
kfree(net_generic(net, *ops->id));
|
||||
}
|
||||
@ -1244,7 +1245,7 @@ static int __register_pernet_operations(struct list_head *list,
|
||||
LIST_HEAD(net_exit_list);
|
||||
|
||||
list_add_tail(&ops->list, list);
|
||||
if (ops->init || (ops->id && ops->size)) {
|
||||
if (ops->init || ops->id) {
|
||||
/* We held write locked pernet_ops_rwsem, and parallel
|
||||
* setup_net() and cleanup_net() are not possible.
|
||||
*/
|
||||
@ -1310,6 +1311,9 @@ static int register_pernet_operations(struct list_head *list,
|
||||
{
|
||||
int error;
|
||||
|
||||
if (WARN_ON(!!ops->id ^ !!ops->size))
|
||||
return -EINVAL;
|
||||
|
||||
if (ops->id) {
|
||||
error = ida_alloc_min(&net_generic_ids, MIN_PERNET_OPS_ID,
|
||||
GFP_KERNEL);
|
||||
|
Loading…
Reference in New Issue
Block a user