diff options
Diffstat (limited to 'mm/shmem.c')
| -rw-r--r-- | mm/shmem.c | 18 | 
1 files changed, 15 insertions, 3 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index 67afba5117f..89341b658bd 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -643,7 +643,7 @@ static void shmem_evict_inode(struct inode *inode)  		kfree(info->symlink);  	simple_xattrs_free(&info->xattrs); -	BUG_ON(inode->i_blocks); +	WARN_ON(inode->i_blocks);  	shmem_free_inode(inode->i_sb);  	clear_inode(inode);  } @@ -1145,8 +1145,20 @@ repeat:  		if (!error) {  			error = shmem_add_to_page_cache(page, mapping, index,  						gfp, swp_to_radix_entry(swap)); -			/* We already confirmed swap, and make no allocation */ -			VM_BUG_ON(error); +			/* +			 * We already confirmed swap under page lock, and make +			 * no memory allocation here, so usually no possibility +			 * of error; but free_swap_and_cache() only trylocks a +			 * page, so it is just possible that the entry has been +			 * truncated or holepunched since swap was confirmed. +			 * shmem_undo_range() will have done some of the +			 * unaccounting, now delete_from_swap_cache() will do +			 * the rest (including mem_cgroup_uncharge_swapcache). +			 * Reset swap.val? No, leave it so "failed" goes back to +			 * "repeat": reading a hole and writing should succeed. +			 */ +			if (error) +				delete_from_swap_cache(page);  		}  		if (error)  			goto failed;  |