aboutsummaryrefslogtreecommitdiff
path: root/sys/netgraph/ng_socket.c
diff options
context:
space:
mode:
authorGleb Smirnoff <glebius@FreeBSD.org>2005-07-05 17:35:20 +0000
committerGleb Smirnoff <glebius@FreeBSD.org>2005-07-05 17:35:20 +0000
commit8afe16d57ba4342c1af786f76697aeab17d598b6 (patch)
tree7c65a2a332dab7cec59b3eb4bdcbf403ceaac133 /sys/netgraph/ng_socket.c
parent7906787a5f72aad5315b40024365f5a53e8f911a (diff)
Notes
Diffstat (limited to 'sys/netgraph/ng_socket.c')
-rw-r--r--sys/netgraph/ng_socket.c45
1 files changed, 44 insertions, 1 deletions
diff --git a/sys/netgraph/ng_socket.c b/sys/netgraph/ng_socket.c
index c016955de996..63be343ba21b 100644
--- a/sys/netgraph/ng_socket.c
+++ b/sys/netgraph/ng_socket.c
@@ -131,6 +131,7 @@ static int ng_bind(struct sockaddr *nam, struct ngpcb *pcbp);
static int ngs_mod_event(module_t mod, int event, void *data);
static int ship_msg(struct ngpcb *pcbp, struct ng_mesg *msg,
struct sockaddr_ng *addr);
+static void ng_socket_item_applied(void *context, int error);
/* Netgraph type descriptor */
static struct ng_type typestruct = {
@@ -208,6 +209,7 @@ ngc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
struct mbuf *control, struct thread *td)
{
struct ngpcb *const pcbp = sotongpcb(so);
+ struct ngsock *const priv = NG_NODE_PRIVATE(pcbp->sockdata->node);
struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr;
struct ng_mesg *msg;
struct mbuf *m0;
@@ -332,7 +334,29 @@ ngc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
item->el_dest->nd_type->name);
#endif
SAVE_LINE(item);
- error = ng_snd_item(item, NG_NOFLAGS);
+ /*
+ * We do not want to return from syscall until the item
+ * is processed by destination node. We register callback
+ * on the item, which will update priv->error when item
+ * was applied.
+ * If ng_snd_item() has queued item, we sleep until
+ * callback wakes us up.
+ */
+ item->apply = ng_socket_item_applied;
+ item->context = priv;
+ priv->error = -1;
+
+ error = ng_snd_item(item, NG_PROGRESS);
+
+ if (error == EINPROGRESS) {
+ mtx_lock(&priv->mtx);
+ if (priv->error == -1)
+ msleep(priv, &priv->mtx, 0, "ngsock", 0);
+ mtx_unlock(&priv->mtx);
+ KASSERT(priv->error != -1,
+ ("ng_socket: priv->error wasn't updated"));
+ error = priv->error;
+ }
release:
if (path != NULL)
@@ -553,6 +577,8 @@ ng_attach_cntl(struct socket *so)
}
NG_NODE_SET_PRIVATE(privdata->node, privdata);
+ mtx_init(&privdata->mtx, "ng_socket", NULL, MTX_DEF);
+
/* Link the pcb and the node private data */
privdata->ctlsock = pcbp;
pcbp->sockdata = privdata;
@@ -813,6 +839,10 @@ ship_msg(struct ngpcb *pcbp, struct ng_mesg *msg, struct sockaddr_ng *addr)
return (0);
}
+/***************************************************************
+ Netgraph node
+***************************************************************/
+
/*
* You can only create new nodes from the socket end of things.
*/
@@ -1020,10 +1050,23 @@ ngs_shutdown(node_p node)
}
NG_NODE_SET_PRIVATE(node, NULL);
NG_NODE_UNREF(node);
+ mtx_destroy(&priv->mtx);
FREE(priv, M_NETGRAPH_SOCK);
return (0);
}
+static void
+ng_socket_item_applied(void *context, int error)
+{
+ struct ngsock *const priv = (struct ngsock *)context;
+
+ mtx_lock(&priv->mtx);
+ priv->error = error;
+ wakeup(priv);
+ mtx_unlock(&priv->mtx);
+
+}
+
static int
dummy_disconnect(struct socket *so)
{