[PATCH v2 23/41] CAPI: Use kref on capiminor

Jan Kiszka <[email protected]>
Newsgroups gmane.linux.network,gmane.linux.kernel,gmane.linux.isdn.i4l.devel,gmane.linux.isdn.i4l.user
Message-ID <dd97f250aec5139ce55bb88f41822f2fe76ee4e9.1265659935.git.jan.kiszka@web.de>
Install a reference counter for capiminor objects. Acquire it when
obtaining a capiminor from the array during capinc_tty_open, drop it
when closing the tty again. Another reference is held for the hook-up
with capincci.

Signed-off-by: Jan Kiszka <[email protected]>
---
 drivers/isdn/capi/capi.c |   37 ++++++++++++++++++++++++++++---------
 1 files changed, 28 insertions(+), 9 deletions(-)

diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index b1de0cb..732cdb5 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -83,6 +83,8 @@ struct datahandle_queue {
 };
 
 struct capiminor {
+	struct kref kref;
+
 	struct capincci  *nccip;
 	unsigned int      minor;
 	struct dentry *capifs_dentry;
@@ -223,6 +225,8 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
 		return NULL;
 	}
 
+	kref_init(&mp->kref);
+
 	mp->ap = ap;
 	mp->ncci = ncci;
 	mp->msgid = 0;
@@ -265,18 +269,11 @@ err_out1:
 	return NULL;
 }
 
-static void capiminor_free(struct capiminor *mp)
+static void capiminor_destroy(struct kref *kref)
 {
-	unsigned long flags;
-
-	tty_unregister_device(capinc_tty_driver, mp->minor);
-
-	write_lock_irqsave(&capiminors_lock, flags);
-	capiminors[mp->minor] = NULL;
-	write_unlock_irqrestore(&capiminors_lock, flags);
+	struct capiminor *mp = container_of(kref, struct capiminor, kref);
 
 	kfree_skb(mp->ttyskb);
-	mp->ttyskb = NULL;
 	skb_queue_purge(&mp->inqueue);
 	skb_queue_purge(&mp->outqueue);
 	capiminor_del_all_ack(mp);
@@ -289,11 +286,31 @@ static struct capiminor *capiminor_get(unsigned int minor)
 
 	read_lock(&capiminors_lock);
 	mp = capiminors[minor];
+	if (mp)
+		kref_get(&mp->kref);
 	read_unlock(&capiminors_lock);
 
 	return mp;
 }
 
+static inline void capiminor_put(struct capiminor *mp)
+{
+	kref_put(&mp->kref, capiminor_destroy);
+}
+
+static void capiminor_free(struct capiminor *mp)
+{
+	unsigned long flags;
+
+	tty_unregister_device(capinc_tty_driver, mp->minor);
+
+	write_lock_irqsave(&capiminors_lock, flags);
+	capiminors[mp->minor] = NULL;
+	write_unlock_irqrestore(&capiminors_lock, flags);
+
+	capiminor_put(mp);
+}
+
 /* -------- struct capincci ----------------------------------------- */
 
 static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np)
@@ -1029,6 +1046,8 @@ static void capinc_tty_close(struct tty_struct * tty, struct file * file)
 #endif
 		if (mp->nccip == NULL)
 			capiminor_free(mp);
+
+		capiminor_put(mp);
 	}
 
 #ifdef _DEBUG_REFCOUNT
-- 
1.6.0.2

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.