|
@@ -129,6 +129,7 @@ struct dio {
|
|
|
/* AIO related stuff */
|
|
|
struct kiocb *iocb; /* kiocb */
|
|
|
int is_async; /* is IO async ? */
|
|
|
+ int io_error; /* IO error in completion path */
|
|
|
ssize_t result; /* IO result */
|
|
|
};
|
|
|
|
|
@@ -250,6 +251,10 @@ static void finished_one_bio(struct dio *dio)
|
|
|
((offset + transferred) > dio->i_size))
|
|
|
transferred = dio->i_size - offset;
|
|
|
|
|
|
+ /* check for error in completion path */
|
|
|
+ if (dio->io_error)
|
|
|
+ transferred = dio->io_error;
|
|
|
+
|
|
|
dio_complete(dio, offset, transferred);
|
|
|
|
|
|
/* Complete AIO later if falling back to buffered i/o */
|
|
@@ -406,7 +411,7 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio)
|
|
|
int page_no;
|
|
|
|
|
|
if (!uptodate)
|
|
|
- dio->result = -EIO;
|
|
|
+ dio->io_error = -EIO;
|
|
|
|
|
|
if (dio->is_async && dio->rw == READ) {
|
|
|
bio_check_pages_dirty(bio); /* transfers ownership */
|
|
@@ -971,6 +976,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
|
|
|
dio->next_block_for_io = -1;
|
|
|
|
|
|
dio->page_errors = 0;
|
|
|
+ dio->io_error = 0;
|
|
|
dio->result = 0;
|
|
|
dio->iocb = iocb;
|
|
|
dio->i_size = i_size_read(inode);
|