[2.6.22.2 review 77/84] Keep rfcomm_dev on the list until it isfreed

From: Greg KH
Date: Tue Aug 07 2007 - 17:28:23 EST


From: Ville Tervo <ville.tervo@xxxxxxxxx>

This patch changes the RFCOMM TTY release process so that the TTY is kept
on the list until it is really freed. A new device flag is used to keep
track of released TTYs.

Signed-off-by: Ville Tervo <ville.tervo@xxxxxxxxx>
Signed-off-by: Marcel Holtmann <marcel@xxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>

---
include/net/bluetooth/rfcomm.h | 1 +
net/bluetooth/rfcomm/tty.c | 30 ++++++++++++++++++++++--------
2 files changed, 23 insertions(+), 8 deletions(-)

--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -323,6 +323,7 @@ int rfcomm_connect_ind(struct rfcomm_se
#define RFCOMM_RELEASE_ONHUP 1
#define RFCOMM_HANGUP_NOW 2
#define RFCOMM_TTY_ATTACHED 3
+#define RFCOMM_TTY_RELEASED 4

struct rfcomm_dev_req {
s16 dev_id;
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -95,6 +95,10 @@ static void rfcomm_dev_destruct(struct r

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);
+
rfcomm_dlc_lock(dlc);
/* Detach DLC if it's owned by this dev */
if (dlc->owner == dev)
@@ -156,8 +160,13 @@ static inline struct rfcomm_dev *rfcomm_
read_lock(&rfcomm_dev_lock);

dev = __rfcomm_dev_get(id);
- if (dev)
- rfcomm_dev_hold(dev);
+
+ if (dev) {
+ if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
+ dev = NULL;
+ else
+ rfcomm_dev_hold(dev);
+ }

read_unlock(&rfcomm_dev_lock);

@@ -265,6 +274,12 @@ out:

dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL);

+ if (IS_ERR(dev->tty_dev)) {
+ list_del(&dev->list);
+ kfree(dev);
+ return PTR_ERR(dev->tty_dev);
+ }
+
return dev->id;
}

@@ -272,10 +287,7 @@ static void rfcomm_dev_del(struct rfcomm
{
BT_DBG("dev %p", dev);

- write_lock_bh(&rfcomm_dev_lock);
- list_del_init(&dev->list);
- write_unlock_bh(&rfcomm_dev_lock);
-
+ set_bit(RFCOMM_TTY_RELEASED, &dev->flags);
rfcomm_dev_put(dev);
}

@@ -329,7 +341,7 @@ static int rfcomm_create_dev(struct sock
if (copy_from_user(&req, arg, sizeof(req)))
return -EFAULT;

- BT_DBG("sk %p dev_id %id flags 0x%x", sk, req.dev_id, req.flags);
+ BT_DBG("sk %p dev_id %d flags 0x%x", sk, req.dev_id, req.flags);

if (req.flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN))
return -EPERM;
@@ -370,7 +382,7 @@ static int rfcomm_release_dev(void __use
if (copy_from_user(&req, arg, sizeof(req)))
return -EFAULT;

- BT_DBG("dev_id %id flags 0x%x", req.dev_id, req.flags);
+ BT_DBG("dev_id %d flags 0x%x", req.dev_id, req.flags);

if (!(dev = rfcomm_dev_get(req.dev_id)))
return -ENODEV;
@@ -419,6 +431,8 @@ static int rfcomm_get_dev_list(void __us

list_for_each(p, &rfcomm_dev_list) {
struct rfcomm_dev *dev = list_entry(p, struct rfcomm_dev, list);
+ if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
+ continue;
(di + n)->id = dev->id;
(di + n)->flags = dev->flags;
(di + n)->state = dev->dlc->state;

--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/