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; |
