From: Corey Minyard <minyard@acm.org>
To: linux-kernel@vger.kernel.org
Cc: akpm@osdl.org, paulmck@us.ibm.com
Subject: [PATCH] ipmi: use rcu lock for using command receivers
Date: Fri, 28 Oct 2005 08:19:44 -0500 [thread overview]
Message-ID: <20051028131944.GA10285@i2.minyard.local> (raw)
I finally got some time to think this through and test it.
This patch is in addition to the ipmi-use-refcount-in-message-handler
patch.
Thanks again, Paul, for seeing this.
Use rcu_read_lock for the cmd_rcvrs list, since that was what
what intended, anyway. This means that all the users of the
cmd_rcvrs_lock are tasks, so the irq disables are no longer
required for that lock and it can become a semaphore.
Signed-off-by: Corey Minyard <minyard@acm.org>
Index: linux-2.6.14-rc4/drivers/char/ipmi/ipmi_msghandler.c
===================================================================
--- linux-2.6.14-rc4.orig/drivers/char/ipmi/ipmi_msghandler.c
+++ linux-2.6.14-rc4/drivers/char/ipmi/ipmi_msghandler.c
@@ -209,7 +209,7 @@ struct ipmi_smi
/* The list of command receivers that are registered for commands
on this interface. */
- spinlock_t cmd_rcvrs_lock;
+ struct semaphore cmd_rcvrs_lock;
struct list_head cmd_rcvrs;
/* Events that were queues because no one was there to receive
@@ -345,7 +345,6 @@ static void clean_up_interface_data(ipmi
{
int i;
struct cmd_rcvr *rcvr, *rcvr2;
- unsigned long flags;
struct list_head list;
free_recv_msg_list(&intf->waiting_msgs);
@@ -353,10 +352,10 @@ static void clean_up_interface_data(ipmi
/* Wholesale remove all the entries from the list in the
* interface and wait for RCU to know that none are in use. */
- spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags);
+ down(&intf->cmd_rcvrs_lock);
list_add_rcu(&list, &intf->cmd_rcvrs);
list_del_rcu(&intf->cmd_rcvrs);
- spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags);
+ up(&intf->cmd_rcvrs_lock);
synchronize_rcu();
list_for_each_entry_safe(rcvr, rcvr2, &list, link)
@@ -812,7 +811,7 @@ int ipmi_destroy_user(ipmi_user_t user)
* since other things may be using it till we do
* synchronize_rcu()) then free everything in that list.
*/
- spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags);
+ down(&intf->cmd_rcvrs_lock);
list_for_each_safe_rcu(entry1, entry2, &intf->cmd_rcvrs) {
rcvr = list_entry(entry1, struct cmd_rcvr, link);
if (rcvr->user == user) {
@@ -821,7 +820,7 @@ int ipmi_destroy_user(ipmi_user_t user)
rcvrs = rcvr;
}
}
- spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags);
+ up(&intf->cmd_rcvrs_lock);
synchronize_rcu();
while (rcvrs) {
rcvr = rcvrs;
@@ -950,7 +949,7 @@ int ipmi_register_for_cmd(ipmi_user_t
rcvr->netfn = netfn;
rcvr->user = user;
- spin_lock_irq(&intf->cmd_rcvrs_lock);
+ down(&intf->cmd_rcvrs_lock);
/* Make sure the command/netfn is not already registered. */
entry = find_cmd_rcvr(intf, netfn, cmd);
if (entry) {
@@ -961,7 +960,7 @@ int ipmi_register_for_cmd(ipmi_user_t
list_add_rcu(&rcvr->link, &intf->cmd_rcvrs);
out_unlock:
- spin_unlock_irq(&intf->cmd_rcvrs_lock);
+ up(&intf->cmd_rcvrs_lock);
if (rv)
kfree(rcvr);
@@ -975,17 +974,17 @@ int ipmi_unregister_for_cmd(ipmi_user_t
ipmi_smi_t intf = user->intf;
struct cmd_rcvr *rcvr;
- spin_lock_irq(&intf->cmd_rcvrs_lock);
+ down(&intf->cmd_rcvrs_lock);
/* Make sure the command/netfn is not already registered. */
rcvr = find_cmd_rcvr(intf, netfn, cmd);
if ((rcvr) && (rcvr->user == user)) {
list_del_rcu(&rcvr->link);
- spin_unlock_irq(&intf->cmd_rcvrs_lock);
+ up(&intf->cmd_rcvrs_lock);
synchronize_rcu();
kfree(rcvr);
return 0;
} else {
- spin_unlock_irq(&intf->cmd_rcvrs_lock);
+ up(&intf->cmd_rcvrs_lock);
return -ENOENT;
}
}
@@ -1858,7 +1857,7 @@ int ipmi_register_smi(struct ipmi_smi_ha
spin_lock_init(&intf->events_lock);
INIT_LIST_HEAD(&intf->waiting_events);
intf->waiting_events_count = 0;
- spin_lock_init(&intf->cmd_rcvrs_lock);
+ init_MUTEX(&intf->cmd_rcvrs_lock);
INIT_LIST_HEAD(&intf->cmd_rcvrs);
init_waitqueue_head(&intf->waitq);
@@ -2058,14 +2057,14 @@ static int handle_ipmb_get_msg_cmd(ipmi_
netfn = msg->rsp[4] >> 2;
cmd = msg->rsp[8];
- spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags);
+ rcu_read_lock();
rcvr = find_cmd_rcvr(intf, netfn, cmd);
if (rcvr) {
user = rcvr->user;
kref_get(&user->refcount);
} else
user = NULL;
- spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags);
+ rcu_read_unlock();
if (user == NULL) {
/* We didn't find a user, deliver an error response. */
@@ -2238,14 +2237,14 @@ static int handle_lan_get_msg_cmd(ipmi_s
netfn = msg->rsp[6] >> 2;
cmd = msg->rsp[10];
- spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags);
+ rcu_read_lock();
rcvr = find_cmd_rcvr(intf, netfn, cmd);
if (rcvr) {
user = rcvr->user;
kref_get(&user->refcount);
} else
user = NULL;
- spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags);
+ rcu_read_unlock();
if (user == NULL) {
/* We didn't find a user, just give up. */
next reply other threads:[~2005-10-28 13:19 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-10-28 13:19 Corey Minyard [this message]
2005-10-28 17:37 ` [PATCH] ipmi: use rcu lock for using command receivers Paul E. McKenney
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=20051028131944.GA10285@i2.minyard.local \
--to=minyard@acm.org \
--cc=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
--cc=paulmck@us.ibm.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.