Bluetooth: Convert link keys list to use RCU
[firefly-linux-kernel-4.4.55.git] / net / bluetooth / hci_core.c
index a67a4b8e4e1cc4ca859032eb357c21a82a509c3a..5c319a49a5a4ca8e510a28fe553b5c59c74c2a15 100644 (file)
@@ -274,15 +274,13 @@ static const struct file_operations inquiry_cache_fops = {
 static int link_keys_show(struct seq_file *f, void *ptr)
 {
        struct hci_dev *hdev = f->private;
-       struct list_head *p, *n;
+       struct link_key *key;
 
-       hci_dev_lock(hdev);
-       list_for_each_safe(p, n, &hdev->link_keys) {
-               struct link_key *key = list_entry(p, struct link_key, list);
+       rcu_read_lock();
+       list_for_each_entry_rcu(key, &hdev->link_keys, list)
                seq_printf(f, "%pMR %u %*phN %u\n", &key->bdaddr, key->type,
                           HCI_LINK_KEY_SIZE, key->val, key->pin_len);
-       }
-       hci_dev_unlock(hdev);
+       rcu_read_unlock();
 
        return 0;
 }
@@ -3101,15 +3099,11 @@ void hci_uuids_clear(struct hci_dev *hdev)
 
 void hci_link_keys_clear(struct hci_dev *hdev)
 {
-       struct list_head *p, *n;
-
-       list_for_each_safe(p, n, &hdev->link_keys) {
-               struct link_key *key;
-
-               key = list_entry(p, struct link_key, list);
+       struct link_key *key;
 
-               list_del(p);
-               kfree(key);
+       list_for_each_entry_rcu(key, &hdev->link_keys, list) {
+               list_del_rcu(&key->list);
+               kfree_rcu(key, rcu);
        }
 }
 
@@ -3137,9 +3131,14 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
 {
        struct link_key *k;
 
-       list_for_each_entry(k, &hdev->link_keys, list)
-               if (bacmp(bdaddr, &k->bdaddr) == 0)
+       rcu_read_lock();
+       list_for_each_entry_rcu(k, &hdev->link_keys, list) {
+               if (bacmp(bdaddr, &k->bdaddr) == 0) {
+                       rcu_read_unlock();
                        return k;
+               }
+       }
+       rcu_read_unlock();
 
        return NULL;
 }
@@ -3290,7 +3289,7 @@ struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn,
                key = kzalloc(sizeof(*key), GFP_KERNEL);
                if (!key)
                        return NULL;
-               list_add(&key->list, &hdev->link_keys);
+               list_add_rcu(&key->list, &hdev->link_keys);
        }
 
        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)
 
        BT_DBG("%s removing %pMR", hdev->name, bdaddr);
 
-       list_del(&key->list);
-       kfree(key);
+       list_del_rcu(&key->list);
+       kfree_rcu(key, rcu);
 
        return 0;
 }