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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Filesystem Devel]     [Linux NFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]     [X.Org]

  Powered by Linux