[Devel] [PATCH RH9 19/26] proc connector: take number of listeners and per-cpu conters from VE
Pavel Tikhomirov
ptikhomirov at virtuozzo.com
Thu Oct 7 15:53:59 MSK 2021
From: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>
Instead of static variables.
Signed-off-by: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>
Reviewed-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
khorenko@: rebase to RHEL8.4 notes:
- proc_event_counts completely rewritten
+++
proc connector: protect from task cpu migration in send_msg_ve
this_cpu_ptr() should be used under local_lock() (or task migration
should be disabled instead), so switch the order.
Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn at virtuozzo.com>
(cherry picked from vz8 commit 3dcf53e526938e05eb88af5957984bda77b41819)
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
drivers/connector/cn_proc.c | 67 ++++++++++++++++++++++++++-----------
include/linux/connector.h | 3 +-
2 files changed, 49 insertions(+), 21 deletions(-)
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index a73d074ef488..838aeae09fcd 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -37,7 +37,6 @@ 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 };
/* local_event.count is used as the sequence number of the netlink message */
@@ -45,15 +44,21 @@ struct local_event {
local_lock_t lock;
__u32 count;
};
-static DEFINE_PER_CPU(struct local_event, local_event) = {
- .lock = INIT_LOCAL_LOCK(lock),
-};
-static inline void send_msg(struct cn_msg *msg)
+static inline void send_msg_ve(struct ve_struct *ve, struct cn_msg *msg)
{
- local_lock(&local_event.lock);
+ struct local_event *le_ptr;
+
+ /*
+ * The following hack with local_event->lock address works only
+ * till the "lock" is the first field in the local_event struct,
+ * so be of the safe side.
+ */
+ BUILD_BUG_ON(offsetof(struct local_event, lock) != 0);
+ local_lock(&ve->cn->local_event->lock);
- msg->seq = __this_cpu_inc_return(local_event.count) - 1;
+ le_ptr = this_cpu_ptr(ve->cn->local_event);
+ msg->seq = le_ptr->count++;
((struct proc_event *)msg->data)->cpu = smp_processor_id();
/*
@@ -64,7 +69,7 @@ static inline void send_msg(struct cn_msg *msg)
*/
cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_NOWAIT);
- local_unlock(&local_event.lock);
+ local_unlock(&ve->cn->local_event->lock);
}
static struct cn_msg *cn_msg_fill(__u8 *buffer,
@@ -92,6 +97,13 @@ static struct cn_msg *cn_msg_fill(__u8 *buffer,
return fill_event(ev, task, cookie) ? msg : NULL;
}
+static int proc_event_num_listeners(struct ve_struct *ve)
+{
+ if (ve->cn)
+ return atomic_read(&ve->cn->proc_event_num_listeners);
+ return 0;
+}
+
static void proc_event_connector(struct task_struct *task,
int what, int cookie,
bool (*fill_event)(struct proc_event *ev,
@@ -100,8 +112,9 @@ static void proc_event_connector(struct task_struct *task,
{
struct cn_msg *msg;
__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
+ struct ve_struct *ve = task->task_ve;
- if (atomic_read(&proc_event_num_listeners) < 1)
+ if (proc_event_num_listeners(ve) < 1)
return;
msg = cn_msg_fill(buffer, task, what, cookie, fill_event);
@@ -109,7 +122,7 @@ static void proc_event_connector(struct task_struct *task,
return;
/* If cn_netlink_send() failed, the data is not sent */
- send_msg(msg);
+ send_msg_ve(ve, msg);
}
static bool fill_fork_event(struct proc_event *ev, struct task_struct *task,
@@ -284,13 +297,13 @@ void proc_exit_connector(struct task_struct *task)
* values because it's not being returned via syscall return
* mechanisms.
*/
-static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
+static void cn_proc_ack(struct ve_struct *ve, int err, int rcvd_seq, int rcvd_ack)
{
struct cn_msg *msg;
struct proc_event *ev;
__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
- if (atomic_read(&proc_event_num_listeners) < 1)
+ if (proc_event_num_listeners(ve) < 1)
return;
msg = buffer_to_cn_msg(buffer);
@@ -305,7 +318,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
msg->ack = rcvd_ack + 1;
msg->len = sizeof(*ev);
msg->flags = 0; /* not used */
- send_msg(msg);
+ send_msg_ve(ve, msg);
}
/**
@@ -316,6 +329,7 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg,
struct netlink_skb_parms *nsp)
{
enum proc_cn_mcast_op *mc_op = NULL;
+ struct ve_struct *ve = get_exec_env();
int err = 0;
if (msg->len != sizeof(*mc_op))
@@ -339,10 +353,10 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg,
mc_op = (enum proc_cn_mcast_op *)msg->data;
switch (*mc_op) {
case PROC_CN_MCAST_LISTEN:
- atomic_inc(&proc_event_num_listeners);
+ atomic_inc(&ve->cn->proc_event_num_listeners);
break;
case PROC_CN_MCAST_IGNORE:
- atomic_dec(&proc_event_num_listeners);
+ atomic_dec(&ve->cn->proc_event_num_listeners);
break;
default:
err = EINVAL;
@@ -350,22 +364,37 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg,
}
out:
- cn_proc_ack(err, msg->seq, msg->ack);
+ cn_proc_ack(ve, err, msg->seq, msg->ack);
}
int cn_proc_init_ve(struct ve_struct *ve)
{
- int err = cn_add_callback_ve(ve, &cn_proc_event_id,
- "cn_proc",
- &cn_proc_mcast_ctl);
+ int err, cpu;
+ struct local_event *le_ptr;
+
+ ve->cn->local_event = alloc_percpu(struct local_event);
+ if (!ve->cn->local_event)
+ return -ENOMEM;
+
+ for_each_possible_cpu(cpu) {
+ le_ptr = per_cpu_ptr(ve->cn->local_event, cpu);
+ local_lock_init(&le_ptr->lock);
+ }
+
+ err = cn_add_callback_ve(ve, &cn_proc_event_id,
+ "cn_proc",
+ &cn_proc_mcast_ctl);
if (err) {
pr_warn("VE#%d: cn_proc failed to register\n", ve->veid);
+ free_percpu(ve->cn->local_event);
return err;
}
+ atomic_set(&ve->cn->proc_event_num_listeners, 0);
return 0;
}
void cn_proc_fini_ve(struct ve_struct *ve)
{
cn_del_callback_ve(ve, &cn_proc_event_id);
+ free_percpu(ve->cn->local_event);
}
diff --git a/include/linux/connector.h b/include/linux/connector.h
index 23ba9dd97571..fa270a61e577 100644
--- a/include/linux/connector.h
+++ b/include/linux/connector.h
@@ -59,8 +59,7 @@ struct cn_private {
int cn_already_initialized;
atomic_t proc_event_num_listeners;
- u32 __percpu *proc_event_counts;
-
+ struct local_event __percpu *local_event;
};
struct ve_struct;
--
2.31.1
More information about the Devel
mailing list