Commit 3c3bea26 authored by Ian Abbott's avatar Ian Abbott Committed by Greg Kroah-Hartman

staging: comedi: check for more errors for zero-length read

If the "read" file operation handler, `comedi_read()` is passed 0 for
the amount to read, some error conditions are currently skipped and the
function just returns 0.  Change it to check those error conditions and
return an error value if appropriate.  The trickiest case is the check
for when the previously set up asynchronous command has terminated with
an error.  In that case, `-EPIPE` is returned (as it is for a read of
non-zero length) and the subdevice gets marked as non-busy.

A zero-length read that returns 0 has no other effects, in particular,
it does not cause the subdevice to be marked as non-busy, and the return
value does not indicate an "end-of-file" condition.
Signed-off-by: default avatarIan Abbott <abbotti@mev.co.uk>
Reviewed-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 39582847
...@@ -2478,15 +2478,13 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, ...@@ -2478,15 +2478,13 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
} }
async = s->async; async = s->async;
if (!nbytes)
goto out;
if (s->busy != file || (async->cmd.flags & CMDF_WRITE)) { if (s->busy != file || (async->cmd.flags & CMDF_WRITE)) {
retval = -EINVAL; retval = -EINVAL;
goto out; goto out;
} }
add_wait_queue(&async->wait_head, &wait); add_wait_queue(&async->wait_head, &wait);
while (nbytes > 0 && !retval) { while (count == 0 && !retval) {
unsigned int rp, n1, n2; unsigned int rp, n1, n2;
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
...@@ -2500,9 +2498,12 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, ...@@ -2500,9 +2498,12 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
if (!comedi_is_runflags_running(runflags)) { if (!comedi_is_runflags_running(runflags)) {
if (comedi_is_runflags_in_error(runflags)) if (comedi_is_runflags_in_error(runflags))
retval = -EPIPE; retval = -EPIPE;
if (retval || nbytes)
become_nonbusy = true; become_nonbusy = true;
break; break;
} }
if (nbytes == 0)
break;
if (file->f_flags & O_NONBLOCK) { if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN; retval = -EAGAIN;
break; break;
...@@ -2539,7 +2540,6 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, ...@@ -2539,7 +2540,6 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
nbytes -= n; nbytes -= n;
buf += n; buf += n;
break; /* makes device work like a pipe */
} }
remove_wait_queue(&async->wait_head, &wait); remove_wait_queue(&async->wait_head, &wait);
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment