Commit 38bdbd8e authored by David S. Miller's avatar David S. Miller
parents 773c3e75 6b4ff2d7
...@@ -644,8 +644,10 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0, ...@@ -644,8 +644,10 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0,
/* Walk through entries, checking offsets. */ /* Walk through entries, checking offsets. */
xt_entry_foreach(iter, entry0, newinfo->size) { xt_entry_foreach(iter, entry0, newinfo->size) {
ret = check_entry_size_and_hooks(iter, newinfo, entry0, ret = check_entry_size_and_hooks(iter, newinfo, entry0,
entry0 + repl->size, repl->hook_entry, repl->underflow, entry0 + repl->size,
repl->valid_hooks); repl->hook_entry,
repl->underflow,
repl->valid_hooks);
if (ret != 0) if (ret != 0)
break; break;
++i; ++i;
...@@ -730,7 +732,7 @@ static void get_counters(const struct xt_table_info *t, ...@@ -730,7 +732,7 @@ static void get_counters(const struct xt_table_info *t,
i = 0; i = 0;
xt_entry_foreach(iter, t->entries[curcpu], t->size) { xt_entry_foreach(iter, t->entries[curcpu], t->size) {
SET_COUNTER(counters[i], iter->counters.bcnt, SET_COUNTER(counters[i], iter->counters.bcnt,
iter->counters.pcnt); iter->counters.pcnt);
++i; ++i;
} }
...@@ -741,7 +743,7 @@ static void get_counters(const struct xt_table_info *t, ...@@ -741,7 +743,7 @@ static void get_counters(const struct xt_table_info *t,
xt_info_wrlock(cpu); xt_info_wrlock(cpu);
xt_entry_foreach(iter, t->entries[cpu], t->size) { xt_entry_foreach(iter, t->entries[cpu], t->size) {
ADD_COUNTER(counters[i], iter->counters.bcnt, ADD_COUNTER(counters[i], iter->counters.bcnt,
iter->counters.pcnt); iter->counters.pcnt);
++i; ++i;
} }
xt_info_wrunlock(cpu); xt_info_wrunlock(cpu);
...@@ -1356,8 +1358,11 @@ static int translate_compat_table(const char *name, ...@@ -1356,8 +1358,11 @@ static int translate_compat_table(const char *name,
/* Walk through entries, checking offsets. */ /* Walk through entries, checking offsets. */
xt_entry_foreach(iter0, entry0, total_size) { xt_entry_foreach(iter0, entry0, total_size) {
ret = check_compat_entry_size_and_hooks(iter0, info, &size, ret = check_compat_entry_size_and_hooks(iter0, info, &size,
entry0, entry0 + total_size, hook_entries, underflows, entry0,
name); entry0 + total_size,
hook_entries,
underflows,
name);
if (ret != 0) if (ret != 0)
goto out_unlock; goto out_unlock;
++j; ++j;
...@@ -1401,8 +1406,8 @@ static int translate_compat_table(const char *name, ...@@ -1401,8 +1406,8 @@ static int translate_compat_table(const char *name,
pos = entry1; pos = entry1;
size = total_size; size = total_size;
xt_entry_foreach(iter0, entry0, total_size) { xt_entry_foreach(iter0, entry0, total_size) {
ret = compat_copy_entry_from_user(iter0, &pos, ret = compat_copy_entry_from_user(iter0, &pos, &size,
&size, name, newinfo, entry1); name, newinfo, entry1);
if (ret != 0) if (ret != 0)
break; break;
} }
...@@ -1617,7 +1622,7 @@ static int compat_copy_entries_to_user(unsigned int total_size, ...@@ -1617,7 +1622,7 @@ static int compat_copy_entries_to_user(unsigned int total_size,
size = total_size; size = total_size;
xt_entry_foreach(iter, loc_cpu_entry, total_size) { xt_entry_foreach(iter, loc_cpu_entry, total_size) {
ret = compat_copy_entry_to_user(iter, &pos, ret = compat_copy_entry_to_user(iter, &pos,
&size, counters, i++); &size, counters, i++);
if (ret != 0) if (ret != 0)
break; break;
} }
......
...@@ -836,8 +836,10 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, ...@@ -836,8 +836,10 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,
/* Walk through entries, checking offsets. */ /* Walk through entries, checking offsets. */
xt_entry_foreach(iter, entry0, newinfo->size) { xt_entry_foreach(iter, entry0, newinfo->size) {
ret = check_entry_size_and_hooks(iter, newinfo, entry0, ret = check_entry_size_and_hooks(iter, newinfo, entry0,
entry0 + repl->size, repl->hook_entry, repl->underflow, entry0 + repl->size,
repl->valid_hooks); repl->hook_entry,
repl->underflow,
repl->valid_hooks);
if (ret != 0) if (ret != 0)
return ret; return ret;
++i; ++i;
...@@ -918,7 +920,7 @@ get_counters(const struct xt_table_info *t, ...@@ -918,7 +920,7 @@ get_counters(const struct xt_table_info *t,
i = 0; i = 0;
xt_entry_foreach(iter, t->entries[curcpu], t->size) { xt_entry_foreach(iter, t->entries[curcpu], t->size) {
SET_COUNTER(counters[i], iter->counters.bcnt, SET_COUNTER(counters[i], iter->counters.bcnt,
iter->counters.pcnt); iter->counters.pcnt);
++i; ++i;
} }
...@@ -929,7 +931,7 @@ get_counters(const struct xt_table_info *t, ...@@ -929,7 +931,7 @@ get_counters(const struct xt_table_info *t,
xt_info_wrlock(cpu); xt_info_wrlock(cpu);
xt_entry_foreach(iter, t->entries[cpu], t->size) { xt_entry_foreach(iter, t->entries[cpu], t->size) {
ADD_COUNTER(counters[i], iter->counters.bcnt, ADD_COUNTER(counters[i], iter->counters.bcnt,
iter->counters.pcnt); iter->counters.pcnt);
++i; /* macro does multi eval of i */ ++i; /* macro does multi eval of i */
} }
xt_info_wrunlock(cpu); xt_info_wrunlock(cpu);
...@@ -1540,7 +1542,7 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, ...@@ -1540,7 +1542,7 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
j = 0; j = 0;
xt_ematch_foreach(ematch, e) { xt_ematch_foreach(ematch, e) {
ret = compat_find_calc_match(ematch, name, ret = compat_find_calc_match(ematch, name,
&e->ip, e->comefrom, &off); &e->ip, e->comefrom, &off);
if (ret != 0) if (ret != 0)
goto release_matches; goto release_matches;
++j; ++j;
...@@ -1701,8 +1703,11 @@ translate_compat_table(struct net *net, ...@@ -1701,8 +1703,11 @@ translate_compat_table(struct net *net,
/* Walk through entries, checking offsets. */ /* Walk through entries, checking offsets. */
xt_entry_foreach(iter0, entry0, total_size) { xt_entry_foreach(iter0, entry0, total_size) {
ret = check_compat_entry_size_and_hooks(iter0, info, &size, ret = check_compat_entry_size_and_hooks(iter0, info, &size,
entry0, entry0 + total_size, hook_entries, underflows, entry0,
name); entry0 + total_size,
hook_entries,
underflows,
name);
if (ret != 0) if (ret != 0)
goto out_unlock; goto out_unlock;
++j; ++j;
...@@ -1746,8 +1751,8 @@ translate_compat_table(struct net *net, ...@@ -1746,8 +1751,8 @@ translate_compat_table(struct net *net,
pos = entry1; pos = entry1;
size = total_size; size = total_size;
xt_entry_foreach(iter0, entry0, total_size) { xt_entry_foreach(iter0, entry0, total_size) {
ret = compat_copy_entry_from_user(iter0, &pos, ret = compat_copy_entry_from_user(iter0, &pos, &size,
&size, name, newinfo, entry1); name, newinfo, entry1);
if (ret != 0) if (ret != 0)
break; break;
} }
...@@ -1927,7 +1932,7 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, ...@@ -1927,7 +1932,7 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
size = total_size; size = total_size;
xt_entry_foreach(iter, loc_cpu_entry, total_size) { xt_entry_foreach(iter, loc_cpu_entry, total_size) {
ret = compat_copy_entry_to_user(iter, &pos, ret = compat_copy_entry_to_user(iter, &pos,
&size, counters, i++); &size, counters, i++);
if (ret != 0) if (ret != 0)
break; break;
} }
......
...@@ -866,8 +866,10 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0, ...@@ -866,8 +866,10 @@ translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,
/* Walk through entries, checking offsets. */ /* Walk through entries, checking offsets. */
xt_entry_foreach(iter, entry0, newinfo->size) { xt_entry_foreach(iter, entry0, newinfo->size) {
ret = check_entry_size_and_hooks(iter, newinfo, entry0, ret = check_entry_size_and_hooks(iter, newinfo, entry0,
entry0 + repl->size, repl->hook_entry, repl->underflow, entry0 + repl->size,
repl->valid_hooks); repl->hook_entry,
repl->underflow,
repl->valid_hooks);
if (ret != 0) if (ret != 0)
return ret; return ret;
++i; ++i;
...@@ -948,7 +950,7 @@ get_counters(const struct xt_table_info *t, ...@@ -948,7 +950,7 @@ get_counters(const struct xt_table_info *t,
i = 0; i = 0;
xt_entry_foreach(iter, t->entries[curcpu], t->size) { xt_entry_foreach(iter, t->entries[curcpu], t->size) {
SET_COUNTER(counters[i], iter->counters.bcnt, SET_COUNTER(counters[i], iter->counters.bcnt,
iter->counters.pcnt); iter->counters.pcnt);
++i; ++i;
} }
...@@ -959,7 +961,7 @@ get_counters(const struct xt_table_info *t, ...@@ -959,7 +961,7 @@ get_counters(const struct xt_table_info *t,
xt_info_wrlock(cpu); xt_info_wrlock(cpu);
xt_entry_foreach(iter, t->entries[cpu], t->size) { xt_entry_foreach(iter, t->entries[cpu], t->size) {
ADD_COUNTER(counters[i], iter->counters.bcnt, ADD_COUNTER(counters[i], iter->counters.bcnt,
iter->counters.pcnt); iter->counters.pcnt);
++i; ++i;
} }
xt_info_wrunlock(cpu); xt_info_wrunlock(cpu);
...@@ -1573,7 +1575,7 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, ...@@ -1573,7 +1575,7 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
j = 0; j = 0;
xt_ematch_foreach(ematch, e) { xt_ematch_foreach(ematch, e) {
ret = compat_find_calc_match(ematch, name, ret = compat_find_calc_match(ematch, name,
&e->ipv6, e->comefrom, &off); &e->ipv6, e->comefrom, &off);
if (ret != 0) if (ret != 0)
goto release_matches; goto release_matches;
++j; ++j;
...@@ -1734,8 +1736,11 @@ translate_compat_table(struct net *net, ...@@ -1734,8 +1736,11 @@ translate_compat_table(struct net *net,
/* Walk through entries, checking offsets. */ /* Walk through entries, checking offsets. */
xt_entry_foreach(iter0, entry0, total_size) { xt_entry_foreach(iter0, entry0, total_size) {
ret = check_compat_entry_size_and_hooks(iter0, info, &size, ret = check_compat_entry_size_and_hooks(iter0, info, &size,
entry0, entry0 + total_size, hook_entries, underflows, entry0,
name); entry0 + total_size,
hook_entries,
underflows,
name);
if (ret != 0) if (ret != 0)
goto out_unlock; goto out_unlock;
++j; ++j;
...@@ -1779,8 +1784,8 @@ translate_compat_table(struct net *net, ...@@ -1779,8 +1784,8 @@ translate_compat_table(struct net *net,
pos = entry1; pos = entry1;
size = total_size; size = total_size;
xt_entry_foreach(iter0, entry0, total_size) { xt_entry_foreach(iter0, entry0, total_size) {
ret = compat_copy_entry_from_user(iter0, &pos, ret = compat_copy_entry_from_user(iter0, &pos, &size,
&size, name, newinfo, entry1); name, newinfo, entry1);
if (ret != 0) if (ret != 0)
break; break;
} }
...@@ -1960,7 +1965,7 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table, ...@@ -1960,7 +1965,7 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
size = total_size; size = total_size;
xt_entry_foreach(iter, loc_cpu_entry, total_size) { xt_entry_foreach(iter, loc_cpu_entry, total_size) {
ret = compat_copy_entry_to_user(iter, &pos, ret = compat_copy_entry_to_user(iter, &pos,
&size, counters, i++); &size, counters, i++);
if (ret != 0) if (ret != 0)
break; break;
} }
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/list.h>
/* for sysctl */ /* for sysctl */
#include <linux/fs.h> #include <linux/fs.h>
...@@ -85,25 +86,25 @@ static int sysctl_ip_vs_lblcr_expiration = 24*60*60*HZ; ...@@ -85,25 +86,25 @@ static int sysctl_ip_vs_lblcr_expiration = 24*60*60*HZ;
/* /*
* IPVS destination set structure and operations * IPVS destination set structure and operations
*/ */
struct ip_vs_dest_list { struct ip_vs_dest_set_elem {
struct ip_vs_dest_list *next; /* list link */ struct list_head list; /* list link */
struct ip_vs_dest *dest; /* destination server */ struct ip_vs_dest *dest; /* destination server */
}; };
struct ip_vs_dest_set { struct ip_vs_dest_set {
atomic_t size; /* set size */ atomic_t size; /* set size */
unsigned long lastmod; /* last modified time */ unsigned long lastmod; /* last modified time */
struct ip_vs_dest_list *list; /* destination list */ struct list_head list; /* destination list */
rwlock_t lock; /* lock for this list */ rwlock_t lock; /* lock for this list */
}; };
static struct ip_vs_dest_list * static struct ip_vs_dest_set_elem *
ip_vs_dest_set_insert(struct ip_vs_dest_set *set, struct ip_vs_dest *dest) ip_vs_dest_set_insert(struct ip_vs_dest_set *set, struct ip_vs_dest *dest)
{ {
struct ip_vs_dest_list *e; struct ip_vs_dest_set_elem *e;
for (e=set->list; e!=NULL; e=e->next) { list_for_each_entry(e, &set->list, list) {
if (e->dest == dest) if (e->dest == dest)
/* already existed */ /* already existed */
return NULL; return NULL;
...@@ -118,9 +119,7 @@ ip_vs_dest_set_insert(struct ip_vs_dest_set *set, struct ip_vs_dest *dest) ...@@ -118,9 +119,7 @@ ip_vs_dest_set_insert(struct ip_vs_dest_set *set, struct ip_vs_dest *dest)
atomic_inc(&dest->refcnt); atomic_inc(&dest->refcnt);
e->dest = dest; e->dest = dest;
/* link it to the list */ list_add(&e->list, &set->list);
e->next = set->list;
set->list = e;
atomic_inc(&set->size); atomic_inc(&set->size);
set->lastmod = jiffies; set->lastmod = jiffies;
...@@ -130,34 +129,33 @@ ip_vs_dest_set_insert(struct ip_vs_dest_set *set, struct ip_vs_dest *dest) ...@@ -130,34 +129,33 @@ ip_vs_dest_set_insert(struct ip_vs_dest_set *set, struct ip_vs_dest *dest)
static void static void
ip_vs_dest_set_erase(struct ip_vs_dest_set *set, struct ip_vs_dest *dest) ip_vs_dest_set_erase(struct ip_vs_dest_set *set, struct ip_vs_dest *dest)
{ {
struct ip_vs_dest_list *e, **ep; struct ip_vs_dest_set_elem *e;
for (ep=&set->list, e=*ep; e!=NULL; e=*ep) { list_for_each_entry(e, &set->list, list) {
if (e->dest == dest) { if (e->dest == dest) {
/* HIT */ /* HIT */
*ep = e->next;
atomic_dec(&set->size); atomic_dec(&set->size);
set->lastmod = jiffies; set->lastmod = jiffies;
atomic_dec(&e->dest->refcnt); atomic_dec(&e->dest->refcnt);
list_del(&e->list);
kfree(e); kfree(e);
break; break;
} }
ep = &e->next;
} }
} }
static void ip_vs_dest_set_eraseall(struct ip_vs_dest_set *set) static void ip_vs_dest_set_eraseall(struct ip_vs_dest_set *set)
{ {
struct ip_vs_dest_list *e, **ep; struct ip_vs_dest_set_elem *e, *ep;
write_lock(&set->lock); write_lock(&set->lock);
for (ep=&set->list, e=*ep; e!=NULL; e=*ep) { list_for_each_entry_safe(e, ep, &set->list, list) {
*ep = e->next;
/* /*
* We don't kfree dest because it is refered either * We don't kfree dest because it is refered either
* by its service or by the trash dest list. * by its service or by the trash dest list.
*/ */
atomic_dec(&e->dest->refcnt); atomic_dec(&e->dest->refcnt);
list_del(&e->list);
kfree(e); kfree(e);
} }
write_unlock(&set->lock); write_unlock(&set->lock);
...@@ -166,7 +164,7 @@ static void ip_vs_dest_set_eraseall(struct ip_vs_dest_set *set) ...@@ -166,7 +164,7 @@ static void ip_vs_dest_set_eraseall(struct ip_vs_dest_set *set)
/* get weighted least-connection node in the destination set */ /* get weighted least-connection node in the destination set */
static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set) static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set)
{ {
register struct ip_vs_dest_list *e; register struct ip_vs_dest_set_elem *e;
struct ip_vs_dest *dest, *least; struct ip_vs_dest *dest, *least;
int loh, doh; int loh, doh;
...@@ -174,7 +172,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set) ...@@ -174,7 +172,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set)
return NULL; return NULL;
/* select the first destination server, whose weight > 0 */ /* select the first destination server, whose weight > 0 */
for (e=set->list; e!=NULL; e=e->next) { list_for_each_entry(e, &set->list, list) {
least = e->dest; least = e->dest;
if (least->flags & IP_VS_DEST_F_OVERLOAD) if (least->flags & IP_VS_DEST_F_OVERLOAD)
continue; continue;
...@@ -190,7 +188,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set) ...@@ -190,7 +188,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set)
/* find the destination with the weighted least load */ /* find the destination with the weighted least load */
nextstage: nextstage:
for (e=e->next; e!=NULL; e=e->next) { list_for_each_entry(e, &set->list, list) {
dest = e->dest; dest = e->dest;
if (dest->flags & IP_VS_DEST_F_OVERLOAD) if (dest->flags & IP_VS_DEST_F_OVERLOAD)
continue; continue;
...@@ -220,7 +218,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set) ...@@ -220,7 +218,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set)
/* get weighted most-connection node in the destination set */ /* get weighted most-connection node in the destination set */
static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set) static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set)
{ {
register struct ip_vs_dest_list *e; register struct ip_vs_dest_set_elem *e;
struct ip_vs_dest *dest, *most; struct ip_vs_dest *dest, *most;
int moh, doh; int moh, doh;
...@@ -228,7 +226,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set) ...@@ -228,7 +226,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set)
return NULL; return NULL;
/* select the first destination server, whose weight > 0 */ /* select the first destination server, whose weight > 0 */
for (e=set->list; e!=NULL; e=e->next) { list_for_each_entry(e, &set->list, list) {
most = e->dest; most = e->dest;
if (atomic_read(&most->weight) > 0) { if (atomic_read(&most->weight) > 0) {
moh = atomic_read(&most->activeconns) * 50 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,7 +238,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set)
/* find the destination with the weighted most load */ /* find the destination with the weighted most load */
nextstage: nextstage:
for (e=e->next; e!=NULL; e=e->next) { list_for_each_entry(e, &set->list, list) {
dest = e->dest; dest = e->dest;
doh = atomic_read(&dest->activeconns) * 50 doh = atomic_read(&dest->activeconns) * 50
+ atomic_read(&dest->inactconns); + 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,7 +387,7 @@ ip_vs_lblcr_new(struct ip_vs_lblcr_table *tbl, const union nf_inet_addr *daddr,
/* initilize its dest set */ /* initilize its dest set */
atomic_set(&(en->set.size), 0); atomic_set(&(en->set.size), 0);
en->set.list = NULL; INIT_LIST_HEAD(&en->set.list);
rwlock_init(&en->set.lock); rwlock_init(&en->set.lock);
ip_vs_lblcr_hash(tbl, en); ip_vs_lblcr_hash(tbl, en);
......
...@@ -768,7 +768,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, ...@@ -768,7 +768,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
} }
instance_destroy(inst); instance_destroy(inst);
goto out; goto out_put;
default: default:
ret = -ENOTSUPP; ret = -ENOTSUPP;
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment