Author: lstewart
Date: Tue Nov 16 07:57:56 2010
New Revision: 215391
URL: http://svn.freebsd.org/changeset/base/215391

Log:
  On CC algorithm module unload, we walk the list of active TCP control blocks.
  Any found to be using the algorithm that is about to go away are switched back
  to NewReno to avoid leaving dangling pointers which would trigger a panic. For
  VIMAGE kernels, there is a list per vnet to walk, yet the implementation was
  only examining one of the vnet lists.
  
  Fix the implementation of the above feature for VIMAGE kernels by looping
  through all active TCP control blocks across all vnets.
  
  Sponsored by: FreeBSD Foundation
  Tested by:    Mikolaj Golub <to.my.trociny at gmail com>
  Reviewed by:  bz (briefly)
  MFC after:    11 weeks

Modified:
  head/sys/netinet/cc/cc.c

Modified: head/sys/netinet/cc/cc.c
==============================================================================
--- head/sys/netinet/cc/cc.c    Tue Nov 16 07:55:36 2010        (r215390)
+++ head/sys/netinet/cc/cc.c    Tue Nov 16 07:57:56 2010        (r215391)
@@ -193,6 +193,7 @@ cc_deregister_algo(struct cc_algo *remov
        struct tcpcb *tp;
        struct inpcb *inp;
        int err;
+       VNET_ITERATOR_DECL(vnet_iter);
 
        err = ENOENT;
 
@@ -221,9 +222,10 @@ cc_deregister_algo(struct cc_algo *remov
        
        if (!err) {
                /*
-                * Check all active control blocks and change any that are
-                * using this algorithm back to newreno. If the algorithm that
-                * was in use requires cleanup code to be run, call it.
+                * Check all active control blocks across all network stacks and
+                * change any that are using this algorithm back to newreno. If
+                * the algorithm that was in use requires cleanup code to be
+                * run, call it.
                 *
                 * New connections already part way through being initialised
                 * with the CC algo we're removing will not race with this code
@@ -231,30 +233,39 @@ cc_deregister_algo(struct cc_algo *remov
                 * We therefore don't enter the loop below until the connection
                 * list has stabilised.
                 */
-               INP_INFO_RLOCK(&V_tcbinfo);
-               LIST_FOREACH(inp, &V_tcb, inp_list) {
-                       INP_WLOCK(inp);
-                       /* Important to skip tcptw structs. */
-                       if (!(inp->inp_flags & INP_TIMEWAIT) &&
-                           (tp = intotcpcb(inp)) != NULL) {
-                               /*
-                                * By holding INP_WLOCK here, we are
-                                * assured that the connection is not
-                                * currently executing inside the CC
-                                * module's functions i.e. it is safe to
-                                * make the switch back to newreno.
-                                */
-                               if (CC_ALGO(tp) == remove_cc) {
-                                       tmpfuncs = CC_ALGO(tp);
-                                       /* Newreno does not require any init. */
-                                       CC_ALGO(tp) = &newreno_cc_algo;
-                                       if (tmpfuncs->cb_destroy != NULL)
-                                               tmpfuncs->cb_destroy(tp->ccv);
+               VNET_LIST_RLOCK();
+               VNET_FOREACH(vnet_iter) {
+                       CURVNET_SET(vnet_iter);
+                       INP_INFO_RLOCK(&V_tcbinfo);
+                       LIST_FOREACH(inp, &V_tcb, inp_list) {
+                               INP_WLOCK(inp);
+                               /* Important to skip tcptw structs. */
+                               if (!(inp->inp_flags & INP_TIMEWAIT) &&
+                                   (tp = intotcpcb(inp)) != NULL) {
+                                       /*
+                                        * By holding INP_WLOCK here, we are
+                                        * assured that the connection is not
+                                        * currently executing inside the CC
+                                        * module's functions i.e. it is safe
+                                        * to make the switch back to newreno.
+                                        */
+                                       if (CC_ALGO(tp) == remove_cc) {
+                                               tmpfuncs = CC_ALGO(tp);
+                                               /*
+                                                * Newreno does not
+                                                * require any init.
+                                                */
+                                               CC_ALGO(tp) = &newreno_cc_algo;
+                                               if (tmpfuncs->cb_destroy != 
NULL)
+                                                       
tmpfuncs->cb_destroy(tp->ccv);
+                                       }
                                }
+                               INP_WUNLOCK(inp);
                        }
-                       INP_WUNLOCK(inp);
+                       INP_INFO_RUNLOCK(&V_tcbinfo);
+                       CURVNET_RESTORE();
                }
-               INP_INFO_RUNLOCK(&V_tcbinfo);
+               VNET_LIST_RUNLOCK();
        }
 
        return (err);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to