summary refs log tree commit diff
path: root/fs/sysfs/inode.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2007-03-15 15:51:28 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-03-15 15:29:26 -0700
commite7b0d26a86943370c04d6833c6edba2a72a6e240 (patch)
tree696e696176a1e72abb80afa6112fc057b39bf86b /fs/sysfs/inode.c
parentd9a9cdfb078d755e648d53ec25b7370f84ee5729 (diff)
downloadlinux-e7b0d26a86943370c04d6833c6edba2a72a6e240.tar.gz
[PATCH] sysfs: reinstate exclusion between method calls and attribute unregistration
This patch (as869) reinstates the mutual exclusion between sysfs
attribute method calls and attribute unregistration.  The
previously-reported deadlocks have been fixed, and this exclusion is
by far the simplest way to avoid races during driver unbinding.

The check for orphaned read-buffers has been moved down slightly, so
that the remainder of a partially-read buffer will still be available
to userspace even after the attribute has been unregistered.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Cc: Hugh Dickins <hugh@veritas.com>
Cc: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/sysfs/inode.c')
-rw-r--r--fs/sysfs/inode.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index ccb7d722c558..4de5c6b89918 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -222,13 +222,17 @@ const unsigned char * sysfs_get_name(struct sysfs_dirent *sd)
 
 static inline void orphan_all_buffers(struct inode *node)
 {
-	struct sysfs_buffer_collection *set = node->i_private;
+	struct sysfs_buffer_collection *set;
 	struct sysfs_buffer *buf;
 
 	mutex_lock_nested(&node->i_mutex, I_MUTEX_CHILD);
-	if (node->i_private) {
-		list_for_each_entry(buf, &set->associates, associates)
+	set = node->i_private;
+	if (set) {
+		list_for_each_entry(buf, &set->associates, associates) {
+			down(&buf->sem);
 			buf->orphaned = 1;
+			up(&buf->sem);
+		}
 	}
 	mutex_unlock(&node->i_mutex);
 }