[Devel] [PATCH 6/6] proc connector: switch logic on per-net basis
Stanislav Kinsburskiy
skinsbursky at virtuozzo.com
Tue Aug 15 15:42:19 MSK 2017
This patch enables per-net containerization for proc connector.
Note: check for cn_net_id when accessing listeners is required, because proc
connector helpers are called from the early beginning, i.e. before per-net
operations were initialized.
https://jira.sw.ru/browse/PSBM-60227
Signed-off-by: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>
---
drivers/connector/cn_proc.c | 49 ++++++++++++++++------------------------
drivers/connector/connector.c | 50 +++++++----------------------------------
2 files changed, 28 insertions(+), 71 deletions(-)
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 7117c4d..c5bd47b 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -52,33 +52,41 @@ static inline struct cn_msg *buffer_to_cn_msg(__u8 *buffer)
return (struct cn_msg *)(buffer + 4);
}
-static atomic_t proc_event_num_listeners = ATOMIC_INIT(0);
static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC };
-/* proc_event_counts is used as the sequence number of the netlink message */
-static DEFINE_PER_CPU(__u32, proc_event_counts) = { 0 };
-
static inline void get_seq(struct net *net, __u32 *ts, int *cpu)
{
+ struct cn_net *cnn = net_generic(net, cn_net_id);
+
preempt_disable();
- *ts = __this_cpu_inc_return(proc_event_counts) - 1;
+ *ts = __this_cpu_inc_return(*cnn->proc_event_counts) - 1;
*cpu = smp_processor_id();
preempt_enable();
}
static int get_listeners(struct net *net)
{
- return atomic_read(&proc_event_num_listeners);
+ if (cn_net_id) {
+ struct cn_net *cnn = net_generic(net, cn_net_id);
+ return atomic_read(&cnn->proc_event_num_listeners);
+ }
+ return 0;
}
static void inc_listeners(struct net *net)
{
- atomic_inc(&proc_event_num_listeners);
+ if (cn_net_id) {
+ struct cn_net *cnn = net_generic(net, cn_net_id);
+ atomic_inc(&cnn->proc_event_num_listeners);
+ }
}
static void dec_listeners(struct net *net)
{
- atomic_dec(&proc_event_num_listeners);
+ if (cn_net_id) {
+ struct cn_net *cnn = net_generic(net, cn_net_id);
+ atomic_dec(&cnn->proc_event_num_listeners);
+ }
}
static struct net *task_net(struct task_struct *task)
@@ -397,12 +405,12 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg,
* and user namespaces so ignore requestors from
* other namespaces.
*/
- if ((current_user_ns() != &init_user_ns) ||
- (task_active_pid_ns(current) != &init_pid_ns))
+ if (!current_user_ns_initial() ||
+ (task_active_pid_ns(current) != get_exec_env()->ve_ns->pid_ns))
return;
/* Can only change if privileged. */
- if (!__netlink_ns_capable(nsp, &init_user_ns, CAP_NET_ADMIN)) {
+ if (!__netlink_ns_capable(nsp, ve_init_user_ns(), CAP_NET_ADMIN)) {
err = EPERM;
goto out;
}
@@ -456,22 +464,3 @@ void __net_exit cn_proc_exit_net(struct net *net)
free_percpu(cnn->proc_event_counts);
}
-
-/*
- * cn_proc_init - initialization entry point
- *
- * Adds the connector callback to the connector driver.
- */
-static int __init cn_proc_init(void)
-{
- int err = cn_add_callback(&cn_proc_event_id,
- "cn_proc",
- &cn_proc_mcast_ctl);
- if (err) {
- pr_warn("cn_proc failed to register\n");
- return err;
- }
- return 0;
-}
-
-module_init(cn_proc_init);
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index e098d6f..9b2c537d 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -40,10 +40,6 @@ MODULE_AUTHOR("Evgeniy Polyakov <zbr at ioremap.net>");
MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector.");
MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_CONNECTOR);
-static struct cn_dev cdev;
-
-static int cn_already_initialized;
-
/*
* msg->seq and msg->ack are used to determine message genealogy.
* When someone sends message it puts there locally unique sequence
@@ -68,7 +64,10 @@ static int cn_already_initialized;
static struct cn_dev *get_cdev(void)
{
- return &cdev;
+ struct net *net = get_exec_env()->ve_netns;
+ struct cn_net *cnn = net_generic(net, cn_net_id);
+
+ return cnn->cdev;
}
int cn_netlink_send(struct cn_msg *msg, u32 __group, gfp_t gfp_mask)
@@ -189,7 +188,9 @@ static void cn_rx_skb(struct sk_buff *__skb)
static int cn_initialized(struct net *net)
{
- return cn_already_initialized;
+ struct cn_net *cnn = net_generic(net, cn_net_id);
+
+ return cnn->cn_already_initialized;
}
/*
@@ -377,47 +378,14 @@ static struct pernet_operations cn_pernet_ops = {
.size = sizeof(struct cn_net),
};
-static struct cn_dev cdev = {
- .input = cn_rx_skb,
-};
-
static int cn_init(void)
{
- struct cn_dev *dev = get_cdev();
- struct netlink_kernel_cfg cfg = {
- .groups = CN_NETLINK_USERS + 0xf,
- .input = dev->input,
- };
-
- (void) cn_pernet_ops;
-
- dev->nls = netlink_kernel_create(&init_net, NETLINK_CONNECTOR, &cfg);
- if (!dev->nls)
- return -EIO;
-
- dev->cbdev = cn_queue_alloc_dev("cqueue", dev->nls);
- if (!dev->cbdev) {
- netlink_kernel_release(dev->nls);
- return -EINVAL;
- }
-
- cn_already_initialized = 1;
-
- proc_create("connector", S_IRUGO, init_net.proc_net, &cn_file_ops);
-
- return 0;
+ return register_pernet_subsys(&cn_pernet_ops);
}
static void cn_fini(void)
{
- struct cn_dev *dev = get_cdev();
-
- cn_already_initialized = 0;
-
- remove_proc_entry("connector", init_net.proc_net);
-
- cn_queue_free_dev(dev->cbdev);
- netlink_kernel_release(dev->nls);
+ return unregister_pernet_subsys(&cn_pernet_ops);
}
subsys_initcall(cn_init);
More information about the Devel
mailing list