Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=8de0a15483b357d0f0b821330ec84d1660cadc4e
Commit:     8de0a15483b357d0f0b821330ec84d1660cadc4e
Parent:     84950cf0ba02fd6a5defe2511bc41f9aa2237632
Author:     Ville Tervo <[EMAIL PROTECTED]>
AuthorDate: Wed Jul 11 09:23:41 2007 +0200
Committer:  Marcel Holtmann <[EMAIL PROTECTED]>
CommitDate: Wed Jul 11 07:06:51 2007 +0200

    [Bluetooth] Keep rfcomm_dev on the list until it is freed
    
    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 <[EMAIL PROTECTED]>
    Signed-off-by: Marcel Holtmann <[EMAIL PROTECTED]>
---
 include/net/bluetooth/rfcomm.h |    1 +
 net/bluetooth/rfcomm/tty.c     |   30 ++++++++++++++++++++++--------
 2 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 3c563f0..25aa575 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -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;
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index ba469b0..23ba61a 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -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)
@@ -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);
 
@@ -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_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);
 }
 
@@ -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;
@@ -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;
@@ -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;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to