same bugs in the two
files (uml-linux-2.4.26-3):
arch/um/drivers/line.c
int
line_write(struct line *lines, struct tty_struct *tty, int
from_user,
const char *buf, int len)
{
struct line *line;
char *new;
unsigned long flags;
int n, err, i, ret = 0;
const char *buf, int len)
{
struct line *line;
char *new;
unsigned long flags;
int n, err, i, ret = 0;
if(tty->stopped) return 0;
if(from_user){
new = kmalloc(len, GFP_KERNEL);
if(new == NULL)
return(0);
n = copy_from_user(new, buf, len);
buf = new;
if(n == len){
len = -EFAULT;
goto out_free;
}
new = kmalloc(len, GFP_KERNEL);
if(new == NULL)
return(0);
n = copy_from_user(new, buf, len);
buf = new;
if(n == len){
len = -EFAULT;
goto out_free;
}
len -=
n;
}
}
i =
minor(tty->device) - tty->driver.minor_start;
line = &lines[i];
line = &lines[i];
down(&line->sem);
========================> may cause shedule in
interrrupt
if(line->head != line->tail){
local_irq_save(flags);
ret += buffer_data(line, buf, len);
err = flush_buffer(line);
local_irq_restore(flags);
if(err <= 0)
goto out_up;
}
if(line->head != line->tail){
local_irq_save(flags);
ret += buffer_data(line, buf, len);
err = flush_buffer(line);
local_irq_restore(flags);
if(err <= 0)
goto out_up;
}
in arch/um/drivers/stdio_console.c
static void
console_write(struct console *console, const char *string,
unsigned len)
{
struct line *line = &vts[console->index];
unsigned len)
{
struct line *line = &vts[console->index];
if(con_init_done)
down(&line->sem); ========================> may cause shedule in interrrupt
console_write_chan(&line->chan_list, string, len);
if(con_init_done)
up(&line->sem);
}
down(&line->sem); ========================> may cause shedule in interrrupt
console_write_chan(&line->chan_list, string, len);
if(con_init_done)
up(&line->sem);
}
my fix is
change
[EMAIL PROTECTED]
drivers]$ diff -Nru line.c line.c.old
--- line.c 2005-04-28 09:22:29.000000000 +0800
+++ line.c.old 2005-04-26 09:38:18.000000000 +0800
@@ -134,9 +134,7 @@
i = minor(tty->device) - tty->driver.minor_start;
line = &lines[i];
--- line.c 2005-04-28 09:22:29.000000000 +0800
+++ line.c.old 2005-04-26 09:38:18.000000000 +0800
@@ -134,9 +134,7 @@
i = minor(tty->device) - tty->driver.minor_start;
line = &lines[i];
-
if(!in_interrupt())
- down(&line->sem);
-
+ down(&line->sem);
if(line->head != line->tail){
local_irq_save(flags);
ret += buffer_data(line, buf, len);
@@ -159,8 +157,7 @@
ret += buffer_data(line, buf + n, len);
}
out_up:
- if(!in_interrupt())
- up(&line->sem);
+ up(&line->sem);
- down(&line->sem);
-
+ down(&line->sem);
if(line->head != line->tail){
local_irq_save(flags);
ret += buffer_data(line, buf, len);
@@ -159,8 +157,7 @@
ret += buffer_data(line, buf + n, len);
}
out_up:
- if(!in_interrupt())
- up(&line->sem);
+ up(&line->sem);
out_free:
if(from_user)
if(from_user)
---
stdio_console.c 2005-04-26 14:41:05.000000000
+0800
+++ stdio_console.c.bak 2005-04-26 14:33:30.000000000 +0800
@@ -188,10 +188,10 @@
{
struct line *line = &vts[console->index];
+++ stdio_console.c.bak 2005-04-26 14:33:30.000000000 +0800
@@ -188,10 +188,10 @@
{
struct line *line = &vts[console->index];
- if(con_init_done
&& !in_interrupt())
+ if(con_init_done)
down(&line->sem);
console_write_chan(&line->chan_list, string, len);
- if(con_init_done && !in_interrupt())
+ if(con_init_done)
up(&line->sem);
}
+ if(con_init_done)
down(&line->sem);
console_write_chan(&line->chan_list, string, len);
- if(con_init_done && !in_interrupt())
+ if(con_init_done)
up(&line->sem);
}
please help to
confirm if it's correct?
best regards
Yu Dong
Tel: 010-65642141
Email: w4760c@motorola.com
Email: w4760c@motorola.com
PCS Beijing Design Center
Motorola(China) Electronics Ltd.
Motorola(China) Electronics Ltd.