diff options
-rw-r--r-- | drivers/usb/core/sysfs.c | 6 | ||||
-rw-r--r-- | fs/sysfs/dir.c | 31 | ||||
-rw-r--r-- | include/linux/device.h | 3 | ||||
-rw-r--r-- | include/linux/sysfs.h | 12 |
4 files changed, 44 insertions, 8 deletions
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 566d9f94f735..9a56e3adf476 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c | |||
@@ -73,7 +73,7 @@ set_bConfigurationValue(struct device *dev, struct device_attribute *attr, | |||
73 | return (value < 0) ? value : count; | 73 | return (value < 0) ? value : count; |
74 | } | 74 | } |
75 | 75 | ||
76 | static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR, | 76 | static DEVICE_ATTR_IGNORE_LOCKDEP(bConfigurationValue, S_IRUGO | S_IWUSR, |
77 | show_bConfigurationValue, set_bConfigurationValue); | 77 | show_bConfigurationValue, set_bConfigurationValue); |
78 | 78 | ||
79 | /* String fields */ | 79 | /* String fields */ |
@@ -595,7 +595,7 @@ static ssize_t usb_dev_authorized_store(struct device *dev, | |||
595 | return result < 0? result : size; | 595 | return result < 0? result : size; |
596 | } | 596 | } |
597 | 597 | ||
598 | static DEVICE_ATTR(authorized, 0644, | 598 | static DEVICE_ATTR_IGNORE_LOCKDEP(authorized, 0644, |
599 | usb_dev_authorized_show, usb_dev_authorized_store); | 599 | usb_dev_authorized_show, usb_dev_authorized_store); |
600 | 600 | ||
601 | /* "Safely remove a device" */ | 601 | /* "Safely remove a device" */ |
@@ -618,7 +618,7 @@ static ssize_t usb_remove_store(struct device *dev, | |||
618 | usb_unlock_device(udev); | 618 | usb_unlock_device(udev); |
619 | return rc; | 619 | return rc; |
620 | } | 620 | } |
621 | static DEVICE_ATTR(remove, 0200, NULL, usb_remove_store); | 621 | static DEVICE_ATTR_IGNORE_LOCKDEP(remove, 0200, NULL, usb_remove_store); |
622 | 622 | ||
623 | 623 | ||
624 | static struct attribute *dev_attrs[] = { | 624 | static struct attribute *dev_attrs[] = { |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 24fa995f0312..e6bb9b2a4cbe 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -132,6 +132,24 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) | |||
132 | rb_erase(&sd->s_rb, &sd->s_parent->s_dir.children); | 132 | rb_erase(&sd->s_rb, &sd->s_parent->s_dir.children); |
133 | } | 133 | } |
134 | 134 | ||
135 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
136 | |||
137 | /* Test for attributes that want to ignore lockdep for read-locking */ | ||
138 | static bool ignore_lockdep(struct sysfs_dirent *sd) | ||
139 | { | ||
140 | return sysfs_type(sd) == SYSFS_KOBJ_ATTR && | ||
141 | sd->s_attr.attr->ignore_lockdep; | ||
142 | } | ||
143 | |||
144 | #else | ||
145 | |||
146 | static inline bool ignore_lockdep(struct sysfs_dirent *sd) | ||
147 | { | ||
148 | return true; | ||
149 | } | ||
150 | |||
151 | #endif | ||
152 | |||
135 | /** | 153 | /** |
136 | * sysfs_get_active - get an active reference to sysfs_dirent | 154 | * sysfs_get_active - get an active reference to sysfs_dirent |
137 | * @sd: sysfs_dirent to get an active reference to | 155 | * @sd: sysfs_dirent to get an active reference to |
@@ -155,15 +173,17 @@ struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) | |||
155 | return NULL; | 173 | return NULL; |
156 | 174 | ||
157 | t = atomic_cmpxchg(&sd->s_active, v, v + 1); | 175 | t = atomic_cmpxchg(&sd->s_active, v, v + 1); |
158 | if (likely(t == v)) { | 176 | if (likely(t == v)) |
159 | rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_); | 177 | break; |
160 | return sd; | ||
161 | } | ||
162 | if (t < 0) | 178 | if (t < 0) |
163 | return NULL; | 179 | return NULL; |
164 | 180 | ||
165 | cpu_relax(); | 181 | cpu_relax(); |
166 | } | 182 | } |
183 | |||
184 | if (likely(!ignore_lockdep(sd))) | ||
185 | rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_); | ||
186 | return sd; | ||
167 | } | 187 | } |
168 | 188 | ||
169 | /** | 189 | /** |
@@ -180,7 +200,8 @@ void sysfs_put_active(struct sysfs_dirent *sd) | |||
180 | if (unlikely(!sd)) | 200 | if (unlikely(!sd)) |
181 | return; | 201 | return; |
182 | 202 | ||
183 | rwsem_release(&sd->dep_map, 1, _RET_IP_); | 203 | if (likely(!ignore_lockdep(sd))) |
204 | rwsem_release(&sd->dep_map, 1, _RET_IP_); | ||
184 | v = atomic_dec_return(&sd->s_active); | 205 | v = atomic_dec_return(&sd->s_active); |
185 | if (likely(v != SD_DEACTIVATED_BIAS)) | 206 | if (likely(v != SD_DEACTIVATED_BIAS)) |
186 | return; | 207 | return; |
diff --git a/include/linux/device.h b/include/linux/device.h index a8db2cfa2c81..e04f5776f6d0 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -504,6 +504,9 @@ ssize_t device_store_int(struct device *dev, struct device_attribute *attr, | |||
504 | #define DEVICE_INT_ATTR(_name, _mode, _var) \ | 504 | #define DEVICE_INT_ATTR(_name, _mode, _var) \ |
505 | struct dev_ext_attribute dev_attr_##_name = \ | 505 | struct dev_ext_attribute dev_attr_##_name = \ |
506 | { __ATTR(_name, _mode, device_show_int, device_store_int), &(_var) } | 506 | { __ATTR(_name, _mode, device_show_int, device_store_int), &(_var) } |
507 | #define DEVICE_ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) \ | ||
508 | struct device_attribute dev_attr_##_name = \ | ||
509 | __ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) | ||
507 | 510 | ||
508 | extern int device_create_file(struct device *device, | 511 | extern int device_create_file(struct device *device, |
509 | const struct device_attribute *entry); | 512 | const struct device_attribute *entry); |
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 0010009b2f00..381f06db2fe5 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h | |||
@@ -27,6 +27,7 @@ struct attribute { | |||
27 | const char *name; | 27 | const char *name; |
28 | umode_t mode; | 28 | umode_t mode; |
29 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 29 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
30 | bool ignore_lockdep:1; | ||
30 | struct lock_class_key *key; | 31 | struct lock_class_key *key; |
31 | struct lock_class_key skey; | 32 | struct lock_class_key skey; |
32 | #endif | 33 | #endif |
@@ -80,6 +81,17 @@ struct attribute_group { | |||
80 | 81 | ||
81 | #define __ATTR_NULL { .attr = { .name = NULL } } | 82 | #define __ATTR_NULL { .attr = { .name = NULL } } |
82 | 83 | ||
84 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
85 | #define __ATTR_IGNORE_LOCKDEP(_name, _mode, _show, _store) { \ | ||
86 | .attr = {.name = __stringify(_name), .mode = _mode, \ | ||
87 | .ignore_lockdep = true }, \ | ||
88 | .show = _show, \ | ||
89 | .store = _store, \ | ||
90 | } | ||
91 | #else | ||
92 | #define __ATTR_IGNORE_LOCKDEP __ATTR | ||
93 | #endif | ||
94 | |||
83 | #define attr_name(_attr) (_attr).attr.name | 95 | #define attr_name(_attr) (_attr).attr.name |
84 | 96 | ||
85 | struct file; | 97 | struct file; |