aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorGleb Smirnoff <glebius@FreeBSD.org>2021-08-06 20:16:32 +0000
committerGleb Smirnoff <glebius@FreeBSD.org>2021-09-10 18:27:04 +0000
commitb2954f0a8f7db160053555d4ad86ce3abf036077 (patch)
treed663eb1c6c71f681af6313f17bebda1531bd789b /sys
parent26cf4b53d9c12238479d4b2068d3037cb1940a39 (diff)
Diffstat (limited to 'sys')
-rw-r--r--sys/netgraph/netgraph.h1
-rw-r--r--sys/netgraph/ng_base.c50
2 files changed, 41 insertions, 10 deletions
diff --git a/sys/netgraph/netgraph.h b/sys/netgraph/netgraph.h
index 9cc298b38236..d0be5a88b088 100644
--- a/sys/netgraph/netgraph.h
+++ b/sys/netgraph/netgraph.h
@@ -1162,6 +1162,7 @@ int ng_send_fn1(node_p node, hook_p hook, ng_item_fn *fn, void *arg1,
int ng_send_fn2(node_p node, hook_p hook, item_p pitem, ng_item_fn2 *fn,
void *arg1, int arg2, int flags);
int ng_uncallout(struct callout *c, node_p node);
+int ng_uncallout_drain(struct callout *c, node_p node);
int ng_callout(struct callout *c, node_p node, hook_p hook, int ticks,
ng_item_fn *fn, void * arg1, int arg2);
#define ng_callout_init(c) callout_init(c, 1)
diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c
index e0832e794089..655761c2f897 100644
--- a/sys/netgraph/ng_base.c
+++ b/sys/netgraph/ng_base.c
@@ -3816,20 +3816,18 @@ ng_callout(struct callout *c, node_p node, hook_p hook, int ticks,
return (0);
}
-/* A special modified version of callout_stop() */
-int
-ng_uncallout(struct callout *c, node_p node)
+/*
+ * Free references and item if callout_stop/callout_drain returned 1,
+ * meaning that callout was successfully stopped and now references
+ * belong to us.
+ */
+static void
+ng_uncallout_internal(struct callout *c, node_p node)
{
item_p item;
- int rval;
-
- KASSERT(c != NULL, ("ng_uncallout: NULL callout"));
- KASSERT(node != NULL, ("ng_uncallout: NULL node"));
- rval = callout_stop(c);
item = c->c_arg;
- /* Do an extra check */
- if ((rval > 0) && (c->c_func == &ng_callout_trampoline) &&
+ if ((c->c_func == &ng_callout_trampoline) &&
(item != NULL) && (NGI_NODE(item) == node)) {
/*
* We successfully removed it from the queue before it ran
@@ -3839,6 +3837,38 @@ ng_uncallout(struct callout *c, node_p node)
NG_FREE_ITEM(item);
}
c->c_arg = NULL;
+}
+
+
+/* A special modified version of callout_stop() */
+int
+ng_uncallout(struct callout *c, node_p node)
+{
+ int rval;
+
+ rval = callout_stop(c);
+ if (rval > 0)
+ /*
+ * XXXGL: in case if callout is already running and next
+ * invocation is scheduled at the same time, callout_stop()
+ * returns 0. See d153eeee97d. In this case netgraph(4) would
+ * leak resources. However, no nodes are known to induce such
+ * behavior.
+ */
+ ng_uncallout_internal(c, node);
+
+ return (rval);
+}
+
+/* A special modified version of callout_drain() */
+int
+ng_uncallout_drain(struct callout *c, node_p node)
+{
+ int rval;
+
+ rval = callout_drain(c);
+ if (rval > 0)
+ ng_uncallout_internal(c, node);
return (rval);
}