From 4d730c35200c4b9a0ce31c9b95cb1a2030ad2139 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Mon, 9 Aug 2010 17:19:06 -0700 Subject: [PATCH] --- yaml --- r: 207231 b: refs/heads/master c: ff36b801624d02a876bb7deded6ab860ea3503f2 h: refs/heads/master i: 207229: f74ba0bb7d1a7230b1285a3b2c3c80cf4be8f595 207227: ea76ec19e7d6369b34b5f6adf10183399b78141d 207223: f56ed7325192cb6da6a3339a19ad14b21e18720c 207215: f2a7a3f99bb7b34e15307d69bfe2b720823c8132 207199: b8e849a3885753eb501d242d18a6644156991207 207167: 627dc00dc8f25a04c10b99fb1ec40e2daca7ce9c 207103: 016038080b2bd131dce11acc1a25239d1e261b7c v: v3 --- [refs] | 2 +- trunk/mm/shmem.c | 70 +++++++++++++++++++++++++++++++++--------------- 2 files changed, 50 insertions(+), 22 deletions(-) diff --git a/[refs] b/[refs] index c71090b20fd1..766d6e9b0f5e 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 7e496299d4d2ad8083effed6c5a18313a919edc6 +refs/heads/master: ff36b801624d02a876bb7deded6ab860ea3503f2 diff --git a/trunk/mm/shmem.c b/trunk/mm/shmem.c index 0618fdad406c..566f9a481e64 100644 --- a/trunk/mm/shmem.c +++ b/trunk/mm/shmem.c @@ -1222,6 +1222,7 @@ static int shmem_getpage(struct inode *inode, unsigned long idx, struct shmem_sb_info *sbinfo; struct page *filepage = *pagep; struct page *swappage; + struct page *prealloc_page = NULL; swp_entry_t *entry; swp_entry_t swap; gfp_t gfp; @@ -1246,7 +1247,6 @@ static int shmem_getpage(struct inode *inode, unsigned long idx, filepage = find_lock_page(mapping, idx); if (filepage && PageUptodate(filepage)) goto done; - error = 0; gfp = mapping_gfp_mask(mapping); if (!filepage) { /* @@ -1257,7 +1257,19 @@ static int shmem_getpage(struct inode *inode, unsigned long idx, if (error) 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) { + if (mem_cgroup_cache_charge(prealloc_page, + current->mm, GFP_KERNEL)) { + page_cache_release(prealloc_page); + prealloc_page = NULL; + } + } + } } + error = 0; spin_lock(&info->lock); shmem_recalc_inode(inode); @@ -1405,28 +1417,38 @@ static int shmem_getpage(struct inode *inode, unsigned long idx, if (!filepage) { int ret; - spin_unlock(&info->lock); - filepage = shmem_alloc_page(gfp, info, idx); - if (!filepage) { - shmem_unacct_blocks(info->flags, 1); - shmem_free_blocks(inode, 1); - error = -ENOMEM; - goto failed; - } - SetPageSwapBacked(filepage); + if (!prealloc_page) { + spin_unlock(&info->lock); + filepage = shmem_alloc_page(gfp, info, idx); + if (!filepage) { + shmem_unacct_blocks(info->flags, 1); + shmem_free_blocks(inode, 1); + 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); - shmem_unacct_blocks(info->flags, 1); - shmem_free_blocks(inode, 1); - filepage = NULL; - goto failed; + /* + * Precharge page while we can wait, compensate + * after + */ + error = mem_cgroup_cache_charge(filepage, + current->mm, GFP_KERNEL); + 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); + } else { + filepage = prealloc_page; + prealloc_page = NULL; + SetPageSwapBacked(filepage); } - spin_lock(&info->lock); entry = shmem_swp_alloc(info, idx, sgp); if (IS_ERR(entry)) error = PTR_ERR(entry); @@ -1467,13 +1489,19 @@ static int shmem_getpage(struct inode *inode, unsigned long idx, } done: *pagep = filepage; - return 0; + error = 0; + goto out; failed: if (*pagep != filepage) { 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; }