Page MenuHomeFreeBSD

D57519.diff
No OneTemporary

D57519.diff

diff --git a/sys/netlink/netlink.h b/sys/netlink/netlink.h
--- a/sys/netlink/netlink.h
+++ b/sys/netlink/netlink.h
@@ -90,6 +90,7 @@
#define NETLINK_GET_STRICT_CHK 12 /* Strict header checking */
#define NETLINK_MSG_INFO 257 /* (FreeBSD-specific) Receive message originator data in cmsg */
+#define NETLINK_SND_SYNC 258 /* (FreeBSD-specific) Process send operations synchronously */
/*
* RFC 3549, 2.3.2 Netlink Message Header
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
@@ -593,6 +593,52 @@
NL_LOG(LOG_DEBUG2, "sending message to kernel %u bytes", nb->datalen);
SOCK_SENDBUF_LOCK(so);
+
+ /* Sync path */
+ if (nlp->nl_flags & NLF_SND_SYNC) {
+ /*
+ * Wait for the queue to drain completely to prevent
+ * out-of-order execution of requests.
+ */
+ while (!TAILQ_EMPTY(&sb->nl_queue)) {
+ /* To avoid potential deadlock, we kick the async path */
+ NLP_LOCK(nlp);
+ nl_schedule_taskqueue(nlp);
+ NLP_UNLOCK(nlp);
+
+ if ((so->so_state & SS_NBIO) ||
+ (flags & (MSG_NBIO | MSG_DONTWAIT)) != 0) {
+ SOCK_SENDBUF_UNLOCK(so);
+ error = EWOULDBLOCK;
+ goto out;
+ }
+
+ error = mtx_sleep(&sb->nl_queue, SOCK_SENDBUF_MTX(so),
+ PCATCH, "nlsync", hz);
+ if (error != 0) {
+ /*
+ * Timeout, possibly indicating that the recv
+ * buffer is full. We need to notify the user to
+ * read it.
+ */
+ if (error == EWOULDBLOCK) {
+ error = ENOBUFS;
+ }
+ SOCK_SENDBUF_UNLOCK(so);
+ goto out;
+ }
+ }
+ SOCK_SENDBUF_UNLOCK(so);
+
+ error = nl_process_nbuf_sync(so, nb, nlp);
+ if (error == 0) {
+ NL_LOG(LOG_DEBUG3, "success");
+ nl_buf_free(nb);
+ nb = NULL;
+ }
+ goto out;
+ }
+
restart:
if (sb->sb_hiwat - sb->sb_ccc >= nb->datalen) {
TAILQ_INSERT_TAIL(&sb->nl_queue, nb, tailq);
@@ -840,6 +886,8 @@
return (NLF_STRICT);
case NETLINK_MSG_INFO:
return (NLF_MSG_INFO);
+ case NETLINK_SND_SYNC:
+ return (NLF_SND_SYNC);
}
return (0);
@@ -881,13 +929,15 @@
case NETLINK_EXT_ACK:
case NETLINK_GET_STRICT_CHK:
case NETLINK_MSG_INFO:
+ case NETLINK_SND_SYNC:
error = sooptcopyin(sopt, &optval, sizeof(optval), sizeof(optval));
if (error != 0)
break;
flag = nl_getoptflag(sopt->sopt_name);
- if ((flag == NLF_MSG_INFO) && nlp->nl_linux) {
+ if ((flag == NLF_MSG_INFO || flag == NLF_SND_SYNC) &&
+ nlp->nl_linux) {
error = EINVAL;
break;
}
@@ -915,6 +965,7 @@
case NETLINK_EXT_ACK:
case NETLINK_GET_STRICT_CHK:
case NETLINK_MSG_INFO:
+ case NETLINK_SND_SYNC:
NLCTL_RLOCK();
optval = (nlp->nl_flags & nl_getoptflag(sopt->sopt_name)) != 0;
NLCTL_RUNLOCK();
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
@@ -133,6 +133,8 @@
break;
}
}
+ if (TAILQ_EMPTY(&sb->nl_queue))
+ wakeup(&sb->nl_queue);
SOCK_SENDBUF_UNLOCK(so);
return (reschedule);
@@ -368,3 +370,28 @@
} else
return (true);
}
+
+int
+nl_process_nbuf_sync(struct socket *so, struct nl_buf *nb, struct nlpcb *nlp)
+{
+
+ struct sockbuf *sb = &so->so_rcv;
+
+ /*
+ * Do not process queued up requests if there is no space to queue
+ * replies.
+ */
+ SOCK_RECVBUF_LOCK(so);
+ if (sb->sb_hiwat <= sb->sb_ccc) {
+ SOCK_RECVBUF_UNLOCK(so);
+ NL_LOG(LOG_DEBUG3, "socket %p stuck", so);
+ return (ENOBUFS);
+ }
+ SOCK_RECVBUF_UNLOCK(so);
+
+ if (!nl_process_nbuf(nb, nlp)) {
+ return (ENOBUFS);
+ }
+
+ return (0);
+}
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
@@ -91,6 +91,7 @@
#define NLF_EXT_ACK 0x02 /* Allow including extended TLVs in ack */
#define NLF_STRICT 0x04 /* Perform strict header checks */
#define NLF_MSG_INFO 0x08 /* Send caller info along with the notifications */
+#define NLF_SND_SYNC 0x10 /* Process send operations synchronously */
SYSCTL_DECL(_net_netlink);
SYSCTL_DECL(_net_netlink_debug);
@@ -138,6 +139,7 @@
void nl_set_source_metadata(struct mbuf *m, int num_messages);
struct nl_buf *nl_buf_alloc(size_t len, int mflag);
void nl_buf_free(struct nl_buf *nb);
+int nl_process_nbuf_sync(struct socket *so, struct nl_buf *nb, struct nlpcb *nlp);
#define MAX_FAMILIES 20
#define MAX_GROUPS 64

File Metadata

Mime Type
text/plain
Expires
Sat, Jun 13, 2:27 PM (7 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33926100
Default Alt Text
D57519.diff (4 KB)

Event Timeline