| From stable-bounces@linux.kernel.org Wed Feb 28 20:14:55 2007 |
| From: Andrew Morton <akpm@linux-foundation.org> |
| Date: Wed, 28 Feb 2007 20:13:21 -0800 |
| Subject: throttle_vm_writeout(): don't loop on GFP_NOFS and GFP_NOIO allocations |
| To: torvalds@linux-foundation.org |
| Cc: nickpiggin@yahoo.com.au, galak@kernel.crashing.org, zaitcev@redhat.com, akpm@linux-foundation.org, stable@kernel.org, hirofumi@mail.parknet.co.jp |
| Message-ID: <200703010413.l214DLO1004150@shell0.pdx.osdl.net> |
| |
| |
| From: Andrew Morton <akpm@linux-foundation.org> |
| |
| throttle_vm_writeout() is designed to wait for the dirty levels to subside. |
| But if the caller holds IO or FS locks, we might be holding up that writeout. |
| |
| So change it to take a single nap to give other devices a chance to clean some |
| memory, then return. |
| |
| Cc: Nick Piggin <nickpiggin@yahoo.com.au> |
| Cc: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> |
| Cc: Kumar Gala <galak@kernel.crashing.org> |
| Cc: Pete Zaitcev <zaitcev@redhat.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| include/linux/writeback.h | 2 +- |
| mm/page-writeback.c | 13 +++++++++++-- |
| mm/vmscan.c | 2 +- |
| 3 files changed, 13 insertions(+), 4 deletions(-) |
| |
| --- linux-2.6.20.1.orig/include/linux/writeback.h |
| +++ linux-2.6.20.1/include/linux/writeback.h |
| @@ -84,7 +84,7 @@ static inline void wait_on_inode(struct |
| int wakeup_pdflush(long nr_pages); |
| void laptop_io_completion(void); |
| void laptop_sync_completion(void); |
| -void throttle_vm_writeout(void); |
| +void throttle_vm_writeout(gfp_t gfp_mask); |
| |
| /* These are exported to sysctl. */ |
| extern int dirty_background_ratio; |
| --- linux-2.6.20.1.orig/mm/page-writeback.c |
| +++ linux-2.6.20.1/mm/page-writeback.c |
| @@ -296,11 +296,21 @@ void balance_dirty_pages_ratelimited_nr( |
| } |
| EXPORT_SYMBOL(balance_dirty_pages_ratelimited_nr); |
| |
| -void throttle_vm_writeout(void) |
| +void throttle_vm_writeout(gfp_t gfp_mask) |
| { |
| long background_thresh; |
| long dirty_thresh; |
| |
| + if ((gfp_mask & (__GFP_FS|__GFP_IO)) != (__GFP_FS|__GFP_IO)) { |
| + /* |
| + * The caller might hold locks which can prevent IO completion |
| + * or progress in the filesystem. So we cannot just sit here |
| + * waiting for IO to complete. |
| + */ |
| + congestion_wait(WRITE, HZ/10); |
| + return; |
| + } |
| + |
| for ( ; ; ) { |
| get_dirty_limits(&background_thresh, &dirty_thresh, NULL); |
| |
| @@ -317,7 +327,6 @@ void throttle_vm_writeout(void) |
| } |
| } |
| |
| - |
| /* |
| * writeback at least _min_pages, and keep writing until the amount of dirty |
| * memory is less than the background threshold, or until we're all clean. |
| --- linux-2.6.20.1.orig/mm/vmscan.c |
| +++ linux-2.6.20.1/mm/vmscan.c |
| @@ -949,7 +949,7 @@ static unsigned long shrink_zone(int pri |
| } |
| } |
| |
| - throttle_vm_writeout(); |
| + throttle_vm_writeout(sc->gfp_mask); |
| |
| atomic_dec(&zone->reclaim_in_progress); |
| return nr_reclaimed; |