diff options
| -rw-r--r-- | mm/shmem.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index 67afba5117f2..dc12264f44f5 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
| @@ -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; |
