svn commit: r353353 - head/sys/netinet
Hans Petter Selasky
hselasky at FreeBSD.org
Wed Oct 9 16:48:49 UTC 2019
Author: hselasky
Date: Wed Oct 9 16:48:48 2019
New Revision: 353353
URL: https://svnweb.freebsd.org/changeset/base/353353
Log:
Fix locking order reversal in the TCP ratelimit code by moving
destructors outside the rsmtx mutex.
Witness message:
lock order reversal: (sleepable after non-sleepable)
1st tcp_rs_mtx (rsmtx) @ sys/netinet/tcp_ratelimit.c:242
2nd sysctl lock (sysctl lock) @ sys/kern/kern_sysctl.c:607
Backtrace:
witness_debugger
witness_checkorder
_rm_wlock_debug
sysctl_ctx_free
rs_destroy
epoch_call_task
gtaskqueue_run_locked
gtaskqueue_thread_loop
Discussed with: rrs@
Sponsored by: Mellanox Technologies
Modified:
head/sys/netinet/tcp_ratelimit.c
Modified: head/sys/netinet/tcp_ratelimit.c
==============================================================================
--- head/sys/netinet/tcp_ratelimit.c Wed Oct 9 16:42:51 2019 (r353352)
+++ head/sys/netinet/tcp_ratelimit.c Wed Oct 9 16:48:48 2019 (r353353)
@@ -237,34 +237,37 @@ static void
rs_destroy(epoch_context_t ctx)
{
struct tcp_rate_set *rs;
+ bool do_free_rs;
rs = __containerof(ctx, struct tcp_rate_set, rs_epoch_ctx);
+
mtx_lock(&rs_mtx);
rs->rs_flags &= ~RS_FUNERAL_SCHD;
- if (rs->rs_flows_using == 0) {
- /*
- * In theory its possible (but unlikely)
- * that while the delete was occuring
- * and we were applying the DEAD flag
- * someone slipped in and found the
- * interface in a lookup. While we
- * decided rs_flows_using were 0 and
- * scheduling the epoch_call, the other
- * thread incremented rs_flow_using. This
- * is because users have a pointer and
- * we only use the rs_flows_using in an
- * atomic fashion, i.e. the other entities
- * are not protected. To assure this did
- * not occur, we check rs_flows_using here
- * before deleteing.
- */
+ /*
+ * In theory its possible (but unlikely)
+ * that while the delete was occuring
+ * and we were applying the DEAD flag
+ * someone slipped in and found the
+ * interface in a lookup. While we
+ * decided rs_flows_using were 0 and
+ * scheduling the epoch_call, the other
+ * thread incremented rs_flow_using. This
+ * is because users have a pointer and
+ * we only use the rs_flows_using in an
+ * atomic fashion, i.e. the other entities
+ * are not protected. To assure this did
+ * not occur, we check rs_flows_using here
+ * before deleting.
+ */
+ do_free_rs = (rs->rs_flows_using == 0);
+ rs_number_dead--;
+ mtx_unlock(&rs_mtx);
+
+ if (do_free_rs) {
sysctl_ctx_free(&rs->sysctl_ctx);
free(rs->rs_rlt, M_TCPPACE);
free(rs, M_TCPPACE);
- rs_number_dead--;
}
- mtx_unlock(&rs_mtx);
-
}
#ifdef INET
More information about the svn-src-head
mailing list