Commit 2f3edc69 authored by James Bottomley's avatar James Bottomley

[SCSI] transport_class: BUG if we can't release the attribute container

Every current transport class calls transport_container_release but
ignores the return value.  This is catastrophic if it returns an error
because the containers are part of a global list and the next action of
almost every transport class is to free the memory used by the
container.

Fix this by making transport_container_release a void, but making it BUG
if attribute_container_release returns an error ... this catches the
root cause of a system panic much earlier.  If we don't do this, we get
an eventual BUG when the attribute container list notices the corruption
caused by the freed memory it's still referencing.

Also made attribute_container_release __must_check as a reminder.

Cc: Greg KH <greg@kroah.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent fa8e36c3
...@@ -108,7 +108,8 @@ EXPORT_SYMBOL_GPL(anon_transport_class_register); ...@@ -108,7 +108,8 @@ EXPORT_SYMBOL_GPL(anon_transport_class_register);
*/ */
void anon_transport_class_unregister(struct anon_transport_class *atc) void anon_transport_class_unregister(struct anon_transport_class *atc)
{ {
attribute_container_unregister(&atc->container); if (unlikely(attribute_container_unregister(&atc->container)))
BUG();
} }
EXPORT_SYMBOL_GPL(anon_transport_class_unregister); EXPORT_SYMBOL_GPL(anon_transport_class_unregister);
......
...@@ -289,7 +289,7 @@ raid_class_release(struct raid_template *r) ...@@ -289,7 +289,7 @@ raid_class_release(struct raid_template *r)
{ {
struct raid_internal *i = to_raid_internal(r); struct raid_internal *i = to_raid_internal(r);
attribute_container_unregister(&i->r.raid_attrs.ac); BUG_ON(attribute_container_unregister(&i->r.raid_attrs.ac));
kfree(i); kfree(i);
} }
......
...@@ -37,7 +37,7 @@ attribute_container_set_no_classdevs(struct attribute_container *atc) ...@@ -37,7 +37,7 @@ attribute_container_set_no_classdevs(struct attribute_container *atc)
} }
int attribute_container_register(struct attribute_container *cont); int attribute_container_register(struct attribute_container *cont);
int attribute_container_unregister(struct attribute_container *cont); int __must_check attribute_container_unregister(struct attribute_container *cont);
void attribute_container_create_device(struct device *dev, void attribute_container_create_device(struct device *dev,
int (*fn)(struct attribute_container *, int (*fn)(struct attribute_container *,
struct device *, struct device *,
......
...@@ -86,9 +86,10 @@ static inline int transport_container_register(struct transport_container *tc) ...@@ -86,9 +86,10 @@ static inline int transport_container_register(struct transport_container *tc)
return attribute_container_register(&tc->ac); return attribute_container_register(&tc->ac);
} }
static inline int transport_container_unregister(struct transport_container *tc) static inline void transport_container_unregister(struct transport_container *tc)
{ {
return attribute_container_unregister(&tc->ac); if (unlikely(attribute_container_unregister(&tc->ac)))
BUG();
} }
int transport_class_register(struct transport_class *); int transport_class_register(struct transport_class *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment