aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2007-05-11 01:22:51 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-11 11:29:35 -0400
commit0ea971801625184a91a6d80ea85e53875caa0bf5 (patch)
tree6f4144b7ba809fccfe6d75314df8c348596c9a01 /fs
parente10cc1df1d2014f68a4bdcf73f6dd122c4561f94 (diff)
consolidate generic_writepages and mpage_writepages
Clean up massive code duplication between mpage_writepages() and generic_writepages(). The new generic function, write_cache_pages() takes a function pointer argument, which will be called for each page to be written. Maybe cifs_writepages() too can use this infrastructure, but I'm not touching that with a ten-foot pole. The upcoming page writeback support in fuse will also want this. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Acked-by: Christoph Hellwig <hch@infradead.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/mpage.c174
1 files changed, 45 insertions, 129 deletions
diff --git a/fs/mpage.c b/fs/mpage.c
index 0fb914fc2ee0..c1698f2291aa 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -454,11 +454,18 @@ EXPORT_SYMBOL(mpage_readpage);
454 * written, so it can intelligently allocate a suitably-sized BIO. For now, 454 * written, so it can intelligently allocate a suitably-sized BIO. For now,
455 * just allocate full-size (16-page) BIOs. 455 * just allocate full-size (16-page) BIOs.
456 */ 456 */
457static struct bio * 457struct mpage_data {
458__mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block, 458 struct bio *bio;
459 sector_t *last_block_in_bio, int *ret, struct writeback_control *wbc, 459 sector_t last_block_in_bio;
460 writepage_t writepage_fn) 460 get_block_t *get_block;
461 unsigned use_writepage;
462};
463
464static int __mpage_writepage(struct page *page, struct writeback_control *wbc,
465 void *data)
461{ 466{
467 struct mpage_data *mpd = data;
468 struct bio *bio = mpd->bio;
462 struct address_space *mapping = page->mapping; 469 struct address_space *mapping = page->mapping;
463 struct inode *inode = page->mapping->host; 470 struct inode *inode = page->mapping->host;
464 const unsigned blkbits = inode->i_blkbits; 471 const unsigned blkbits = inode->i_blkbits;
@@ -476,6 +483,7 @@ __mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block,
476 int length; 483 int length;
477 struct buffer_head map_bh; 484 struct buffer_head map_bh;
478 loff_t i_size = i_size_read(inode); 485 loff_t i_size = i_size_read(inode);
486 int ret = 0;
479 487
480 if (page_has_buffers(page)) { 488 if (page_has_buffers(page)) {
481 struct buffer_head *head = page_buffers(page); 489 struct buffer_head *head = page_buffers(page);
@@ -538,7 +546,7 @@ __mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block,
538 546
539 map_bh.b_state = 0; 547 map_bh.b_state = 0;
540 map_bh.b_size = 1 << blkbits; 548 map_bh.b_size = 1 << blkbits;
541 if (get_block(inode, block_in_file, &map_bh, 1)) 549 if (mpd->get_block(inode, block_in_file, &map_bh, 1))
542 goto confused; 550 goto confused;
543 if (buffer_new(&map_bh)) 551 if (buffer_new(&map_bh))
544 unmap_underlying_metadata(map_bh.b_bdev, 552 unmap_underlying_metadata(map_bh.b_bdev,
@@ -584,7 +592,7 @@ page_is_mapped:
584 /* 592 /*
585 * This page will go to BIO. Do we need to send this BIO off first? 593 * This page will go to BIO. Do we need to send this BIO off first?
586 */ 594 */
587 if (bio && *last_block_in_bio != blocks[0] - 1) 595 if (bio && mpd->last_block_in_bio != blocks[0] - 1)
588 bio = mpage_bio_submit(WRITE, bio); 596 bio = mpage_bio_submit(WRITE, bio);
589 597
590alloc_new: 598alloc_new:
@@ -641,7 +649,7 @@ alloc_new:
641 boundary_block, 1 << blkbits); 649 boundary_block, 1 << blkbits);
642 } 650 }
643 } else { 651 } else {
644 *last_block_in_bio = blocks[blocks_per_page - 1]; 652 mpd->last_block_in_bio = blocks[blocks_per_page - 1];
645 } 653 }
646 goto out; 654 goto out;
647 655
@@ -649,18 +657,19 @@ confused:
649 if (bio) 657 if (bio)
650 bio = mpage_bio_submit(WRITE, bio); 658 bio = mpage_bio_submit(WRITE, bio);
651 659
652 if (writepage_fn) { 660 if (mpd->use_writepage) {
653 *ret = (*writepage_fn)(page, wbc); 661 ret = mapping->a_ops->writepage(page, wbc);
654 } else { 662 } else {
655 *ret = -EAGAIN; 663 ret = -EAGAIN;
656 goto out; 664 goto out;
657 } 665 }
658 /* 666 /*
659 * The caller has a ref on the inode, so *mapping is stable 667 * The caller has a ref on the inode, so *mapping is stable
660 */ 668 */
661 mapping_set_error(mapping, *ret); 669 mapping_set_error(mapping, ret);
662out: 670out:
663 return bio; 671 mpd->bio = bio;
672 return ret;
664} 673}
665 674
666/** 675/**
@@ -683,120 +692,27 @@ out:
683 * the call was made get new I/O started against them. If wbc->sync_mode is 692 * the call was made get new I/O started against them. If wbc->sync_mode is
684 * WB_SYNC_ALL then we were called for data integrity and we must wait for 693 * WB_SYNC_ALL then we were called for data integrity and we must wait for
685 * existing IO to complete. 694 * existing IO to complete.
686 *
687 * If you fix this you should check generic_writepages() also!
688 */ 695 */
689int 696int
690mpage_writepages(struct address_space *mapping, 697mpage_writepages(struct address_space *mapping,
691 struct writeback_control *wbc, get_block_t get_block) 698 struct writeback_control *wbc, get_block_t get_block)
692{ 699{
693 struct backing_dev_info *bdi = mapping->backing_dev_info; 700 int ret;
694 struct bio *bio = NULL; 701
695 sector_t last_block_in_bio = 0; 702 if (!get_block)
696 int ret = 0; 703 ret = generic_writepages(mapping, wbc);
697 int done = 0; 704 else {
698 int (*writepage)(struct page *page, struct writeback_control *wbc); 705 struct mpage_data mpd = {
699 struct pagevec pvec; 706 .bio = NULL,
700 int nr_pages; 707 .last_block_in_bio = 0,
701 pgoff_t index; 708 .get_block = get_block,
702 pgoff_t end; /* Inclusive */ 709 .use_writepage = 1,
703 int scanned = 0; 710 };
704 int range_whole = 0; 711
705 712 ret = write_cache_pages(mapping, wbc, __mpage_writepage, &mpd);
706 if (wbc->nonblocking && bdi_write_congested(bdi)) { 713 if (mpd.bio)
707 wbc->encountered_congestion = 1; 714 mpage_bio_submit(WRITE, mpd.bio);
708 return 0;
709 }
710
711 writepage = NULL;
712 if (get_block == NULL)
713 writepage = mapping->a_ops->writepage;
714
715 pagevec_init(&pvec, 0);
716 if (wbc->range_cyclic) {
717 index = mapping->writeback_index; /* Start from prev offset */
718 end = -1;
719 } else {
720 index = wbc->range_start >> PAGE_CACHE_SHIFT;
721 end = wbc->range_end >> PAGE_CACHE_SHIFT;
722 if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
723 range_whole = 1;
724 scanned = 1;
725 } 715 }
726retry:
727 while (!done && (index <= end) &&
728 (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
729 PAGECACHE_TAG_DIRTY,
730 min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1))) {
731 unsigned i;
732
733 scanned = 1;
734 for (i = 0; i < nr_pages; i++) {
735 struct page *page = pvec.pages[i];
736
737 /*
738 * At this point we hold neither mapping->tree_lock nor
739 * lock on the page itself: the page may be truncated or
740 * invalidated (changing page->mapping to NULL), or even
741 * swizzled back from swapper_space to tmpfs file
742 * mapping
743 */
744
745 lock_page(page);
746
747 if (unlikely(page->mapping != mapping)) {
748 unlock_page(page);
749 continue;
750 }
751
752 if (!wbc->range_cyclic && page->index > end) {
753 done = 1;
754 unlock_page(page);
755 continue;
756 }
757
758 if (wbc->sync_mode != WB_SYNC_NONE)
759 wait_on_page_writeback(page);
760
761 if (PageWriteback(page) ||
762 !clear_page_dirty_for_io(page)) {
763 unlock_page(page);
764 continue;
765 }
766
767 if (writepage) {
768 ret = (*writepage)(page, wbc);
769 mapping_set_error(mapping, ret);
770 } else {
771 bio = __mpage_writepage(bio, page, get_block,
772 &last_block_in_bio, &ret, wbc,
773 page->mapping->a_ops->writepage);
774 }
775 if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE))
776 unlock_page(page);
777 if (ret || (--(wbc->nr_to_write) <= 0))
778 done = 1;
779 if (wbc->nonblocking && bdi_write_congested(bdi)) {
780 wbc->encountered_congestion = 1;
781 done = 1;
782 }
783 }
784 pagevec_release(&pvec);
785 cond_resched();
786 }
787 if (!scanned && !done) {
788 /*
789 * We hit the last page and there is more work to be done: wrap
790 * back to the start of the file
791 */
792 scanned = 1;
793 index = 0;
794 goto retry;
795 }
796 if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
797 mapping->writeback_index = index;
798 if (bio)
799 mpage_bio_submit(WRITE, bio);
800 return ret; 716 return ret;
801} 717}
802EXPORT_SYMBOL(mpage_writepages); 718EXPORT_SYMBOL(mpage_writepages);
@@ -804,15 +720,15 @@ EXPORT_SYMBOL(mpage_writepages);
804int mpage_writepage(struct page *page, get_block_t get_block, 720int mpage_writepage(struct page *page, get_block_t get_block,
805 struct writeback_control *wbc) 721 struct writeback_control *wbc)
806{ 722{
807 int ret = 0; 723 struct mpage_data mpd = {
808 struct bio *bio; 724 .bio = NULL,
809 sector_t last_block_in_bio = 0; 725 .last_block_in_bio = 0,
810 726 .get_block = get_block,
811 bio = __mpage_writepage(NULL, page, get_block, 727 .use_writepage = 0,
812 &last_block_in_bio, &ret, wbc, NULL); 728 };
813 if (bio) 729 int ret = __mpage_writepage(page, wbc, &mpd);
814 mpage_bio_submit(WRITE, bio); 730 if (mpd.bio)
815 731 mpage_bio_submit(WRITE, mpd.bio);
816 return ret; 732 return ret;
817} 733}
818EXPORT_SYMBOL(mpage_writepage); 734EXPORT_SYMBOL(mpage_writepage);