Page MenuHomeFreeBSD

D39180.diff
No OneTemporary

D39180.diff

diff --git a/sys/netlink/netlink_domain.c b/sys/netlink/netlink_domain.c
--- a/sys/netlink/netlink_domain.c
+++ b/sys/netlink/netlink_domain.c
@@ -46,6 +46,8 @@
#include <sys/syslog.h>
#include <sys/priv.h> /* priv_check */
+#include <sys/syscallsubr.h>
+
#include <netlink/netlink.h>
#include <netlink/netlink_ctl.h>
#include <netlink/netlink_var.h>
@@ -268,6 +270,18 @@
return (0);
}
+static int
+nlp_thread_init(struct thread *td, void *thunk)
+{
+ struct nlpcb *nlp = thunk;
+
+ nlp->nl_thread = td;
+
+ cpu_fork_kthread_handler(td, nl_taskqueue_handler, nlp);
+
+ return (0);
+}
+
static int
nl_pru_attach(struct socket *so, int proto, struct thread *td)
{
@@ -312,11 +326,20 @@
refcount_init(&nlp->nl_refcount, 1);
nl_init_io(nlp);
+ error = thread_create(td, NULL, nlp_thread_init, nlp);
+ if (error != 0) {
+ free(nlp, M_PCB);
+ return (error);
+ }
+ NL_LOG(LOG_DEBUG2, "thread %p created", nlp->nl_thread);
+
+#if 0
nlp->nl_taskqueue = taskqueue_create("netlink_socket", M_WAITOK,
taskqueue_thread_enqueue, &nlp->nl_taskqueue);
TASK_INIT(&nlp->nl_task, 0, nl_taskqueue_handler, nlp);
- taskqueue_start_threads(&nlp->nl_taskqueue, 1, PWAIT,
- "netlink_socket (PID %u)", nlp->nl_process_id);
+ taskqueue_start_threads_in_proc(&nlp->nl_taskqueue, 1, PWAIT,
+ td->td_proc, "netlink_socket (PID %u)", nlp->nl_process_id);
+#endif
NLCTL_WLOCK(ctl);
/* XXX: check ctl is still alive */
@@ -477,9 +500,26 @@
nlp->nl_active = false;
NLP_UNLOCK(nlp);
+ NL_LOG(LOG_DEBUG2, "Waking up thread %p", nlp->nl_thread);
+ wakeup_any(nlp);
+
+ NLP_LOCK(nlp);
+ if (!nlp->nl_dead) {
+ NL_LOG(LOG_DEBUG2, "Waiting till the thread dies");
+ mtx_sleep(&nlp->nl_epoch_ctx, &nlp->nl_lock, 0, "dying", 0);
+ }
+ NL_LOG(LOG_DEBUG2, "Thread %p set dead to %s", nlp->nl_thread, nlp->nl_dead ? "true" : "false");
+ MPASS(nlp->nl_dead);
+ NLP_UNLOCK(nlp);
+
+ int error = kern_thr_exit(nlp->nl_thread);
+ NL_LOG(LOG_DEBUG2, "thread_exit(%p) returned %d", nlp->nl_thread, error);
+
+#if 0
/* Wait till all scheduled work has been completed */
taskqueue_drain_all(nlp->nl_taskqueue);
taskqueue_free(nlp->nl_taskqueue);
+#endif
NLCTL_WLOCK(ctl);
NLP_LOCK(nlp);
diff --git a/sys/netlink/netlink_io.c b/sys/netlink/netlink_io.c
--- a/sys/netlink/netlink_io.c
+++ b/sys/netlink/netlink_io.c
@@ -129,7 +129,7 @@
{
if (!nlp->nl_task_pending) {
nlp->nl_task_pending = true;
- taskqueue_enqueue(nlp->nl_taskqueue, &nlp->nl_task);
+ wakeup_any(nlp);
NL_LOG(LOG_DEBUG3, "taskqueue scheduled");
} else {
NL_LOG(LOG_DEBUG3, "taskqueue schedule skipped");
@@ -301,13 +301,33 @@
}
void
-nl_taskqueue_handler(void *_arg, int pending)
+nl_taskqueue_handler(void *_arg)
{
struct nlpcb *nlp = (struct nlpcb *)_arg;
CURVNET_SET(nlp->nl_socket->so_vnet);
- nl_process_received(nlp);
+
+ NL_LOG(LOG_DEBUG2, "work thread %p for nlp %p started", nlp->nl_thread, nlp);
+
+ NLP_LOCK(nlp);
+ while (true) {
+ NL_LOG(LOG_DEBUG2, "sleeping / waiting for work");
+ mtx_sleep(nlp, &nlp->nl_lock, 0, "nlp sleep", 0);
+ NL_LOG(LOG_DEBUG2, "worken up, socket is %s", nlp->nl_active ? "active":"dying");
+ if (__predict_false(!nlp->nl_active))
+ break;
+ NLP_UNLOCK(nlp);
+ nl_process_received(nlp);
+ NLP_LOCK(nlp);
+ }
+ nlp->nl_dead = true;
+ NL_LOG(LOG_DEBUG2, "SET dead to true");
+ NLP_UNLOCK(nlp);
+
CURVNET_RESTORE();
+
+ wakeup_one(&nlp->nl_epoch_ctx);
+ NL_LOG(LOG_DEBUG2, "work thread %p for nlp %p ended", nlp->nl_thread, nlp);
}
static __noinline void
diff --git a/sys/netlink/netlink_var.h b/sys/netlink/netlink_var.h
--- a/sys/netlink/netlink_var.h
+++ b/sys/netlink/netlink_var.h
@@ -61,10 +61,10 @@
bool nl_task_pending;
bool nl_tx_blocked; /* No new requests accepted */
bool nl_linux; /* true if running under compat */
+ bool nl_dead;
struct nl_io_queue rx_queue;
struct nl_io_queue tx_queue;
- struct taskqueue *nl_taskqueue;
- struct task nl_task;
+ struct thread *nl_thread;
struct ucred *nl_cred; /* Copy of nl_socket->so_cred */
uint64_t nl_dropped_bytes;
uint64_t nl_dropped_messages;
@@ -139,7 +139,7 @@
void nl_init_io(struct nlpcb *nlp);
void nl_free_io(struct nlpcb *nlp);
-void nl_taskqueue_handler(void *_arg, int pending);
+void nl_taskqueue_handler(void *_arg);
int nl_receive_async(struct mbuf *m, struct socket *so);
void nl_process_receive_locked(struct nlpcb *nlp);
diff --git a/sys/netlink/route/iface.c b/sys/netlink/route/iface.c
--- a/sys/netlink/route/iface.c
+++ b/sys/netlink/route/iface.c
@@ -928,14 +928,11 @@
}
static void
-rtnl_handle_ifevent(struct ifnet *ifp, int nlmsg_type, bool modify, int if_flags_mask)
+rtnl_handle_ifevent(struct ifnet *ifp, int nlmsg_type, int if_flags_mask)
{
struct nlmsghdr hdr = { .nlmsg_type = nlmsg_type };
struct nl_writer nw = {};
- if (modify)
- hdr.nlmsg_flags |= NLM_F_REPLACE;
-
if (!nl_has_listeners(NETLINK_ROUTE, RTNLGRP_LINK))
return;

File Metadata

Mime Type
text/plain
Expires
Mon, May 18, 11:52 PM (11 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33277536
Default Alt Text
D39180.diff (4 KB)

Event Timeline