aboutsummaryrefslogtreecommitdiffstats
path: root/mm/page-writeback.c
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 /mm/page-writeback.c
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 'mm/page-writeback.c')
-rw-r--r--mm/page-writeback.c59
1 files changed, 40 insertions, 19 deletions
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 63cd88840eb2..eec1481ba44f 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -588,31 +588,27 @@ void __init page_writeback_init(void)
588} 588}
589 589
590/** 590/**
591 * generic_writepages - walk the list of dirty pages of the given address space and writepage() all of them. 591 * write_cache_pages - walk the list of dirty pages of the given address space and write all of them.
592 * @mapping: address space structure to write 592 * @mapping: address space structure to write
593 * @wbc: subtract the number of written pages from *@wbc->nr_to_write 593 * @wbc: subtract the number of written pages from *@wbc->nr_to_write
594 * @writepage: function called for each page
595 * @data: data passed to writepage function
594 * 596 *
595 * This is a library function, which implements the writepages() 597 * If a page is already under I/O, write_cache_pages() skips it, even
596 * address_space_operation.
597 *
598 * If a page is already under I/O, generic_writepages() skips it, even
599 * if it's dirty. This is desirable behaviour for memory-cleaning writeback, 598 * if it's dirty. This is desirable behaviour for memory-cleaning writeback,
600 * but it is INCORRECT for data-integrity system calls such as fsync(). fsync() 599 * but it is INCORRECT for data-integrity system calls such as fsync(). fsync()
601 * and msync() need to guarantee that all the data which was dirty at the time 600 * and msync() need to guarantee that all the data which was dirty at the time
602 * the call was made get new I/O started against them. If wbc->sync_mode is 601 * the call was made get new I/O started against them. If wbc->sync_mode is
603 * WB_SYNC_ALL then we were called for data integrity and we must wait for 602 * WB_SYNC_ALL then we were called for data integrity and we must wait for
604 * existing IO to complete. 603 * existing IO to complete.
605 *
606 * Derived from mpage_writepages() - if you fix this you should check that
607 * also!
608 */ 604 */
609int generic_writepages(struct address_space *mapping, 605int write_cache_pages(struct address_space *mapping,
610 struct writeback_control *wbc) 606 struct writeback_control *wbc, writepage_t writepage,
607 void *data)
611{ 608{
612 struct backing_dev_info *bdi = mapping->backing_dev_info; 609 struct backing_dev_info *bdi = mapping->backing_dev_info;
613 int ret = 0; 610 int ret = 0;
614 int done = 0; 611 int done = 0;
615 int (*writepage)(struct page *page, struct writeback_control *wbc);
616 struct pagevec pvec; 612 struct pagevec pvec;
617 int nr_pages; 613 int nr_pages;
618 pgoff_t index; 614 pgoff_t index;
@@ -625,12 +621,6 @@ int generic_writepages(struct address_space *mapping,
625 return 0; 621 return 0;
626 } 622 }
627 623
628 writepage = mapping->a_ops->writepage;
629
630 /* deal with chardevs and other special file */
631 if (!writepage)
632 return 0;
633
634 pagevec_init(&pvec, 0); 624 pagevec_init(&pvec, 0);
635 if (wbc->range_cyclic) { 625 if (wbc->range_cyclic) {
636 index = mapping->writeback_index; /* Start from prev offset */ 626 index = mapping->writeback_index; /* Start from prev offset */
@@ -682,8 +672,7 @@ retry:
682 continue; 672 continue;
683 } 673 }
684 674
685 ret = (*writepage)(page, wbc); 675 ret = (*writepage)(page, wbc, data);
686 mapping_set_error(mapping, ret);
687 676
688 if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE)) 677 if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE))
689 unlock_page(page); 678 unlock_page(page);
@@ -710,6 +699,38 @@ retry:
710 mapping->writeback_index = index; 699 mapping->writeback_index = index;
711 return ret; 700 return ret;
712} 701}
702EXPORT_SYMBOL(write_cache_pages);
703
704/*
705 * Function used by generic_writepages to call the real writepage
706 * function and set the mapping flags on error
707 */
708static int __writepage(struct page *page, struct writeback_control *wbc,
709 void *data)
710{
711 struct address_space *mapping = data;
712 int ret = mapping->a_ops->writepage(page, wbc);
713 mapping_set_error(mapping, ret);
714 return ret;
715}
716
717/**
718 * generic_writepages - walk the list of dirty pages of the given address space and writepage() all of them.
719 * @mapping: address space structure to write
720 * @wbc: subtract the number of written pages from *@wbc->nr_to_write
721 *
722 * This is a library function, which implements the writepages()
723 * address_space_operation.
724 */
725int generic_writepages(struct address_space *mapping,
726 struct writeback_control *wbc)
727{
728 /* deal with chardevs and other special file */
729 if (!mapping->a_ops->writepage)
730 return 0;
731
732 return write_cache_pages(mapping, wbc, __writepage, mapping);
733}
713 734
714EXPORT_SYMBOL(generic_writepages); 735EXPORT_SYMBOL(generic_writepages);
715 736