diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/page-writeback.c | 59 | ||||
-rw-r--r-- | mm/thrash.c | 5 | ||||
-rw-r--r-- | mm/vmstat.c | 2 |
3 files changed, 43 insertions, 23 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 | ||
diff --git a/mm/thrash.c b/mm/thrash.c index 9ef9071f99bc..c4c5205a9c35 100644 --- a/mm/thrash.c +++ b/mm/thrash.c | |||
@@ -48,9 +48,8 @@ void grab_swap_token(void) | |||
48 | if (current_interval < current->mm->last_interval) | 48 | if (current_interval < current->mm->last_interval) |
49 | current->mm->token_priority++; | 49 | current->mm->token_priority++; |
50 | else { | 50 | else { |
51 | current->mm->token_priority--; | 51 | if (likely(current->mm->token_priority > 0)) |
52 | if (unlikely(current->mm->token_priority < 0)) | 52 | current->mm->token_priority--; |
53 | current->mm->token_priority = 0; | ||
54 | } | 53 | } |
55 | /* Check if we deserve the token */ | 54 | /* Check if we deserve the token */ |
56 | if (current->mm->token_priority > | 55 | if (current->mm->token_priority > |
diff --git a/mm/vmstat.c b/mm/vmstat.c index 9832d9a41d8c..8faf27e5aa98 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c | |||
@@ -698,7 +698,7 @@ static void __devinit start_cpu_timer(int cpu) | |||
698 | { | 698 | { |
699 | struct delayed_work *vmstat_work = &per_cpu(vmstat_work, cpu); | 699 | struct delayed_work *vmstat_work = &per_cpu(vmstat_work, cpu); |
700 | 700 | ||
701 | INIT_DELAYED_WORK(vmstat_work, vmstat_update); | 701 | INIT_DELAYED_WORK_DEFERRABLE(vmstat_work, vmstat_update); |
702 | schedule_delayed_work_on(cpu, vmstat_work, HZ + cpu); | 702 | schedule_delayed_work_on(cpu, vmstat_work, HZ + cpu); |
703 | } | 703 | } |
704 | 704 | ||