From 2f3edc6936e3f6be3f1df1e89c141ae028fa605e Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 2 Apr 2008 10:05:48 -0500 Subject: [PATCH] [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 Signed-off-by: James Bottomley --- drivers/base/transport_class.c | 3 ++- drivers/scsi/raid_class.c | 2 +- include/linux/attribute_container.h | 2 +- include/linux/transport_class.h | 5 +++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/base/transport_class.c b/drivers/base/transport_class.c index 40bca48abc12..cabd0edf2156 100644 --- a/drivers/base/transport_class.c +++ b/drivers/base/transport_class.c @@ -108,7 +108,8 @@ EXPORT_SYMBOL_GPL(anon_transport_class_register); */ 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); diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c index 86e13183c9ba..52182a744ba6 100644 --- a/drivers/scsi/raid_class.c +++ b/drivers/scsi/raid_class.c @@ -289,7 +289,7 @@ raid_class_release(struct raid_template *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); } diff --git a/include/linux/attribute_container.h b/include/linux/attribute_container.h index f5582332af04..574b201b99d8 100644 --- a/include/linux/attribute_container.h +++ b/include/linux/attribute_container.h @@ -37,7 +37,7 @@ attribute_container_set_no_classdevs(struct attribute_container *atc) } 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, int (*fn)(struct attribute_container *, struct device *, diff --git a/include/linux/transport_class.h b/include/linux/transport_class.h index 1d6cc22e5f42..6696cf79c4f7 100644 --- a/include/linux/transport_class.h +++ b/include/linux/transport_class.h @@ -86,9 +86,10 @@ static inline int transport_container_register(struct transport_container *tc) 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 *);