summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
cb6f3f7)
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>
struct link_key {
struct list_head list;
struct link_key {
struct list_head list;
bdaddr_t bdaddr;
u8 type;
u8 val[HCI_LINK_KEY_SIZE];
bdaddr_t bdaddr;
u8 type;
u8 val[HCI_LINK_KEY_SIZE];
static int link_keys_show(struct seq_file *f, void *ptr)
{
struct hci_dev *hdev = f->private;
static int link_keys_show(struct seq_file *f, void *ptr)
{
struct hci_dev *hdev = f->private;
- struct list_head *p, *n;
- 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);
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);
void hci_link_keys_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);
- list_del(p);
- kfree(key);
+ list_for_each_entry_rcu(key, &hdev->link_keys, list) {
+ list_del_rcu(&key->list);
+ kfree_rcu(key, rcu);
- 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();
+ }
+ }
+ rcu_read_unlock();
key = kzalloc(sizeof(*key), GFP_KERNEL);
if (!key)
return NULL;
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);
}
BT_DBG("%s key for %pMR type %u", hdev->name, bdaddr, type);
BT_DBG("%s removing %pMR", hdev->name, bdaddr);
BT_DBG("%s removing %pMR", hdev->name, bdaddr);
- list_del(&key->list);
- kfree(key);
+ list_del_rcu(&key->list);
+ kfree_rcu(key, rcu);
*/
if (key->type == HCI_LK_DEBUG_COMBINATION &&
!test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags)) {
*/
if (key->type == HCI_LK_DEBUG_COMBINATION &&
!test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags)) {
- list_del(&key->list);
- kfree(key);
+ list_del_rcu(&key->list);
+ kfree_rcu(key, rcu);
} else if (conn) {
if (persistent)
clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
} else if (conn) {
if (persistent)
clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags);