forked from mirrors/linux
		
	tmpfs: change final i_blocks BUG to WARNING
Under a particular load on one machine, I have hit shmem_evict_inode()'s BUG_ON(inode->i_blocks), enough times to narrow it down to a particular race between swapout and eviction. It comes from the "if (freed > 0)" asymmetry in shmem_recalc_inode(), and the lack of coherent locking between mapping's nrpages and shmem's swapped count. There's a window in shmem_writepage(), between lowering nrpages in shmem_delete_from_page_cache() and then raising swapped count, when the freed count appears to be +1 when it should be 0, and then the asymmetry stops it from being corrected with -1 before hitting the BUG. One answer is coherent locking: using tree_lock throughout, without info->lock; reasonable, but the raw_spin_lock in percpu_counter_add() on used_blocks makes that messier than expected. Another answer may be a further effort to eliminate the weird shmem_recalc_inode() altogether, but previous attempts at that failed. So far undecided, but for now change the BUG_ON to WARN_ON: in usual circumstances it remains a useful consistency check. Signed-off-by: Hugh Dickins <hughd@google.com> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									215c02bc33
								
							
						
					
					
						commit
						0f3c42f522
					
				
					 1 changed files with 1 additions and 1 deletions
				
			
		| 
						 | 
					@ -643,7 +643,7 @@ static void shmem_evict_inode(struct inode *inode)
 | 
				
			||||||
		kfree(info->symlink);
 | 
							kfree(info->symlink);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	simple_xattrs_free(&info->xattrs);
 | 
						simple_xattrs_free(&info->xattrs);
 | 
				
			||||||
	BUG_ON(inode->i_blocks);
 | 
						WARN_ON(inode->i_blocks);
 | 
				
			||||||
	shmem_free_inode(inode->i_sb);
 | 
						shmem_free_inode(inode->i_sb);
 | 
				
			||||||
	clear_inode(inode);
 | 
						clear_inode(inode);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue