[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <27240C0AC20F114CBF8149A2696CBE4A109B17@SHSMSX101.ccr.corp.intel.com>
Date: Mon, 2 Jul 2012 10:36:45 +0000
From: "Liu, Chuansheng" <chuansheng.liu@...el.com>
To: "'linux-kernel@...r.kernel.org' (linux-kernel@...r.kernel.org)"
<linux-kernel@...r.kernel.org>
CC: "a.p.zijlstra@...llo.nl" <a.p.zijlstra@...llo.nl>,
"kay@...y.org" <kay@...y.org>,
"gregkh@...uxfoundation.org" <gregkh@...uxfoundation.org>,
"mingo@...e.hu" <mingo@...e.hu>
Subject: [PATCH] printk: replacing the raw_spin_lock/unlock with
raw_spin_lock_irqsave/irqrestore
From: liu chuansheng <chuansheng.liu@...el.com>
Subject: [PATCH] printk: replacing the raw_spin_lock/unlock with raw_spin_lock_irqsave/irqrestore
In function devkmsg_read/writev/llseek/poll/open()..., the function
raw_spin_lock/unlock is used, there is potential deadlock case happening.
CPU1: thread1 doing the cat /dev/kmsg:
raw_spin_lock(&logbuf_lock);
while (user->seq == log_next_seq) {
when thread1 run here, at this time one interrupt is coming on CPU1 and running
based on this thread,if the interrupt handle called the printk which need the
logbuf_lock spin also, it will cause deadlock.
So we should use raw_spin_lock_irq_save/irqrestore here.
Signed-off-by: liu chuansheng <chuansheng.liu@...el.com>
---
kernel/printk.c | 28 ++++++++++++++++------------
1 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/kernel/printk.c b/kernel/printk.c
index dba1821..f57dc7b 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -423,6 +423,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
size_t i;
size_t len;
ssize_t ret;
+ unsigned long flags;
if (!user)
return -EBADF;
@@ -430,20 +431,20 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
ret = mutex_lock_interruptible(&user->lock);
if (ret)
return ret;
- raw_spin_lock(&logbuf_lock);
+ raw_spin_lock_irqsave(&logbuf_lock, flags);
while (user->seq == log_next_seq) {
if (file->f_flags & O_NONBLOCK) {
ret = -EAGAIN;
- raw_spin_unlock(&logbuf_lock);
+ raw_spin_unlock_irqrestore(&logbuf_lock, flags);
goto out;
}
- raw_spin_unlock(&logbuf_lock);
+ raw_spin_unlock_irqrestore(&logbuf_lock, flags);
ret = wait_event_interruptible(log_wait,
user->seq != log_next_seq);
if (ret)
goto out;
- raw_spin_lock(&logbuf_lock);
+ raw_spin_lock_irqsave(&logbuf_lock, flags);
}
if (user->seq < log_first_seq) {
@@ -451,7 +452,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
user->idx = log_first_idx;
user->seq = log_first_seq;
ret = -EPIPE;
- raw_spin_unlock(&logbuf_lock);
+ raw_spin_unlock_irqrestore(&logbuf_lock, flags);
goto out;
}
@@ -501,7 +502,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
user->idx = log_next(user->idx);
user->seq++;
- raw_spin_unlock(&logbuf_lock);
+ raw_spin_unlock_irqrestore(&logbuf_lock, flags);
if (len > count) {
ret = -EINVAL;
@@ -522,13 +523,14 @@ static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence)
{
struct devkmsg_user *user = file->private_data;
loff_t ret = 0;
+ unsigned long flags;
if (!user)
return -EBADF;
if (offset)
return -ESPIPE;
- raw_spin_lock(&logbuf_lock);
+ raw_spin_lock_irqsave(&logbuf_lock, flags);
switch (whence) {
case SEEK_SET:
/* the first record */
@@ -552,7 +554,7 @@ static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence)
default:
ret = -EINVAL;
}
- raw_spin_unlock(&logbuf_lock);
+ raw_spin_unlock_irqrestore(&logbuf_lock, flags);
return ret;
}
@@ -560,20 +562,21 @@ static unsigned int devkmsg_poll(struct file *file, poll_table *wait)
{
struct devkmsg_user *user = file->private_data;
int ret = 0;
+ unsigned long flags;
if (!user)
return POLLERR|POLLNVAL;
poll_wait(file, &log_wait, wait);
- raw_spin_lock(&logbuf_lock);
+ raw_spin_lock_irqsave(&logbuf_lock, flags);
if (user->seq < log_next_seq) {
/* return error when data has vanished underneath us */
if (user->seq < log_first_seq)
ret = POLLIN|POLLRDNORM|POLLERR|POLLPRI;
ret = POLLIN|POLLRDNORM;
}
- raw_spin_unlock(&logbuf_lock);
+ raw_spin_unlock_irqrestore(&logbuf_lock, flags);
return ret;
}
@@ -582,6 +585,7 @@ static int devkmsg_open(struct inode *inode, struct file *file)
{
struct devkmsg_user *user;
int err;
+ unsigned long flags;
/* write-only does not need any file context */
if ((file->f_flags & O_ACCMODE) == O_WRONLY)
@@ -597,10 +601,10 @@ static int devkmsg_open(struct inode *inode, struct file *file)
mutex_init(&user->lock);
- raw_spin_lock(&logbuf_lock);
+ raw_spin_lock_irqsave(&logbuf_lock, flags);
user->idx = log_first_idx;
user->seq = log_first_seq;
- raw_spin_unlock(&logbuf_lock);
+ raw_spin_unlock_irqrestore(&logbuf_lock, flags);
file->private_data = user;
return 0;
--
1.7.0.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists