netgraph7: Factor out and inline item reference counting code.
authorNuno Antunes <nuno.antunes@gmail.com>
Tue, 15 Jul 2014 02:16:18 +0000 (03:16 +0100)
committerNuno Antunes <nuno.antunes@gmail.com>
Wed, 16 Jul 2014 05:56:16 +0000 (06:56 +0100)
* Netgraph7 assumes that nodes synchronously consume the items passed to them,
  i.e. either 1) immediatly drop the item or 2) immediatly pass the item to the
  next node.

  The previous assumption is not true for nodes that have their own internal
  item queues and defer the processing of the item.  Such nodes can use these
  routines to prevent the items from being freed too early.

* Move the apply callback check into the item reference release code.

sys/netgraph7/netgraph.h
sys/netgraph7/netgraph/ng_base.c
sys/netgraph7/netgraph2.h

index b0ab39d..0a7f65d 100644 (file)
@@ -623,7 +623,7 @@ struct ng_item {
         * and its context.
         */
        struct ng_apply_info    *apply;
-       u_int   depth;
+       u_int   refs;
 #ifdef NETGRAPH_DEBUG /*----------------------------------------------*/
        char *lastfile;
        int  lastline;
index 956de06..5f60666 100644 (file)
@@ -224,7 +224,6 @@ static int  ng_mkpeer(node_p node, const char *name, const char *name2,
                    char *type);
 static void    ng_name_rehash(void);
 static void    ng_ID_rehash(void);
-static void    ng_check_apply(item_p item, int error);
 static boolean_t       bzero_ctor(void *obj, void *private, int ocflags);
 
 /* Imported, these used to be externally visible, some may go back. */
@@ -755,7 +754,6 @@ ng_unref_node(node_p node)
        if (node == &ng_deadnode)
                return;
 
-
        if (refcount_release(&node->nd_refs)) { /* we were the last */
 
                node->nd_type->refs--; /* XXX maybe should get types lock? */
@@ -1921,7 +1919,7 @@ ng_snd_item(item_p item, int flags)
         * Every time an item is sent or forwarded we hold a reference on it
         * to postone the callback (if there is one) and item freedom.
         */
-       refcount_acquire(&item->depth);
+       ng_ref_item(item);
 
        /*
         * Node is never optional.
@@ -1943,7 +1941,7 @@ ng_snd_item(item_p item, int flags)
        /*
         * Always queue items entering netgraph for the first time.
         */
-       if (item->depth == 1) {
+       if (item->refs == 1) {
                struct lwkt_msg *msg = &item->el_lmsg;
 
                lwkt_initmsg(msg, &ng_panic_reply_port, 0);
@@ -2104,10 +2102,8 @@ ng_apply_item(item_p item)
        ng_leave_readwrite(node);
 
        /* Free the item if we own the last reference to it. */
-       if (refcount_release(&item->depth)) {
-               ng_check_apply(item, error);
-               ng_free_item(item);
-       }
+       ng_unref_item(item, error);
+
        NG_NODE_UNREF(node);
 
        return (error);
@@ -2684,18 +2680,6 @@ ng_free_apply(apply_p apply)
        objcache_put(ng_apply_oc, apply);
 }
 
-static void
-ng_check_apply(item_p item, int error)
-{
-       if (item->apply == NULL)
-               return;
-
-       KKASSERT(item->apply->apply != NULL);
-       (*item->apply->apply)(item->apply->context, error);
-       ng_free_apply(item->apply);
-       item->apply = NULL;
-}
-
 /************************************************************************
                        Module routines
 ************************************************************************/
index e8226cd..207d148 100644 (file)
 #ifndef _NETGRAPH_NETGRAPH2_H_
 #define _NETGRAPH_NETGRAPH2_H_
 
+/*
+ * This header implements the netgraph kernel public inline functions.
+ */
+
 #ifndef _KERNEL
 #error "kernel only header file"
 #endif
@@ -54,4 +58,34 @@ ng_cpuport(int cpu)
        return ng_msgport[cpu];
 }
 
+/*
+ * Grab a reference on the item.
+ */
+static __inline void
+ng_ref_item(item_p item)
+{
+       refcount_acquire(&item->refs);
+}
+
+/*
+ * Release a reference on the item.
+ *
+ * When the last reference is released, call the item's callback function if
+ * there is one and free the item.
+ */
+static __inline void
+ng_unref_item(item_p item, int error)
+{
+       if (refcount_release(&item->refs)) {
+               /* We have released the last reference */
+               if (item->apply != NULL) {
+                       KKASSERT(item->apply->apply != NULL);
+                       (*item->apply->apply)(item->apply->context, error);
+                       ng_free_apply(item->apply);
+                       item->apply = NULL;
+               }
+               ng_free_item(item);
+       }
+}
+
 #endif /* _NETGRAPH_NETGRAPH2_H_ */