From: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
To: Linux Containers <containers@lists.osdl.org>,
Linux MM <linux-mm@kvack.org>
Cc: Balbir Singh <balbir@linux.vnet.ibm.com>,
Pavel Emelyanov <xemul@openvz.org>,
KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>,
YAMAMOTO Takashi <yamamoto@valinux.co.jp>,
Hugh Dickins <hugh@veritas.com>,
"IKEDA, Munehiro" <m-ikeda@ds.jp.nec.com>
Subject: [PATCH 3/4] swapcgroup: implement charge/uncharge
Date: Thu, 22 May 2008 15:20:05 +0900 [thread overview]
Message-ID: <48351095.3040009@mxp.nes.nec.co.jp> (raw)
In-Reply-To: <48350F15.9070007@mxp.nes.nec.co.jp>
This patch implements charge and uncharge of swapcgroup.
- what will be charged ?
charge the number of swap entries in bytes.
- when to charge/uncharge ?
charge at get_swap_entry(), and uncharge at swap_entry_free().
- to what group charge the swap entry ?
To determine to what mem_cgroup the swap entry should be charged,
I changed the argument of get_swap_entry() from (void) to
(struct page *). As a result, get_swap_entry() can determine
to what mem_cgroup it should charge the swap entry
by referring to page->page_cgroup->mem_cgroup.
- from what group uncharge the swap entry ?
I added to swap_info_struct a member 'struct swap_cgroup **',
array of pointer to which swap_cgroup the swap entry is
charged.
Signed-off-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
---
include/linux/memcontrol.h | 21 +++++++++++++++++++
include/linux/swap.h | 4 +-
mm/memcontrol.c | 47 ++++++++++++++++++++++++++++++++++++++++++++
mm/shmem.c | 2 +-
mm/swap_state.c | 2 +-
mm/swapfile.c | 14 ++++++++++++-
6 files changed, 85 insertions(+), 5 deletions(-)
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index fdf3967..a7e6621 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -24,6 +24,7 @@ struct mem_cgroup;
struct page_cgroup;
struct page;
struct mm_struct;
+struct swap_info_struct;
#ifdef CONFIG_CGROUP_MEM_RES_CTLR
@@ -172,5 +173,25 @@ static inline long mem_cgroup_calc_reclaim_inactive(struct mem_cgroup *mem,
}
#endif /* CONFIG_CGROUP_MEM_CONT */
+#ifdef CONFIG_CGROUP_SWAP_RES_CTLR
+extern int swap_cgroup_charge(struct page *page,
+ struct swap_info_struct *si,
+ unsigned long offset);
+extern void swap_cgroup_uncharge(struct swap_info_struct *si,
+ unsigned long offset);
+#else /* CONFIG_CGROUP_SWAP_RES_CTLR */
+static inline int swap_cgroup_charge(struct page *page,
+ struct swap_info_struct *si,
+ unsigned long offset)
+{
+ return 0;
+}
+
+static inline void swap_cgroup_uncharge(struct swap_info_struct *si,
+ unsigned long offset)
+{
+}
+#endif /* CONFIG_CGROUP_SWAP_RES_CTLR */
+
#endif /* _LINUX_MEMCONTROL_H */
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 67de27b..18887f0 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -241,7 +241,7 @@ extern struct page *swapin_readahead(swp_entry_t, gfp_t,
/* linux/mm/swapfile.c */
extern long total_swap_pages;
extern void si_swapinfo(struct sysinfo *);
-extern swp_entry_t get_swap_page(void);
+extern swp_entry_t get_swap_page(struct page *);
extern swp_entry_t get_swap_page_of_type(int);
extern int swap_duplicate(swp_entry_t);
extern int valid_swaphandles(swp_entry_t, unsigned long *);
@@ -342,7 +342,7 @@ static inline int remove_exclusive_swap_page(struct page *p)
return 0;
}
-static inline swp_entry_t get_swap_page(void)
+static inline swp_entry_t get_swap_page(struct page *page)
{
swp_entry_t entry;
entry.val = 0;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index a837215..84e803d 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1220,3 +1220,50 @@ struct cgroup_subsys mem_cgroup_subsys = {
.attach = mem_cgroup_move_task,
.early_init = 0,
};
+
+#ifdef CONFIG_CGROUP_SWAP_RES_CTLR
+int swap_cgroup_charge(struct page *page,
+ struct swap_info_struct *si,
+ unsigned long offset)
+{
+ int ret;
+ struct page_cgroup *pc;
+ struct mem_cgroup *mem;
+
+ lock_page_cgroup(page);
+ pc = page_get_page_cgroup(page);
+ if (unlikely(!pc))
+ mem = &init_mem_cgroup;
+ else
+ mem = pc->mem_cgroup;
+ unlock_page_cgroup(page);
+
+ css_get(&mem->css);
+ ret = res_counter_charge(&mem->swap_res, PAGE_SIZE);
+ if (!ret)
+ si->memcg[offset] = mem;
+ else
+ css_put(&mem->css);
+
+ return ret;
+}
+
+void swap_cgroup_uncharge(struct swap_info_struct *si,
+ unsigned long offset)
+{
+ struct mem_cgroup *mem = si->memcg[offset];
+
+ /* "mem" would be NULL:
+ * 1. when get_swap_page() failed at charging swap_cgroup,
+ * and called swap_entry_free().
+ * 2. when this swap entry had been assigned by
+ * get_swap_page_of_type() (via SWSUSP?).
+ */
+ if (mem) {
+ res_counter_uncharge(&mem->swap_res, PAGE_SIZE);
+ si->memcg[offset] = NULL;
+ css_put(&mem->css);
+ }
+}
+#endif
+
diff --git a/mm/shmem.c b/mm/shmem.c
index 95b056d..69f8909 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1029,7 +1029,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
* want to check if there's a redundant swappage to be discarded.
*/
if (wbc->for_reclaim)
- swap = get_swap_page();
+ swap = get_swap_page(page);
else
swap.val = 0;
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 676e191..a78d617 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -130,7 +130,7 @@ int add_to_swap(struct page * page, gfp_t gfp_mask)
BUG_ON(!PageUptodate(page));
for (;;) {
- entry = get_swap_page();
+ entry = get_swap_page(page);
if (!entry.val)
return 0;
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 232bf20..682b71e 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -172,7 +172,10 @@ no_page:
return 0;
}
-swp_entry_t get_swap_page(void)
+/* get_swap_page() calls this */
+static int swap_entry_free(struct swap_info_struct *, unsigned long);
+
+swp_entry_t get_swap_page(struct page *page)
{
struct swap_info_struct *si;
pgoff_t offset;
@@ -201,6 +204,14 @@ swp_entry_t get_swap_page(void)
swap_list.next = next;
offset = scan_swap_map(si);
if (offset) {
+ /*
+ * This should be the first use of this swap entry.
+ * So, charge this swap entry here.
+ */
+ if (swap_cgroup_charge(page, si, offset)) {
+ swap_entry_free(si, offset);
+ goto noswap;
+ }
spin_unlock(&swap_lock);
return swp_entry(type, offset);
}
@@ -285,6 +296,7 @@ static int swap_entry_free(struct swap_info_struct *p, unsigned long offset)
swap_list.next = p - swap_info;
nr_swap_pages++;
p->inuse_pages--;
+ swap_cgroup_uncharge(p, offset);
}
}
return count;
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2008-05-22 6:20 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-05-22 6:13 [PATCH 0/4] swapcgroup(v2) Daisuke Nishimura
2008-05-22 6:17 ` [PATCH 1/4] swapcgroup: add cgroup files Daisuke Nishimura
2008-05-22 6:18 ` [PATCH 2/4] swapcgroup: add member to swap_info_struct for cgroup Daisuke Nishimura
2008-05-22 7:23 ` KAMEZAWA Hiroyuki
2008-05-22 8:46 ` Daisuke Nishimura
2008-05-22 9:35 ` KAMEZAWA Hiroyuki
2008-05-22 6:20 ` Daisuke Nishimura [this message]
2008-05-22 7:37 ` [PATCH 3/4] swapcgroup: implement charge/uncharge KAMEZAWA Hiroyuki
2008-05-23 11:52 ` Daisuke Nishimura
2008-05-26 0:57 ` KAMEZAWA Hiroyuki
2008-05-27 13:42 ` KAMEZAWA Hiroyuki
2008-05-22 6:22 ` [PATCH 4/4] swapcgroup: modify vm_swap_full for cgroup Daisuke Nishimura
2008-05-22 6:45 ` YAMAMOTO Takashi
2008-05-22 12:34 ` Daisuke Nishimura
2008-05-25 23:35 ` YAMAMOTO Takashi
2008-05-22 7:39 ` KAMEZAWA Hiroyuki
2008-05-22 8:00 ` KOSAKI Motohiro
2008-05-22 12:22 ` Daisuke Nishimura
2008-05-22 12:32 ` KOSAKI Motohiro
2008-05-23 12:26 ` Daisuke Nishimura
2008-05-22 7:44 ` [PATCH 0/4] swapcgroup(v2) KAMEZAWA Hiroyuki
2008-05-23 2:10 ` Daisuke Nishimura
2008-05-23 2:42 ` Daisuke Nishimura
2008-05-22 21:27 ` Balbir Singh
2008-05-23 4:27 ` Daisuke Nishimura
2008-05-27 7:31 ` YAMAMOTO Takashi
2008-05-27 7:42 ` Balbir Singh
2008-05-27 8:30 ` Daisuke Nishimura
2008-05-27 13:18 ` Balbir Singh
2008-05-27 13:42 ` Daisuke Nishimura
2008-05-27 13:46 ` Balbir Singh
2008-05-27 14:00 ` Daisuke Nishimura
2008-05-23 2:26 ` Rik van Riel
2008-05-23 3:10 ` KAMEZAWA Hiroyuki
2008-05-23 3:32 ` Rik van Riel
2008-05-23 3:59 ` Balbir Singh
2008-05-23 4:30 ` KOSAKI Motohiro
2008-05-23 4:51 ` Balbir Singh
2008-05-23 5:23 ` KAMEZAWA Hiroyuki
2008-05-23 5:29 ` David Singleton
2008-05-23 6:00 ` KOSAKI Motohiro
2008-05-23 6:45 ` Balbir Singh
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=48351095.3040009@mxp.nes.nec.co.jp \
--to=nishimura@mxp.nes.nec.co.jp \
--cc=balbir@linux.vnet.ibm.com \
--cc=containers@lists.osdl.org \
--cc=hugh@veritas.com \
--cc=kamezawa.hiroyu@jp.fujitsu.com \
--cc=linux-mm@kvack.org \
--cc=m-ikeda@ds.jp.nec.com \
--cc=xemul@openvz.org \
--cc=yamamoto@valinux.co.jp \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox