aboutsummaryrefslogtreecommitdiffstats
path: root/mm/swapfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/swapfile.c')
-rw-r--r--mm/swapfile.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c
index eec5ca758a23..da422c47e2ee 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -33,6 +33,7 @@
33#include <asm/pgtable.h> 33#include <asm/pgtable.h>
34#include <asm/tlbflush.h> 34#include <asm/tlbflush.h>
35#include <linux/swapops.h> 35#include <linux/swapops.h>
36#include <linux/page_cgroup.h>
36 37
37static DEFINE_SPINLOCK(swap_lock); 38static DEFINE_SPINLOCK(swap_lock);
38static unsigned int nr_swapfiles; 39static unsigned int nr_swapfiles;
@@ -470,8 +471,9 @@ out:
470 return NULL; 471 return NULL;
471} 472}
472 473
473static int swap_entry_free(struct swap_info_struct *p, unsigned long offset) 474static int swap_entry_free(struct swap_info_struct *p, swp_entry_t ent)
474{ 475{
476 unsigned long offset = swp_offset(ent);
475 int count = p->swap_map[offset]; 477 int count = p->swap_map[offset];
476 478
477 if (count < SWAP_MAP_MAX) { 479 if (count < SWAP_MAP_MAX) {
@@ -486,6 +488,7 @@ static int swap_entry_free(struct swap_info_struct *p, unsigned long offset)
486 swap_list.next = p - swap_info; 488 swap_list.next = p - swap_info;
487 nr_swap_pages++; 489 nr_swap_pages++;
488 p->inuse_pages--; 490 p->inuse_pages--;
491 mem_cgroup_uncharge_swap(ent);
489 } 492 }
490 } 493 }
491 return count; 494 return count;
@@ -501,7 +504,7 @@ void swap_free(swp_entry_t entry)
501 504
502 p = swap_info_get(entry); 505 p = swap_info_get(entry);
503 if (p) { 506 if (p) {
504 swap_entry_free(p, swp_offset(entry)); 507 swap_entry_free(p, entry);
505 spin_unlock(&swap_lock); 508 spin_unlock(&swap_lock);
506 } 509 }
507} 510}
@@ -581,7 +584,7 @@ int free_swap_and_cache(swp_entry_t entry)
581 584
582 p = swap_info_get(entry); 585 p = swap_info_get(entry);
583 if (p) { 586 if (p) {
584 if (swap_entry_free(p, swp_offset(entry)) == 1) { 587 if (swap_entry_free(p, entry) == 1) {
585 page = find_get_page(&swapper_space, entry.val); 588 page = find_get_page(&swapper_space, entry.val);
586 if (page && !trylock_page(page)) { 589 if (page && !trylock_page(page)) {
587 page_cache_release(page); 590 page_cache_release(page);
@@ -690,17 +693,18 @@ unsigned int count_swap_pages(int type, int free)
690static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd, 693static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
691 unsigned long addr, swp_entry_t entry, struct page *page) 694 unsigned long addr, swp_entry_t entry, struct page *page)
692{ 695{
696 struct mem_cgroup *ptr = NULL;
693 spinlock_t *ptl; 697 spinlock_t *ptl;
694 pte_t *pte; 698 pte_t *pte;
695 int ret = 1; 699 int ret = 1;
696 700
697 if (mem_cgroup_charge(page, vma->vm_mm, GFP_KERNEL)) 701 if (mem_cgroup_try_charge_swapin(vma->vm_mm, page, GFP_KERNEL, &ptr))
698 ret = -ENOMEM; 702 ret = -ENOMEM;
699 703
700 pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); 704 pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
701 if (unlikely(!pte_same(*pte, swp_entry_to_pte(entry)))) { 705 if (unlikely(!pte_same(*pte, swp_entry_to_pte(entry)))) {
702 if (ret > 0) 706 if (ret > 0)
703 mem_cgroup_uncharge_page(page); 707 mem_cgroup_cancel_charge_swapin(ptr);
704 ret = 0; 708 ret = 0;
705 goto out; 709 goto out;
706 } 710 }
@@ -710,6 +714,7 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
710 set_pte_at(vma->vm_mm, addr, pte, 714 set_pte_at(vma->vm_mm, addr, pte,
711 pte_mkold(mk_pte(page, vma->vm_page_prot))); 715 pte_mkold(mk_pte(page, vma->vm_page_prot)));
712 page_add_anon_rmap(page, vma, addr); 716 page_add_anon_rmap(page, vma, addr);
717 mem_cgroup_commit_charge_swapin(page, ptr);
713 swap_free(entry); 718 swap_free(entry);
714 /* 719 /*
715 * Move the page to the active list so it is not 720 * Move the page to the active list so it is not
@@ -1492,6 +1497,9 @@ asmlinkage long sys_swapoff(const char __user * specialfile)
1492 spin_unlock(&swap_lock); 1497 spin_unlock(&swap_lock);
1493 mutex_unlock(&swapon_mutex); 1498 mutex_unlock(&swapon_mutex);
1494 vfree(swap_map); 1499 vfree(swap_map);
1500 /* Destroy swap account informatin */
1501 swap_cgroup_swapoff(type);
1502
1495 inode = mapping->host; 1503 inode = mapping->host;
1496 if (S_ISBLK(inode->i_mode)) { 1504 if (S_ISBLK(inode->i_mode)) {
1497 struct block_device *bdev = I_BDEV(inode); 1505 struct block_device *bdev = I_BDEV(inode);
@@ -1809,6 +1817,11 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
1809 } 1817 }
1810 swap_map[page_nr] = SWAP_MAP_BAD; 1818 swap_map[page_nr] = SWAP_MAP_BAD;
1811 } 1819 }
1820
1821 error = swap_cgroup_swapon(type, maxpages);
1822 if (error)
1823 goto bad_swap;
1824
1812 nr_good_pages = swap_header->info.last_page - 1825 nr_good_pages = swap_header->info.last_page -
1813 swap_header->info.nr_badpages - 1826 swap_header->info.nr_badpages -
1814 1 /* header page */; 1827 1 /* header page */;
@@ -1880,6 +1893,7 @@ bad_swap:
1880 bd_release(bdev); 1893 bd_release(bdev);
1881 } 1894 }
1882 destroy_swap_extents(p); 1895 destroy_swap_extents(p);
1896 swap_cgroup_swapoff(type);
1883bad_swap_2: 1897bad_swap_2:
1884 spin_lock(&swap_lock); 1898 spin_lock(&swap_lock);
1885 p->swap_file = NULL; 1899 p->swap_file = NULL;