• Chunxin Zang's avatar
    mm/vmscan: fix infinite loop in drop_slab_node · 069c411d
    Chunxin Zang authored
    We have observed that drop_caches can take a considerable amount of
    time (<put data here>).  Especially when there are many memcgs involved
    because they are adding an additional overhead.
    
    It is quite unfortunate that the operation cannot be interrupted by a
    signal currently.  Add a check for fatal signals into the main loop so
    that userspace can control early bailout.
    
    There are two reasons:
    
    1. We have too many memcgs, even though one object freed in one memcg,
       the sum of object is bigger than 10.
    
    2. We spend a lot of time in traverse memcg once.  So, the memcg who
       traversed at the first have been freed many objects.  Traverse memcg
       next time, the freed count bigger than 10 again.
    
    We can get the following info through 'ps':
    
      root:~# ps -aux | grep drop
      root  357956 ... R    Aug25 21119854:55 echo 3 > /proc/sys/vm/drop_caches
      root 1771385 ... R    Aug16 21146421:17 echo 3 > /proc/sys/vm/drop_caches
      root 1986319 ... R    18:56 117:27 echo 3 > /proc/sys/vm/drop_caches
      root 2002148 ... R    Aug24 5720:39 echo 3 > /proc/sys/vm/drop_caches
      root 2564666 ... R    18:59 113:58 echo 3 > /proc/sys/vm/drop_caches
      root 2639347 ... R    Sep03 2383:39 echo 3 > /proc/sys/vm/drop_caches
      root 3904747 ... R    03:35 993:31 echo 3 > /proc/sys/vm/drop_caches
      root 4016780 ... R    Aug21 7882:18 echo 3 > /proc/sys/vm/drop_caches
    
    Use bpftrace follow 'freed' value in drop_slab_node:
    
      root:~# bpftrace -e 'kprobe:drop_slab_node+70 {@ret=hist(reg("bp")); }'
      Attaching 1 probe...
      ^B^C
    
      @ret:
      [64, 128)        1 |                                                    |
      [128, 256)      28 |                                                    |
      [256, 512)     107 |@                                                   |
      [512, 1K)      298 |@@@                                                 |
      [1K, 2K)       613 |@@@@@@@                                             |
      [2K, 4K)      4435 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
      [4K, 8K)       442 |@@@@@                                               |
      [8K, 16K)      299 |@@@                                                 |
      [16K, 32K)     100 |@                                                   |
      [32K, 64K)     139 |@                                                   |
      [64K, 128K)     56 |                                                    |
      [128K, 256K)    26 |                                                    |
      [256K, 512K)     2 |                                                    |
    
    In the while loop, we can check whether the TASK_KILLABLE signal is set,
    if so, we should break the loop.
    Signed-off-by: default avatarChunxin Zang <zangchunxin@bytedance.com>
    Signed-off-by: default avatarMuchun Song <songmuchun@bytedance.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Acked-by: default avatarChris Down <chris@chrisdown.name>
    Acked-by: default avatarMichal Hocko <mhocko@suse.com>
    Cc: Vlastimil Babka <vbabka@suse.cz>
    Cc: Matthew Wilcox <willy@infradead.org>
    Link: https://lkml.kernel.org/r/20200909152047.27905-1-zangchunxin@bytedance.comSigned-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    069c411d
vmscan.c 123 KB