LVS
lvs-devel
Google
 
Web LinuxVirtualServer.org

[RFC PATCH net-next 3/4] ipvs: check return value of add_dest

To: <wensong@xxxxxxxxxxxx>, <horms@xxxxxxxxxxxx>, <ja@xxxxxx>
Subject: [RFC PATCH net-next 3/4] ipvs: check return value of add_dest
Cc: <lvs-devel@xxxxxxxxxxxxxxx>, <kernel-team@xxxxxx>, Alex Gartrell <agartrell@xxxxxx>
From: Alex Gartrell <agartrell@xxxxxx>
Date: Mon, 23 Feb 2015 21:07:41 -0800
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

<Prev in Thread] Current Thread [Next in Thread>