register_pernet_subsys 笔记

pernet ops

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* register_pernet_subsys - register a network namespace subsystem
* @ops: pernet operations structure for the subsystem
*
* Register a subsystem which has init and exit functions
* that are called when network namespaces are created and
* destroyed respectively.
*
* When registered all network namespace init functions are
* called for every existing network namespace. Allowing kernel
* modules to have a race free view of the set of network namespaces.
*
* When a new network namespace is created all of the init
* methods are called in the order in which they were registered.
*
* When a network namespace is destroyed all of the exit methods
* are called in the reverse of the order with which they were
* registered.
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
int register_pernet_subsys(struct pernet_operations *ops)
{
int error;
mutex_lock(&net_mutex);
error = register_pernet_operations(first_device, ops);
mutex_unlock(&net_mutex);
return error;
}
===>static int register_pernet_operations(struct list_head *list,
struct pernet_operations *ops)
{
error = __register_pernet_operations(list, ops);
}

======>#ifdef CONFIG_NET_NS
static int __register_pernet_operations(struct list_head *list,
struct pernet_operations *ops)
LIST_HEAD(net_exit_list);

list_add_tail(&ops->list, list);
if (ops->init || (ops->id && ops->size)) {
for_each_net(net) {
error = ops_init(ops, net);
if (error)
goto out_undo;
list_add_tail(&net->exit_list, &net_exit_list);
}
}
return 0;


========>#ifdef CONFIG_NET_NS
static int __register_pernet_operations(struct list_head *list,
struct pernet_operations *ops)
struct net *net;
int error;
LIST_HEAD(net_exit_list);

list_add_tail(&ops->list, list);
if (ops->init || (ops->id && ops->size)) {
for_each_net(net) {
=============> error = ops_init(ops, net);
if (error)
goto out_undo;
=============> list_add_tail(&net->exit_list, &net_exit_list);<<< confused?!!! net_exit_list局部变量?

}
}
return 0;


=============>static int ops_init(const struct pernet_operations *ops, struct net *net)
{
int err;
if (ops->id && ops->size) {
void *data = kzalloc(ops->size, GFP_KERNEL);
if (!data)
return -ENOMEM;

err = net_assign_generic(net, *ops->id, data);
if (err) {
kfree(data);
return err;
}
}
if (ops->init)
return ops->init(net);<====== the ops->init will be called.
return 0;
}

####Fox example
inet6_init in pernet.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static struct pernet_operations inet6_net_ops = { 
.init = inet6_net_init,
.exit = inet6_net_exit,
};
static int __init inet6_init(void)
{
.....
err = register_pernet_subsys(&inet6_net_ops);
if (err)
goto register_pernet_fail;
.....
}
call: ops->init(net);<====== the ops->init will be called.
equal with ======= .init = inet6_net_init,
inet6_net_init(net);