For output buffers, there's no guarantee that the buffer won't be full in the first iteration of the loop in which case we would block independently of userspace passing O_NONBLOCK or not. Fix it by always checking the flag before going to sleep. While at it (and as it's a bit related), refactored the loop so that the stop condition is 'written != n', i.e, run the loop until all data has been copied into the IIO buffers. This makes the code a bit simpler. Fixes: 9eeee3b0bf190 ("iio: Add output buffer support") Signed-off-by: Nuno Sá <nuno.sa@xxxxxxxxxx> --- drivers/iio/industrialio-buffer.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index c56cf748fde1..7e7ee307a3f7 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -203,21 +203,24 @@ static ssize_t iio_buffer_write(struct file *filp, const char __user *buf, break; } + if (filp->f_flags & O_NONBLOCK) { + if (!written) + ret = -EAGAIN; + break; + } + wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); continue; } ret = rb->access->write(rb, n - written, buf + written); - if (ret == 0 && (filp->f_flags & O_NONBLOCK)) - ret = -EAGAIN; + if (ret < 0) + break; - if (ret > 0) { - written += ret; - if (written != n && !(filp->f_flags & O_NONBLOCK)) - continue; - } - } while (ret == 0); + written += ret; + + } while (written != n); remove_wait_queue(&rb->pollq, &wait); return ret < 0 ? ret : written; -- 2.39.2