Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F159299355
D57519.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D57519.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D57519: netlink: Add sync path in user-kernel interface
Attached
Detach File
Event Timeline
Log In to Comment