Module Name:    src
Committed By:   ozaki-r
Date:           Tue May 29 04:36:48 UTC 2018

Modified Files:
        src/sys/netinet6: in6_var.h mld6.c

Log Message:
Improve atomicity of in6_leavegroup and in6_delmulti


To generate a diff of this commit:
cvs rdiff -u -r1.98 -r1.99 src/sys/netinet6/in6_var.h
cvs rdiff -u -r1.94 -r1.95 src/sys/netinet6/mld6.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/netinet6/in6_var.h
diff -u src/sys/netinet6/in6_var.h:1.98 src/sys/netinet6/in6_var.h:1.99
--- src/sys/netinet6/in6_var.h:1.98	Thu Apr 19 21:22:02 2018
+++ src/sys/netinet6/in6_var.h	Tue May 29 04:36:47 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_var.h,v 1.98 2018/04/19 21:22:02 christos Exp $	*/
+/*	$NetBSD: in6_var.h,v 1.99 2018/05/29 04:36:47 ozaki-r Exp $	*/
 /*	$KAME: in6_var.h,v 1.81 2002/06/08 11:16:51 itojun Exp $	*/
 
 /*
@@ -691,6 +691,7 @@ void	in6_purge_multi(struct ifnet *);
 struct	in6_multi *in6_addmulti(struct in6_addr *, struct ifnet *,
 	int *, int);
 void	in6_delmulti(struct in6_multi *);
+void	in6_delmulti_locked(struct in6_multi *);
 struct in6_multi_mship *in6_joingroup(struct ifnet *, struct in6_addr *,
 	int *, int);
 int	in6_leavegroup(struct in6_multi_mship *);

Index: src/sys/netinet6/mld6.c
diff -u src/sys/netinet6/mld6.c:1.94 src/sys/netinet6/mld6.c:1.95
--- src/sys/netinet6/mld6.c:1.94	Tue May 29 04:36:15 2018
+++ src/sys/netinet6/mld6.c	Tue May 29 04:36:47 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: mld6.c,v 1.94 2018/05/29 04:36:15 ozaki-r Exp $	*/
+/*	$NetBSD: mld6.c,v 1.95 2018/05/29 04:36:47 ozaki-r Exp $	*/
 /*	$KAME: mld6.c,v 1.25 2001/01/16 14:14:18 itojun Exp $	*/
 
 /*
@@ -102,7 +102,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.94 2018/05/29 04:36:15 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.95 2018/05/29 04:36:47 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -815,12 +815,12 @@ in6m_destroy(struct in6_multi *in6m)
  * Delete a multicast address record.
  */
 void
-in6_delmulti(struct in6_multi *in6m)
+in6_delmulti_locked(struct in6_multi *in6m)
 {
 
+	KASSERT(rw_write_held(&in6_multilock));
 	KASSERT(in6m->in6m_refcount > 0);
 
-	rw_enter(&in6_multilock, RW_WRITER);
 	/*
 	 * The caller should have a reference to in6m. So we don't need to care
 	 * of releasing the lock in mld_stoptimer.
@@ -828,6 +828,14 @@ in6_delmulti(struct in6_multi *in6m)
 	mld_stoptimer(in6m);
 	if (--in6m->in6m_refcount == 0)
 		in6m_destroy(in6m);
+}
+
+void
+in6_delmulti(struct in6_multi *in6m)
+{
+
+	rw_enter(&in6_multilock, RW_WRITER);
+	in6_delmulti_locked(in6m);
 	rw_exit(&in6_multilock);
 }
 
@@ -937,12 +945,13 @@ in6_leavegroup(struct in6_multi_mship *i
 {
 	struct in6_multi *in6m;
 
-	rw_enter(&in6_multilock, RW_READER);
+	rw_enter(&in6_multilock, RW_WRITER);
 	in6m = imm->i6mm_maddr;
-	rw_exit(&in6_multilock);
+	imm->i6mm_maddr = NULL;
 	if (in6m != NULL) {
-		in6_delmulti(in6m);
+		in6_delmulti_locked(in6m);
 	}
+	rw_exit(&in6_multilock);
 	free(imm, M_IPMADDR);
 	return 0;
 }

Reply via email to