diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/page-writeback.c | 59 |
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 | */ |
609 | int generic_writepages(struct address_space *mapping, | 605 | int 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 | } |
702 | EXPORT_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 | */ | ||
708 | static 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 | */ | ||
725 | int 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 | ||
714 | EXPORT_SYMBOL(generic_writepages); | 735 | EXPORT_SYMBOL(generic_writepages); |
715 | 736 | ||