diff options
author | glebius <glebius@FreeBSD.org> | 2005-07-05 17:35:20 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2005-07-05 17:35:20 +0000 |
commit | fcbdfd0eb4f509af7f2a382daaf2c52ce49704c8 (patch) | |
tree | 7c65a2a332dab7cec59b3eb4bdcbf403ceaac133 /sys/netgraph/ng_base.c | |
parent | 9c552f7c01059c885fb0604e8fc082ce51f3228a (diff) | |
download | FreeBSD-src-fcbdfd0eb4f509af7f2a382daaf2c52ce49704c8.zip FreeBSD-src-fcbdfd0eb4f509af7f2a382daaf2c52ce49704c8.tar.gz |
In the splnet times, netgraph was functional and synchronous. Nowadays,
an item may be queued and processed later. While this is OK for mbufs,
this is a problem for control messages.
In the framework:
- Add optional callback function pointer to an item. When item gets
applied the callback is executed from ng_apply_item().
- Add new flag NG_PROGRESS. If this flag is supplied, then return
EINPROGRESS instead of 0 in case if item failed to deliver
synchronously and was queued.
- Honor NG_PROGRESS in ng_snd_item().
In ng_socket:
- When userland sends control message add callback to the item.
- If ng_snd_item() returns EINPROGRESS, then sleep.
This change fixes possible races in ngctl(8) scripts.
Reviewed by: julian
Approved by: re (scottl)
Diffstat (limited to 'sys/netgraph/ng_base.c')
-rw-r--r-- | sys/netgraph/ng_base.c | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c index 00650eec..5a9f8d9 100644 --- a/sys/netgraph/ng_base.c +++ b/sys/netgraph/ng_base.c @@ -2211,7 +2211,11 @@ ng_snd_item(item_p item, int flags) ng_setisr(node); } mtx_unlock_spin(&(ngq->q_mtx)); - return (0); + + if (flags & NG_PROGRESS) + return (EINPROGRESS); + else + return (0); } /* * Take a queue item and a node and see if we can apply the item to @@ -2237,7 +2241,10 @@ ng_snd_item(item_p item, int flags) * have been queued in thises cases. */ if (item == NULL) { - return (0); + if (flags & NG_PROGRESS) + return (EINPROGRESS); + else + return (0); } #ifdef NETGRAPH_DEBUG @@ -2333,11 +2340,25 @@ ng_apply_item(node_p node, item_p item) int error = 0; ng_rcvdata_t *rcvdata; ng_rcvmsg_t *rcvmsg; + ng_apply_t *apply = NULL; + void *context = NULL; NGI_GET_HOOK(item, hook); /* clears stored hook */ #ifdef NETGRAPH_DEBUG _ngi_check(item, __FILE__, __LINE__); #endif + + /* + * If item has apply callback, store it. Clear callback + * immediately, two avoid another call in case if + * item would be reused by destination node. + */ + if (item->apply != NULL) { + apply = item->apply; + context = item->context; + item->apply = NULL; + } + switch (item->el_flags & NGQF_TYPE) { case NGQF_DATA: /* @@ -2453,6 +2474,11 @@ ng_apply_item(node_p node, item_p item) } else { ng_leave_write(&node->nd_input_queue); } + + /* Apply callback. */ + if (apply != NULL) + (*apply)(context, error); + return (error); } |