diff options
| author | Takashi Iwai <tiwai@suse.de> | 2012-01-31 15:13:14 +0100 | 
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2012-01-31 15:13:14 +0100 | 
| commit | ea51e5040e24eefe44d70bc654a237ca1f0225b0 (patch) | |
| tree | df2e5922dcdfafae62a10d8cd97f98121064fc23 /kernel/futex.c | |
| parent | 3422a47041b8cb8f14ac1e3926bcf711121df6dc (diff) | |
| parent | 8dbd52daee38adaae4d5a674bcca837e694a4f4c (diff) | |
Merge branch 'fix/asoc' into for-linus
Diffstat (limited to 'kernel/futex.c')
| -rw-r--r-- | kernel/futex.c | 28 | 
1 files changed, 20 insertions, 8 deletions
| diff --git a/kernel/futex.c b/kernel/futex.c index ea87f4d2f455..1614be20173d 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -314,17 +314,29 @@ again:  #endif  	lock_page(page_head); + +	/* +	 * If page_head->mapping is NULL, then it cannot be a PageAnon +	 * page; but it might be the ZERO_PAGE or in the gate area or +	 * in a special mapping (all cases which we are happy to fail); +	 * or it may have been a good file page when get_user_pages_fast +	 * found it, but truncated or holepunched or subjected to +	 * invalidate_complete_page2 before we got the page lock (also +	 * cases which we are happy to fail).  And we hold a reference, +	 * so refcount care in invalidate_complete_page's remove_mapping +	 * prevents drop_caches from setting mapping to NULL beneath us. +	 * +	 * The case we do have to guard against is when memory pressure made +	 * shmem_writepage move it from filecache to swapcache beneath us: +	 * an unlikely race, but we do need to retry for page_head->mapping. +	 */  	if (!page_head->mapping) { +		int shmem_swizzled = PageSwapCache(page_head);  		unlock_page(page_head);  		put_page(page_head); -		/* -		* ZERO_PAGE pages don't have a mapping. Avoid a busy loop -		* trying to find one. RW mapping would have COW'd (and thus -		* have a mapping) so this page is RO and won't ever change. -		*/ -		if ((page_head == ZERO_PAGE(address))) -			return -EFAULT; -		goto again; +		if (shmem_swizzled) +			goto again; +		return -EFAULT;  	}  	/* | 
