aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2014-11-19 08:22:22 -0500
committerMarcel Holtmann <marcel@holtmann.org>2014-11-19 10:19:47 -0500
commit0378b59770130a994272b176a2a4346dc27361e9 (patch)
tree38615471a8b13d1e3b4d8d0ad5bfee0b75053249
parentcb6f3f7ace0e61285db22508a9efd8a5aeca0af5 (diff)
Bluetooth: Convert link keys list to use RCU
This patch converts the hdev->link_keys list to be protected through RCU, thereby eliminating the need to hold the hdev lock while accessing the list. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/bluetooth/hci_core.h1
-rw-r--r--net/bluetooth/hci_core.c37
-rw-r--r--net/bluetooth/hci_event.c4
3 files changed, 21 insertions, 21 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index a805b3d97c0b..396c09840fdf 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -130,6 +130,7 @@ struct smp_irk {
130 130
131struct link_key { 131struct link_key {
132 struct list_head list; 132 struct list_head list;
133 struct rcu_head rcu;
133 bdaddr_t bdaddr; 134 bdaddr_t bdaddr;
134 u8 type; 135 u8 type;
135 u8 val[HCI_LINK_KEY_SIZE]; 136 u8 val[HCI_LINK_KEY_SIZE];
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index a67a4b8e4e1c..5c319a49a5a4 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -274,15 +274,13 @@ static const struct file_operations inquiry_cache_fops = {
274static int link_keys_show(struct seq_file *f, void *ptr) 274static int link_keys_show(struct seq_file *f, void *ptr)
275{ 275{
276 struct hci_dev *hdev = f->private; 276 struct hci_dev *hdev = f->private;
277 struct list_head *p, *n; 277 struct link_key *key;
278 278
279 hci_dev_lock(hdev); 279 rcu_read_lock();
280 list_for_each_safe(p, n, &hdev->link_keys) { 280 list_for_each_entry_rcu(key, &hdev->link_keys, list)
281 struct link_key *key = list_entry(p, struct link_key, list);
282 seq_printf(f, "%pMR %u %*phN %u\n", &key->bdaddr, key->type, 281 seq_printf(f, "%pMR %u %*phN %u\n", &key->bdaddr, key->type,
283 HCI_LINK_KEY_SIZE, key->val, key->pin_len); 282 HCI_LINK_KEY_SIZE, key->val, key->pin_len);
284 } 283 rcu_read_unlock();
285 hci_dev_unlock(hdev);
286 284
287 return 0; 285 return 0;
288} 286}
@@ -3101,15 +3099,11 @@ void hci_uuids_clear(struct hci_dev *hdev)
3101 3099
3102void hci_link_keys_clear(struct hci_dev *hdev) 3100void hci_link_keys_clear(struct hci_dev *hdev)
3103{ 3101{
3104 struct list_head *p, *n; 3102 struct link_key *key;
3105
3106 list_for_each_safe(p, n, &hdev->link_keys) {
3107 struct link_key *key;
3108
3109 key = list_entry(p, struct link_key, list);
3110 3103
3111 list_del(p); 3104 list_for_each_entry_rcu(key, &hdev->link_keys, list) {
3112 kfree(key); 3105 list_del_rcu(&key->list);
3106 kfree_rcu(key, rcu);
3113 } 3107 }
3114} 3108}
3115 3109
@@ -3137,9 +3131,14 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
3137{ 3131{
3138 struct link_key *k; 3132 struct link_key *k;
3139 3133
3140 list_for_each_entry(k, &hdev->link_keys, list) 3134 rcu_read_lock();
3141 if (bacmp(bdaddr, &k->bdaddr) == 0) 3135 list_for_each_entry_rcu(k, &hdev->link_keys, list) {
3136 if (bacmp(bdaddr, &k->bdaddr) == 0) {
3137 rcu_read_unlock();
3142 return k; 3138 return k;
3139 }
3140 }
3141 rcu_read_unlock();
3143 3142
3144 return NULL; 3143 return NULL;
3145} 3144}
@@ -3290,7 +3289,7 @@ struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn,
3290 key = kzalloc(sizeof(*key), GFP_KERNEL); 3289 key = kzalloc(sizeof(*key), GFP_KERNEL);
3291 if (!key) 3290 if (!key)
3292 return NULL; 3291 return NULL;
3293 list_add(&key->list, &hdev->link_keys); 3292 list_add_rcu(&key->list, &hdev->link_keys);
3294 } 3293 }
3295 3294
3296 BT_DBG("%s key for %pMR type %u", hdev->name, bdaddr, type); 3295 BT_DBG("%s key for %pMR type %u", hdev->name, bdaddr, type);
@@ -3383,8 +3382,8 @@ int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
3383 3382
3384 BT_DBG("%s removing %pMR", hdev->name, bdaddr); 3383 BT_DBG("%s removing %pMR", hdev->name, bdaddr);
3385 3384
3386 list_del(&key->list); 3385 list_del_rcu(&key->list);
3387 kfree(key); 3386 kfree_rcu(key, rcu);
3388 3387
3389 return 0; 3388 return 0;
3390} 3389}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 54680fd39608..bd0a80120665 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3324,8 +3324,8 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
3324 */ 3324 */
3325 if (key->type == HCI_LK_DEBUG_COMBINATION && 3325 if (key->type == HCI_LK_DEBUG_COMBINATION &&
3326 !test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags)) { 3326 !test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags)) {
3327 list_del(&key->list); 3327 list_del_rcu(&key->list);
3328 kfree(key); 3328 kfree_rcu(key, rcu);
3329 } else if (conn) { 3329 } else if (conn) {
3330 if (persistent) 3330 if (persistent)
3331 clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags); 3331 clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags);