02 Oct, 2009

3 commits

  • In charge/uncharge/reclaim path, usage_in_excess is calculated repeatedly
    and it takes res_counter's spin_lock every time.

    This patch removes unnecessary calls for res_count_soft_limit_excess.

    Reviewed-by: Daisuke Nishimura
    Signed-off-by: KAMEZAWA Hiroyuki
    Cc: Paul Menage
    Cc: Li Zefan
    Cc: Balbir Singh
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    KAMEZAWA Hiroyuki
     
  • This patch clean up/fixes for memcg's uncharge soft limit path.

    Problems:
    Now, res_counter_charge()/uncharge() handles softlimit information at
    charge/uncharge and softlimit-check is done when event counter per memcg
    goes over limit. Now, event counter per memcg is updated only when
    memory usage is over soft limit. Here, considering hierarchical memcg
    management, ancesotors should be taken care of.

    Now, ancerstors(hierarchy) are handled in charge() but not in uncharge().
    This is not good.

    Prolems:
    1. memcg's event counter incremented only when softlimit hits. That's bad.
    It makes event counter hard to be reused for other purpose.

    2. At uncharge, only the lowest level rescounter is handled. This is bug.
    Because ancesotor's event counter is not incremented, children should
    take care of them.

    3. res_counter_uncharge()'s 3rd argument is NULL in most case.
    ops under res_counter->lock should be small. No "if" sentense is better.

    Fixes:
    * Removed soft_limit_xx poitner and checks in charge and uncharge.
    Do-check-only-when-necessary scheme works enough well without them.

    * make event-counter of memcg incremented at every charge/uncharge.
    (per-cpu area will be accessed soon anyway)

    * All ancestors are checked at soft-limit-check. This is necessary because
    ancesotor's event counter may never be modified. Then, they should be
    checked at the same time.

    Reviewed-by: Daisuke Nishimura
    Signed-off-by: KAMEZAWA Hiroyuki
    Cc: Paul Menage
    Cc: Li Zefan
    Cc: Balbir Singh
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    KAMEZAWA Hiroyuki
     
  • __mem_cgroup_largest_soft_limit_node() returns a mem_cgroup_per_zone "mz"
    with incremnted mz->mem->css's refcnt. Then, the caller of this function
    has to call css_put(mz->mem->css).

    But, mz can be !NULL even if "not found" i.e. without css_get(). By
    this, css->refcnt will go down to minus.

    This may cause various things...one of results will be
    initite-loop in css_tryget() as this.

    INFO: RCU detected CPU 0 stall (t=10000 jiffies)
    sending NMI to all CPUs:
    NMI backtrace for cpu 0
    CPU 0:

    <> [] trace_hardirqs_off+0xd/0x10
    [] flat_send_IPI_mask+0x90/0xb0
    [] flat_send_IPI_all+0x69/0x70
    [] arch_trigger_all_cpu_backtrace+0x62/0xa0
    [] __rcu_pending+0x7e/0x370
    [] rcu_check_callbacks+0x47/0x130
    [] update_process_times+0x46/0x70
    [] tick_sched_timer+0x60/0x160
    [] ? tick_sched_timer+0x0/0x160
    [] __run_hrtimer+0xba/0x150
    [] hrtimer_interrupt+0xd5/0x1b0
    [] ? trace_hardirqs_off_thunk+0x3a/0x3c
    [] smp_apic_timer_interrupt+0x6d/0x9b
    [] apic_timer_interrupt+0x13/0x20
    [] ? mem_cgroup_walk_tree+0x156/0x180
    [] ? mem_cgroup_walk_tree+0x73/0x180
    [] ? mem_cgroup_walk_tree+0x32/0x180
    [] ? mem_cgroup_get_local_stat+0x0/0x110
    [] ? mem_control_stat_show+0x14b/0x330
    [] ? cgroup_seqfile_show+0x3d/0x60

    Above shows CPU0 caught in css_tryget()'s inifinite loop because
    of bad refcnt.

    This is a fix to set mz=NULL at the top of retry path.

    Signed-off-by: KAMEZAWA Hiroyuki
    Acked-by: Paul Menage
    Cc: Li Zefan
    Cc: Balbir Singh
    Cc: Daisuke Nishimura
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    KAMEZAWA Hiroyuki
     

24 Sep, 2009

9 commits

  • We now count MEM_CGROUP_STAT_SWAPOUT, so we can show swap usage. It would
    be useful for users to show swap usage in memory.stat file, because they
    don't need calculate memsw.usage - res.usage to know swap usage.

    Signed-off-by: Daisuke Nishimura
    Reviewed-by: KAMEZAWA Hiroyuki
    Reviewed-by: Balbir Singh
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Daisuke Nishimura
     
  • Reduce the resource counter overhead (mostly spinlock) associated with the
    root cgroup. This is a part of the several patches to reduce mem cgroup
    overhead. I had posted other approaches earlier (including using percpu
    counters). Those patches will be a natural addition and will be added
    iteratively on top of these.

    The patch stops resource counter accounting for the root cgroup. The data
    for display is derived from the statisitcs we maintain via
    mem_cgroup_charge_statistics (which is more scalable). What happens today
    is that, we do double accounting, once using res_counter_charge() and once
    using memory_cgroup_charge_statistics(). For the root, since we don't
    implement limits any more, we don't need to track every charge via
    res_counter_charge() and check for limit being exceeded and reclaim.

    The main mem->res usage_in_bytes can be derived by summing the cache and
    rss usage data from memory statistics (MEM_CGROUP_STAT_RSS and
    MEM_CGROUP_STAT_CACHE). However, for memsw->res usage_in_bytes, we need
    additional data about swapped out memory. This patch adds a
    MEM_CGROUP_STAT_SWAPOUT and uses that along with MEM_CGROUP_STAT_RSS and
    MEM_CGROUP_STAT_CACHE to derive the memsw data. This data is computed
    recursively when hierarchy is enabled.

    The tests results I see on a 24 way show that

    1. The lock contention disappears from /proc/lock_stats
    2. The results of the test are comparable to running with
    cgroup_disable=memory.

    Here is a sample of my program runs

    Without Patch

    Performance counter stats for '/home/balbir/parallel_pagefault':

    7192804.124144 task-clock-msecs # 23.937 CPUs
    424691 context-switches # 0.000 M/sec
    267 CPU-migrations # 0.000 M/sec
    28498113 page-faults # 0.004 M/sec
    5826093739340 cycles # 809.989 M/sec
    408883496292 instructions # 0.070 IPC
    7057079452 cache-references # 0.981 M/sec
    3036086243 cache-misses # 0.422 M/sec

    300.485365680 seconds time elapsed

    With cgroup_disable=memory

    Performance counter stats for '/home/balbir/parallel_pagefault':

    7182183.546587 task-clock-msecs # 23.915 CPUs
    425458 context-switches # 0.000 M/sec
    203 CPU-migrations # 0.000 M/sec
    92545093 page-faults # 0.013 M/sec
    6034363609986 cycles # 840.185 M/sec
    437204346785 instructions # 0.072 IPC
    6636073192 cache-references # 0.924 M/sec
    2358117732 cache-misses # 0.328 M/sec

    300.320905827 seconds time elapsed

    With this patch applied

    Performance counter stats for '/home/balbir/parallel_pagefault':

    7191619.223977 task-clock-msecs # 23.955 CPUs
    422579 context-switches # 0.000 M/sec
    88 CPU-migrations # 0.000 M/sec
    91946060 page-faults # 0.013 M/sec
    5957054385619 cycles # 828.333 M/sec
    1058117350365 instructions # 0.178 IPC
    9161776218 cache-references # 1.274 M/sec
    1920494280 cache-misses # 0.267 M/sec

    300.218764862 seconds time elapsed

    Data from Prarit (kernel compile with make -j64 on a 64
    CPU/32G machine)

    For a single run

    Without patch

    real 27m8.988s
    user 87m24.916s
    sys 382m6.037s

    With patch

    real 4m18.607s
    user 84m58.943s
    sys 50m52.682s

    With config turned off

    real 4m54.972s
    user 90m13.456s
    sys 50m19.711s

    NOTE: The data looks counterintuitive due to the increased performance
    with the patch, even over the config being turned off. We probably need
    more runs, but so far all testing has shown that the patches definitely
    help.

    [akpm@linux-foundation.org: coding-style fixes]
    Signed-off-by: Balbir Singh
    Cc: Prarit Bhargava
    Cc: Andi Kleen
    Reviewed-by: KAMEZAWA Hiroyuki
    Reviewed-by: Daisuke Nishimura
    Cc: KOSAKI Motohiro
    Cc: Paul Menage
    Cc: Li Zefan
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Balbir Singh
     
  • Implement reclaim from groups over their soft limit

    Permit reclaim from memory cgroups on contention (via the direct reclaim
    path).

    memory cgroup soft limit reclaim finds the group that exceeds its soft
    limit by the largest number of pages and reclaims pages from it and then
    reinserts the cgroup into its correct place in the rbtree.

    Add additional checks to mem_cgroup_hierarchical_reclaim() to detect long
    loops in case all swap is turned off. The code has been refactored and
    the loop check (loop < 2) has been enhanced for soft limits. For soft
    limits, we try to do more targetted reclaim. Instead of bailing out after
    two loops, the routine now reclaims memory proportional to the size by
    which the soft limit is exceeded. The proportion has been empirically
    determined.

    [akpm@linux-foundation.org: build fix]
    [kamezawa.hiroyu@jp.fujitsu.com: fix softlimit css refcnt handling]
    [nishimura@mxp.nes.nec.co.jp: refcount of the "victim" should be decremented before exiting the loop]
    Signed-off-by: Balbir Singh
    Cc: KAMEZAWA Hiroyuki
    Cc: Li Zefan
    Acked-by: KOSAKI Motohiro
    Signed-off-by: KAMEZAWA Hiroyuki
    Signed-off-by: Daisuke Nishimura
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Balbir Singh
     
  • Refactor mem_cgroup_hierarchical_reclaim()

    Refactor the arguments passed to mem_cgroup_hierarchical_reclaim() into
    flags, so that new parameters don't have to be passed as we make the
    reclaim routine more flexible

    Signed-off-by: Balbir Singh
    Cc: KAMEZAWA Hiroyuki
    Cc: Li Zefan
    Cc: KOSAKI Motohiro
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Balbir Singh
     
  • Organize cgroups over soft limit in a RB-Tree

    Introduce an RB-Tree for storing memory cgroups that are over their soft
    limit. The overall goal is to

    1. Add a memory cgroup to the RB-Tree when the soft limit is exceeded.
    We are careful about updates, updates take place only after a particular
    time interval has passed
    2. We remove the node from the RB-Tree when the usage goes below the soft
    limit

    The next set of patches will exploit the RB-Tree to get the group that is
    over its soft limit by the largest amount and reclaim from it, when we
    face memory contention.

    [hugh.dickins@tiscali.co.uk: CONFIG_CGROUP_MEM_RES_CTLR=y CONFIG_PREEMPT=y fails to boot]
    Signed-off-by: Balbir Singh
    Signed-off-by: KAMEZAWA Hiroyuki
    Cc: Li Zefan
    Cc: KOSAKI Motohiro
    Signed-off-by: Hugh Dickins
    Cc: Jiri Slaby
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Balbir Singh
     
  • Add an interface to allow get/set of soft limits. Soft limits for memory
    plus swap controller (memsw) is currently not supported. Resource
    counters have been enhanced to support soft limits and new type
    RES_SOFT_LIMIT has been added. Unlike hard limits, soft limits can be
    directly set and do not need any reclaim or checks before setting them to
    a newer value.

    Kamezawa-San raised a question as to whether soft limit should belong to
    res_counter. Since all resources understand the basic concepts of hard
    and soft limits, it is justified to add soft limits here. Soft limits are
    a generic resource usage feature, even file system quotas support soft
    limits.

    Signed-off-by: Balbir Singh
    Cc: KAMEZAWA Hiroyuki
    Cc: Li Zefan
    Cc: KOSAKI Motohiro
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Balbir Singh
     
  • Add comments for the reason of smp_wmb() in mem_cgroup_commit_charge().

    [akpm@linux-foundation.org: coding-style fixes]
    Cc: Daisuke Nishimura
    Cc: Balbir Singh
    Signed-off-by: KAMEZAWA Hiroyuki
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    KAMEZAWA Hiroyuki
     
  • Change the memory cgroup to remove the overhead associated with accounting
    all pages in the root cgroup. As a side-effect, we can no longer set a
    memory hard limit in the root cgroup.

    A new flag to track whether the page has been accounted or not has been
    added as well. Flags are now set atomically for page_cgroup,
    pcg_default_flags is now obsolete and removed.

    [akpm@linux-foundation.org: fix a few documentation glitches]
    Signed-off-by: Balbir Singh
    Signed-off-by: Daisuke Nishimura
    Reviewed-by: KAMEZAWA Hiroyuki
    Cc: Daisuke Nishimura
    Cc: Li Zefan
    Cc: Paul Menage
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Balbir Singh
     
  • Alter the ss->can_attach and ss->attach functions to be able to deal with
    a whole threadgroup at a time, for use in cgroup_attach_proc. (This is a
    pre-patch to cgroup-procs-writable.patch.)

    Currently, new mode of the attach function can only tell the subsystem
    about the old cgroup of the threadgroup leader. No subsystem currently
    needs that information for each thread that's being moved, but if one were
    to be added (for example, one that counts tasks within a group) this bit
    would need to be reworked a bit to tell the subsystem the right
    information.

    [hidave.darkstar@gmail.com: fix build]
    Signed-off-by: Ben Blum
    Signed-off-by: Paul Menage
    Acked-by: Li Zefan
    Reviewed-by: Matt Helsley
    Cc: "Eric W. Biederman"
    Cc: Oleg Nesterov
    Cc: Peter Zijlstra
    Cc: Ingo Molnar
    Cc: Dave Young
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Ben Blum
     

22 Sep, 2009

1 commit


30 Jul, 2009

1 commit

  • After commit ec64f51545fffbc4cb968f0cea56341a4b07e85a ("cgroup: fix
    frequent -EBUSY at rmdir"), cgroup's rmdir (especially against memcg)
    doesn't return -EBUSY by temporary ref counts. That commit expects all
    refs after pre_destroy() is temporary but...it wasn't. Then, rmdir can
    wait permanently. This patch tries to fix that and change followings.

    - set CGRP_WAIT_ON_RMDIR flag before pre_destroy().
    - clear CGRP_WAIT_ON_RMDIR flag when the subsys finds racy case.
    if there are sleeping ones, wakes them up.
    - rmdir() sleeps only when CGRP_WAIT_ON_RMDIR flag is set.

    Tested-by: Daisuke Nishimura
    Reported-by: Daisuke Nishimura
    Reviewed-by: Paul Menage
    Acked-by: Balbir Sigh
    Signed-off-by: KAMEZAWA Hiroyuki
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    KAMEZAWA Hiroyuki
     

11 Jul, 2009

1 commit


19 Jun, 2009

5 commits

  • Try to fix memcg's lru rotation sanity: make memcg use the same logic as
    the global LRU does.

    Now, at __isolate_lru_page() retruns -EBUSY, the page is rotated to the
    tail of LRU in global LRU's isolate LRU pages. But in memcg, it's not
    handled. This makes memcg do the same behavior as global LRU and rotate
    LRU in the page is busy.

    Signed-off-by: KAMEZAWA Hiroyuki
    Cc: KOSAKI Motohiro
    Acked-by: Daisuke Nishimura
    Cc: Balbir Singh
    Cc: Mel Gorman
    Cc: Minchan Kim
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    KAMEZAWA Hiroyuki
     
  • A user can set memcg.limit_in_bytes == memcg.memsw.limit_in_bytes when the
    user just want to limit the total size of applications, in other words,
    not very interested in memory usage itself. In this case, swap-out will
    be done only by global-LRU.

    But, under current implementation, memory.limit_in_bytes is checked at
    first and try_to_free_page() may do swap-out. But, that swap-out is
    useless for memsw.limit_in_bytes and the thread may hit limit again.

    This patch tries to fix the current behavior at memory.limit ==
    memsw.limit case. And documentation is updated to explain the behavior of
    this special case.

    Signed-off-by: KAMEZAWA Hiroyuki
    Cc: Daisuke Nishimura
    Cc: Balbir Singh
    Cc: Li Zefan
    Cc: Dhaval Giani
    Cc: YAMAMOTO Takashi
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    KAMEZAWA Hiroyuki
     
  • This patch fixes mis-accounting of swap usage in memcg.

    In the current implementation, memcg's swap account is uncharged only when
    swap is completely freed. But there are several cases where swap cannot
    be freed cleanly. For handling that, this patch changes that memcg
    uncharges swap account when swap has no references other than cache.

    By this, memcg's swap entry accounting can be fully synchronous with the
    application's behavior.

    This patch also changes memcg's hooks for swap-out.

    Signed-off-by: KAMEZAWA Hiroyuki
    Cc: Daisuke Nishimura
    Acked-by: Balbir Singh
    Cc: Hugh Dickins
    Cc: Johannes Weiner
    Cc: Li Zefan
    Cc: Dhaval Giani
    Cc: YAMAMOTO Takashi
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    KAMEZAWA Hiroyuki
     
  • We don't need to check do_swap_account in the case that the function which
    checks do_swap_account will never get called if do_swap_account == 0.

    Signed-off-by: Li Zefan
    Cc: Balbir Singh
    Acked-by: KAMEZAWA Hiroyuki
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Li Zefan
     
  • Add file RSS tracking per memory cgroup

    We currently don't track file RSS, the RSS we report is actually anon RSS.
    All the file mapped pages, come in through the page cache and get
    accounted there. This patch adds support for accounting file RSS pages.
    It should

    1. Help improve the metrics reported by the memory resource controller
    2. Will form the basis for a future shared memory accounting heuristic
    that has been proposed by Kamezawa.

    Unfortunately, we cannot rename the existing "rss" keyword used in
    memory.stat to "anon_rss". We however, add "mapped_file" data and hope to
    educate the end user through documentation.

    [hugh.dickins@tiscali.co.uk: fix mem_cgroup_update_mapped_file_stat oops]
    Signed-off-by: Balbir Singh
    Acked-by: KAMEZAWA Hiroyuki
    Cc: Li Zefan
    Cc: Paul Menage
    Cc: Dhaval Giani
    Cc: Daisuke Nishimura
    Cc: YAMAMOTO Takashi
    Cc: KOSAKI Motohiro
    Cc: David Rientjes
    Signed-off-by: Hugh Dickins
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Balbir Singh
     

17 Jun, 2009

1 commit

  • When the file LRU lists are dominated by streaming IO pages, evict those
    pages first, before considering evicting other pages.

    This should be safe from deadlocks or performance problems
    because only three things can happen to an inactive file page:

    1) referenced twice and promoted to the active list
    2) evicted by the pageout code
    3) under IO, after which it will get evicted or promoted

    The pages freed in this way can either be reused for streaming IO, or
    allocated for something else. If the pages are used for streaming IO,
    this pageout pattern continues. Otherwise, we will fall back to the
    normal pageout pattern.

    Signed-off-by: Rik van Riel
    Reported-by: Elladan
    Cc: KOSAKI Motohiro
    Cc: Peter Zijlstra
    Cc: Lee Schermerhorn
    Acked-by: Johannes Weiner
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Rik van Riel
     

29 May, 2009

2 commits

  • Fix build warning, "mem_cgroup_is_obsolete defined but not used" when
    CONFIG_DEBUG_VM is not set. Also avoid checking for !mem again and again.

    Signed-off-by: Nikanth Karthikesan
    Acked-by: Pekka Enberg
    Acked-by: KAMEZAWA Hiroyuki
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Nikanth Karthikesan
     
  • mapping->tree_lock can be acquired from interrupt context. Then,
    following dead lock can occur.

    Assume "A" as a page.

    CPU0:
    lock_page_cgroup(A)
    interrupted
    -> take mapping->tree_lock.
    CPU1:
    take mapping->tree_lock
    -> lock_page_cgroup(A)

    This patch tries to fix above deadlock by moving memcg's hook to out of
    mapping->tree_lock. charge/uncharge of pagecache/swapcache is protected
    by page lock, not tree_lock.

    After this patch, lock_page_cgroup() is not called under mapping->tree_lock.

    Signed-off-by: KAMEZAWA Hiroyuki
    Signed-off-by: Daisuke Nishimura
    Cc: Balbir Singh
    Cc: Daisuke Nishimura
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Daisuke Nishimura
     

03 May, 2009

2 commits

  • Current mem_cgroup_shrink_usage() has two problems.

    1. It doesn't call mem_cgroup_out_of_memory and doesn't update
    last_oom_jiffies, so pagefault_out_of_memory invokes global OOM.

    2. Considering hierarchy, shrinking has to be done from the
    mem_over_limit, not from the memcg which the page would be charged to.

    mem_cgroup_try_charge_swapin() does all of these things properly, so we
    use it and call cancel_charge_swapin when it succeeded.

    The name of "shrink_usage" is not appropriate for this behavior, so we
    change it too.

    Signed-off-by: Daisuke Nishimura
    Acked-by: KAMEZAWA Hiroyuki
    Cc: Li Zefan
    Cc: Paul Menage
    Cc: Dhaval Giani
    Cc: Daisuke Nishimura
    Cc: YAMAMOTO Takashi
    Cc: KOSAKI Motohiro
    Cc: David Rientjes
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Daisuke Nishimura
     
  • This is a bugfix for commit 3c776e64660028236313f0e54f3a9945764422df
    ("memcg: charge swapcache to proper memcg").

    Used bit of swapcache is solid under page lock, but considering
    move_account, pc->mem_cgroup is not.

    We need lock_page_cgroup() anyway.

    Signed-off-by: Daisuke Nishimura
    Acked-by: KAMEZAWA Hiroyuki
    Cc: Balbir Singh
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Daisuke Nishimura
     

14 Apr, 2009

1 commit


03 Apr, 2009

10 commits

  • Current mem_cgroup_cache_charge is a bit complicated especially
    in the case of shmem's swap-in.

    This patch cleans it up by using try_charge_swapin and commit_charge_swapin.

    Signed-off-by: Daisuke Nishimura
    Acked-by: KAMEZAWA Hiroyuki
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Daisuke Nishimura
     
  • 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
    Cc: Li Zefan
    Cc: Balbir Singh
    Cc: Paul Menage
    Cc: Hugh Dickins
    Signed-off-by: Daisuke Nishimura
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    KAMEZAWA Hiroyuki
     
  • memcg_test.txt says at 4.1:

    This swap-in is one of the most complicated work. In do_swap_page(),
    following events occur when pte is unchanged.

    (1) the page (SwapCache) is looked up.
    (2) lock_page()
    (3) try_charge_swapin()
    (4) reuse_swap_page() (may call delete_swap_cache())
    (5) commit_charge_swapin()
    (6) swap_free().

    Considering following situation for example.

    (A) The page has not been charged before (2) and reuse_swap_page()
    doesn't call delete_from_swap_cache().
    (B) The page has not been charged before (2) and reuse_swap_page()
    calls delete_from_swap_cache().
    (C) The page has been charged before (2) and reuse_swap_page() doesn't
    call delete_from_swap_cache().
    (D) The page has been charged before (2) and reuse_swap_page() calls
    delete_from_swap_cache().

    memory.usage/memsw.usage changes to this page/swp_entry will be
    Case (A) (B) (C) (D)
    Event
    Before (2) 0/ 1 0/ 1 1/ 1 1/ 1
    ===========================================
    (3) +1/+1 +1/+1 +1/+1 +1/+1
    (4) - 0/ 0 - -1/ 0
    (5) 0/-1 0/ 0 -1/-1 0/ 0
    (6) - 0/-1 - 0/-1
    ===========================================
    Result 1/ 1 1/ 1 1/ 1 1/ 1

    In any cases, charges to this page should be 1/ 1.

    In case of (D), mem_cgroup_try_get_from_swapcache() returns NULL
    (because lookup_swap_cgroup() returns NULL), so "+1/+1" at (3) means
    charges to the memcg("foo") to which the "current" belongs.
    OTOH, "-1/0" at (4) and "0/-1" at (6) means uncharges from the memcg("baa")
    to which the page has been charged.

    So, if the "foo" and "baa" is different(for example because of task move),
    this charge will be moved from "baa" to "foo".

    I think this is an unexpected behavior.

    This patch fixes this by modifying mem_cgroup_try_get_from_swapcache()
    to return the memcg to which the swapcache has been charged if PCG_USED bit
    is set.
    IIUC, checking PCG_USED bit of swapcache is safe under page lock.

    Signed-off-by: Daisuke Nishimura
    Cc: Balbir Singh
    Cc: KAMEZAWA Hiroyuki
    Cc: Li Zefan
    Cc: Hugh Dickins
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Daisuke Nishimura
     
  • Currently, mem_cgroup_calc_mapped_ratio() is unused at all. it can be
    removed and KAMEZAWA-san suggested it.

    Signed-off-by: KOSAKI Motohiro
    Cc: KAMEZAWA Hiroyuki
    Acked-by: Balbir Singh
    Cc: Johannes Weiner
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    KOSAKI Motohiro
     
  • Add RSS and swap to OOM output from memcg

    Display memcg values like failcnt, usage and limit when an OOM occurs due
    to memcg.

    Thanks to Johannes Weiner, Li Zefan, David Rientjes, Kamezawa Hiroyuki,
    Daisuke Nishimura and KOSAKI Motohiro for review.

    Sample output
    -------------

    Task in /a/x killed as a result of limit of /a
    memory: usage 1048576kB, limit 1048576kB, failcnt 4183
    memory+swap: usage 1400964kB, limit 9007199254740991kB, failcnt 0

    [akpm@linux-foundation.org: compilation fix]
    [akpm@linux-foundation.org: fix kerneldoc and whitespace]
    [akpm@linux-foundation.org: add printk facility level]
    Signed-off-by: Balbir Singh
    Cc: KAMEZAWA Hiroyuki
    Cc: Daisuke Nishimura
    Cc: Li Zefan
    Cc: Paul Menage
    Cc: David Rientjes
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Balbir Singh
     
  • This patch tries to fix OOM Killer problems caused by hierarchy.
    Now, memcg itself has OOM KILL function (in oom_kill.c) and tries to
    kill a task in memcg.

    But, when hierarchy is used, it's broken and correct task cannot
    be killed. For example, in following cgroup

    /groupA/ hierarchy=1, limit=1G,
    01 nolimit
    02 nolimit
    All tasks' memory usage under /groupA, /groupA/01, groupA/02 is limited to
    groupA's 1Gbytes but OOM Killer just kills tasks in groupA.

    This patch provides makes the bad process be selected from all tasks
    under hierarchy. BTW, currently, oom_jiffies is updated against groupA
    in above case. oom_jiffies of tree should be updated.

    To see how oom_jiffies is used, please check mem_cgroup_oom_called()
    callers.

    [akpm@linux-foundation.org: build fix]
    [akpm@linux-foundation.org: const fix]
    Signed-off-by: KAMEZAWA Hiroyuki
    Cc: Paul Menage
    Cc: Li Zefan
    Cc: Balbir Singh
    Cc: Daisuke Nishimura
    Cc: David Rientjes
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    KAMEZAWA Hiroyuki
     
  • As pointed out, shrinking memcg's limit should return -EBUSY after
    reasonable retries. This patch tries to fix the current behavior of
    shrink_usage.

    Before looking into "shrink should return -EBUSY" problem, we should fix
    hierarchical reclaim code. It compares current usage and current limit,
    but it only makes sense when the kernel reclaims memory because hit
    limits. This is also a problem.

    What this patch does are.

    1. add new argument "shrink" to hierarchical reclaim. If "shrink==true",
    hierarchical reclaim returns immediately and the caller checks the kernel
    should shrink more or not.
    (At shrinking memory, usage is always smaller than limit. So check for
    usage < limit is useless.)

    2. For adjusting to above change, 2 changes in "shrink"'s retry path.
    2-a. retry_count depends on # of children because the kernel visits
    the children under hierarchy one by one.
    2-b. rather than checking return value of hierarchical_reclaim's progress,
    compares usage-before-shrink and usage-after-shrink.
    If usage-before-shrink
    Signed-off-by: KAMEZAWA Hiroyuki
    Cc: Paul Menage
    Cc: Balbir Singh
    Cc: Daisuke Nishimura
    Cc: David Rientjes
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    KAMEZAWA Hiroyuki
     
  • Clean up memory.stat file routine and show "total" hierarchical stat.

    This patch does
    - renamed get_all_zonestat to be get_local_zonestat.
    - remove old mem_cgroup_stat_desc, which is only for per-cpu stat.
    - add mcs_stat to cover both of per-cpu/per-lru stat.
    - add "total" stat of hierarchy (*)
    - add a callback system to scan all memcg under a root.
    == "total" is added.
    [kamezawa@localhost ~]$ cat /opt/cgroup/xxx/memory.stat
    cache 0
    rss 0
    pgpgin 0
    pgpgout 0
    inactive_anon 0
    active_anon 0
    inactive_file 0
    active_file 0
    unevictable 0
    hierarchical_memory_limit 50331648
    hierarchical_memsw_limit 9223372036854775807
    total_cache 65536
    total_rss 192512
    total_pgpgin 218
    total_pgpgout 155
    total_inactive_anon 0
    total_active_anon 135168
    total_inactive_file 61440
    total_active_file 4096
    total_unevictable 0
    ==
    (*) maybe the user can do calc hierarchical stat by his own program
    in userland but if it can be written in clean way, it's worth to be
    shown, I think.

    Signed-off-by: KAMEZAWA Hiroyuki
    Cc: Paul Menage
    Cc: Li Zefan
    Cc: Balbir Singh
    Cc: Daisuke Nishimura
    Cc: David Rientjes
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    KAMEZAWA Hiroyuki
     
  • Assigning CSS ID for each memcg and use css_get_next() for scanning hierarchy.

    Assume folloing tree.

    group_A (ID=3)
    /01 (ID=4)
    /0A (ID=7)
    /02 (ID=10)
    group_B (ID=5)
    and task in group_A/01/0A hits limit at group_A.

    reclaim will be done in following order (round-robin).
    group_A(3) -> group_A/01 (4) -> group_A/01/0A (7) -> group_A/02(10)
    -> group_A -> .....

    Round robin by ID. The last visited cgroup is recorded and restart
    from it when it start reclaim again.
    (More smart algorithm can be implemented..)

    No cgroup_mutex or hierarchy_mutex is required.

    Signed-off-by: KAMEZAWA Hiroyuki
    Cc: Paul Menage
    Cc: Li Zefan
    Cc: Balbir Singh
    Cc: Daisuke Nishimura
    Cc: David Rientjes
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    KAMEZAWA Hiroyuki
     
  • In following situation, with memory subsystem,

    /groupA use_hierarchy==1
    /01 some tasks
    /02 some tasks
    /03 some tasks
    /04 empty

    When tasks under 01/02/03 hit limit on /groupA, hierarchical reclaim
    is triggered and the kernel walks tree under groupA. In this case,
    rmdir /groupA/04 fails with -EBUSY frequently because of temporal
    refcnt from the kernel.

    In general. cgroup can be rmdir'd if there are no children groups and
    no tasks. Frequent fails of rmdir() is not useful to users.
    (And the reason for -EBUSY is unknown to users.....in most cases)

    This patch tries to modify above behavior, by
    - retries if css_refcnt is got by someone.
    - add "return value" to pre_destroy() and allows subsystem to
    say "we're really busy!"

    Signed-off-by: KAMEZAWA Hiroyuki
    Cc: Paul Menage
    Cc: Li Zefan
    Cc: Balbir Singh
    Cc: Daisuke Nishimura
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    KAMEZAWA Hiroyuki
     

30 Jan, 2009

2 commits

  • N_POSSIBLE doesn't means there is memory...and force_empty can
    visit invalid node which have no pgdat.

    To visit all valid nodes, N_HIGH_MEMORY should be used.

    Reported-by: Li Zefan
    Signed-off-by: KAMEZAWA Hiroyuki
    Tested-by: Li Zefan
    Cc: Balbir Singh
    Cc: Daisuke Nishimura
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    KAMEZAWA Hiroyuki
     
  • The lifetime of struct cgroup and struct mem_cgroup is different and
    mem_cgroup has its own reference count for handling references from
    swap_cgroup.

    This causes strange problem that the parent mem_cgroup dies while child
    mem_cgroup alive, and this problem causes a bug in case of
    use_hierarchy==1 because res_counter_uncharge climbs up the tree.

    This patch is for avoiding it by getting the parent at create, and putting
    it at freeing.

    Signed-off-by: Daisuke Nishimura
    Reviewed-by; KAMEZAWA Hiroyuki
    Cc: Balbir Singh
    Cc: Pavel Emelyanov
    Cc: Li Zefan
    Cc: Paul Menage
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Daisuke Nishimura
     

16 Jan, 2009

2 commits

  • (suppose: memcg->use_hierarchy == 0 and memcg->swappiness == 60)

    echo 10 > /memcg/0/swappiness |
    mem_cgroup_swappiness_write() |
    ... | echo 1 > /memcg/0/use_hierarchy
    | mkdir /mnt/0/1
    | sub_memcg->swappiness = 60;
    memcg->swappiness = 10; |

    In the above scenario, we end up having 2 different swappiness
    values in a single hierarchy.

    We should hold cgroup_lock() when cheking cgrp->children list.

    Signed-off-by: Li Zefan
    Acked-by: KAMEZAWA Hiroyuki
    Cc: Balbir Singh
    Cc: Paul Menage
    Cc: Daisuke Nishimura
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Li Zefan
     
  • At system boot when creating the top cgroup, mem_cgroup_create() calls
    enable_swap_cgroup() which is marked as __init, so mark
    mem_cgroup_create() as __ref to avoid false section mismatch warning.

    Reported-by: Rakib Mullick
    Signed-off-by: Li Zefan
    Acked-by; KAMEZAWA Hiroyuki
    Cc: Balbir Singh
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Li Zefan