Commit Graph

18 Commits

Author SHA1 Message Date
Suren Baghdasaryan
16c2b1d94f ANDROID: page_pinner: prevent pp_buffer access before initialization
If page_pinner is configured with page_pinner_enabled=false and
failure_tracking=true, pp_buffer will be accessed without being
initialized. Prevent this by adding page_pinner_inited checks in
functions that access it.

Fixes: 898cfbf094a2 ("ANDROID: mm: introduce page_pinner")
Bug: 259024332
Bug: 260179017
Change-Id: I8f612cae3e74d36e8a4eee5edec25281246cbe5e
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
(cherry picked from commit 23fb3111f63e5fe239a769668275c20493a5849c)
2023-03-23 13:28:36 -07:00
Lee Jones
e096145ac3 ANDROID: mm: page_pinner: ensure do_div() arguments matches with respect to type
Fixes the following compiler warnings:

  mm/page_pinner.c:240:28: error: comparison of distinct pointer types
      ('typeof ((ts_usec)) *' (aka 'long long *') and 'uint64_t *'
      (aka 'unsigned long long *')) [-Werror,-Wcompare-distinct-pointer-types]
                unsigned long rem_usec = do_div(ts_usec, 1000000);
                                         ^~~~~~~~~~~~~~~~~~~~~~~~
  include/asm-generic/div64.h:226:28: note: expanded from macro 'do_div'
        (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
               ~~~~~~~~~~~~~~~~~~ ^  ~~~~~~~~~~~~~~~
  mm/page_pinner.c:312:13: error: comparison of distinct pointer types
      ('typeof ((ts_usec)) *' (aka 'long long *') and 'uint64_t *'
      (aka 'unsigned long long *')) [-Werror,-Wcompare-distinct-pointer-types]
        rem_usec = do_div(ts_usec, 1000000);
                   ^~~~~~~~~~~~~~~~~~~~~~~~
  include/asm-generic/div64.h:226:28: note: expanded from macro 'do_div'
        (void)(((typeof((n)) *)0) == ((uint64_t *)0));  \
               ~~~~~~~~~~~~~~~~~~ ^  ~~~~~~~~~~~~~~~

Bug: 261962742
Signed-off-by: Lee Jones <joneslee@google.com>
Change-Id: I63bc6e2d82bfd757c4bf9df53a1a17a1a6235ba7
2023-01-26 11:34:37 +00:00
Charan Teja Kalla
99f0160022 ANDROID: mm: page_pinner: use page_ext_get/put() to work with page_ext
Use page_ext_get/put() to work with the page extended information
without which the page extended information may not be valid.

Bug: 2129036
Change-Id: Ibfe036b9ecef0e2551b5d0da1011cacbb0a5c3e6
Signed-off-by: Charan Teja Kalla <quic_charante@quicinc.com>
2022-08-30 04:03:20 +00:00
Minchan Kim
4ebb639f0d ANDROID: mm: page_pinner: fix build warning
Fix build warning below.

> All warnings (new ones prefixed by >>):
>
> >> mm/page_pinner.c:304:22: warning: variable 'page_pinner' set but not used [-Wunused-but-set-variable]
>            struct page_pinner *page_pinner;
>                                ^
>    1 warning generated.
>

Fixes: ddc4a48797 ("ANDROID: mm: page_pinner: introduce failure_tracking feature")
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Minchan Kim <minchan@google.com>
Change-Id: I02cfd98f9c33745920f883d5e2e2bc2730f662a2
2022-03-10 21:35:16 +00:00
Todd Kjos
66e24eb093 Revert "ANDROID: mm: page_pinner: use EXPORT_SYMBOL_GPL"
This reverts commit d820d22b5d.

Reason for revert: Needed for non-GPL use of put_page() which is allowed by upstream kernel.

Change-Id: I9a2a51c1e2d11ccc5403fc5a8510f577446add92
Signed-off-by: Todd Kjos <tkjos@google.com>
2021-09-23 23:47:26 +00:00
Minchan Kim
d820d22b5d ANDROID: mm: page_pinner: use EXPORT_SYMBOL_GPL
GKI requires EXPORT_SYMBOL_GPL so change it.

Bug: 192475091
Signed-off-by: Minchan Kim <minchan@google.com>
Change-Id: Iba310d0a78f6ddb1e7980177fe7c624d0a0f254a
2021-07-14 03:38:32 +00:00
Minchan Kim
13362ab28e ANDROID: mm: page_pinner: add state of page_pinner
To keep track of page migration failures, record the following
page states to capture natural state transitions of a page during
migration:

  * detected
  * put reference count
  * free

With such transition change, it was a lot easier to analyze page
migration failure issues. Since we already have annotation on the
put_page side, this patch adds the record in free path and page
migration failure path.

Bug: 192475091
Signed-off-by: Minchan Kim <minchan@google.com>
Change-Id: I18182d3fd62850c5580c9e89a5362bdae630f153
2021-07-12 13:57:40 -07:00
Minchan Kim
3254948484 ANDROID: mm: page_pinner: add more struct page fields
While I was investigating CMA allocation latency, adding fields below
were very useful to detect the CMA allocation latency issues.
This patch adds following fields of struct page.

for struct page:

  int count
  int mapcount
  struct address_space

This patch removes page_mt since it was not useful ever for me.

Bug: 192475091
Signed-off-by: Minchan Kim <minchan@google.com>
Change-Id: I312505901a227cd404555f845550d2a9c9ce89da
2021-07-12 13:57:40 -07:00
Minchan Kim
0445b67bee ANDROID: mm: page_pinner: change timestamp format
This patch changes timestamp format to align with trace event time format.
It was much easier to parse page_pinner event order by the time with
trace event.

Bug: 192475091
Signed-off-by: Minchan Kim <minchan@google.com>
Change-Id: Ib0e81a47df588a2f6ebf842a5f3c5b298da4fe40
2021-07-12 13:57:40 -07:00
Minchan Kim
71da06728c ANDROID: mm: page_pinner: print_page_pinner refactoring
For print_page_pinner argument passing, use the one structure
parameter instead of several parameters with fields of the
structure.

Bug: 192475091
Signed-off-by: Minchan Kim <minchan@google.com>
Change-Id: I3816eb6154c6c56a66ee9079091880afda817914
2021-07-12 13:57:40 -07:00
Minchan Kim
b83e564914 ANDROID: mm: page_pinner: remove shared_count
Since we don't use it, remove it.

Bug: 192475091
Signed-off-by: Minchan Kim <minchan@google.com>
Change-Id: I04fe617f9203a6bbab5ebc424f7025df8f6d50ac
2021-07-12 13:57:40 -07:00
Minchan Kim
849f048050 ANDROID: mm: page_pinner: remove WARN_ON_ONCE
There are several path the WARN_ON_ONCE could be triggered but
it doesn't mean real bug since we intentionally allow it to make
code simple at this moment. So just remove the warnings	to prevent
folks confused it.

Bug: 192475091
Signed-off-by: Minchan Kim <minchan@google.com>
Change-Id: I7d14c8490db841f61b01fe7c16b406c9b1850c46
2021-07-12 13:57:39 -07:00
Minchan Kim
9a453100fc ANDROID: mm: page_pinner: fix typos
Fix typos.

Bug: 192475091
Signed-off-by: Minchan Kim <minchan@google.com>
Change-Id: Ida3ae53f775b35e61e66703ed8409c0b6a1e04f0
2021-07-12 13:57:39 -07:00
Minchan Kim
d012783a86 ANDROID: mm: page_pinner: reset migration failed page
Currently, __reset_page_pinner reset only PAGE_EXT_GET page freeing,
not PAGE_EXT_PINNER_MIGRATION_FAILED page. It should handle both
cases to prevent wrong PAGE_EXT_PINNER_MIGRATION_FAILED setting.

Bug: 192475091
Signed-off-by: Minchan Kim <minchan@google.com>
Change-Id: I9b4124393ee432c7cb29cd12d160ecf2a1e34360
2021-07-12 13:57:39 -07:00
Minchan Kim
7d3618b8b9 ANDROID: fix permission error of page_pinner
longterm_pinner/alloc_contig_failed should be 444
for reading for everyone and threshold/failure_traking
should be 644 to allow read/write root.

Bug: 191827366
Signed-off-by: Minchan Kim <minchan@google.com>
Change-Id: I5493c6ae6d39b692282e5428416da80a7d555aa0
2021-06-23 18:36:15 +00:00
Minchan Kim
3a71ca1496 ANDROID: mm: page_pinner: skip marking failure on freeable pages
Sometime, pages are temporarily pinnned during migration and the migration
fails. However, putback_movable_pages will end up freeing them if their
page refcount are 1. Thus, it doesn't need to mark them as failure, which
just consumes page_pinner logbuffer to lose old history.

Bug: 188908895
Signed-off-by: Minchan Kim <minchan@google.com>
Change-Id: I8564b72b212a5095cfe3ba6bf5622a9b62f5b455
2021-05-24 23:45:11 +00:00
Minchan Kim
ddc4a48797 ANDROID: mm: page_pinner: introduce failure_tracking feature
CMA allocation can fail by temporal page refcount increasement
by get_page API as well as get_user_pages friends.
However, since get_page is one of the most hot function, it is
hard to hook get_page to get callstack everytime due to
performance concern. Furthermore, get_page could be nested
multiple times so we couldn't track all of the pin sites on
limited space of page_pinner.

Thus, here approach is keep tracking of put_page callsite rather
than get_page once VM found the page migration failed.
It's based on assumption:

1. Since it's temporal page refcount, it could be released soon
   before overflowing dmesg log buffer
2. developer can find the pair of get_page by reviewing put_page.

By default, it's eanbled. If you want to disable it:

  echo 0 > $debugfs/page_pinner/failure_tracking

You can capture the tracking using:

  cat $debugfs/page_pinner/alloc_contig_failed

note: the example below is artificial:

Page pinned ts 386067292 us count 0
PFN 10162530 Block 9924 type Isolate Flags 0x800000000008000c(uptodate|dirty|swapbacked)
 __page_pinner_migration_failed+0x30/0x104
 putback_lru_page+0x90/0xac
 putback_movable_pages+0xc4/0x204
 __alloc_contig_migrate_range+0x290/0x31c
 alloc_contig_range+0x114/0x2bc
 cma_alloc+0x2d8/0x698
 cma_alloc_write+0x58/0xb8
 simple_attr_write+0xd4/0x124
 debugfs_attr_write+0x50/0xd8
 full_proxy_write+0x70/0xf8
 vfs_write+0x168/0x3a8
 ksys_write+0x7c/0xec
 __arm64_sys_write+0x20/0x30
 el0_svc_common+0xa4/0x180
 do_el0_svc+0x28/0x88
 el0_svc+0x14/0x24

Page pinned ts 385867394 us count 0
PFN 10162530 Block 9924 type Isolate Flags 0x800000000008000c(uptodate|dirty|swapbacked)
 __page_pinner_migration_failed+0x30/0x104
 __alloc_contig_migrate_range+0x200/0x31c
 alloc_contig_range+0x114/0x2bc
 cma_alloc+0x2d8/0x698
 cma_alloc_write+0x58/0xb8
 simple_attr_write+0xd4/0x124
 debugfs_attr_write+0x50/0xd8
 full_proxy_write+0x70/0xf8
 vfs_write+0x168/0x3a8
 ksys_write+0x7c/0xec
 __arm64_sys_write+0x20/0x30
 el0_svc_common+0xa4/0x180
 do_el0_svc+0x28/0x88
 el0_svc+0x14/0x24
 el0_sync_handler+0x88/0xec
 el0_sync+0x198/0x1c0

Bug: 183414571
Signed-off-by: Minchan Kim <minchan@kernel.org>
Signed-off-by: Minchan Kim <minchan@google.com>
Change-Id: Ie79902c18390eb9f320d823839bb9d9a7fdcdb31
2021-04-30 09:13:34 -07:00
Minchan Kim
6e12c5b7d4 ANDROID: mm: introduce page_pinner
For CMA allocation, it's really critical to migrate a page but
sometimes it fails. One of the reasons is some driver holds a
page refcount for a long time so VM couldn't migrate the page
at that time.

The concern here is there is no way to find the who hold the
refcount of the page effectively. This patch introduces feature
to keep tracking page's pinner. All get_page sites are vulnerable
to pin a page for a long time but the cost to keep track it would
be significat since get_page is the most frequent kernel operation.
Furthermore, the page could be not user page but kernel page which
is not related to the page migration failure. So, this patch keeps
tracking only get_user_pages/follow_page with (FOLL_GET|PIN friends
because they are the very common APIs to pin user pages which could
cause migration failure and the less frequent than get_page so
runtime cost wouldn't be that big but could cover many cases
effectively.

This patch also introduces put_user_page API. It aims for attributing
"the pinner releases the page from now on" while it release the
page refcount. Thus, any user of get_user_pages/follow_page(FOLL_GET)
must use put_user_page as pair of those functions. Otherwise,
page_pinner will treat them long term pinner as false postive but
nothing should affect stability.

* $debugfs/page_pinner/threshold

It indicates threshold(microsecond) to flag long term pinning.
It's configurable(Default is 300000us). Once you write new value
to the threshold, old data will clear.

* $debugfs/page_pinner/longterm_pinner

It shows call sites where the duration of pinning was greater than
the threshold. Internally, it uses a static array to keep 4096
elements and overwrites old ones once overflow happens. Therefore,
you could lose some information.

example)
Page pinned ts 76953865787 us count 1
PFN 9856945 Block 9625 type Movable Flags 0x8000000000080014(uptodate|lru|swapbacked)
 __set_page_pinner+0x34/0xcc
 try_grab_page+0x19c/0x1a0
 follow_page_pte+0x1c0/0x33c
 follow_page_mask+0xc0/0xc8
 __get_user_pages+0x178/0x414
 __gup_longterm_locked+0x80/0x148
 internal_get_user_pages_fast+0x140/0x174
 pin_user_pages_fast+0x24/0x40
 CCC
 BBB
 AAA
 __arm64_sys_ioctl+0x94/0xd0
 el0_svc_common+0xa4/0x180
 do_el0_svc+0x28/0x88
 el0_svc+0x14/0x24

note: page_pinner doesn't guarantee attributing/unattributing are
atomic if they happen at the same time. It's just best effort so
false-positive could happen.

Bug: 183414571
Signed-off-by: Minchan Kim <minchan@kernel.org>
Signed-off-by: Minchan Kim <minchan@google.com>
Change-Id: Ife37ec360eef993d390b9c131732218a4dfd2f04
2021-04-30 09:13:34 -07:00