mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Jan Kiszka <jan.kiszka@web.de>
To: David Miller <davem@davemloft.net>, Karsten Keil <isdn@linux-pingi.de>
Cc: linux-kernel@vger.kernel.org,
	i4ldeveloper@listserv.isdn4linux.de,
	isdn4linux@listserv.isdn4linux.de, netdev@vger.kernel.org,
	Alan Cox <alan@lxorguk.ukuu.org.uk>,
	Marcel Holtmann <marcel@holtmann.org>
Subject: [PATCH v2 11/41] CAPI: Rework application locking
Date: Mon,  8 Feb 2010 21:12:15 +0100	[thread overview]
Message-ID: <6910ecb2ed7918dcb79d22c7c1545d2fcdaa8473.1265659934.git.jan.kiszka@web.de> (raw)
In-Reply-To: <cover.1265659933.git.jan.kiszka@web.de>
In-Reply-To: <cover.1265659933.git.jan.kiszka@web.de>

Drop the application rw-lock in favour of RCU. This synchronizes
capi20_release against capi_ctr_handle_message which may dereference an
application from (soft-)IRQ context. Any other access to the application
list is now protected by the capi_controller_lock as well. This also
allows to safely inspect applications for /proc dumping by holding
capi_controller_lock.

At this chance, drop some useless release_in_progress checks where we
obtained the application pointer from the list (which becomes NULL on
release_in_progress).

Signed-off-by: Jan Kiszka <jan.kiszka@web.de>
---
 drivers/isdn/capi/kcapi.c      |   52 +++++++++++++++++-----------------------
 drivers/isdn/capi/kcapi_proc.c |   11 +++++---
 2 files changed, 29 insertions(+), 34 deletions(-)

diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
index a99f7e3..0b4c8a7 100644
--- a/drivers/isdn/capi/kcapi.c
+++ b/drivers/isdn/capi/kcapi.c
@@ -34,6 +34,7 @@
 #include <linux/b1lli.h>
 #endif
 #include <linux/mutex.h>
+#include <linux/rcupdate.h>
 
 static int showcapimsgs = 0;
 
@@ -64,8 +65,6 @@ DEFINE_MUTEX(capi_drivers_lock);
 struct capi_ctr *capi_controller[CAPI_MAXCONTR];
 DEFINE_MUTEX(capi_controller_lock);
 
-static DEFINE_RWLOCK(application_lock);
-
 struct capi20_appl *capi_applications[CAPI_MAXAPPL];
 
 static int ncontrollers;
@@ -103,7 +102,7 @@ static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid)
 	if (applid - 1 >= CAPI_MAXAPPL)
 		return NULL;
 
-	return capi_applications[applid - 1];
+	return rcu_dereference(capi_applications[applid - 1]);
 }
 
 /* -------- util functions ------------------------------------ */
@@ -186,7 +185,7 @@ static void notify_up(u32 contr)
 
 		for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
 			ap = get_capi_appl_by_nr(applid);
-			if (!ap || ap->release_in_progress)
+			if (!ap)
 				continue;
 			register_appl(ctr, applid, &ap->rparam);
 		}
@@ -216,7 +215,7 @@ static void ctr_down(struct capi_ctr *ctr, int new_state)
 
 	for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
 		ap = get_capi_appl_by_nr(applid);
-		if (ap && !ap->release_in_progress)
+		if (ap)
 			capi_ctr_put(ctr);
 	}
 
@@ -336,7 +335,6 @@ void capi_ctr_handle_message(struct capi_ctr *ctr, u16 appl,
 	struct capi20_appl *ap;
 	int showctl = 0;
 	u8 cmd, subcmd;
-	unsigned long flags;
 	_cdebbuf *cdb;
 
 	if (ctr->state != CAPI_CTR_RUNNING) {
@@ -384,10 +382,10 @@ void capi_ctr_handle_message(struct capi_ctr *ctr, u16 appl,
 
 	}
 
-	read_lock_irqsave(&application_lock, flags);
+	rcu_read_lock();
 	ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data));
-	if ((!ap) || (ap->release_in_progress)) {
-		read_unlock_irqrestore(&application_lock, flags);
+	if (!ap) {
+		rcu_read_unlock();
 		cdb = capi_message2str(skb->data);
 		if (cdb) {
 			printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n",
@@ -401,7 +399,7 @@ void capi_ctr_handle_message(struct capi_ctr *ctr, u16 appl,
 	}
 	skb_queue_tail(&ap->recv_queue, skb);
 	schedule_work(&ap->recv_work);
-	read_unlock_irqrestore(&application_lock, flags);
+	rcu_read_unlock();
 
 	return;
 
@@ -656,40 +654,35 @@ u16 capi20_register(struct capi20_appl *ap)
 {
 	int i;
 	u16 applid;
-	unsigned long flags;
 
 	DBG("");
 
 	if (ap->rparam.datablklen < 128)
 		return CAPI_LOGBLKSIZETOSMALL;
 
-	write_lock_irqsave(&application_lock, flags);
+	ap->nrecvctlpkt = 0;
+	ap->nrecvdatapkt = 0;
+	ap->nsentctlpkt = 0;
+	ap->nsentdatapkt = 0;
+	mutex_init(&ap->recv_mtx);
+	skb_queue_head_init(&ap->recv_queue);
+	INIT_WORK(&ap->recv_work, recv_handler);
+	ap->release_in_progress = 0;
+
+	mutex_lock(&capi_controller_lock);
 
 	for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
 		if (capi_applications[applid - 1] == NULL)
 			break;
 	}
 	if (applid > CAPI_MAXAPPL) {
-		write_unlock_irqrestore(&application_lock, flags);
+		mutex_unlock(&capi_controller_lock);
 		return CAPI_TOOMANYAPPLS;
 	}
 
 	ap->applid = applid;
 	capi_applications[applid - 1] = ap;
 
-	ap->nrecvctlpkt = 0;
-	ap->nrecvdatapkt = 0;
-	ap->nsentctlpkt = 0;
-	ap->nsentdatapkt = 0;
-	mutex_init(&ap->recv_mtx);
-	skb_queue_head_init(&ap->recv_queue);
-	INIT_WORK(&ap->recv_work, recv_handler);
-	ap->release_in_progress = 0;
-
-	write_unlock_irqrestore(&application_lock, flags);
-	
-	mutex_lock(&capi_controller_lock);
-
 	for (i = 0; i < CAPI_MAXCONTR; i++) {
 		if (!capi_controller[i] ||
 		    capi_controller[i]->state != CAPI_CTR_RUNNING)
@@ -721,16 +714,15 @@ EXPORT_SYMBOL(capi20_register);
 u16 capi20_release(struct capi20_appl *ap)
 {
 	int i;
-	unsigned long flags;
 
 	DBG("applid %#x", ap->applid);
 
-	write_lock_irqsave(&application_lock, flags);
+	mutex_lock(&capi_controller_lock);
+
 	ap->release_in_progress = 1;
 	capi_applications[ap->applid - 1] = NULL;
-	write_unlock_irqrestore(&application_lock, flags);
 
-	mutex_lock(&capi_controller_lock);
+	synchronize_rcu();
 
 	for (i = 0; i < CAPI_MAXCONTR; i++) {
 		if (!capi_controller[i] ||
diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c
index 3e6e17a..ea2dff6 100644
--- a/drivers/isdn/capi/kcapi_proc.c
+++ b/drivers/isdn/capi/kcapi_proc.c
@@ -139,9 +139,11 @@ static const struct file_operations proc_contrstats_ops = {
 //      applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt
 // ---------------------------------------------------------------------------
 
-static void *
-applications_start(struct seq_file *seq, loff_t *pos)
+static void *applications_start(struct seq_file *seq, loff_t *pos)
+	__acquires(capi_controller_lock)
 {
+	mutex_lock(&capi_controller_lock);
+
 	if (*pos < CAPI_MAXAPPL)
 		return &capi_applications[*pos];
 
@@ -158,9 +160,10 @@ applications_next(struct seq_file *seq, void *v, loff_t *pos)
 	return NULL;
 }
 
-static void
-applications_stop(struct seq_file *seq, void *v)
+static void applications_stop(struct seq_file *seq, void *v)
+	__releases(capi_controller_lock)
 {
+	mutex_unlock(&capi_controller_lock);
 }
 
 static int
-- 
1.6.0.2


  parent reply	other threads:[~2010-02-08 20:21 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-02-08 20:12 [PATCH v2 00/41] CAPI: Major rework, tons of bug fixes Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 01/41] CAPI: Fix leaks in capifs_new_ncci Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 02/41] CAPI: Sanitize capifs API Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 03/41] CAPI: Eliminate capifs_root variable Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 04/41] CAPI: Pin capifs instead of mounting it Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 05/41] CAPI: Reduce chattiness during module loading/removal Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 06/41] CAPI: Call a controller 'controller', not 'card' Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 07/41] CAPI: Convert capi drivers rwlock into mutex Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 08/41] CAPI: Rework capi_ctr_ready/down Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 09/41] CAPI: Rework controller state notifier Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 10/41] CAPI: Rework locking of controller data structures Jan Kiszka
2010-02-08 20:12 ` Jan Kiszka [this message]
2010-02-08 20:12 ` [PATCH v2 12/41] CAPI: Reduce #ifdef mess around CONFIG_ISDN_CAPI_MIDDLEWARE Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 13/41] CAPI: Convert capidev_list_lock into a mutex Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 14/41] CAPI: Clean up capi_open/release Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 15/41] CAPI: Rework locking of capidev members Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 16/41] CAPI: Use non-atomic allocation during NCCI setup Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 17/41] CAPI: Fix racy capi_read Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 18/41] CAPI: Switch NCCI list to standard doubly linked list Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 19/41] CAPI: Switch capiminor list to array Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 20/41] CAPI: Clean up capinc_tty_init/exit Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 21/41] CAPI: Dynamically register minor devices Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 22/41] CAPI: Use dynamic major for NCCI TTYs by default Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 23/41] CAPI: Use kref on capiminor Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 24/41] CAPI: Establish install/cleanup handlers for capiminor TTYs Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 25/41] CAPI: Use tty_port to keep track of capiminor's tty Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 26/41] CAPI: Drop remaining NULL checks on tty->driver_data Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 27/41] CAPI: Issue synchronous hangup on capincci_free_minor Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 28/41] CAPI: Drop obsolete nccip from capiminor struct Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 29/41] CAPI: Clean up capiminors_lock Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 30/41] CAPI: Drop atomic ttyopencount Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 31/41] CAPI: Drop handle_minor_recv from capinc_tty_write Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 32/41] CAPI: Rework capiminor RX handler Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 33/41] CAPI: Rename datahandle_queue -> ackqueue_entry Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 34/41] CAPI: Use atomics for capiminor's datahandle and msgid Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 35/41] CAPI: Drop capiminor's unused inbytes counter Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 36/41] CAPI: Fix locking around capiminor's output queue and drop workaround_lock Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 37/41] CAPI: Clean up capiminor_*_ack Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 38/41] CAPI: Drop return value of handle_minor_send Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 39/41] CAPI: Drop special controller lookup from capi20_put_message Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 40/41] CAPI: Schedule capifs for removal Jan Kiszka
2010-02-08 20:12 ` [PATCH v2 41/41] CAPI: Remove experimental tag from middleware feature Jan Kiszka
2010-02-08 21:38 ` [PATCH v2 00/41] CAPI: Major rework, tons of bug fixes Alan Cox
2010-02-09 12:54 ` Karsten Keil
2010-02-16  4:09   ` David Miller
2010-02-10 15:07 ` Tilman Schmidt
2010-02-17  0:02 ` David Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6910ecb2ed7918dcb79d22c7c1545d2fcdaa8473.1265659934.git.jan.kiszka@web.de \
    --to=jan.kiszka@web.de \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=davem@davemloft.net \
    --cc=i4ldeveloper@listserv.isdn4linux.de \
    --cc=isdn4linux@listserv.isdn4linux.de \
    --cc=isdn@linux-pingi.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=marcel@holtmann.org \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®