diff options
author | Gianluca Anzolin <gianluca@sottospazio.it> | 2013-07-29 15:08:09 (GMT) |
---|---|---|
committer | Gustavo Padovan <gustavo.padovan@collabora.co.uk> | 2013-08-21 14:47:06 (GMT) |
commit | ebe937f74b8a72cf3ceeae5c2194a160bb092901 (patch) | |
tree | a5da8a08933923db90297ca5a02ed6d02606f593 /net/bluetooth | |
parent | 396dc223dd36edd218650d042a07c5e61f022c5b (diff) | |
download | linux-ebe937f74b8a72cf3ceeae5c2194a160bb092901.tar.xz |
Bluetooth: Remove the device from the list in the destructor
The current code removes the device from the device list in several
places. Do it only in the destructor instead and in the error path of
rfcomm_add_dev() if the device couldn't be initialized.
Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it>
Reviewed-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/rfcomm/tty.c | 27 |
1 files changed, 6 insertions, 21 deletions
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index cd7ff37..9c0e142 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -76,13 +76,6 @@ static void rfcomm_dev_modem_status(struct rfcomm_dlc *dlc, u8 v24_sig); /* ---- Device functions ---- */ -/* - * The reason this isn't actually a race, as you no doubt have a little voice - * screaming at you in your head, is that the refcount should never actually - * reach zero unless the device has already been taken off the list, in - * rfcomm_dev_del(). And if that's not true, we'll hit the BUG() in - * rfcomm_dev_destruct() anyway. - */ static void rfcomm_dev_destruct(struct tty_port *port) { struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port); @@ -90,10 +83,9 @@ static void rfcomm_dev_destruct(struct tty_port *port) BT_DBG("dev %p dlc %p", dev, dlc); - /* Refcount should only hit zero when called from rfcomm_dev_del() - which will have taken us off the list. Everything else are - refcounting bugs. */ - BUG_ON(!list_empty(&dev->list)); + spin_lock(&rfcomm_dev_lock); + list_del(&dev->list); + spin_unlock(&rfcomm_dev_lock); rfcomm_dlc_lock(dlc); /* Detach DLC if it's owned by this dev */ @@ -282,7 +274,9 @@ out: dev->id, NULL); if (IS_ERR(dev->tty_dev)) { err = PTR_ERR(dev->tty_dev); + spin_lock(&rfcomm_dev_lock); list_del(&dev->list); + spin_unlock(&rfcomm_dev_lock); goto free; } @@ -315,10 +309,6 @@ static void rfcomm_dev_del(struct rfcomm_dev *dev) } spin_unlock_irqrestore(&dev->port.lock, flags); - spin_lock(&rfcomm_dev_lock); - list_del_init(&dev->list); - spin_unlock(&rfcomm_dev_lock); - tty_port_put(&dev->port); } @@ -750,13 +740,8 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp) dev->port.tty = NULL; rfcomm_dlc_unlock(dev->dlc); - if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) { - spin_lock(&rfcomm_dev_lock); - list_del_init(&dev->list); - spin_unlock(&rfcomm_dev_lock); - + if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) tty_port_put(&dev->port); - } } else spin_unlock_irqrestore(&dev->port.lock, flags); |