Transitioning if_addr_lock to an rwlock

Bjoern A. Zeeb bz at FreeBSD.org
Tue Jan 3 20:06:30 UTC 2012


On 3. Jan 2012, at 16:23 , John Baldwin wrote:

> On Thursday, December 29, 2011 5:55:39 pm Gleb Smirnoff wrote:
>> On Thu, Dec 29, 2011 at 03:27:26PM -0500, John Baldwin wrote:
>> J> - if_addr_uses.patch     This changes callers of the existing macros to use
>> J>                          either read or write locks.  This is the patch that
>> J>                          could use the most review.
>> 
>> Reviewing your patch I've found several problems not introduced by it,
>> but already existing, and somewhat related to your patch:
>> 
>> 1) Unneeded use of _SAFE version of TAILQ:
>> 
>> igmp.c:3338
>> in6.c:1339
>> mld6.c:2993
> 
> I'll fix these.
> 
>> 2) Potential race when dropping a lock inside FOREACH loop:
>> 
>> igmp.c:2058
>> mld6.c:1419
>> mld6.c:1704 (this one isn't even a SAFE, so would crash earlier)
> 
> These are not easy to fix. :(  Dropping the lock is of course the
> wrong thing to do.  However, there are a few layering violations that
> make this hard to fix properly.  Actually, we might be able to use
> an approach similar to that used in mld_ifdetach() and igmp_ifdetach()
> to fix the cancel timers cases.  Patch below
> 
>> 3) I've found that in6_ifawithifp() doesn't do what it is supposed
>> to, as well as uses incorrect locking during this. As last resort
>> it should run through global list of addresses, not run throgh the
>> ifp one again. Patch attached.
> 
> This looks good to me.  Maybe you can get bz@ to review it?

Will look at that one next.

The two below seem fine.   Would have loved the lock assertions that the
mld6 one has on igmp as well but that's a different (unrelated) story:-)

/bz

> Index: netinet/igmp.c
> ===================================================================
> --- netinet/igmp.c	(revision 229389)
> +++ netinet/igmp.c	(working copy)
> @@ -2004,7 +2003,7 @@
> {
> 	struct ifmultiaddr	*ifma;
> 	struct ifnet		*ifp;
> -	struct in_multi		*inm;
> +	struct in_multi		*inm, *tinm;
> 
> 	CTR3(KTR_IGMPV3, "%s: cancel v3 timers on ifp %p(%s)", __func__,
> 	    igi->igi_ifp, igi->igi_ifp->if_xname);
> @@ -2050,14 +2049,8 @@
> 			 * transition to REPORTING to ensure the host leave
> 			 * message is sent upstream to the old querier --
> 			 * transition to NOT would lose the leave and race.
> -			 *
> -			 * SMPNG: Must drop and re-acquire IF_ADDR_LOCK
> -			 * around inm_release_locked(), as it is not
> -			 * a recursive mutex.
> 			 */
> -			IF_ADDR_UNLOCK(ifp);
> -			inm_release_locked(inm);
> -			IF_ADDR_LOCK(ifp);
> +			SLIST_INSERT_HEAD(&igi->igi_relinmhead, inm, inm_nrele);
> 			/* FALLTHROUGH */
> 		case IGMP_G_QUERY_PENDING_MEMBER:
> 		case IGMP_SG_QUERY_PENDING_MEMBER:
> @@ -2076,6 +2069,10 @@
> 		_IF_DRAIN(&inm->inm_scq);
> 	}
> 	IF_ADDR_UNLOCK(ifp);
> +	SLIST_FOREACH_SAFE(inm, &igi->igi_relinmhead, inm_nrele, tinm) {
> +		SLIST_REMOVE_HEAD(&igi->igi_relinmhead, inm_nrele);
> +		inm_release_locked(inm);
> +	}
> }
> 
> /*
> Index: netinet6/mld6.c
> ===================================================================
> --- netinet6/mld6.c	(revision 229389)
> +++ netinet6/mld6.c	(working copy)
> @@ -1656,7 +1656,7 @@
> {
> 	struct ifmultiaddr	*ifma;
> 	struct ifnet		*ifp;
> -	struct in6_multi		*inm;
> +	struct in6_multi	*inm, *tinm;
> 
> 	CTR3(KTR_MLD, "%s: cancel v2 timers on ifp %p(%s)", __func__,
> 	    mli->mli_ifp, mli->mli_ifp->if_xname);
> @@ -1695,14 +1695,9 @@
> 			 * If we are leaving the group and switching
> 			 * version, we need to release the final
> 			 * reference held for issuing the INCLUDE {}.
> -			 *
> -			 * SMPNG: Must drop and re-acquire IF_ADDR_LOCK
> -			 * around in6m_release_locked(), as it is not
> -			 * a recursive mutex.
> 			 */
> -			IF_ADDR_UNLOCK(ifp);
> -			in6m_release_locked(inm);
> -			IF_ADDR_LOCK(ifp);
> +			SLIST_INSERT_HEAD(&mli->mli_relinmhead, inm,
> +			    in6m_nrele);
> 			/* FALLTHROUGH */
> 		case MLD_G_QUERY_PENDING_MEMBER:
> 		case MLD_SG_QUERY_PENDING_MEMBER:
> @@ -1720,6 +1715,10 @@
> 		}
> 	}
> 	IF_ADDR_UNLOCK(ifp);
> +	SLIST_FOREACH_SAFE(inm, &mli->mli_relinmhead, in6m_nrele, tinm) {
> +		SLIST_REMOVE_HEAD(&mli->mli_relinmhead, in6m_nrele);
> +		in6m_release_locked(inm);
> +	}
> }
> 
> /*
> 
> -- 
> John Baldwin
> _______________________________________________
> freebsd-net at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-net
> To unsubscribe, send any mail to "freebsd-net-unsubscribe at freebsd.org"

-- 
Bjoern A. Zeeb                                 You have to have visions!
   It does not matter how good you are. It matters what good you do!



More information about the freebsd-net mailing list