|
@@ -912,9 +912,13 @@ found:
|
|
|
error = 1;
|
|
|
if (!inode)
|
|
|
goto out;
|
|
|
- error = radix_tree_preload(GFP_KERNEL);
|
|
|
+ /* Precharge page while we can wait, compensate afterwards */
|
|
|
+ error = mem_cgroup_cache_charge(page, current->mm, GFP_KERNEL);
|
|
|
if (error)
|
|
|
goto out;
|
|
|
+ error = radix_tree_preload(GFP_KERNEL);
|
|
|
+ if (error)
|
|
|
+ goto uncharge;
|
|
|
error = 1;
|
|
|
|
|
|
spin_lock(&info->lock);
|
|
@@ -947,6 +951,8 @@ found:
|
|
|
shmem_swp_unmap(ptr);
|
|
|
spin_unlock(&info->lock);
|
|
|
radix_tree_preload_end();
|
|
|
+uncharge:
|
|
|
+ mem_cgroup_uncharge_page(page);
|
|
|
out:
|
|
|
unlock_page(page);
|
|
|
page_cache_release(page);
|
|
@@ -1308,6 +1314,13 @@ repeat:
|
|
|
spin_unlock(&info->lock);
|
|
|
unlock_page(swappage);
|
|
|
page_cache_release(swappage);
|
|
|
+ if (error == -ENOMEM) {
|
|
|
+ /* allow reclaim from this memory cgroup */
|
|
|
+ error = mem_cgroup_cache_charge(NULL,
|
|
|
+ current->mm, gfp & ~__GFP_HIGHMEM);
|
|
|
+ if (error)
|
|
|
+ goto failed;
|
|
|
+ }
|
|
|
goto repeat;
|
|
|
}
|
|
|
} else if (sgp == SGP_READ && !filepage) {
|
|
@@ -1353,6 +1366,17 @@ repeat:
|
|
|
goto failed;
|
|
|
}
|
|
|
|
|
|
+ /* Precharge page while we can wait, compensate after */
|
|
|
+ error = mem_cgroup_cache_charge(filepage, current->mm,
|
|
|
+ gfp & ~__GFP_HIGHMEM);
|
|
|
+ if (error) {
|
|
|
+ page_cache_release(filepage);
|
|
|
+ shmem_unacct_blocks(info->flags, 1);
|
|
|
+ shmem_free_blocks(inode, 1);
|
|
|
+ filepage = NULL;
|
|
|
+ goto failed;
|
|
|
+ }
|
|
|
+
|
|
|
spin_lock(&info->lock);
|
|
|
entry = shmem_swp_alloc(info, idx, sgp);
|
|
|
if (IS_ERR(entry))
|
|
@@ -1364,6 +1388,7 @@ repeat:
|
|
|
if (error || swap.val || 0 != add_to_page_cache_lru(
|
|
|
filepage, mapping, idx, GFP_NOWAIT)) {
|
|
|
spin_unlock(&info->lock);
|
|
|
+ mem_cgroup_uncharge_page(filepage);
|
|
|
page_cache_release(filepage);
|
|
|
shmem_unacct_blocks(info->flags, 1);
|
|
|
shmem_free_blocks(inode, 1);
|
|
@@ -1372,6 +1397,7 @@ repeat:
|
|
|
goto failed;
|
|
|
goto repeat;
|
|
|
}
|
|
|
+ mem_cgroup_uncharge_page(filepage);
|
|
|
info->flags |= SHMEM_PAGEIN;
|
|
|
}
|
|
|
|