aboutsummaryrefslogtreecommitdiffstats
path: root/mm/swapfile.c
diff options
context:
space:
mode:
authorKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>2009-01-07 21:07:58 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-08 11:31:05 -0500
commit27a7faa0779dd13729196c1a818c294f44bbd1ee (patch)
tree30837689bf39eb734a8917f2c912e1b8ac0c28c0 /mm/swapfile.c
parentc077719be8e9e6b55702117513d1b5f41d80404a (diff)
memcg: swap cgroup for remembering usage
For accounting swap, we need a record per swap entry, at least. This patch adds following function. - swap_cgroup_swapon() .... called from swapon - swap_cgroup_swapoff() ... called at the end of swapoff. - swap_cgroup_record() .... record information of swap entry. - swap_cgroup_lookup() .... lookup information of swap entry. This patch just implements "how to record information". No actual method for limit the usage of swap. These routine uses flat table to record and lookup. "wise" lookup system like radix-tree requires requires memory allocation at new records but swap-out is usually called under memory shortage (or memcg hits limit.) So, I used static allocation. (maybe dynamic allocation is not very hard but it adds additional memory allocation in memory shortage path.) Note1: In this, we use pointer to record information and this means 8bytes per swap entry. I think we can reduce this when we create "id of cgroup" in the range of 0-65535 or 0-255. Reported-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> Reviewed-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> Tested-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> Reported-by: Hugh Dickins <hugh@veritas.com> Reported-by: Balbir Singh <balbir@linux.vnet.ibm.com> Reported-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Pavel Emelianov <xemul@openvz.org> Cc: Li Zefan <lizf@cn.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/swapfile.c')
-rw-r--r--mm/swapfile.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/mm/swapfile.c b/mm/swapfile.c
index ddc6d92be2cb..1e7a715a3866 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;
@@ -1494,6 +1495,9 @@ asmlinkage long sys_swapoff(const char __user * specialfile)
1494 spin_unlock(&swap_lock); 1495 spin_unlock(&swap_lock);
1495 mutex_unlock(&swapon_mutex); 1496 mutex_unlock(&swapon_mutex);
1496 vfree(swap_map); 1497 vfree(swap_map);
1498 /* Destroy swap account informatin */
1499 swap_cgroup_swapoff(type);
1500
1497 inode = mapping->host; 1501 inode = mapping->host;
1498 if (S_ISBLK(inode->i_mode)) { 1502 if (S_ISBLK(inode->i_mode)) {
1499 struct block_device *bdev = I_BDEV(inode); 1503 struct block_device *bdev = I_BDEV(inode);
@@ -1811,6 +1815,11 @@ asmlinkage long sys_swapon(const char __user * specialfile, int swap_flags)
1811 } 1815 }
1812 swap_map[page_nr] = SWAP_MAP_BAD; 1816 swap_map[page_nr] = SWAP_MAP_BAD;
1813 } 1817 }
1818
1819 error = swap_cgroup_swapon(type, maxpages);
1820 if (error)
1821 goto bad_swap;
1822
1814 nr_good_pages = swap_header->info.last_page - 1823 nr_good_pages = swap_header->info.last_page -
1815 swap_header->info.nr_badpages - 1824 swap_header->info.nr_badpages -
1816 1 /* header page */; 1825 1 /* header page */;
@@ -1882,6 +1891,7 @@ bad_swap:
1882 bd_release(bdev); 1891 bd_release(bdev);
1883 } 1892 }
1884 destroy_swap_extents(p); 1893 destroy_swap_extents(p);
1894 swap_cgroup_swapoff(type);
1885bad_swap_2: 1895bad_swap_2:
1886 spin_lock(&swap_lock); 1896 spin_lock(&swap_lock);
1887 p->swap_file = NULL; 1897 p->swap_file = NULL;