From: Hugh Dickins 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; } } _