|
@@ -1269,9 +1269,9 @@ repeat:
|
|
|
goto failed;
|
|
|
radix_tree_preload_end();
|
|
|
if (sgp != SGP_READ && !prealloc_page) {
|
|
|
- /* We don't care if this fails */
|
|
|
prealloc_page = shmem_alloc_page(gfp, info, idx);
|
|
|
if (prealloc_page) {
|
|
|
+ SetPageSwapBacked(prealloc_page);
|
|
|
if (mem_cgroup_cache_charge(prealloc_page,
|
|
|
current->mm, GFP_KERNEL)) {
|
|
|
page_cache_release(prealloc_page);
|
|
@@ -1403,7 +1403,8 @@ repeat:
|
|
|
goto repeat;
|
|
|
}
|
|
|
spin_unlock(&info->lock);
|
|
|
- } else {
|
|
|
+
|
|
|
+ } else if (prealloc_page) {
|
|
|
shmem_swp_unmap(entry);
|
|
|
sbinfo = SHMEM_SB(inode->i_sb);
|
|
|
if (sbinfo->max_blocks) {
|
|
@@ -1419,41 +1420,8 @@ repeat:
|
|
|
if (!filepage) {
|
|
|
int ret;
|
|
|
|
|
|
- if (!prealloc_page) {
|
|
|
- spin_unlock(&info->lock);
|
|
|
- filepage = shmem_alloc_page(gfp, info, idx);
|
|
|
- if (!filepage) {
|
|
|
- spin_lock(&info->lock);
|
|
|
- shmem_unacct_blocks(info->flags, 1);
|
|
|
- shmem_free_blocks(inode, 1);
|
|
|
- spin_unlock(&info->lock);
|
|
|
- error = -ENOMEM;
|
|
|
- goto failed;
|
|
|
- }
|
|
|
- SetPageSwapBacked(filepage);
|
|
|
-
|
|
|
- /*
|
|
|
- * Precharge page while we can wait, compensate
|
|
|
- * after
|
|
|
- */
|
|
|
- error = mem_cgroup_cache_charge(filepage,
|
|
|
- current->mm, GFP_KERNEL);
|
|
|
- if (error) {
|
|
|
- page_cache_release(filepage);
|
|
|
- spin_lock(&info->lock);
|
|
|
- shmem_unacct_blocks(info->flags, 1);
|
|
|
- shmem_free_blocks(inode, 1);
|
|
|
- spin_unlock(&info->lock);
|
|
|
- filepage = NULL;
|
|
|
- goto failed;
|
|
|
- }
|
|
|
-
|
|
|
- spin_lock(&info->lock);
|
|
|
- } else {
|
|
|
- filepage = prealloc_page;
|
|
|
- prealloc_page = NULL;
|
|
|
- SetPageSwapBacked(filepage);
|
|
|
- }
|
|
|
+ filepage = prealloc_page;
|
|
|
+ prealloc_page = NULL;
|
|
|
|
|
|
entry = shmem_swp_alloc(info, idx, sgp, gfp);
|
|
|
if (IS_ERR(entry))
|
|
@@ -1492,11 +1460,20 @@ repeat:
|
|
|
SetPageUptodate(filepage);
|
|
|
if (sgp == SGP_DIRTY)
|
|
|
set_page_dirty(filepage);
|
|
|
+ } else {
|
|
|
+ spin_unlock(&info->lock);
|
|
|
+ error = -ENOMEM;
|
|
|
+ goto out;
|
|
|
}
|
|
|
done:
|
|
|
*pagep = filepage;
|
|
|
error = 0;
|
|
|
- goto out;
|
|
|
+out:
|
|
|
+ if (prealloc_page) {
|
|
|
+ mem_cgroup_uncharge_cache_page(prealloc_page);
|
|
|
+ page_cache_release(prealloc_page);
|
|
|
+ }
|
|
|
+ return error;
|
|
|
|
|
|
nospace:
|
|
|
/*
|
|
@@ -1520,12 +1497,7 @@ failed:
|
|
|
unlock_page(filepage);
|
|
|
page_cache_release(filepage);
|
|
|
}
|
|
|
-out:
|
|
|
- if (prealloc_page) {
|
|
|
- mem_cgroup_uncharge_cache_page(prealloc_page);
|
|
|
- page_cache_release(prealloc_page);
|
|
|
- }
|
|
|
- return error;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|