]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
throttle_vm_writeout(): don't loop on GFP_NOFS and GFP_NOIO allocations
authorAndrew Morton <akpm@linux-foundation.org>
Thu, 1 Mar 2007 04:13:21 +0000 (20:13 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 9 Mar 2007 18:50:31 +0000 (10:50 -0800)
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
mm/page-writeback.c
mm/vmscan.c

index fc35e6bdfb93e4bf4d5cac5b50c983e97e846c5a..0c78f7f4a976489064d2508d6e56ae610bf84311 100644 (file)
@@ -84,7 +84,7 @@ static inline void wait_on_inode(struct inode *inode)
 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;
index be0efbde4994f5454198384ce274b62eb827adc4..17255ab1d380323a208b2fe8493bcc95e7bb6929 100644 (file)
@@ -296,11 +296,21 @@ void balance_dirty_pages_ratelimited_nr(struct address_space *mapping,
 }
 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.
index 7430df68cb64aaf2856c7158920442c77fe1cf27..5b4528a49df42b5515af4f926dabb9c391c8a399 100644 (file)
@@ -949,7 +949,7 @@ static unsigned long shrink_zone(int priority, struct zone *zone,
                }
        }
 
-       throttle_vm_writeout();
+       throttle_vm_writeout(sc->gfp_mask);
 
        atomic_dec(&zone->reclaim_in_progress);
        return nr_reclaimed;