diff options
Diffstat (limited to 'fs/block_dev.c')
| -rw-r--r-- | fs/block_dev.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 8b18e43b82fe..d9bdf2b3ade2 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
| @@ -146,7 +146,7 @@ static int blk_end_aio(struct bio *bio, unsigned int bytes_done, int error) | |||
| 146 | iocb->ki_nbytes = -EIO; | 146 | iocb->ki_nbytes = -EIO; |
| 147 | 147 | ||
| 148 | if (atomic_dec_and_test(bio_count)) { | 148 | if (atomic_dec_and_test(bio_count)) { |
| 149 | if (iocb->ki_nbytes < 0) | 149 | if ((long)iocb->ki_nbytes < 0) |
| 150 | aio_complete(iocb, iocb->ki_nbytes, 0); | 150 | aio_complete(iocb, iocb->ki_nbytes, 0); |
| 151 | else | 151 | else |
| 152 | aio_complete(iocb, iocb->ki_left, 0); | 152 | aio_complete(iocb, iocb->ki_left, 0); |
| @@ -190,6 +190,12 @@ static struct page *blk_get_page(unsigned long addr, size_t count, int rw, | |||
| 190 | return pvec->page[pvec->idx++]; | 190 | return pvec->page[pvec->idx++]; |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | /* return a page back to pvec array */ | ||
| 194 | static void blk_unget_page(struct page *page, struct pvec *pvec) | ||
| 195 | { | ||
| 196 | pvec->page[--pvec->idx] = page; | ||
| 197 | } | ||
| 198 | |||
| 193 | static ssize_t | 199 | static ssize_t |
| 194 | blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | 200 | blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, |
| 195 | loff_t pos, unsigned long nr_segs) | 201 | loff_t pos, unsigned long nr_segs) |
| @@ -278,6 +284,8 @@ same_bio: | |||
| 278 | count = min(count, nbytes); | 284 | count = min(count, nbytes); |
| 279 | goto same_bio; | 285 | goto same_bio; |
| 280 | } | 286 | } |
| 287 | } else { | ||
| 288 | blk_unget_page(page, &pvec); | ||
| 281 | } | 289 | } |
| 282 | 290 | ||
| 283 | /* bio is ready, submit it */ | 291 | /* bio is ready, submit it */ |
