diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-26 20:15:20 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-26 20:15:20 -0400 |
| commit | 31453a9764f7e2a72a6e2c502ace586e2663a68c (patch) | |
| tree | 5d4db63de5b4b85d1ffdab4e95a75175a784a10a /mm/backing-dev.c | |
| parent | f9ba5375a8aae4aeea6be15df77e24707a429812 (diff) | |
| parent | 93ed0e2d07b25aff4db1d61bfbcd1e82074c0ad5 (diff) | |
Merge branch 'akpm-incoming-1'
* akpm-incoming-1: (176 commits)
scripts/checkpatch.pl: add check for declaration of pci_device_id
scripts/checkpatch.pl: add warnings for static char that could be static const char
checkpatch: version 0.31
checkpatch: statement/block context analyser should look at sanitised lines
checkpatch: handle EXPORT_SYMBOL for DEVICE_ATTR and similar
checkpatch: clean up structure definition macro handline
checkpatch: update copyright dates
checkpatch: Add additional attribute #defines
checkpatch: check for incorrect permissions
checkpatch: ensure kconfig help checks only apply when we are adding help
checkpatch: simplify and consolidate "missing space after" checks
checkpatch: add check for space after struct, union, and enum
checkpatch: returning errno typically should be negative
checkpatch: handle casts better fixing false categorisation of : as binary
checkpatch: ensure we do not collapse bracketed sections into constants
checkpatch: suggest cleanpatch and cleanfile when appropriate
checkpatch: types may sit on a line on their own
checkpatch: fix regressions in "fix handling of leading spaces"
div64_u64(): improve precision on 32bit platforms
lib/parser: cleanup match_number()
...
Diffstat (limited to 'mm/backing-dev.c')
| -rw-r--r-- | mm/backing-dev.c | 68 |
1 files changed, 65 insertions, 3 deletions
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 65d420499a61..f2eb27884ffa 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c | |||
| @@ -362,7 +362,7 @@ static int bdi_forker_thread(void *ptr) | |||
| 362 | { | 362 | { |
| 363 | struct bdi_writeback *me = ptr; | 363 | struct bdi_writeback *me = ptr; |
| 364 | 364 | ||
| 365 | current->flags |= PF_FLUSHER | PF_SWAPWRITE; | 365 | current->flags |= PF_SWAPWRITE; |
| 366 | set_freezable(); | 366 | set_freezable(); |
| 367 | 367 | ||
| 368 | /* | 368 | /* |
| @@ -729,6 +729,7 @@ static wait_queue_head_t congestion_wqh[2] = { | |||
| 729 | __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]), | 729 | __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]), |
| 730 | __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1]) | 730 | __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1]) |
| 731 | }; | 731 | }; |
| 732 | static atomic_t nr_bdi_congested[2]; | ||
| 732 | 733 | ||
| 733 | void clear_bdi_congested(struct backing_dev_info *bdi, int sync) | 734 | void clear_bdi_congested(struct backing_dev_info *bdi, int sync) |
| 734 | { | 735 | { |
| @@ -736,7 +737,8 @@ void clear_bdi_congested(struct backing_dev_info *bdi, int sync) | |||
| 736 | wait_queue_head_t *wqh = &congestion_wqh[sync]; | 737 | wait_queue_head_t *wqh = &congestion_wqh[sync]; |
| 737 | 738 | ||
| 738 | bit = sync ? BDI_sync_congested : BDI_async_congested; | 739 | bit = sync ? BDI_sync_congested : BDI_async_congested; |
| 739 | clear_bit(bit, &bdi->state); | 740 | if (test_and_clear_bit(bit, &bdi->state)) |
| 741 | atomic_dec(&nr_bdi_congested[sync]); | ||
| 740 | smp_mb__after_clear_bit(); | 742 | smp_mb__after_clear_bit(); |
| 741 | if (waitqueue_active(wqh)) | 743 | if (waitqueue_active(wqh)) |
| 742 | wake_up(wqh); | 744 | wake_up(wqh); |
| @@ -748,7 +750,8 @@ void set_bdi_congested(struct backing_dev_info *bdi, int sync) | |||
| 748 | enum bdi_state bit; | 750 | enum bdi_state bit; |
| 749 | 751 | ||
| 750 | bit = sync ? BDI_sync_congested : BDI_async_congested; | 752 | bit = sync ? BDI_sync_congested : BDI_async_congested; |
| 751 | set_bit(bit, &bdi->state); | 753 | if (!test_and_set_bit(bit, &bdi->state)) |
| 754 | atomic_inc(&nr_bdi_congested[sync]); | ||
| 752 | } | 755 | } |
| 753 | EXPORT_SYMBOL(set_bdi_congested); | 756 | EXPORT_SYMBOL(set_bdi_congested); |
| 754 | 757 | ||
| @@ -764,13 +767,72 @@ EXPORT_SYMBOL(set_bdi_congested); | |||
| 764 | long congestion_wait(int sync, long timeout) | 767 | long congestion_wait(int sync, long timeout) |
| 765 | { | 768 | { |
| 766 | long ret; | 769 | long ret; |
| 770 | unsigned long start = jiffies; | ||
| 767 | DEFINE_WAIT(wait); | 771 | DEFINE_WAIT(wait); |
| 768 | wait_queue_head_t *wqh = &congestion_wqh[sync]; | 772 | wait_queue_head_t *wqh = &congestion_wqh[sync]; |
| 769 | 773 | ||
| 770 | prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE); | 774 | prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE); |
| 771 | ret = io_schedule_timeout(timeout); | 775 | ret = io_schedule_timeout(timeout); |
| 772 | finish_wait(wqh, &wait); | 776 | finish_wait(wqh, &wait); |
| 777 | |||
| 778 | trace_writeback_congestion_wait(jiffies_to_usecs(timeout), | ||
| 779 | jiffies_to_usecs(jiffies - start)); | ||
| 780 | |||
| 773 | return ret; | 781 | return ret; |
| 774 | } | 782 | } |
| 775 | EXPORT_SYMBOL(congestion_wait); | 783 | EXPORT_SYMBOL(congestion_wait); |
| 776 | 784 | ||
| 785 | /** | ||
| 786 | * wait_iff_congested - Conditionally wait for a backing_dev to become uncongested or a zone to complete writes | ||
| 787 | * @zone: A zone to check if it is heavily congested | ||
| 788 | * @sync: SYNC or ASYNC IO | ||
| 789 | * @timeout: timeout in jiffies | ||
| 790 | * | ||
| 791 | * In the event of a congested backing_dev (any backing_dev) and the given | ||
| 792 | * @zone has experienced recent congestion, this waits for up to @timeout | ||
| 793 | * jiffies for either a BDI to exit congestion of the given @sync queue | ||
| 794 | * or a write to complete. | ||
| 795 | * | ||
| 796 | * In the absense of zone congestion, cond_resched() is called to yield | ||
| 797 | * the processor if necessary but otherwise does not sleep. | ||
| 798 | * | ||
| 799 | * The return value is 0 if the sleep is for the full timeout. Otherwise, | ||
| 800 | * it is the number of jiffies that were still remaining when the function | ||
| 801 | * returned. return_value == timeout implies the function did not sleep. | ||
| 802 | */ | ||
| 803 | long wait_iff_congested(struct zone *zone, int sync, long timeout) | ||
| 804 | { | ||
| 805 | long ret; | ||
| 806 | unsigned long start = jiffies; | ||
| 807 | DEFINE_WAIT(wait); | ||
| 808 | wait_queue_head_t *wqh = &congestion_wqh[sync]; | ||
| 809 | |||
| 810 | /* | ||
| 811 | * If there is no congestion, or heavy congestion is not being | ||
| 812 | * encountered in the current zone, yield if necessary instead | ||
| 813 | * of sleeping on the congestion queue | ||
| 814 | */ | ||
| 815 | if (atomic_read(&nr_bdi_congested[sync]) == 0 || | ||
| 816 | !zone_is_reclaim_congested(zone)) { | ||
| 817 | cond_resched(); | ||
| 818 | |||
| 819 | /* In case we scheduled, work out time remaining */ | ||
| 820 | ret = timeout - (jiffies - start); | ||
| 821 | if (ret < 0) | ||
| 822 | ret = 0; | ||
| 823 | |||
| 824 | goto out; | ||
| 825 | } | ||
| 826 | |||
| 827 | /* Sleep until uncongested or a write happens */ | ||
| 828 | prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE); | ||
| 829 | ret = io_schedule_timeout(timeout); | ||
| 830 | finish_wait(wqh, &wait); | ||
| 831 | |||
| 832 | out: | ||
| 833 | trace_writeback_wait_iff_congested(jiffies_to_usecs(timeout), | ||
| 834 | jiffies_to_usecs(jiffies - start)); | ||
| 835 | |||
| 836 | return ret; | ||
| 837 | } | ||
| 838 | EXPORT_SYMBOL(wait_iff_congested); | ||
