ChangeSet 1.1156, 2003/04/28 22:27:58-07:00, greg@kroah.com

kobject: kobj_lock needs to be grabed using spinlock_irq

This is because some subsystems (cough, usb...) can grab a kobject from irq context.
This lock can be completely removed once the sysfs_init() code is cleaned up.

Patch originally by Andrew Morton.


 lib/kobject.c |   24 ++++++++++++++++++------
 1 files changed, 18 insertions(+), 6 deletions(-)


diff -Nru a/lib/kobject.c b/lib/kobject.c
--- a/lib/kobject.c	Tue Apr 29 09:48:29 2003
+++ b/lib/kobject.c	Tue Apr 29 09:48:29 2003
@@ -1,5 +1,8 @@
 /*
  * kobject.c - library routines for handling generic kernel objects
+ *
+ * Copyright (c) 2002-2003 Patrick Mochel <mochel@osdl.org>
+ *
  */
 
 #undef DEBUG
@@ -9,6 +12,8 @@
 #include <linux/module.h>
 #include <linux/stat.h>
 
+/* This lock can be removed entirely when the sysfs_init() code is cleaned up
+ * to not try to reference itself before it is initialized. */
 static spinlock_t kobj_lock = SPIN_LOCK_UNLOCKED;
 
 /**
@@ -336,12 +341,14 @@
 struct kobject * kobject_get(struct kobject * kobj)
 {
 	struct kobject * ret = kobj;
-	spin_lock(&kobj_lock);
+	unsigned long flags;
+
+	spin_lock_irqsave(&kobj_lock, flags);
 	if (kobj && atomic_read(&kobj->refcount) > 0)
 		atomic_inc(&kobj->refcount);
 	else
 		ret = NULL;
-	spin_unlock(&kobj_lock);
+	spin_unlock_irqrestore(&kobj_lock, flags);
 	return ret;
 }
 
@@ -371,10 +378,15 @@
 
 void kobject_put(struct kobject * kobj)
 {
-	if (!atomic_dec_and_lock(&kobj->refcount, &kobj_lock))
-		return;
-	spin_unlock(&kobj_lock);
-	kobject_cleanup(kobj);
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (atomic_dec_and_lock(&kobj->refcount, &kobj_lock)) {
+		spin_unlock_irqrestore(&kobj_lock, flags);
+		kobject_cleanup(kobj);
+	} else {
+		local_irq_restore(flags);
+	}
 }
 
 
