diff options
Diffstat (limited to 'mm/shmem.c')
| -rw-r--r-- | mm/shmem.c | 28 | 
1 files changed, 27 insertions, 1 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index 0f246c44a574..85bed948fafc 100644 --- a/mm/shmem.c +++ b/mm/shmem.c  | |||
| @@ -912,9 +912,13 @@ found: | |||
| 912 | error = 1; | 912 | error = 1; | 
| 913 | if (!inode) | 913 | if (!inode) | 
| 914 | goto out; | 914 | goto out; | 
| 915 | error = radix_tree_preload(GFP_KERNEL); | 915 | /* Precharge page while we can wait, compensate afterwards */ | 
| 916 | error = mem_cgroup_cache_charge(page, current->mm, GFP_KERNEL); | ||
| 916 | if (error) | 917 | if (error) | 
| 917 | goto out; | 918 | goto out; | 
| 919 | error = radix_tree_preload(GFP_KERNEL); | ||
| 920 | if (error) | ||
| 921 | goto uncharge; | ||
| 918 | error = 1; | 922 | error = 1; | 
| 919 | 923 | ||
| 920 | spin_lock(&info->lock); | 924 | spin_lock(&info->lock); | 
| @@ -947,6 +951,8 @@ found: | |||
| 947 | shmem_swp_unmap(ptr); | 951 | shmem_swp_unmap(ptr); | 
| 948 | spin_unlock(&info->lock); | 952 | spin_unlock(&info->lock); | 
| 949 | radix_tree_preload_end(); | 953 | radix_tree_preload_end(); | 
| 954 | uncharge: | ||
| 955 | mem_cgroup_uncharge_page(page); | ||
| 950 | out: | 956 | out: | 
| 951 | unlock_page(page); | 957 | unlock_page(page); | 
| 952 | page_cache_release(page); | 958 | page_cache_release(page); | 
| @@ -1308,6 +1314,13 @@ repeat: | |||
| 1308 | spin_unlock(&info->lock); | 1314 | spin_unlock(&info->lock); | 
| 1309 | unlock_page(swappage); | 1315 | unlock_page(swappage); | 
| 1310 | page_cache_release(swappage); | 1316 | page_cache_release(swappage); | 
| 1317 | if (error == -ENOMEM) { | ||
| 1318 | /* allow reclaim from this memory cgroup */ | ||
| 1319 | error = mem_cgroup_cache_charge(NULL, | ||
| 1320 | current->mm, gfp & ~__GFP_HIGHMEM); | ||
| 1321 | if (error) | ||
| 1322 | goto failed; | ||
| 1323 | } | ||
| 1311 | goto repeat; | 1324 | goto repeat; | 
| 1312 | } | 1325 | } | 
| 1313 | } else if (sgp == SGP_READ && !filepage) { | 1326 | } else if (sgp == SGP_READ && !filepage) { | 
| @@ -1353,6 +1366,17 @@ repeat: | |||
| 1353 | goto failed; | 1366 | goto failed; | 
| 1354 | } | 1367 | } | 
| 1355 | 1368 | ||
| 1369 | /* Precharge page while we can wait, compensate after */ | ||
| 1370 | error = mem_cgroup_cache_charge(filepage, current->mm, | ||
| 1371 | gfp & ~__GFP_HIGHMEM); | ||
| 1372 | if (error) { | ||
| 1373 | page_cache_release(filepage); | ||
| 1374 | shmem_unacct_blocks(info->flags, 1); | ||
| 1375 | shmem_free_blocks(inode, 1); | ||
| 1376 | filepage = NULL; | ||
| 1377 | goto failed; | ||
| 1378 | } | ||
| 1379 | |||
| 1356 | spin_lock(&info->lock); | 1380 | spin_lock(&info->lock); | 
| 1357 | entry = shmem_swp_alloc(info, idx, sgp); | 1381 | entry = shmem_swp_alloc(info, idx, sgp); | 
| 1358 | if (IS_ERR(entry)) | 1382 | if (IS_ERR(entry)) | 
| @@ -1364,6 +1388,7 @@ repeat: | |||
| 1364 | if (error || swap.val || 0 != add_to_page_cache_lru( | 1388 | if (error || swap.val || 0 != add_to_page_cache_lru( | 
| 1365 | filepage, mapping, idx, GFP_NOWAIT)) { | 1389 | filepage, mapping, idx, GFP_NOWAIT)) { | 
| 1366 | spin_unlock(&info->lock); | 1390 | spin_unlock(&info->lock); | 
| 1391 | mem_cgroup_uncharge_page(filepage); | ||
| 1367 | page_cache_release(filepage); | 1392 | page_cache_release(filepage); | 
| 1368 | shmem_unacct_blocks(info->flags, 1); | 1393 | shmem_unacct_blocks(info->flags, 1); | 
| 1369 | shmem_free_blocks(inode, 1); | 1394 | shmem_free_blocks(inode, 1); | 
| @@ -1372,6 +1397,7 @@ repeat: | |||
| 1372 | goto failed; | 1397 | goto failed; | 
| 1373 | goto repeat; | 1398 | goto repeat; | 
| 1374 | } | 1399 | } | 
| 1400 | mem_cgroup_uncharge_page(filepage); | ||
| 1375 | info->flags |= SHMEM_PAGEIN; | 1401 | info->flags |= SHMEM_PAGEIN; | 
| 1376 | } | 1402 | } | 
| 1377 | 1403 | ||
