X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fmpage.c;h=bb9aebe93862d8c03a94990d4b28fc4832e93a1f;hb=f7f1b0f1e2fbadeab12d24236000e778aa9b1ead;hp=4bbf15ee91fe01bcaa529f7e74dbd0e1bb702a36;hpb=e3f6fb6212a7102bdb56ba38fa1e98fe72950475;p=linux-2.6.git diff --git a/fs/mpage.c b/fs/mpage.c index 4bbf15ee9..bb9aebe93 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -79,15 +79,18 @@ static int mpage_end_io_write(struct bio *bio, unsigned int bytes_done, int err) if (--bvec >= bio->bi_io_vec) prefetchw(&bvec->bv_page->flags); - if (!uptodate) + if (!uptodate){ SetPageError(page); + if (page->mapping) + set_bit(AS_EIO, &page->mapping->flags); + } end_page_writeback(page); } while (bvec >= bio->bi_io_vec); bio_put(bio); return 0; } -struct bio *mpage_bio_submit(int rw, struct bio *bio) +static struct bio *mpage_bio_submit(int rw, struct bio *bio) { bio->bi_end_io = mpage_end_io_read; if (rw == WRITE) @@ -98,7 +101,8 @@ struct bio *mpage_bio_submit(int rw, struct bio *bio) static struct bio * mpage_alloc(struct block_device *bdev, - sector_t first_sector, int nr_vecs, int gfp_flags) + sector_t first_sector, int nr_vecs, + unsigned int __nocast gfp_flags) { struct bio *bio; @@ -159,52 +163,6 @@ map_buffer_to_page(struct page *page, struct buffer_head *bh, int page_block) } while (page_bh != head); } -/** - * mpage_readpages - populate an address space with some pages, and - * start reads against them. - * - * @mapping: the address_space - * @pages: The address of a list_head which contains the target pages. These - * pages have their ->index populated and are otherwise uninitialised. - * - * The page at @pages->prev has the lowest file offset, and reads should be - * issued in @pages->prev to @pages->next order. - * - * @nr_pages: The number of pages at *@pages - * @get_block: The filesystem's block mapper function. - * - * This function walks the pages and the blocks within each page, building and - * emitting large BIOs. - * - * If anything unusual happens, such as: - * - * - encountering a page which has buffers - * - encountering a page which has a non-hole after a hole - * - encountering a page with non-contiguous blocks - * - * then this code just gives up and calls the buffer_head-based read function. - * It does handle a page which has holes at the end - that is a common case: - * the end-of-file on blocksize < PAGE_CACHE_SIZE setups. - * - * BH_Boundary explanation: - * - * There is a problem. The mpage read code assembles several pages, gets all - * their disk mappings, and then submits them all. That's fine, but obtaining - * the disk mappings may require I/O. Reads of indirect blocks, for example. - * - * So an mpage read of the first 16 blocks of an ext2 file will cause I/O to be - * submitted in the following order: - * 12 0 1 2 3 4 5 6 7 8 9 10 11 13 14 15 16 - * because the indirect block has to be read to get the mappings of blocks - * 13,14,15,16. Obviously, this impacts performance. - * - * So what we do it to allow the filesystem's get_block() function to set - * BH_Boundary when it maps block 11. BH_Boundary says: mapping of the block - * after this one will require I/O against a block which is probably close to - * this one. So you should push what I/O you have currently accumulated. - * - * This all causes the disk requests to be issued in the correct order. - */ static struct bio * do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages, sector_t *last_block_in_bio, get_block_t get_block) @@ -319,6 +277,52 @@ confused: goto out; } +/** + * mpage_readpages - populate an address space with some pages, and + * start reads against them. + * + * @mapping: the address_space + * @pages: The address of a list_head which contains the target pages. These + * pages have their ->index populated and are otherwise uninitialised. + * + * The page at @pages->prev has the lowest file offset, and reads should be + * issued in @pages->prev to @pages->next order. + * + * @nr_pages: The number of pages at *@pages + * @get_block: The filesystem's block mapper function. + * + * This function walks the pages and the blocks within each page, building and + * emitting large BIOs. + * + * If anything unusual happens, such as: + * + * - encountering a page which has buffers + * - encountering a page which has a non-hole after a hole + * - encountering a page with non-contiguous blocks + * + * then this code just gives up and calls the buffer_head-based read function. + * It does handle a page which has holes at the end - that is a common case: + * the end-of-file on blocksize < PAGE_CACHE_SIZE setups. + * + * BH_Boundary explanation: + * + * There is a problem. The mpage read code assembles several pages, gets all + * their disk mappings, and then submits them all. That's fine, but obtaining + * the disk mappings may require I/O. Reads of indirect blocks, for example. + * + * So an mpage read of the first 16 blocks of an ext2 file will cause I/O to be + * submitted in the following order: + * 12 0 1 2 3 4 5 6 7 8 9 10 11 13 14 15 16 + * because the indirect block has to be read to get the mappings of blocks + * 13,14,15,16. Obviously, this impacts performance. + * + * So what we do it to allow the filesystem's get_block() function to set + * BH_Boundary when it maps block 11. BH_Boundary says: mapping of the block + * after this one will require I/O against a block which is probably close to + * this one. So you should push what I/O you have currently accumulated. + * + * This all causes the disk requests to be issued in the correct order. + */ int mpage_readpages(struct address_space *mapping, struct list_head *pages, unsigned nr_pages, get_block_t get_block) @@ -386,8 +390,9 @@ EXPORT_SYMBOL(mpage_readpage); * just allocate full-size (16-page) BIOs. */ static struct bio * -mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block, - sector_t *last_block_in_bio, int *ret, struct writeback_control *wbc) +__mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block, + sector_t *last_block_in_bio, int *ret, struct writeback_control *wbc, + writepage_t writepage_fn) { struct address_space *mapping = page->mapping; struct inode *inode = page->mapping->host; @@ -580,7 +585,13 @@ alloc_new: confused: if (bio) bio = mpage_bio_submit(WRITE, bio); - *ret = page->mapping->a_ops->writepage(page, wbc); + + if (writepage_fn) { + *ret = (*writepage_fn)(page, wbc); + } else { + *ret = -EAGAIN; + goto out; + } /* * The caller has a ref on the inode, so *mapping is stable */ @@ -706,9 +717,12 @@ retry: &mapping->flags); } } else { - bio = mpage_writepage(bio, page, get_block, - &last_block_in_bio, &ret, wbc); + bio = __mpage_writepage(bio, page, get_block, + &last_block_in_bio, &ret, wbc, + page->mapping->a_ops->writepage); } + if (unlikely(ret == WRITEPAGE_ACTIVATE)) + unlock_page(page); if (ret || (--(wbc->nr_to_write) <= 0)) done = 1; if (wbc->nonblocking && bdi_write_congested(bdi)) { @@ -735,3 +749,19 @@ retry: return ret; } EXPORT_SYMBOL(mpage_writepages); + +int mpage_writepage(struct page *page, get_block_t get_block, + struct writeback_control *wbc) +{ + int ret = 0; + struct bio *bio; + sector_t last_block_in_bio = 0; + + bio = __mpage_writepage(NULL, page, get_block, + &last_block_in_bio, &ret, wbc, NULL); + if (bio) + mpage_bio_submit(WRITE, bio); + + return ret; +} +EXPORT_SYMBOL(mpage_writepage);