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