Reviewed-by: Che-Liang Chiou <clchiou@xxxxxxxxxxxx> On Tue, Apr 17, 2012 at 4:56 PM, Che-liang Chiou <clchiou@xxxxxxxxxxxx> wrote: > I didn't test the patch, but the logic looks fine to me. > > On Wed, Apr 4, 2012 at 4:24 AM, Dmitry Torokhov > <dmitry.torokhov@xxxxxxxxx> wrote: >> Avoid calling wait_event_interruptible() if client requested non-blocking >> read, since it is not guaranteed that another thread will not consume >> event after we checked if serio_raw->head != serio_raw->tail. >> >> Also ensure we do not return 0 but keep waiting instead in blocking case, >> when another thread steals "our" byte. >> >> Signed-off-by: Dmitry Torokhov <dtor@xxxxxxx> >> --- >> drivers/input/serio/serio_raw.c | 43 ++++++++++++++++++++++---------------- >> 1 files changed, 25 insertions(+), 18 deletions(-) >> >> diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c >> index 4494233..094d6fb 100644 >> --- a/drivers/input/serio/serio_raw.c >> +++ b/drivers/input/serio/serio_raw.c >> @@ -165,31 +165,38 @@ static ssize_t serio_raw_read(struct file *file, char __user *buffer, >> struct serio_raw *serio_raw = client->serio_raw; >> char uninitialized_var(c); >> ssize_t read = 0; >> - int retval; >> + int error = 0; >> >> - if (serio_raw->dead) >> - return -ENODEV; >> + do { >> + if (serio_raw->dead) >> + return -ENODEV; >> >> - if (serio_raw->head == serio_raw->tail && (file->f_flags & O_NONBLOCK)) >> - return -EAGAIN; >> + if (serio_raw->head == serio_raw->tail && >> + (file->f_flags & O_NONBLOCK)) >> + return -EAGAIN; >> >> - retval = wait_event_interruptible(serio_raw->wait, >> - serio_raw->head != serio_raw->tail || serio_raw->dead); >> - if (retval) >> - return retval; >> + if (count == 0) >> + break; >> >> - if (serio_raw->dead) >> - return -ENODEV; >> + while (read < count && serio_raw_fetch_byte(serio_raw, &c)) { >> + if (put_user(c, buffer++)) { >> + error = -EFAULT; >> + goto out; >> + } >> + read++; >> + } >> >> - while (read < count && serio_raw_fetch_byte(serio_raw, &c)) { >> - if (put_user(c, buffer++)) { >> - retval = -EFAULT; >> + if (read) >> break; >> - } >> - read++; >> - } >> >> - return read ?: retval; >> + if (!(file->f_flags & O_NONBLOCK)) >> + error = wait_event_interruptible(serio_raw->wait, >> + serio_raw->head != serio_raw->tail || >> + serio_raw->dead); >> + } while (!error); >> + >> +out: >> + return read ?: error; >> } >> >> static ssize_t serio_raw_write(struct file *file, const char __user *buffer, >> -- >> 1.7.7.6 >> >> >> -- >> Dmitry ��.n��������+%������w��{.n�����{��)��^n�r������&��z�ޗ�zf���h���~����������_��+v���)ߣ�