diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2010-02-11 18:21:53 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-03-07 20:04:51 -0500 |
commit | 6992f5334995af474c2b58d010d08bc597f0f2fe (patch) | |
tree | bef650bfb9355b8d7cbb7a5acb3632c02ec7fbe7 | |
parent | a2db6842873c8e5a70652f278d469128cb52db70 (diff) |
sysfs: Use one lockdep class per sysfs attribute.
Acknowledge that the logical sysfs rwsem has one instance per
sysfs attribute with different locking depencencies for different
attributes.
There is a sysfs idiom where writing to one sysfs file causes the
addition or removal of other sysfs files. Lumping all of the
sysfs attributes together in one lock class causes lockdep to
generate lots of false positives.
This introduces the requirement that non-static sysfs attributes
need to be initialized with sysfs_attr_init or sysfs_bin_attr_init.
Strictly speaking this requirement only exists when lockdep is
enabled, and when lockdep is enabled we get a bit fat warning
if this requirement is not met.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Acked-by: WANG Cong <xiyou.wangcong@gmail.com>
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | fs/sysfs/sysfs.h | 7 | ||||
-rw-r--r-- | include/linux/sysfs.h | 18 |
2 files changed, 23 insertions, 2 deletions
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 7db6884f4206..37e0e086233c 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -92,9 +92,12 @@ static inline unsigned int sysfs_type(struct sysfs_dirent *sd) | |||
92 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 92 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
93 | #define sysfs_dirent_init_lockdep(sd) \ | 93 | #define sysfs_dirent_init_lockdep(sd) \ |
94 | do { \ | 94 | do { \ |
95 | static struct lock_class_key __key; \ | 95 | struct attribute *attr = sd->s_attr.attr; \ |
96 | struct lock_class_key *key = attr->key; \ | ||
97 | if (!key) \ | ||
98 | key = &attr->skey; \ | ||
96 | \ | 99 | \ |
97 | lockdep_init_map(&sd->dep_map, "s_active", &__key, 0); \ | 100 | lockdep_init_map(&sd->dep_map, "s_active", key, 0); \ |
98 | } while(0) | 101 | } while(0) |
99 | #else | 102 | #else |
100 | #define sysfs_dirent_init_lockdep(sd) do {} while(0) | 103 | #define sysfs_dirent_init_lockdep(sd) do {} while(0) |
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 3e8526582146..006c359e63c0 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/compiler.h> | 15 | #include <linux/compiler.h> |
16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
17 | #include <linux/list.h> | 17 | #include <linux/list.h> |
18 | #include <linux/lockdep.h> | ||
18 | #include <asm/atomic.h> | 19 | #include <asm/atomic.h> |
19 | 20 | ||
20 | struct kobject; | 21 | struct kobject; |
@@ -29,8 +30,23 @@ struct attribute { | |||
29 | const char *name; | 30 | const char *name; |
30 | struct module *owner; | 31 | struct module *owner; |
31 | mode_t mode; | 32 | mode_t mode; |
33 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
34 | struct lock_class_key *key; | ||
35 | struct lock_class_key skey; | ||
36 | #endif | ||
32 | }; | 37 | }; |
33 | 38 | ||
39 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
40 | #define sysfs_attr_init(attr) \ | ||
41 | do { \ | ||
42 | static struct lock_class_key __key; \ | ||
43 | \ | ||
44 | (attr)->key = &__key; \ | ||
45 | } while(0) | ||
46 | #else | ||
47 | #define sysfs_attr_init(attr) do {} while(0) | ||
48 | #endif | ||
49 | |||
34 | struct attribute_group { | 50 | struct attribute_group { |
35 | const char *name; | 51 | const char *name; |
36 | mode_t (*is_visible)(struct kobject *, | 52 | mode_t (*is_visible)(struct kobject *, |
@@ -74,6 +90,8 @@ struct bin_attribute { | |||
74 | struct vm_area_struct *vma); | 90 | struct vm_area_struct *vma); |
75 | }; | 91 | }; |
76 | 92 | ||
93 | #define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&bin_attr->attr) | ||
94 | |||
77 | struct sysfs_ops { | 95 | struct sysfs_ops { |
78 | ssize_t (*show)(struct kobject *, struct attribute *,char *); | 96 | ssize_t (*show)(struct kobject *, struct attribute *,char *); |
79 | ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); | 97 | ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); |