aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/core/sysfs.c6
-rw-r--r--fs/sysfs/dir.c31
-rw-r--r--include/linux/device.h3
-rw-r--r--include/linux/sysfs.h12
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
76static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR, 76static 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
598static DEVICE_ATTR(authorized, 0644, 598static 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}
621static DEVICE_ATTR(remove, 0200, NULL, usb_remove_store); 621static DEVICE_ATTR_IGNORE_LOCKDEP(remove, 0200, NULL, usb_remove_store);
622 622
623 623
624static struct attribute *dev_attrs[] = { 624static 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 */
138static 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
146static 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
508extern int device_create_file(struct device *device, 511extern 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
85struct file; 97struct file;