aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2008-04-02 11:05:48 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-04-07 13:19:10 -0400
commit2f3edc6936e3f6be3f1df1e89c141ae028fa605e (patch)
tree14198ea135c600b42e4c7416db44967a6517a2db
parentfa8e36c39b00a219d2c37250e493c3421e0e67e9 (diff)
[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: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r--drivers/base/transport_class.c3
-rw-r--r--drivers/scsi/raid_class.c2
-rw-r--r--include/linux/attribute_container.h2
-rw-r--r--include/linux/transport_class.h5
4 files changed, 7 insertions, 5 deletions
diff --git a/drivers/base/transport_class.c b/drivers/base/transport_class.c
index 40bca48abc1..cabd0edf215 100644
--- a/drivers/base/transport_class.c
+++ b/drivers/base/transport_class.c
@@ -108,7 +108,8 @@ EXPORT_SYMBOL_GPL(anon_transport_class_register);
108 */ 108 */
109void anon_transport_class_unregister(struct anon_transport_class *atc) 109void anon_transport_class_unregister(struct anon_transport_class *atc)
110{ 110{
111 attribute_container_unregister(&atc->container); 111 if (unlikely(attribute_container_unregister(&atc->container)))
112 BUG();
112} 113}
113EXPORT_SYMBOL_GPL(anon_transport_class_unregister); 114EXPORT_SYMBOL_GPL(anon_transport_class_unregister);
114 115
diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c
index 86e13183c9b..52182a744ba 100644
--- a/drivers/scsi/raid_class.c
+++ b/drivers/scsi/raid_class.c
@@ -289,7 +289,7 @@ raid_class_release(struct raid_template *r)
289{ 289{
290 struct raid_internal *i = to_raid_internal(r); 290 struct raid_internal *i = to_raid_internal(r);
291 291
292 attribute_container_unregister(&i->r.raid_attrs.ac); 292 BUG_ON(attribute_container_unregister(&i->r.raid_attrs.ac));
293 293
294 kfree(i); 294 kfree(i);
295} 295}
diff --git a/include/linux/attribute_container.h b/include/linux/attribute_container.h
index f5582332af0..574b201b99d 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)
37} 37}
38 38
39int attribute_container_register(struct attribute_container *cont); 39int attribute_container_register(struct attribute_container *cont);
40int attribute_container_unregister(struct attribute_container *cont); 40int __must_check attribute_container_unregister(struct attribute_container *cont);
41void attribute_container_create_device(struct device *dev, 41void attribute_container_create_device(struct device *dev,
42 int (*fn)(struct attribute_container *, 42 int (*fn)(struct attribute_container *,
43 struct device *, 43 struct device *,
diff --git a/include/linux/transport_class.h b/include/linux/transport_class.h
index 1d6cc22e5f4..6696cf79c4f 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)
86 return attribute_container_register(&tc->ac); 86 return attribute_container_register(&tc->ac);
87} 87}
88 88
89static inline int transport_container_unregister(struct transport_container *tc) 89static inline void transport_container_unregister(struct transport_container *tc)
90{ 90{
91 return attribute_container_unregister(&tc->ac); 91 if (unlikely(attribute_container_unregister(&tc->ac)))
92 BUG();
92} 93}
93 94
94int transport_class_register(struct transport_class *); 95int transport_class_register(struct transport_class *);