Commit 232ea4d69d81169453344b7d05203425c88d973b

Authored by Andrew Morton
Committed by Linus Torvalds
1 parent b1a316f6f9

[PATCH] throttle_vm_writeout(): don't loop on GFP_NOFS and GFP_NOIO allocations

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>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 3 changed files with 13 additions and 4 deletions Side-by-side Diff

include/linux/writeback.h
... ... @@ -84,7 +84,7 @@
84 84 int wakeup_pdflush(long nr_pages);
85 85 void laptop_io_completion(void);
86 86 void laptop_sync_completion(void);
87   -void throttle_vm_writeout(void);
  87 +void throttle_vm_writeout(gfp_t gfp_mask);
88 88  
89 89 /* These are exported to sysctl. */
90 90 extern int dirty_background_ratio;
... ... @@ -296,11 +296,21 @@
296 296 }
297 297 EXPORT_SYMBOL(balance_dirty_pages_ratelimited_nr);
298 298  
299   -void throttle_vm_writeout(void)
  299 +void throttle_vm_writeout(gfp_t gfp_mask)
300 300 {
301 301 long background_thresh;
302 302 long dirty_thresh;
303 303  
  304 + if ((gfp_mask & (__GFP_FS|__GFP_IO)) != (__GFP_FS|__GFP_IO)) {
  305 + /*
  306 + * The caller might hold locks which can prevent IO completion
  307 + * or progress in the filesystem. So we cannot just sit here
  308 + * waiting for IO to complete.
  309 + */
  310 + congestion_wait(WRITE, HZ/10);
  311 + return;
  312 + }
  313 +
304 314 for ( ; ; ) {
305 315 get_dirty_limits(&background_thresh, &dirty_thresh, NULL);
306 316  
... ... @@ -316,7 +326,6 @@
316 326 congestion_wait(WRITE, HZ/10);
317 327 }
318 328 }
319   -
320 329  
321 330 /*
322 331 * writeback at least _min_pages, and keep writing until the amount of dirty
... ... @@ -952,7 +952,7 @@
952 952 }
953 953 }
954 954  
955   - throttle_vm_writeout();
  955 + throttle_vm_writeout(sc->gfp_mask);
956 956  
957 957 atomic_dec(&zone->reclaim_in_progress);
958 958 return nr_reclaimed;