diff options
-rw-r--r-- | net/netfilter/ipvs/ip_vs_lblcr.c | 44 |
1 files changed, 21 insertions, 23 deletions
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c index f7476b95ab46..caa58fa1438a 100644 --- a/net/netfilter/ipvs/ip_vs_lblcr.c +++ b/net/netfilter/ipvs/ip_vs_lblcr.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/kernel.h> | 45 | #include <linux/kernel.h> |
46 | #include <linux/skbuff.h> | 46 | #include <linux/skbuff.h> |
47 | #include <linux/jiffies.h> | 47 | #include <linux/jiffies.h> |
48 | #include <linux/list.h> | ||
48 | 49 | ||
49 | /* for sysctl */ | 50 | /* for sysctl */ |
50 | #include <linux/fs.h> | 51 | #include <linux/fs.h> |
@@ -85,25 +86,25 @@ static int sysctl_ip_vs_lblcr_expiration = 24*60*60*HZ; | |||
85 | /* | 86 | /* |
86 | * IPVS destination set structure and operations | 87 | * IPVS destination set structure and operations |
87 | */ | 88 | */ |
88 | struct ip_vs_dest_list { | 89 | struct ip_vs_dest_set_elem { |
89 | struct ip_vs_dest_list *next; /* list link */ | 90 | struct list_head list; /* list link */ |
90 | struct ip_vs_dest *dest; /* destination server */ | 91 | struct ip_vs_dest *dest; /* destination server */ |
91 | }; | 92 | }; |
92 | 93 | ||
93 | struct ip_vs_dest_set { | 94 | struct ip_vs_dest_set { |
94 | atomic_t size; /* set size */ | 95 | atomic_t size; /* set size */ |
95 | unsigned long lastmod; /* last modified time */ | 96 | unsigned long lastmod; /* last modified time */ |
96 | struct ip_vs_dest_list *list; /* destination list */ | 97 | struct list_head list; /* destination list */ |
97 | rwlock_t lock; /* lock for this list */ | 98 | rwlock_t lock; /* lock for this list */ |
98 | }; | 99 | }; |
99 | 100 | ||
100 | 101 | ||
101 | static struct ip_vs_dest_list * | 102 | static struct ip_vs_dest_set_elem * |
102 | ip_vs_dest_set_insert(struct ip_vs_dest_set *set, struct ip_vs_dest *dest) | 103 | ip_vs_dest_set_insert(struct ip_vs_dest_set *set, struct ip_vs_dest *dest) |
103 | { | 104 | { |
104 | struct ip_vs_dest_list *e; | 105 | struct ip_vs_dest_set_elem *e; |
105 | 106 | ||
106 | for (e=set->list; e!=NULL; e=e->next) { | 107 | list_for_each_entry(e, &set->list, list) { |
107 | if (e->dest == dest) | 108 | if (e->dest == dest) |
108 | /* already existed */ | 109 | /* already existed */ |
109 | return NULL; | 110 | return NULL; |
@@ -118,9 +119,7 @@ ip_vs_dest_set_insert(struct ip_vs_dest_set *set, struct ip_vs_dest *dest) | |||
118 | atomic_inc(&dest->refcnt); | 119 | atomic_inc(&dest->refcnt); |
119 | e->dest = dest; | 120 | e->dest = dest; |
120 | 121 | ||
121 | /* link it to the list */ | 122 | list_add(&e->list, &set->list); |
122 | e->next = set->list; | ||
123 | set->list = e; | ||
124 | atomic_inc(&set->size); | 123 | atomic_inc(&set->size); |
125 | 124 | ||
126 | set->lastmod = jiffies; | 125 | set->lastmod = jiffies; |
@@ -130,34 +129,33 @@ ip_vs_dest_set_insert(struct ip_vs_dest_set *set, struct ip_vs_dest *dest) | |||
130 | static void | 129 | static void |
131 | ip_vs_dest_set_erase(struct ip_vs_dest_set *set, struct ip_vs_dest *dest) | 130 | ip_vs_dest_set_erase(struct ip_vs_dest_set *set, struct ip_vs_dest *dest) |
132 | { | 131 | { |
133 | struct ip_vs_dest_list *e, **ep; | 132 | struct ip_vs_dest_set_elem *e; |
134 | 133 | ||
135 | for (ep=&set->list, e=*ep; e!=NULL; e=*ep) { | 134 | list_for_each_entry(e, &set->list, list) { |
136 | if (e->dest == dest) { | 135 | if (e->dest == dest) { |
137 | /* HIT */ | 136 | /* HIT */ |
138 | *ep = e->next; | ||
139 | atomic_dec(&set->size); | 137 | atomic_dec(&set->size); |
140 | set->lastmod = jiffies; | 138 | set->lastmod = jiffies; |
141 | atomic_dec(&e->dest->refcnt); | 139 | atomic_dec(&e->dest->refcnt); |
140 | list_del(&e->list); | ||
142 | kfree(e); | 141 | kfree(e); |
143 | break; | 142 | break; |
144 | } | 143 | } |
145 | ep = &e->next; | ||
146 | } | 144 | } |
147 | } | 145 | } |
148 | 146 | ||
149 | static void ip_vs_dest_set_eraseall(struct ip_vs_dest_set *set) | 147 | static void ip_vs_dest_set_eraseall(struct ip_vs_dest_set *set) |
150 | { | 148 | { |
151 | struct ip_vs_dest_list *e, **ep; | 149 | struct ip_vs_dest_set_elem *e, *ep; |
152 | 150 | ||
153 | write_lock(&set->lock); | 151 | write_lock(&set->lock); |
154 | for (ep=&set->list, e=*ep; e!=NULL; e=*ep) { | 152 | list_for_each_entry_safe(e, ep, &set->list, list) { |
155 | *ep = e->next; | ||
156 | /* | 153 | /* |
157 | * We don't kfree dest because it is refered either | 154 | * We don't kfree dest because it is refered either |
158 | * by its service or by the trash dest list. | 155 | * by its service or by the trash dest list. |
159 | */ | 156 | */ |
160 | atomic_dec(&e->dest->refcnt); | 157 | atomic_dec(&e->dest->refcnt); |
158 | list_del(&e->list); | ||
161 | kfree(e); | 159 | kfree(e); |
162 | } | 160 | } |
163 | write_unlock(&set->lock); | 161 | write_unlock(&set->lock); |
@@ -166,7 +164,7 @@ static void ip_vs_dest_set_eraseall(struct ip_vs_dest_set *set) | |||
166 | /* get weighted least-connection node in the destination set */ | 164 | /* get weighted least-connection node in the destination set */ |
167 | static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set) | 165 | static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set) |
168 | { | 166 | { |
169 | register struct ip_vs_dest_list *e; | 167 | register struct ip_vs_dest_set_elem *e; |
170 | struct ip_vs_dest *dest, *least; | 168 | struct ip_vs_dest *dest, *least; |
171 | int loh, doh; | 169 | int loh, doh; |
172 | 170 | ||
@@ -174,7 +172,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set) | |||
174 | return NULL; | 172 | return NULL; |
175 | 173 | ||
176 | /* select the first destination server, whose weight > 0 */ | 174 | /* select the first destination server, whose weight > 0 */ |
177 | for (e=set->list; e!=NULL; e=e->next) { | 175 | list_for_each_entry(e, &set->list, list) { |
178 | least = e->dest; | 176 | least = e->dest; |
179 | if (least->flags & IP_VS_DEST_F_OVERLOAD) | 177 | if (least->flags & IP_VS_DEST_F_OVERLOAD) |
180 | continue; | 178 | continue; |
@@ -190,7 +188,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set) | |||
190 | 188 | ||
191 | /* find the destination with the weighted least load */ | 189 | /* find the destination with the weighted least load */ |
192 | nextstage: | 190 | nextstage: |
193 | for (e=e->next; e!=NULL; e=e->next) { | 191 | list_for_each_entry(e, &set->list, list) { |
194 | dest = e->dest; | 192 | dest = e->dest; |
195 | if (dest->flags & IP_VS_DEST_F_OVERLOAD) | 193 | if (dest->flags & IP_VS_DEST_F_OVERLOAD) |
196 | continue; | 194 | continue; |
@@ -220,7 +218,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set) | |||
220 | /* get weighted most-connection node in the destination set */ | 218 | /* get weighted most-connection node in the destination set */ |
221 | static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set) | 219 | static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set) |
222 | { | 220 | { |
223 | register struct ip_vs_dest_list *e; | 221 | register struct ip_vs_dest_set_elem *e; |
224 | struct ip_vs_dest *dest, *most; | 222 | struct ip_vs_dest *dest, *most; |
225 | int moh, doh; | 223 | int moh, doh; |
226 | 224 | ||
@@ -228,7 +226,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set) | |||
228 | return NULL; | 226 | return NULL; |
229 | 227 | ||
230 | /* select the first destination server, whose weight > 0 */ | 228 | /* select the first destination server, whose weight > 0 */ |
231 | for (e=set->list; e!=NULL; e=e->next) { | 229 | list_for_each_entry(e, &set->list, list) { |
232 | most = e->dest; | 230 | most = e->dest; |
233 | if (atomic_read(&most->weight) > 0) { | 231 | if (atomic_read(&most->weight) > 0) { |
234 | moh = atomic_read(&most->activeconns) * 50 | 232 | moh = atomic_read(&most->activeconns) * 50 |
@@ -240,7 +238,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set) | |||
240 | 238 | ||
241 | /* find the destination with the weighted most load */ | 239 | /* find the destination with the weighted most load */ |
242 | nextstage: | 240 | nextstage: |
243 | for (e=e->next; e!=NULL; e=e->next) { | 241 | list_for_each_entry(e, &set->list, list) { |
244 | dest = e->dest; | 242 | dest = e->dest; |
245 | doh = atomic_read(&dest->activeconns) * 50 | 243 | doh = atomic_read(&dest->activeconns) * 50 |
246 | + atomic_read(&dest->inactconns); | 244 | + atomic_read(&dest->inactconns); |
@@ -389,7 +387,7 @@ ip_vs_lblcr_new(struct ip_vs_lblcr_table *tbl, const union nf_inet_addr *daddr, | |||
389 | 387 | ||
390 | /* initilize its dest set */ | 388 | /* initilize its dest set */ |
391 | atomic_set(&(en->set.size), 0); | 389 | atomic_set(&(en->set.size), 0); |
392 | en->set.list = NULL; | 390 | INIT_LIST_HEAD(&en->set.list); |
393 | rwlock_init(&en->set.lock); | 391 | rwlock_init(&en->set.lock); |
394 | 392 | ||
395 | ip_vs_lblcr_hash(tbl, en); | 393 | ip_vs_lblcr_hash(tbl, en); |