If at the end of direct_io_worker, dio->result is non-zero then we unconditionally copy that into the return value, potentially ignoring any I/O errors which were accumulated into local variable `ret'. Only do the assignment if `ret' is zero. direct-io.c | 23 ++++++++++------------- 1 files changed, 10 insertions(+), 13 deletions(-) diff -puN fs/direct-io.c~direct-io-retval-fix fs/direct-io.c --- 25/fs/direct-io.c~direct-io-retval-fix 2003-02-14 18:24:07.000000000 -0800 +++ 25-akpm/fs/direct-io.c 2003-02-14 18:24:07.000000000 -0800 @@ -927,20 +927,17 @@ direct_io_worker(int rw, struct kiocb *i ret = dio->result; /* Bytes written */ finished_one_bio(dio); /* This can free the dio */ blk_run_queues(); - goto out; + } else { + finished_one_bio(dio); + ret2 = dio_await_completion(dio); + if (ret == 0) + ret = ret2; + if (ret == 0) + ret = dio->page_errors; + if (ret == 0 && dio->result) + ret = dio->result; + kfree(dio); } - - finished_one_bio(dio); - ret2 = dio_await_completion(dio); - if (ret == 0) - ret = ret2; - if (ret == 0) - ret = dio->page_errors; - - if (dio->result) - ret = dio->result; - kfree(dio); -out: return ret; } _