Improve apply callback error reporting:

Before this patch callback returned result of the last finished call chain.
Now it returns last nonzero result from all call chain results in this request.

As soon as this improvement gives reliable error reporting, it is now possible
to remove dirty workaround in ng_socket, made to return ENOBUFS error statuses
of request-response operations. That workaround was responsible for returning
ENOBUFS errors to completely unrelated requests working at the same time
on socket.
This commit is contained in:
Alexander Motin 2008-03-11 21:58:48 +00:00
parent 1b085fde87
commit 10e873189c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=177071
3 changed files with 28 additions and 10 deletions

View File

@ -608,6 +608,7 @@ struct ng_apply_info {
ng_apply_t *apply;
void *context;
int refs;
int error;
};
struct ng_item {
u_long el_flags;
@ -634,7 +635,7 @@ struct ng_item {
* and its context.
*/
struct ng_apply_info *apply;
void *PAD1;
uintptr_t depth;
#ifdef NETGRAPH_DEBUG /*----------------------------------------------*/
char *lastfile;
int lastline;

View File

@ -2250,9 +2250,13 @@ ng_flush_input_queue(struct ng_queue * ngq)
NG_QUEUE_UNLOCK(ngq);
/* If the item is supplying a callback, call it with an error */
if (item->apply != NULL &&
refcount_release(&item->apply->refs)) {
(*item->apply->apply)(item->apply->context, ENOENT);
if (item->apply != NULL) {
if (item->depth == 1)
item->apply->error = ENOENT;
if (refcount_release(&item->apply->refs)) {
(*item->apply->apply)(item->apply->context,
item->apply->error);
}
}
NG_FREE_ITEM(item);
NG_QUEUE_LOCK(ngq);
@ -2367,6 +2371,7 @@ ng_snd_item(item_p item, int flags)
#ifdef NETGRAPH_DEBUG
_ngi_check(item, __FILE__, __LINE__);
#endif
item->depth = 1;
NG_QUEUE_LOCK(ngq);
ng_queue_rw(ngq, item, rw);
NG_QUEUE_UNLOCK(ngq);
@ -2394,6 +2399,7 @@ ng_snd_item(item_p item, int flags)
NGI_GET_NODE(item, node); /* zaps stored node */
item->depth++;
error = ng_apply_item(node, item, rw); /* drops r/w lock when done */
/*
@ -2413,8 +2419,14 @@ ng_snd_item(item_p item, int flags)
done:
/* If was not sent, apply callback here. */
if (item->apply != NULL && refcount_release(&item->apply->refs))
(*item->apply->apply)(item->apply->context, error);
if (item->apply != NULL) {
if (item->depth == 0 && error != 0)
item->apply->error = error;
if (refcount_release(&item->apply->refs)) {
(*item->apply->apply)(item->apply->context,
item->apply->error);
}
}
NG_FREE_ITEM(item);
return (error);
@ -2430,10 +2442,10 @@ static int
ng_apply_item(node_p node, item_p item, int rw)
{
hook_p hook;
int error = 0;
ng_rcvdata_t *rcvdata;
ng_rcvmsg_t *rcvmsg;
struct ng_apply_info *apply;
int error = 0, depth;
/* Node and item are never optional. */
KASSERT(node != NULL, ("ng_apply_item: node is NULL"));
@ -2445,6 +2457,7 @@ ng_apply_item(node_p node, item_p item, int rw)
#endif
apply = item->apply;
depth = item->depth;
switch (item->el_flags & NGQF_TYPE) {
case NGQF_DATA:
@ -2552,8 +2565,12 @@ ng_apply_item(node_p node, item_p item, int rw)
ng_leave_write(&node->nd_input_queue);
/* Apply callback. */
if (apply != NULL && refcount_release(&apply->refs))
(*apply->apply)(apply->context, error);
if (apply != NULL) {
if (depth == 1 && error != 0)
apply->error = error;
if (refcount_release(&apply->refs))
(*apply->apply)(apply->context, apply->error);
}
return (error);
}

View File

@ -919,7 +919,7 @@ ngs_rcvmsg(node_p node, item_p item, hook_p lasthook)
if (sbappendaddr(&so->so_rcv, (struct sockaddr *)&addr, m, NULL) == 0) {
TRAP_ERROR;
m_freem(m);
error = so->so_error = ENOBUFS;
return (ENOBUFS);
}
sorwakeup(so);