
From: Hugh Dickins <hugh@veritas.com>

move_from_swap_cache and add_to_page_cache_lru are using GFP_ATOMIC,
which can easily fail in an intermittent way.  Rude if shmem_getpage
then fails with -ENOMEM: cond_resched to let kswapd in, and repeat.



 25-akpm/mm/shmem.c |   16 ++++++++--------
 1 files changed, 8 insertions(+), 8 deletions(-)

diff -puN mm/shmem.c~hugh-10-tmpfs-atomics mm/shmem.c
--- 25/mm/shmem.c~hugh-10-tmpfs-atomics	Tue Mar 25 18:34:58 2003
+++ 25-akpm/mm/shmem.c	Tue Mar 25 18:34:58 2003
@@ -838,8 +838,7 @@ repeat:
 			SetPageUptodate(filepage);
 			set_page_dirty(filepage);
 			swap_free(swap);
-		} else if (!(error = move_from_swap_cache(
-				swappage, idx, mapping))) {
+		} else if (move_from_swap_cache(swappage, idx, mapping) == 0) {
 			shmem_swp_set(info, entry, 0);
 			shmem_swp_unmap(entry);
 			spin_unlock(&info->lock);
@@ -850,8 +849,8 @@ repeat:
 			spin_unlock(&info->lock);
 			unlock_page(swappage);
 			page_cache_release(swappage);
-			if (error != -EEXIST)
-				goto failed;
+			/* let kswapd refresh zone for GFP_ATOMICs */
+			cond_resched();
 			goto repeat;
 		}
 	} else if (sgp == SGP_READ && !filepage) {
@@ -897,15 +896,16 @@ repeat:
 				swap = *entry;
 				shmem_swp_unmap(entry);
 			}
-			if (error || swap.val ||
-			    (error = add_to_page_cache_lru(
-					filepage, mapping, idx, GFP_ATOMIC))) {
+			if (error || swap.val || 0 != add_to_page_cache_lru(
+					filepage, mapping, idx, GFP_ATOMIC)) {
 				spin_unlock(&info->lock);
 				page_cache_release(filepage);
 				shmem_free_block(inode);
 				filepage = NULL;
-				if (error != -EEXIST)
+				if (error)
 					goto failed;
+				/* let kswapd refresh zone for GFP_ATOMICs */
+				cond_resched();
 				goto repeat;
 			}
 		}

_
