If the scheduler's add_dest function fails, free the newly allocated or
reclaimed dest and then return the error code to the user.
Signed-off-by: Alex Gartrell <agartrell@xxxxxx>
---
net/netfilter/ipvs/ip_vs_ctl.c | 28 +++++++++++++++++++++-------
1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 6341e3f..d384b7f 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -787,7 +787,7 @@ ip_vs_zero_stats(struct ip_vs_stats *stats)
/*
* Update a destination in the given service
*/
-static void
+static int
__ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
struct ip_vs_dest_user_kern *udest, int add)
{
@@ -795,6 +795,7 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct
ip_vs_dest *dest,
struct ip_vs_service *old_svc;
struct ip_vs_scheduler *sched;
int conn_flags;
+ int ret = 0;
/* We cannot modify an address and change the address family */
BUG_ON(!add && udest->af != dest->af);
@@ -850,12 +851,20 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct
ip_vs_dest *dest,
ip_vs_start_estimator(svc->net, &dest->stats);
list_add_rcu(&dest->n_list, &svc->destinations);
svc->num_dests++;
- if (sched->add_dest)
- sched->add_dest(svc, dest);
+ if (sched->add_dest) {
+ ret = sched->add_dest(svc, dest);
+ if (ret) {
+ ip_vs_stop_estimator(svc->net, &dest->stats);
+ list_del_rcu(&dest->n_list);
+ svc->num_dests--;
+ }
+ }
} else {
if (sched->upd_dest)
sched->upd_dest(svc, dest);
}
+
+ return ret;
}
@@ -867,6 +876,7 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct
ip_vs_dest_user_kern *udest)
{
struct ip_vs_dest *dest;
unsigned int atype, i;
+ int ret;
EnterFunction(2);
@@ -915,10 +925,13 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct
ip_vs_dest_user_kern *udest)
INIT_HLIST_NODE(&dest->d_list);
spin_lock_init(&dest->dst_lock);
spin_lock_init(&dest->stats.lock);
- __ip_vs_update_dest(svc, dest, udest, 1);
+
+ ret = __ip_vs_update_dest(svc, dest, udest, 1);
+ if (ret)
+ kfree(dest);
LeaveFunction(2);
- return 0;
+ return ret;
err_alloc:
kfree(dest);
@@ -977,8 +990,9 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct
ip_vs_dest_user_kern *udest)
IP_VS_DBG_ADDR(svc->af, &dest->vaddr),
ntohs(dest->vport));
- __ip_vs_update_dest(svc, dest, udest, 1);
- ret = 0;
+ ret = __ip_vs_update_dest(svc, dest, udest, 1);
+ if (ret)
+ ip_vs_trash_put_dest(net_ipvs(svc->net), dest, false);
} else {
/*
* Allocate and initialize the dest structure
--
Alex Gartrell <agartrell@xxxxxx>
--
To unsubscribe from this list: send the line "unsubscribe lvs-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
|