LVS
lvs-devel
Google
 
Web LinuxVirtualServer.org

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

To: <wensong@xxxxxxxxxxxx>, <horms@xxxxxxxxxxxx>, <ja@xxxxxx>
Subject: [RFC PATCH net-next 4/4] ipvs: check return value of del_dest
Cc: <lvs-devel@xxxxxxxxxxxxxxx>, <kernel-team@xxxxxx>, Alex Gartrell <agartrell@xxxxxx>
From: Alex Gartrell <agartrell@xxxxxx>
Date: Mon, 23 Feb 2015 21:07:42 -0800
If del_dest returns non-zero, restore flags and the counts in services and
ipvs and leave things as they were.

Signed-off-by: Alex Gartrell <agartrell@xxxxxx>
---
 net/netfilter/ipvs/ip_vs_ctl.c | 42 +++++++++++++++++++++++++-----------------
 1 file changed, 25 insertions(+), 17 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index d384b7f..2e9deb4 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1068,10 +1068,13 @@ static void __ip_vs_del_dest(struct net *net, struct 
ip_vs_dest *dest,
 /*
  *     Unlink a destination from the given service
  */
-static void __ip_vs_unlink_dest(struct ip_vs_service *svc,
-                               struct ip_vs_dest *dest,
-                               int svcupd)
+static int __ip_vs_unlink_dest(struct ip_vs_service *svc,
+                              struct ip_vs_dest *dest,
+                              int svcupd)
 {
+       int ret = 0;
+       int old_flags = dest->flags;
+
        dest->flags &= ~IP_VS_DEST_F_AVAILABLE;
 
        /*
@@ -1080,16 +1083,25 @@ static void __ip_vs_unlink_dest(struct ip_vs_service 
*svc,
        list_del_rcu(&dest->n_list);
        svc->num_dests--;
 
-       if (dest->af != svc->af)
-               net_ipvs(svc->net)->mixed_address_family_dests--;
 
        if (svcupd) {
                struct ip_vs_scheduler *sched;
 
                sched = rcu_dereference_protected(svc->scheduler, 1);
-               if (sched->del_dest)
-                       sched->del_dest(svc, dest);
+               if (sched->del_dest) {
+                       ret = sched->del_dest(svc, dest);
+                       if (ret) {
+                               list_add_rcu(&dest->n_list, &svc->destinations);
+                               dest->flags = old_flags;
+                               svc->num_dests++;
+                       }
+               }
        }
+
+       if (!ret && dest->af != svc->af)
+               net_ipvs(svc->net)->mixed_address_family_dests--;
+
+       return ret;
 }
 
 
@@ -1101,6 +1113,7 @@ ip_vs_del_dest(struct ip_vs_service *svc, struct 
ip_vs_dest_user_kern *udest)
 {
        struct ip_vs_dest *dest;
        __be16 dport = udest->port;
+       int ret;
 
        EnterFunction(2);
 
@@ -1114,19 +1127,14 @@ ip_vs_del_dest(struct ip_vs_service *svc, struct 
ip_vs_dest_user_kern *udest)
                return -ENOENT;
        }
 
-       /*
-        *      Unlink dest from the service
-        */
-       __ip_vs_unlink_dest(svc, dest, 1);
-
-       /*
-        *      Delete the destination
-        */
-       __ip_vs_del_dest(svc->net, dest, false);
+       /* First unlink, and then delete if the unlink worked */
+       ret = __ip_vs_unlink_dest(svc, dest, 1);
+       if (!ret)
+               __ip_vs_del_dest(svc->net, dest, false);
 
        LeaveFunction(2);
 
-       return 0;
+       return ret;
 }
 
 static void ip_vs_dest_trash_expire(unsigned long data)
-- 
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>