]> err.no Git - linux-2.6/commitdiff
[SCSI] transport_class: BUG if we can't release the attribute container
authorJames Bottomley <James.Bottomley@HansenPartnership.com>
Wed, 2 Apr 2008 15:05:48 +0000 (10:05 -0500)
committerJames Bottomley <James.Bottomley@HansenPartnership.com>
Mon, 7 Apr 2008 17:19:10 +0000 (12:19 -0500)
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>
drivers/base/transport_class.c
drivers/scsi/raid_class.c
include/linux/attribute_container.h
include/linux/transport_class.h

index 40bca48abc12dcfa18de9e92c8e4327fb1bf6845..cabd0edf21569c3ea1cd2f3da9c77bfd5007936c 100644 (file)
@@ -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);
 
index 86e13183c9bab421418f3fb706662d0f24d6f666..52182a744ba652fbee765293f576b37fd4c95b7d 100644 (file)
@@ -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);
 }
index f5582332af046d4cb00ea31b3beeebccd7da2384..574b201b99d8b0f31c268434546c4930ceb94eb7 100644 (file)
@@ -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 *,
index 1d6cc22e5f42a49ab4e42a3db982c8b4a9107f04..6696cf79c4f72744a6e3494f1c9b82d5def8271e 100644 (file)
@@ -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 *);