diff options
| author | Gleb Smirnoff <glebius@FreeBSD.org> | 2005-07-05 17:35:20 +0000 |
|---|---|---|
| committer | Gleb Smirnoff <glebius@FreeBSD.org> | 2005-07-05 17:35:20 +0000 |
| commit | 8afe16d57ba4342c1af786f76697aeab17d598b6 (patch) | |
| tree | 7c65a2a332dab7cec59b3eb4bdcbf403ceaac133 /sys/netgraph/ng_socket.c | |
| parent | 7906787a5f72aad5315b40024365f5a53e8f911a (diff) | |
Notes
Diffstat (limited to 'sys/netgraph/ng_socket.c')
| -rw-r--r-- | sys/netgraph/ng_socket.c | 45 |
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) { |
