diff options
Diffstat (limited to 'net/ipv4/ipvs/ip_vs_est.c')
-rw-r--r-- | net/ipv4/ipvs/ip_vs_est.c | 116 |
1 files changed, 39 insertions, 77 deletions
diff --git a/net/ipv4/ipvs/ip_vs_est.c b/net/ipv4/ipvs/ip_vs_est.c index bc04eedd6dbb..5a20f93bd7f9 100644 --- a/net/ipv4/ipvs/ip_vs_est.c +++ b/net/ipv4/ipvs/ip_vs_est.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/sysctl.h> | 19 | #include <linux/sysctl.h> |
20 | #include <linux/list.h> | ||
20 | 21 | ||
21 | #include <net/ip_vs.h> | 22 | #include <net/ip_vs.h> |
22 | 23 | ||
@@ -44,28 +45,11 @@ | |||
44 | */ | 45 | */ |
45 | 46 | ||
46 | 47 | ||
47 | struct ip_vs_estimator | 48 | static void estimation_timer(unsigned long arg); |
48 | { | ||
49 | struct ip_vs_estimator *next; | ||
50 | struct ip_vs_stats *stats; | ||
51 | |||
52 | u32 last_conns; | ||
53 | u32 last_inpkts; | ||
54 | u32 last_outpkts; | ||
55 | u64 last_inbytes; | ||
56 | u64 last_outbytes; | ||
57 | |||
58 | u32 cps; | ||
59 | u32 inpps; | ||
60 | u32 outpps; | ||
61 | u32 inbps; | ||
62 | u32 outbps; | ||
63 | }; | ||
64 | |||
65 | 49 | ||
66 | static struct ip_vs_estimator *est_list = NULL; | 50 | static LIST_HEAD(est_list); |
67 | static DEFINE_RWLOCK(est_lock); | 51 | static DEFINE_SPINLOCK(est_lock); |
68 | static struct timer_list est_timer; | 52 | static DEFINE_TIMER(est_timer, estimation_timer, 0, 0); |
69 | 53 | ||
70 | static void estimation_timer(unsigned long arg) | 54 | static void estimation_timer(unsigned long arg) |
71 | { | 55 | { |
@@ -76,9 +60,9 @@ static void estimation_timer(unsigned long arg) | |||
76 | u64 n_inbytes, n_outbytes; | 60 | u64 n_inbytes, n_outbytes; |
77 | u32 rate; | 61 | u32 rate; |
78 | 62 | ||
79 | read_lock(&est_lock); | 63 | spin_lock(&est_lock); |
80 | for (e = est_list; e; e = e->next) { | 64 | list_for_each_entry(e, &est_list, list) { |
81 | s = e->stats; | 65 | s = container_of(e, struct ip_vs_stats, est); |
82 | 66 | ||
83 | spin_lock(&s->lock); | 67 | spin_lock(&s->lock); |
84 | n_conns = s->conns; | 68 | n_conns = s->conns; |
@@ -114,19 +98,16 @@ static void estimation_timer(unsigned long arg) | |||
114 | s->outbps = (e->outbps+0xF)>>5; | 98 | s->outbps = (e->outbps+0xF)>>5; |
115 | spin_unlock(&s->lock); | 99 | spin_unlock(&s->lock); |
116 | } | 100 | } |
117 | read_unlock(&est_lock); | 101 | spin_unlock(&est_lock); |
118 | mod_timer(&est_timer, jiffies + 2*HZ); | 102 | mod_timer(&est_timer, jiffies + 2*HZ); |
119 | } | 103 | } |
120 | 104 | ||
121 | int ip_vs_new_estimator(struct ip_vs_stats *stats) | 105 | void ip_vs_new_estimator(struct ip_vs_stats *stats) |
122 | { | 106 | { |
123 | struct ip_vs_estimator *est; | 107 | struct ip_vs_estimator *est = &stats->est; |
124 | 108 | ||
125 | est = kzalloc(sizeof(*est), GFP_KERNEL); | 109 | INIT_LIST_HEAD(&est->list); |
126 | if (est == NULL) | ||
127 | return -ENOMEM; | ||
128 | 110 | ||
129 | est->stats = stats; | ||
130 | est->last_conns = stats->conns; | 111 | est->last_conns = stats->conns; |
131 | est->cps = stats->cps<<10; | 112 | est->cps = stats->cps<<10; |
132 | 113 | ||
@@ -142,59 +123,40 @@ int ip_vs_new_estimator(struct ip_vs_stats *stats) | |||
142 | est->last_outbytes = stats->outbytes; | 123 | est->last_outbytes = stats->outbytes; |
143 | est->outbps = stats->outbps<<5; | 124 | est->outbps = stats->outbps<<5; |
144 | 125 | ||
145 | write_lock_bh(&est_lock); | 126 | spin_lock_bh(&est_lock); |
146 | est->next = est_list; | 127 | if (list_empty(&est_list)) |
147 | if (est->next == NULL) { | 128 | mod_timer(&est_timer, jiffies + 2 * HZ); |
148 | setup_timer(&est_timer, estimation_timer, 0); | 129 | list_add(&est->list, &est_list); |
149 | est_timer.expires = jiffies + 2*HZ; | 130 | spin_unlock_bh(&est_lock); |
150 | add_timer(&est_timer); | ||
151 | } | ||
152 | est_list = est; | ||
153 | write_unlock_bh(&est_lock); | ||
154 | return 0; | ||
155 | } | 131 | } |
156 | 132 | ||
157 | void ip_vs_kill_estimator(struct ip_vs_stats *stats) | 133 | void ip_vs_kill_estimator(struct ip_vs_stats *stats) |
158 | { | 134 | { |
159 | struct ip_vs_estimator *est, **pest; | 135 | struct ip_vs_estimator *est = &stats->est; |
160 | int killed = 0; | 136 | |
161 | 137 | spin_lock_bh(&est_lock); | |
162 | write_lock_bh(&est_lock); | 138 | list_del(&est->list); |
163 | pest = &est_list; | 139 | while (list_empty(&est_list) && try_to_del_timer_sync(&est_timer) < 0) { |
164 | while ((est=*pest) != NULL) { | 140 | spin_unlock_bh(&est_lock); |
165 | if (est->stats != stats) { | 141 | cpu_relax(); |
166 | pest = &est->next; | 142 | spin_lock_bh(&est_lock); |
167 | continue; | ||
168 | } | ||
169 | *pest = est->next; | ||
170 | kfree(est); | ||
171 | killed++; | ||
172 | } | 143 | } |
173 | if (killed && est_list == NULL) | 144 | spin_unlock_bh(&est_lock); |
174 | del_timer_sync(&est_timer); | ||
175 | write_unlock_bh(&est_lock); | ||
176 | } | 145 | } |
177 | 146 | ||
178 | void ip_vs_zero_estimator(struct ip_vs_stats *stats) | 147 | void ip_vs_zero_estimator(struct ip_vs_stats *stats) |
179 | { | 148 | { |
180 | struct ip_vs_estimator *e; | 149 | struct ip_vs_estimator *est = &stats->est; |
181 | 150 | ||
182 | write_lock_bh(&est_lock); | 151 | /* set counters zero, caller must hold the stats->lock lock */ |
183 | for (e = est_list; e; e = e->next) { | 152 | est->last_inbytes = 0; |
184 | if (e->stats != stats) | 153 | est->last_outbytes = 0; |
185 | continue; | 154 | est->last_conns = 0; |
186 | 155 | est->last_inpkts = 0; | |
187 | /* set counters zero */ | 156 | est->last_outpkts = 0; |
188 | e->last_conns = 0; | 157 | est->cps = 0; |
189 | e->last_inpkts = 0; | 158 | est->inpps = 0; |
190 | e->last_outpkts = 0; | 159 | est->outpps = 0; |
191 | e->last_inbytes = 0; | 160 | est->inbps = 0; |
192 | e->last_outbytes = 0; | 161 | est->outbps = 0; |
193 | e->cps = 0; | ||
194 | e->inpps = 0; | ||
195 | e->outpps = 0; | ||
196 | e->inbps = 0; | ||
197 | e->outbps = 0; | ||
198 | } | ||
199 | write_unlock_bh(&est_lock); | ||
200 | } | 162 | } |