summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/direct-io.c38
1 files changed, 17 insertions, 21 deletions
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 25dd010a2d44..24d6cd388649 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -290,7 +290,7 @@ static void dio_aio_complete_work(struct work_struct *work)
dio_complete(dio, dio->iocb->ki_pos, 0, true, NULL);
}
-static int dio_bio_complete(struct dio *dio, struct bio *bio);
+static void dio_bio_complete(struct dio *dio, struct bio *bio);
/*
* Asynchronous IO callback.
@@ -302,6 +302,9 @@ static void dio_bio_end_aio(struct bio *bio, int error,
unsigned long remaining;
unsigned long flags;
+ if (error)
+ dio->io_error = error;
+
/* cleanup the bio */
dio_bio_complete(dio, bio);
@@ -334,6 +337,9 @@ static void dio_bio_end_io(struct bio *bio, int error)
struct dio *dio = bio->bi_private;
unsigned long flags;
+ if (error)
+ dio->io_error = error;
+
spin_lock_irqsave(&dio->bio_lock, flags);
bio->bi_private = dio->bio_list;
dio->bio_list = bio;
@@ -463,15 +469,11 @@ static struct bio *dio_await_one(struct dio *dio)
/*
* Process one completed BIO. No locks are held.
*/
-static int dio_bio_complete(struct dio *dio, struct bio *bio)
+static void dio_bio_complete(struct dio *dio, struct bio *bio)
{
- const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
struct bio_vec *bvec;
unsigned i;
- if (!uptodate)
- dio->io_error = -EIO;
-
if (dio->is_async && dio->rw == READ) {
bio_check_pages_dirty(bio); /* transfers ownership */
} else {
@@ -484,7 +486,6 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio)
}
bio_put(bio);
}
- return uptodate ? 0 : -EIO;
}
/*
@@ -511,27 +512,21 @@ static void dio_await_completion(struct dio *dio)
*
* This also helps to limit the peak amount of pinned userspace memory.
*/
-static inline int dio_bio_reap(struct dio *dio, struct dio_submit *sdio)
+static inline void dio_bio_reap(struct dio *dio, struct dio_submit *sdio)
{
- int ret = 0;
-
if (sdio->reap_counter++ >= 64) {
while (dio->bio_list) {
unsigned long flags;
struct bio *bio;
- int ret2;
spin_lock_irqsave(&dio->bio_lock, flags);
bio = dio->bio_list;
dio->bio_list = bio->bi_private;
spin_unlock_irqrestore(&dio->bio_lock, flags);
- ret2 = dio_bio_complete(dio, bio);
- if (ret == 0)
- ret = ret2;
+ dio_bio_complete(dio, bio);
}
sdio->reap_counter = 0;
}
- return ret;
}
/*
@@ -655,19 +650,20 @@ static inline int dio_new_bio(struct dio *dio, struct dio_submit *sdio,
sector_t start_sector, struct buffer_head *map_bh)
{
sector_t sector;
- int ret, nr_pages;
+ int nr_pages;
+
+ dio_bio_reap(dio, sdio);
+
+ if (dio->io_error)
+ return dio->io_error;
- ret = dio_bio_reap(dio, sdio);
- if (ret)
- goto out;
sector = start_sector << (sdio->blkbits - 9);
nr_pages = min(sdio->pages_in_io, bio_get_nr_vecs(map_bh->b_bdev));
nr_pages = min(nr_pages, BIO_MAX_PAGES);
BUG_ON(nr_pages <= 0);
dio_bio_alloc(dio, sdio, map_bh->b_bdev, sector, nr_pages);
sdio->boundary = 0;
-out:
- return ret;
+ return 0;
}
/*