From: Dave Young Date: Fri, 11 Jan 2008 06:22:52 +0000 (-0800) Subject: [BLUETOOTH]: rfcomm tty BUG_ON() code fix X-Git-Tag: v2.6.24-rc8~7^2~8 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f951375d470c1a20d92c34377991197e6bf17990;p=linux-2.6 [BLUETOOTH]: rfcomm tty BUG_ON() code fix 1) In tty.c the BUG_ON at line 115 will never be called, because the the before list_del_init in this same function. 115 BUG_ON(!list_empty(&dev->list)); So move the list_del_init to rfcomm_dev_del 2) The rfcomm_dev_del could be called from diffrent path (rfcomm_tty_hangup/rfcomm_dev_state_change/rfcomm_release_dev), So add another BUG_ON when the rfcomm_dev_del is called more than one time. Signed-off-by: Dave Young Signed-off-by: David S. Miller --- diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index e447651a2d..a6a758dd1f 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -95,9 +95,10 @@ static void rfcomm_dev_destruct(struct rfcomm_dev *dev) BT_DBG("dev %p dlc %p", dev, dlc); - write_lock_bh(&rfcomm_dev_lock); - list_del_init(&dev->list); - write_unlock_bh(&rfcomm_dev_lock); + /* 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)); rfcomm_dlc_lock(dlc); /* Detach DLC if it's owned by this dev */ @@ -109,11 +110,6 @@ static void rfcomm_dev_destruct(struct rfcomm_dev *dev) tty_unregister_device(rfcomm_tty_driver, dev->id); - /* 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)); - kfree(dev); /* It's safe to call module_put() here because socket still @@ -313,7 +309,15 @@ static void rfcomm_dev_del(struct rfcomm_dev *dev) { BT_DBG("dev %p", dev); - set_bit(RFCOMM_TTY_RELEASED, &dev->flags); + if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) + BUG_ON(1); + else + set_bit(RFCOMM_TTY_RELEASED, &dev->flags); + + write_lock_bh(&rfcomm_dev_lock); + list_del_init(&dev->list); + write_unlock_bh(&rfcomm_dev_lock); + rfcomm_dev_put(dev); }