ipvs: Return negative error values from ip_vs_edit_service()
[safe/jmp/linux-2.6] / net / ipv4 / ipvs / ip_vs_est.c
index e700474..4fb620e 100644 (file)
@@ -1,8 +1,6 @@
 /*
  * ip_vs_est.c: simple rate estimator for IPVS
  *
- * Version:     $Id: ip_vs_est.c,v 1.4 2002/11/30 01:50:35 wensong Exp $
- *
  * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
  *
  *              This program is free software; you can redistribute it and/or
  * Changes:
  *
  */
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/jiffies.h>
 #include <linux/slab.h>
 #include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/sysctl.h>
+#include <linux/list.h>
 
 #include <net/ip_vs.h>
 
  */
 
 
-struct ip_vs_estimator
-{
-       struct ip_vs_estimator  *next;
-       struct ip_vs_stats      *stats;
-
-       u32                     last_conns;
-       u32                     last_inpkts;
-       u32                     last_outpkts;
-       u64                     last_inbytes;
-       u64                     last_outbytes;
-
-       u32                     cps;
-       u32                     inpps;
-       u32                     outpps;
-       u32                     inbps;
-       u32                     outbps;
-};
-
+static void estimation_timer(unsigned long arg);
 
-static struct ip_vs_estimator *est_list = NULL;
-static DEFINE_RWLOCK(est_lock);
-static struct timer_list est_timer;
+static LIST_HEAD(est_list);
+static DEFINE_SPINLOCK(est_lock);
+static DEFINE_TIMER(est_timer, estimation_timer, 0, 0);
 
 static void estimation_timer(unsigned long arg)
 {
@@ -77,9 +60,9 @@ static void estimation_timer(unsigned long arg)
        u64 n_inbytes, n_outbytes;
        u32 rate;
 
-       read_lock(&est_lock);
-       for (e = est_list; e; e = e->next) {
-               s = e->stats;
+       spin_lock(&est_lock);
+       list_for_each_entry(e, &est_list, list) {
+               s = container_of(e, struct ip_vs_stats, est);
 
                spin_lock(&s->lock);
                n_conns = s->conns;
@@ -115,20 +98,16 @@ static void estimation_timer(unsigned long arg)
                s->outbps = (e->outbps+0xF)>>5;
                spin_unlock(&s->lock);
        }
-       read_unlock(&est_lock);
+       spin_unlock(&est_lock);
        mod_timer(&est_timer, jiffies + 2*HZ);
 }
 
-int ip_vs_new_estimator(struct ip_vs_stats *stats)
+void ip_vs_new_estimator(struct ip_vs_stats *stats)
 {
-       struct ip_vs_estimator *est;
+       struct ip_vs_estimator *est = &stats->est;
 
-       est = kmalloc(sizeof(*est), GFP_KERNEL);
-       if (est == NULL)
-               return -ENOMEM;
+       INIT_LIST_HEAD(&est->list);
 
-       memset(est, 0, sizeof(*est));
-       est->stats = stats;
        est->last_conns = stats->conns;
        est->cps = stats->cps<<10;
 
@@ -144,60 +123,44 @@ int ip_vs_new_estimator(struct ip_vs_stats *stats)
        est->last_outbytes = stats->outbytes;
        est->outbps = stats->outbps<<5;
 
-       write_lock_bh(&est_lock);
-       est->next = est_list;
-       if (est->next == NULL) {
-               init_timer(&est_timer);
-               est_timer.expires = jiffies + 2*HZ;
-               est_timer.function = estimation_timer;
-               add_timer(&est_timer);
-       }
-       est_list = est;
-       write_unlock_bh(&est_lock);
-       return 0;
+       spin_lock_bh(&est_lock);
+       list_add(&est->list, &est_list);
+       spin_unlock_bh(&est_lock);
 }
 
 void ip_vs_kill_estimator(struct ip_vs_stats *stats)
 {
-       struct ip_vs_estimator *est, **pest;
-       int killed = 0;
-
-       write_lock_bh(&est_lock);
-       pest = &est_list;
-       while ((est=*pest) != NULL) {
-               if (est->stats != stats) {
-                       pest = &est->next;
-                       continue;
-               }
-               *pest = est->next;
-               kfree(est);
-               killed++;
-       }
-       if (killed && est_list == NULL)
-               del_timer_sync(&est_timer);
-       write_unlock_bh(&est_lock);
+       struct ip_vs_estimator *est = &stats->est;
+
+       spin_lock_bh(&est_lock);
+       list_del(&est->list);
+       spin_unlock_bh(&est_lock);
 }
 
 void ip_vs_zero_estimator(struct ip_vs_stats *stats)
 {
-       struct ip_vs_estimator *e;
+       struct ip_vs_estimator *est = &stats->est;
+
+       /* set counters zero, caller must hold the stats->lock lock */
+       est->last_inbytes = 0;
+       est->last_outbytes = 0;
+       est->last_conns = 0;
+       est->last_inpkts = 0;
+       est->last_outpkts = 0;
+       est->cps = 0;
+       est->inpps = 0;
+       est->outpps = 0;
+       est->inbps = 0;
+       est->outbps = 0;
+}
 
-       write_lock_bh(&est_lock);
-       for (e = est_list; e; e = e->next) {
-               if (e->stats != stats)
-                       continue;
-
-               /* set counters zero */
-               e->last_conns = 0;
-               e->last_inpkts = 0;
-               e->last_outpkts = 0;
-               e->last_inbytes = 0;
-               e->last_outbytes = 0;
-               e->cps = 0;
-               e->inpps = 0;
-               e->outpps = 0;
-               e->inbps = 0;
-               e->outbps = 0;
-       }
-       write_unlock_bh(&est_lock);
+int __init ip_vs_estimator_init(void)
+{
+       mod_timer(&est_timer, jiffies + 2 * HZ);
+       return 0;
+}
+
+void ip_vs_estimator_cleanup(void)
+{
+       del_timer_sync(&est_timer);
 }