]> Pileus Git - ~andy/linux/blobdiff - fs/direct-io.c
sparc: bpf_jit_comp: can call module_free() from any context
[~andy/linux] / fs / direct-io.c
index f853263cf74f8abf29016db5e44eaa9e0de44abc..7ab90f5081eebc4ab8b0de88bef8d0b6310ed113 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/uio.h>
 #include <linux/atomic.h>
 #include <linux/prefetch.h>
+#include <linux/aio.h>
 
 /*
  * How many user pages to map in one call to get_user_pages().  This determines
@@ -441,8 +442,8 @@ static struct bio *dio_await_one(struct dio *dio)
 static int dio_bio_complete(struct dio *dio, struct bio *bio)
 {
        const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
-       struct bio_vec *bvec = bio->bi_io_vec;
-       int page_no;
+       struct bio_vec *bvec;
+       unsigned i;
 
        if (!uptodate)
                dio->io_error = -EIO;
@@ -450,8 +451,8 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio)
        if (dio->is_async && dio->rw == READ) {
                bio_check_pages_dirty(bio);     /* transfers ownership */
        } else {
-               for (page_no = 0; page_no < bio->bi_vcnt; page_no++) {
-                       struct page *page = bvec[page_no].bv_page;
+               bio_for_each_segment_all(bvec, bio, i) {
+                       struct page *page = bvec->bv_page;
 
                        if (dio->rw == READ && !PageCompound(page))
                                set_page_dirty_lock(page);
@@ -672,12 +673,6 @@ static inline int dio_send_cur_page(struct dio *dio, struct dio_submit *sdio,
                if (sdio->final_block_in_bio != sdio->cur_page_block ||
                    cur_offset != bio_next_offset)
                        dio_bio_submit(dio, sdio);
-               /*
-                * Submit now if the underlying fs is about to perform a
-                * metadata read
-                */
-               else if (sdio->boundary)
-                       dio_bio_submit(dio, sdio);
        }
 
        if (sdio->bio == NULL) {
@@ -737,16 +732,6 @@ submit_page_section(struct dio *dio, struct dio_submit *sdio, struct page *page,
            sdio->cur_page_block +
            (sdio->cur_page_len >> sdio->blkbits) == blocknr) {
                sdio->cur_page_len += len;
-
-               /*
-                * If sdio->boundary then we want to schedule the IO now to
-                * avoid metadata seeks.
-                */
-               if (sdio->boundary) {
-                       ret = dio_send_cur_page(dio, sdio, map_bh);
-                       page_cache_release(sdio->cur_page);
-                       sdio->cur_page = NULL;
-               }
                goto out;
        }
 
@@ -758,7 +743,7 @@ submit_page_section(struct dio *dio, struct dio_submit *sdio, struct page *page,
                page_cache_release(sdio->cur_page);
                sdio->cur_page = NULL;
                if (ret)
-                       goto out;
+                       return ret;
        }
 
        page_cache_get(page);           /* It is in dio */
@@ -768,6 +753,16 @@ submit_page_section(struct dio *dio, struct dio_submit *sdio, struct page *page,
        sdio->cur_page_block = blocknr;
        sdio->cur_page_fs_offset = sdio->block_in_file << sdio->blkbits;
 out:
+       /*
+        * If sdio->boundary then we want to schedule the IO now to
+        * avoid metadata seeks.
+        */
+       if (sdio->boundary) {
+               ret = dio_send_cur_page(dio, sdio, map_bh);
+               dio_bio_submit(dio, sdio);
+               page_cache_release(sdio->cur_page);
+               sdio->cur_page = NULL;
+       }
        return ret;
 }
 
@@ -969,7 +964,8 @@ do_holes:
                        this_chunk_bytes = this_chunk_blocks << blkbits;
                        BUG_ON(this_chunk_bytes == 0);
 
-                       sdio->boundary = buffer_boundary(map_bh);
+                       if (this_chunk_blocks == sdio->blocks_available)
+                               sdio->boundary = buffer_boundary(map_bh);
                        ret = submit_page_section(dio, sdio, page,
                                                  offset_in_page,
                                                  this_chunk_bytes,