diff options
author | Hal Rosenstock <halr@voltaire.com> | 2005-07-27 14:45:31 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-27 19:26:11 -0400 |
commit | 2c153b934dca08d58e0aafde18a182e0891aa201 (patch) | |
tree | e650b3894abf254694e71a8f11ce8b3f72ec5558 /drivers/infiniband | |
parent | dbf9227bd3dff71c3c2f540cc3e96098d2ab41e7 (diff) |
[PATCH] IB: Eliminate MAD cache leak associated with local completions
Eliminate MAD cache leak associated with local completions. Also, when
canceling MAD, empty local completion list as well.
Signed-off-by: Hal Rosenstock <halr@voltaire.com>
Cc: Roland Dreier <rolandd@cisco.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/core/mad.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index e96ca278c90e..8948f6f300a4 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c | |||
@@ -1994,6 +1994,8 @@ static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv) | |||
1994 | 1994 | ||
1995 | /* Empty wait list to prevent receives from finding a request */ | 1995 | /* Empty wait list to prevent receives from finding a request */ |
1996 | list_splice_init(&mad_agent_priv->wait_list, &cancel_list); | 1996 | list_splice_init(&mad_agent_priv->wait_list, &cancel_list); |
1997 | /* Empty local completion list as well */ | ||
1998 | list_splice_init(&mad_agent_priv->local_list, &cancel_list); | ||
1997 | spin_unlock_irqrestore(&mad_agent_priv->lock, flags); | 1999 | spin_unlock_irqrestore(&mad_agent_priv->lock, flags); |
1998 | 2000 | ||
1999 | /* Report all cancelled requests */ | 2001 | /* Report all cancelled requests */ |
@@ -2108,6 +2110,7 @@ static void local_completions(void *data) | |||
2108 | struct ib_mad_local_private *local; | 2110 | struct ib_mad_local_private *local; |
2109 | struct ib_mad_agent_private *recv_mad_agent; | 2111 | struct ib_mad_agent_private *recv_mad_agent; |
2110 | unsigned long flags; | 2112 | unsigned long flags; |
2113 | int recv = 0; | ||
2111 | struct ib_wc wc; | 2114 | struct ib_wc wc; |
2112 | struct ib_mad_send_wc mad_send_wc; | 2115 | struct ib_mad_send_wc mad_send_wc; |
2113 | 2116 | ||
@@ -2123,10 +2126,10 @@ static void local_completions(void *data) | |||
2123 | recv_mad_agent = local->recv_mad_agent; | 2126 | recv_mad_agent = local->recv_mad_agent; |
2124 | if (!recv_mad_agent) { | 2127 | if (!recv_mad_agent) { |
2125 | printk(KERN_ERR PFX "No receive MAD agent for local completion\n"); | 2128 | printk(KERN_ERR PFX "No receive MAD agent for local completion\n"); |
2126 | kmem_cache_free(ib_mad_cache, local->mad_priv); | ||
2127 | goto local_send_completion; | 2129 | goto local_send_completion; |
2128 | } | 2130 | } |
2129 | 2131 | ||
2132 | recv = 1; | ||
2130 | /* | 2133 | /* |
2131 | * Defined behavior is to complete response | 2134 | * Defined behavior is to complete response |
2132 | * before request | 2135 | * before request |
@@ -2169,6 +2172,8 @@ local_send_completion: | |||
2169 | spin_lock_irqsave(&mad_agent_priv->lock, flags); | 2172 | spin_lock_irqsave(&mad_agent_priv->lock, flags); |
2170 | list_del(&local->completion_list); | 2173 | list_del(&local->completion_list); |
2171 | atomic_dec(&mad_agent_priv->refcount); | 2174 | atomic_dec(&mad_agent_priv->refcount); |
2175 | if (!recv) | ||
2176 | kmem_cache_free(ib_mad_cache, local->mad_priv); | ||
2172 | kfree(local); | 2177 | kfree(local); |
2173 | } | 2178 | } |
2174 | spin_unlock_irqrestore(&mad_agent_priv->lock, flags); | 2179 | spin_unlock_irqrestore(&mad_agent_priv->lock, flags); |