diff options
author | KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> | 2009-04-02 19:57:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-02 22:04:56 -0400 |
commit | a3b2d692690aef228e493b1beaafe5364cab3237 (patch) | |
tree | d3ad99c5370462861a1b918b4136e7bd7ad78e52 /mm/page_cgroup.c | |
parent | 3c776e64660028236313f0e54f3a9945764422df (diff) |
cgroups: use css id in swap cgroup for saving memory v5
Try to use CSS ID for records in swap_cgroup. By this, on 64bit machine,
size of swap_cgroup goes down to 2 bytes from 8bytes.
This means, when 2GB of swap is equipped, (assume the page size is 4096bytes)
From size of swap_cgroup = 2G/4k * 8 = 4Mbytes.
To size of swap_cgroup = 2G/4k * 2 = 1Mbytes.
Reduction is large. Of course, there are trade-offs. This CSS ID will
add overhead to swap-in/swap-out/swap-free.
But in general,
- swap is a resource which the user tend to avoid use.
- If swap is never used, swap_cgroup area is not used.
- Reading traditional manuals, size of swap should be proportional to
size of memory. Memory size of machine is increasing now.
I think reducing size of swap_cgroup makes sense.
Note:
- ID->CSS lookup routine has no locks, it's under RCU-Read-Side.
- memcg can be obsolete at rmdir() but not freed while refcnt from
swap_cgroup is available.
Changelog v4->v5:
- reworked on to memcg-charge-swapcache-to-proper-memcg.patch
Changlog ->v4:
- fixed not configured case.
- deleted unnecessary comments.
- fixed NULL pointer bug.
- fixed message in dmesg.
[nishimura@mxp.nes.nec.co.jp: css_tryget can be called twice in !PageCgroupUsed case]
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Li Zefan <lizf@cn.fujitsu.com>
Cc: Balbir Singh <balbir@in.ibm.com>
Cc: Paul Menage <menage@google.com>
Cc: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/page_cgroup.c')
-rw-r--r-- | mm/page_cgroup.c | 32 |
1 files changed, 14 insertions, 18 deletions
diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c index ceecfbb143fa..ebf81074bed4 100644 --- a/mm/page_cgroup.c +++ b/mm/page_cgroup.c | |||
@@ -285,12 +285,8 @@ struct swap_cgroup_ctrl { | |||
285 | 285 | ||
286 | struct swap_cgroup_ctrl swap_cgroup_ctrl[MAX_SWAPFILES]; | 286 | struct swap_cgroup_ctrl swap_cgroup_ctrl[MAX_SWAPFILES]; |
287 | 287 | ||
288 | /* | ||
289 | * This 8bytes seems big..maybe we can reduce this when we can use "id" for | ||
290 | * cgroup rather than pointer. | ||
291 | */ | ||
292 | struct swap_cgroup { | 288 | struct swap_cgroup { |
293 | struct mem_cgroup *val; | 289 | unsigned short id; |
294 | }; | 290 | }; |
295 | #define SC_PER_PAGE (PAGE_SIZE/sizeof(struct swap_cgroup)) | 291 | #define SC_PER_PAGE (PAGE_SIZE/sizeof(struct swap_cgroup)) |
296 | #define SC_POS_MASK (SC_PER_PAGE - 1) | 292 | #define SC_POS_MASK (SC_PER_PAGE - 1) |
@@ -342,10 +338,10 @@ not_enough_page: | |||
342 | * @ent: swap entry to be recorded into | 338 | * @ent: swap entry to be recorded into |
343 | * @mem: mem_cgroup to be recorded | 339 | * @mem: mem_cgroup to be recorded |
344 | * | 340 | * |
345 | * Returns old value at success, NULL at failure. | 341 | * Returns old value at success, 0 at failure. |
346 | * (Of course, old value can be NULL.) | 342 | * (Of course, old value can be 0.) |
347 | */ | 343 | */ |
348 | struct mem_cgroup *swap_cgroup_record(swp_entry_t ent, struct mem_cgroup *mem) | 344 | unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id) |
349 | { | 345 | { |
350 | int type = swp_type(ent); | 346 | int type = swp_type(ent); |
351 | unsigned long offset = swp_offset(ent); | 347 | unsigned long offset = swp_offset(ent); |
@@ -354,18 +350,18 @@ struct mem_cgroup *swap_cgroup_record(swp_entry_t ent, struct mem_cgroup *mem) | |||
354 | struct swap_cgroup_ctrl *ctrl; | 350 | struct swap_cgroup_ctrl *ctrl; |
355 | struct page *mappage; | 351 | struct page *mappage; |
356 | struct swap_cgroup *sc; | 352 | struct swap_cgroup *sc; |
357 | struct mem_cgroup *old; | 353 | unsigned short old; |
358 | 354 | ||
359 | if (!do_swap_account) | 355 | if (!do_swap_account) |
360 | return NULL; | 356 | return 0; |
361 | 357 | ||
362 | ctrl = &swap_cgroup_ctrl[type]; | 358 | ctrl = &swap_cgroup_ctrl[type]; |
363 | 359 | ||
364 | mappage = ctrl->map[idx]; | 360 | mappage = ctrl->map[idx]; |
365 | sc = page_address(mappage); | 361 | sc = page_address(mappage); |
366 | sc += pos; | 362 | sc += pos; |
367 | old = sc->val; | 363 | old = sc->id; |
368 | sc->val = mem; | 364 | sc->id = id; |
369 | 365 | ||
370 | return old; | 366 | return old; |
371 | } | 367 | } |
@@ -374,9 +370,9 @@ struct mem_cgroup *swap_cgroup_record(swp_entry_t ent, struct mem_cgroup *mem) | |||
374 | * lookup_swap_cgroup - lookup mem_cgroup tied to swap entry | 370 | * lookup_swap_cgroup - lookup mem_cgroup tied to swap entry |
375 | * @ent: swap entry to be looked up. | 371 | * @ent: swap entry to be looked up. |
376 | * | 372 | * |
377 | * Returns pointer to mem_cgroup at success. NULL at failure. | 373 | * Returns CSS ID of mem_cgroup at success. 0 at failure. (0 is invalid ID) |
378 | */ | 374 | */ |
379 | struct mem_cgroup *lookup_swap_cgroup(swp_entry_t ent) | 375 | unsigned short lookup_swap_cgroup(swp_entry_t ent) |
380 | { | 376 | { |
381 | int type = swp_type(ent); | 377 | int type = swp_type(ent); |
382 | unsigned long offset = swp_offset(ent); | 378 | unsigned long offset = swp_offset(ent); |
@@ -385,16 +381,16 @@ struct mem_cgroup *lookup_swap_cgroup(swp_entry_t ent) | |||
385 | struct swap_cgroup_ctrl *ctrl; | 381 | struct swap_cgroup_ctrl *ctrl; |
386 | struct page *mappage; | 382 | struct page *mappage; |
387 | struct swap_cgroup *sc; | 383 | struct swap_cgroup *sc; |
388 | struct mem_cgroup *ret; | 384 | unsigned short ret; |
389 | 385 | ||
390 | if (!do_swap_account) | 386 | if (!do_swap_account) |
391 | return NULL; | 387 | return 0; |
392 | 388 | ||
393 | ctrl = &swap_cgroup_ctrl[type]; | 389 | ctrl = &swap_cgroup_ctrl[type]; |
394 | mappage = ctrl->map[idx]; | 390 | mappage = ctrl->map[idx]; |
395 | sc = page_address(mappage); | 391 | sc = page_address(mappage); |
396 | sc += pos; | 392 | sc += pos; |
397 | ret = sc->val; | 393 | ret = sc->id; |
398 | return ret; | 394 | return ret; |
399 | } | 395 | } |
400 | 396 | ||
@@ -432,7 +428,7 @@ int swap_cgroup_swapon(int type, unsigned long max_pages) | |||
432 | 428 | ||
433 | printk(KERN_INFO | 429 | printk(KERN_INFO |
434 | "swap_cgroup: uses %ld bytes of vmalloc for pointer array space" | 430 | "swap_cgroup: uses %ld bytes of vmalloc for pointer array space" |
435 | " and %ld bytes to hold mem_cgroup pointers on swap\n", | 431 | " and %ld bytes to hold mem_cgroup information per swap ents\n", |
436 | array_size, length * PAGE_SIZE); | 432 | array_size, length * PAGE_SIZE); |
437 | printk(KERN_INFO | 433 | printk(KERN_INFO |
438 | "swap_cgroup can be disabled by noswapaccount boot option.\n"); | 434 | "swap_cgroup can be disabled by noswapaccount boot option.\n"); |