Skip to content

Commit

Permalink
[Bluetooth] Keep rfcomm_dev on the list until it is freed
Browse files Browse the repository at this point in the history
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@nokia.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
  • Loading branch information
Ville Tervo authored and Marcel Holtmann committed Jul 11, 2007
1 parent 84950cf commit 8de0a15
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 8 deletions.
1 change: 1 addition & 0 deletions include/net/bluetooth/rfcomm.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc
#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;
Expand Down
30 changes: 22 additions & 8 deletions net/bluetooth/rfcomm/tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +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);

rfcomm_dlc_lock(dlc);
/* Detach DLC if it's owned by this dev */
if (dlc->owner == dev)
Expand Down Expand Up @@ -156,8 +160,13 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id)
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);

Expand Down Expand Up @@ -265,17 +274,20 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)

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;
}

static void rfcomm_dev_del(struct rfcomm_dev *dev)
{
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);
}

Expand Down Expand Up @@ -329,7 +341,7 @@ static int rfcomm_create_dev(struct sock *sk, void __user *arg)
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;
Expand Down Expand Up @@ -370,7 +382,7 @@ static int rfcomm_release_dev(void __user *arg)
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;
Expand Down Expand Up @@ -419,6 +431,8 @@ static int rfcomm_get_dev_list(void __user *arg)

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;
Expand Down

0 comments on commit 8de0a15

Please sign in to comment.