memcg: add page_cgroup flags for page tracking

Add additional flags to page_cgroup to track dirty/writeback/
unstable_nfs pages within a mem_cgroup.
Ref: https://lkml.org/lkml/2011/8/17/194

Signed-off-by: Sha Zhengju <handai.szj@taobao.com>
memcg: add dirty stats and rework page accounting rountine

Add memcg routines to count dirty, writeback, and unstable_NFS pages.
These routines are not yet used by the kernel to count such pages.  A
later change adds kernel calls to these new routines.

Ref: https://lkml.org/lkml/2011/8/17/199

Signed-off-by: Sha Zhengju <handai.szj@taobao.com>
memcg: add kernel calls for memcg dirty/writeback/unstable_nfs page

Add calls into memcg dirty page accounting.  Notify memcg when pages
transition between clean, file dirty, writeback, and unstable nfs.  This
allows the memory controller to maintain an accurate view of the amount
of its memory that is dirty.

Ref: https://lkml.org/lkml/2011/8/17/196

Signed-off-by: Sha Zhengju <handai.szj@taobao.com>
memcg: add mem_cgroup_mark_inode_dirty()

Create the mem_cgroup_mark_inode_dirty() routine, which is called when
an inode is marked dirty.  In kernels without memcg, this is an inline
no-op.

Add i_memcg field to struct address_space.  When an inode is marked
dirty with mem_cgroup_mark_inode_dirty(), the css_id of current memcg is
recorded in i_memcg.  Per-memcg writeback (introduced in a latter
change) uses this field to isolate inodes associated with a particular
memcg. The type of i_memcg is an 'unsigned short' because it stores
the css_id of the memcg.

A mem_cgroup_mark_inode_dirty() tracepoint is also included to allow for
easier understanding of memcg writeback operation.

Ref: https://lkml.org/lkml/2011/8/17/200

Signed-off-by: Sha Zhengju <handai.szj@taobao.com>
memcg: add dirty limits to mem_cgroup

Extend mem_cgroup to contain dirty page limits.

Ref: https://lkml.org/lkml/2011/8/17/197

Signed-off-by: Sha Zhengju <handai.szj@taobao.com>
memcg: add cgroupfs interface to memcg dirty limits

Add cgroupfs interface to memcg dirty page limits:
  Direct write-out is controlled with:
  - memory.dirty_ratio
  - memory.dirty_limit_in_bytes

  Background write-out is controlled with:
  - memory.dirty_background_ratio
  - memory.dirty_background_limit_bytes

Other memcg cgroupfs files support 'M', 'm', 'k', 'K', 'g'
and 'G' suffixes for byte counts.  This patch provides the
same functionality for memory.dirty_limit_in_bytes and
memory.dirty_background_limit_bytes.

Ref: https://lkml.org/lkml/2011/8/17/198

Signed-off-by: Sha Zhengju <handai.szj@taobao.com>
memcg: dirty page accounting support routines

Added memcg dirty page accounting support routines.  These routines are
used by later changes to provide memcg aware writeback and dirty page
limiting.  A mem_cgroup_dirty_info() tracepoint is is also included to
allow for easier understanding of memcg writeback operation.

Ref: https://lkml.org/lkml/2011/8/17/203

Signed-off-by: Sha Zhengju <handai.szj@taobao.com>
memcg: create support routines for writeback

Introduce memcg routines to assist in per-memcg writeback:

- mem_cgroups_over_bground_dirty_thresh() determines if any cgroups need
  writeback because they are over their dirty memory threshold.

- should_writeback_mem_cgroup_inode() will be called by writeback to
  determine if a particular inode should be written back.  The answer
  depends on the writeback context (foreground, background,
  try_to_free_pages, etc.).

- mem_cgroup_writeback_done() is used periodically during writeback to
  update memcg writeback data.

These routines make use of a new over_bground_dirty_thresh bitmap that
indicates which mem_cgroup are over their respective dirty background
threshold.  As this bitmap is indexed by css_id, the largest possible
css_id value is needed to create the bitmap.  So move the definition of
CSS_ID_MAX from cgroup.c to cgroup.h.  This allows users of css_id() to
know the largest possible css_id value.  This knowledge can be used to
build such per-cgroup bitmaps.

Ref: https://lkml.org/lkml/2011/8/17/202

Signed-off-by: Sha Zhengju <handai.szj@taobao.com>
writeback: pass writeback_control into move_expired_inodes()

A later change to move_expired_inodes() requires passing fields from
writeback_control descriptor into memcontrol code when determining if an
inode should be written back considered.

Ref: https://lkml.org/lkml/2011/8/17/201

Signed-off-by: Sha Zhengju <handai.szj@taobao.com>
writeback: make background writeback cgroup aware

When the system is under background dirty memory threshold but some
cgroups are over their background dirty memory thresholds, then only
writeback inodes associated with the over-limit cgroups.

In addition to checking if the system dirty memory usage is over the
system background threshold, over_bground_thresh() now checks if any
cgroups are over their respective background dirty memory thresholds.

If over-limit cgroups are found, then the new
writeback_control.for_cgroup field is set to distinguish between system
and memcg overages.  The new writeback_control.shared_inodes field is
also set.  Inodes written by multiple cgroup are marked owned by
I_MEMCG_SHARED rather than a particular cgroup.  Such shared inodes
cannot easily be attributed to a cgroup, so per-cgroup writeback
(futures version of wakeup_flusher_threads and balance_dirty_pages)
performs suboptimally in the presence of shared inodes.  Therefore,
write shared inodes when performing cgroup background writeback.

If performing cgroup writeback, move_expired_inodes() skips inodes that
do not contribute dirty pages to the cgroup being written back.

After writing some pages, wb_writeback() will call
mem_cgroup_writeback_done() to update the set of over-bg-limits memcg.

This change also makes wakeup_flusher_threads() memcg aware so that
per-cgroup try_to_free_pages() is able to operate more efficiently
without having to write pages of foreign containers.  This change adds a
mem_cgroup parameter to wakeup_flusher_threads() to allow callers,
especially try_to_free_pages() and foreground writeback from
balance_dirty_pages(), to specify a particular cgroup to write inodes
from.

Ref: https://lkml.org/lkml/2011/8/17/205

Signed-off-by: Sha Zhengju <handai.szj@taobao.com>
memcg: create support routines for page writeback

Introduce memcg routines to assist in per-memcg dirty page management:

- mem_cgroup_balance_dirty_pages() walks a memcg hierarchy comparing
  dirty memory usage against memcg foreground and background thresholds.
  If an over-background-threshold memcg is found, then per-memcg
  background writeback is queued.  Per-memcg writeback differs from
  classic, non-memcg, per bdi writeback by setting the new
  writeback_control.for_cgroup bit.

  If an over-foreground-threshold memcg is found, then foreground
  writeout occurs.  When performing foreground writeout, first consider
  inodes exclusive to the memcg.  If unable to make enough progress,
  then consider inodes shared between memcg.  Such cross-memcg inode
  sharing likely to be rare in situations that use per-cgroup memory
  isolation.  So the approach tries to handle the common case well
  without falling over in cases where such sharing exists.  This routine
  is used by balance_dirty_pages() in a later change.

- mem_cgroup_hierarchical_dirty_info() returns the dirty memory usage
  and limits of the memcg closest to (or over) its dirty limit.  This
  will be used by throttle_vm_writeout() in a latter change.

Ref: https://lkml.org/lkml/2011/8/17/204

Signed-off-by: Sha Zhengju <handai.szj@taobao.com>
memcg: check memcg dirty limits in page writeback

If the current process is in a non-root memcg, then
balance_dirty_pages() will consider the memcg dirty limits as well as
the system-wide limits.  This allows different cgroups to have distinct
dirty limits which trigger direct and background writeback at different
levels.

If called with a mem_cgroup, then throttle_vm_writeout() queries the
given cgroup for its dirty memory usage limits.

Ref: https://lkml.org/lkml/2011/8/17/206

Signed-off-by: Sha Zhengju <handai.szj@taobao.com>
memcg: Document cgroup dirty memory interfaces

Signed-off-by: Sha Zhengju <handai.szj@taobao.com>