git: cd7306bb1fd1 - main - ip_mroute: split mrouter interface deactivation and if_free

From: Wojciech Macek <wma_at_FreeBSD.org>
Date: Fri, 04 Feb 2022 09:25:26 UTC
The branch main has been updated by wma:

URL: https://cgit.FreeBSD.org/src/commit/?id=cd7306bb1fd1c4f2b2875bb7947ef5ee905f5f26

commit cd7306bb1fd1c4f2b2875bb7947ef5ee905f5f26
Author:     Sylvian Meygret <sylvain.meygret.external@stormshield.eu>
AuthorDate: 2022-02-04 09:19:55 +0000
Commit:     Wojciech Macek <wma@FreeBSD.org>
CommitDate: 2022-02-04 09:25:07 +0000

    ip_mroute: split mrouter interface deactivation and if_free
    
    Move if_free outside MRW_LOCK. This will silence LOR message
    which might appere during deinitialization.
---
 sys/netinet/ip_mroute.c | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c
index c678acd650c0..99ec2952de88 100644
--- a/sys/netinet/ip_mroute.c
+++ b/sys/netinet/ip_mroute.c
@@ -316,7 +316,7 @@ static void	bw_upcalls_send(void);
 static int	del_bw_upcall(struct bw_upcall *);
 static int	del_mfc(struct mfcctl2 *);
 static int	del_vif(vifi_t);
-static int	del_vif_locked(vifi_t);
+static int	del_vif_locked(vifi_t, struct ifnet **);
 static void	expire_bw_upcalls_send(void *);
 static void	expire_mfc(struct mfc *);
 static void	expire_upcalls(void *);
@@ -621,7 +621,8 @@ static void
 if_detached_event(void *arg __unused, struct ifnet *ifp)
 {
     vifi_t vifi;
-    u_long i;
+    u_long i, vifi_cnt = 0;
+    struct ifnet *free_ptr;
 
     MRW_WLOCK();
 
@@ -650,10 +651,20 @@ if_detached_event(void *arg __unused, struct ifnet *ifp)
 			}
 		}
 	}
-	del_vif_locked(vifi);
+	del_vif_locked(vifi, &free_ptr);
+	if (free_ptr != NULL)
+		vifi_cnt++;
     }
 
     MRW_WUNLOCK();
+
+    /*
+     * Free IFP. We don't have to use free_ptr here as it is the same
+     * that ifp. Perform free as many times as required in case
+     * refcount is greater than 1.
+     */
+    for (i = 0; i < vifi_cnt; i++)
+	    if_free(ifp);
 }
 
 static void
@@ -982,10 +993,12 @@ add_vif(struct vifctl *vifcp)
  * Delete a vif from the vif table
  */
 static int
-del_vif_locked(vifi_t vifi)
+del_vif_locked(vifi_t vifi, struct ifnet **ifp_free)
 {
     struct vif *vifp;
 
+    *ifp_free = NULL;
+
     MRW_WLOCK_ASSERT();
 
     if (vifi >= V_numvifs) {
@@ -1004,7 +1017,7 @@ del_vif_locked(vifi_t vifi)
 	if (vifp->v_ifp) {
 	    if (vifp->v_ifp == V_multicast_register_if)
 	        V_multicast_register_if = NULL;
-	    if_free(vifp->v_ifp);
+	    *ifp_free = vifp->v_ifp;
 	}
     }
 
@@ -1027,11 +1040,15 @@ static int
 del_vif(vifi_t vifi)
 {
     int cc;
+    struct ifnet *free_ptr;
 
     MRW_WLOCK();
-    cc = del_vif_locked(vifi);
+    cc = del_vif_locked(vifi, &free_ptr);
     MRW_WUNLOCK();
 
+    if (free_ptr)
+	    if_free(free_ptr);
+
     return cc;
 }