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 67afba5117f2..89341b658bd0 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -643,7 +643,7 @@ static void shmem_evict_inode(struct inode *inode) | |||
643 | kfree(info->symlink); | 643 | kfree(info->symlink); |
644 | 644 | ||
645 | simple_xattrs_free(&info->xattrs); | 645 | simple_xattrs_free(&info->xattrs); |
646 | BUG_ON(inode->i_blocks); | 646 | WARN_ON(inode->i_blocks); |
647 | shmem_free_inode(inode->i_sb); | 647 | shmem_free_inode(inode->i_sb); |
648 | clear_inode(inode); | 648 | clear_inode(inode); |
649 | } | 649 | } |
@@ -1145,8 +1145,20 @@ repeat: | |||
1145 | if (!error) { | 1145 | if (!error) { |
1146 | error = shmem_add_to_page_cache(page, mapping, index, | 1146 | error = shmem_add_to_page_cache(page, mapping, index, |
1147 | gfp, swp_to_radix_entry(swap)); | 1147 | gfp, swp_to_radix_entry(swap)); |
1148 | /* We already confirmed swap, and make no allocation */ | 1148 | /* |
1149 | VM_BUG_ON(error); | 1149 | * We already confirmed swap under page lock, and make |
1150 | * no memory allocation here, so usually no possibility | ||
1151 | * of error; but free_swap_and_cache() only trylocks a | ||
1152 | * page, so it is just possible that the entry has been | ||
1153 | * truncated or holepunched since swap was confirmed. | ||
1154 | * shmem_undo_range() will have done some of the | ||
1155 | * unaccounting, now delete_from_swap_cache() will do | ||
1156 | * the rest (including mem_cgroup_uncharge_swapcache). | ||
1157 | * Reset swap.val? No, leave it so "failed" goes back to | ||
1158 | * "repeat": reading a hole and writing should succeed. | ||
1159 | */ | ||
1160 | if (error) | ||
1161 | delete_from_swap_cache(page); | ||
1150 | } | 1162 | } |
1151 | if (error) | 1163 | if (error) |
1152 | goto failed; | 1164 | goto failed; |