aboutsummaryrefslogtreecommitdiff
path: root/mm
diff options
context:
space:
mode:
authorHugh Dickins <hughd@google.com>2012-11-16 14:15:04 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-11-26 12:14:19 -0800
commit347bd4501eec64db816bcd2438e38784f0107041 (patch)
tree8ce6c93bf699a4675ccb99cfa42d91ce0d52c327 /mm
parente7c1a252a7236c6a318c703a1bf29e3261a44e9c (diff)
tmpfs: change final i_blocks BUG to WARNING
commit 0f3c42f522dc1ad7e27affc0a4aa8c790bce0a66 upstream. 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> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/shmem.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/mm/shmem.c b/mm/shmem.c
index 4ae737ebf820..31e1506eb5cd 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -654,7 +654,7 @@ static void shmem_evict_inode(struct inode *inode)
kfree(xattr->name);
kfree(xattr);
}
- BUG_ON(inode->i_blocks);
+ WARN_ON(inode->i_blocks);
shmem_free_inode(inode->i_sb);
clear_inode(inode);
}