Skip to content
  • Daisuke Nishimura's avatar
    memcg: avoid deadlock between move charge and try_charge() · b1dd693e
    Daisuke Nishimura authored
    
    
    __mem_cgroup_try_charge() can be called under down_write(&mmap_sem)(e.g.
    mlock does it). This means it can cause deadlock if it races with move charge:
    
    Ex.1)
                    move charge             |        try charge
      --------------------------------------+------------------------------
        mem_cgroup_can_attach()             |  down_write(&mmap_sem)
          mc.moving_task = current          |    ..
          mem_cgroup_precharge_mc()         |  __mem_cgroup_try_charge()
            mem_cgroup_count_precharge()    |    prepare_to_wait()
              down_read(&mmap_sem)          |    if (mc.moving_task)
              -> cannot aquire the lock     |    -> true
                                            |      schedule()
    
    Ex.2)
                    move charge             |        try charge
      --------------------------------------+------------------------------
        mem_cgroup_can_attach()             |
          mc.moving_task = current          |
          mem_cgroup_precharge_mc()         |
            mem_cgroup_count_precharge()    |
              down_read(&mmap_sem)          |
              ..                            |
              up_read(&mmap_sem)            |
                                            |  down_write(&mmap_sem)
        mem_cgroup_move_task()              |    ..
          mem_cgroup_move_charge()          |  __mem_cgroup_try_charge()
            down_read(&mmap_sem)            |    prepare_to_wait()
            -> cannot aquire the lock       |    if (mc.moving_task)
                                            |    -> true
                                            |      schedule()
    
    To avoid this deadlock, we do all the move charge works (both can_attach() and
    attach()) under one mmap_sem section.
    And after this patch, we set/clear mc.moving_task outside mc.lock, because we
    use the lock only to check mc.from/to.
    
    Signed-off-by: default avatarDaisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
    Cc: Balbir Singh <balbir@linux.vnet.ibm.com>
    Acked-by: default avatarKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
    Cc: <stable@kernel.org>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    b1dd693e