diff options
Diffstat (limited to 'mm/memcontrol.c')
| -rw-r--r-- | mm/memcontrol.c | 23 | 
1 files changed, 20 insertions, 3 deletions
| diff --git a/mm/memcontrol.c b/mm/memcontrol.c index e717964cb5a0..fd4529d86de5 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
| @@ -1207,6 +1207,12 @@ static int mem_cgroup_move_account(struct page_cgroup *pc, | |||
| 1207 | ret = 0; | 1207 | ret = 0; | 
| 1208 | out: | 1208 | out: | 
| 1209 | unlock_page_cgroup(pc); | 1209 | unlock_page_cgroup(pc); | 
| 1210 | /* | ||
| 1211 | * We charges against "to" which may not have any tasks. Then, "to" | ||
| 1212 | * can be under rmdir(). But in current implementation, caller of | ||
| 1213 | * this function is just force_empty() and it's garanteed that | ||
| 1214 | * "to" is never removed. So, we don't check rmdir status here. | ||
| 1215 | */ | ||
| 1210 | return ret; | 1216 | return ret; | 
| 1211 | } | 1217 | } | 
| 1212 | 1218 | ||
| @@ -1428,6 +1434,7 @@ __mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr, | |||
| 1428 | return; | 1434 | return; | 
| 1429 | if (!ptr) | 1435 | if (!ptr) | 
| 1430 | return; | 1436 | return; | 
| 1437 | cgroup_exclude_rmdir(&ptr->css); | ||
| 1431 | pc = lookup_page_cgroup(page); | 1438 | pc = lookup_page_cgroup(page); | 
| 1432 | mem_cgroup_lru_del_before_commit_swapcache(page); | 1439 | mem_cgroup_lru_del_before_commit_swapcache(page); | 
| 1433 | __mem_cgroup_commit_charge(ptr, pc, ctype); | 1440 | __mem_cgroup_commit_charge(ptr, pc, ctype); | 
| @@ -1457,8 +1464,12 @@ __mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr, | |||
| 1457 | } | 1464 | } | 
| 1458 | rcu_read_unlock(); | 1465 | rcu_read_unlock(); | 
| 1459 | } | 1466 | } | 
| 1460 | /* add this page(page_cgroup) to the LRU we want. */ | 1467 | /* | 
| 1461 | 1468 | * At swapin, we may charge account against cgroup which has no tasks. | |
| 1469 | * So, rmdir()->pre_destroy() can be called while we do this charge. | ||
| 1470 | * In that case, we need to call pre_destroy() again. check it here. | ||
| 1471 | */ | ||
| 1472 | cgroup_release_and_wakeup_rmdir(&ptr->css); | ||
| 1462 | } | 1473 | } | 
| 1463 | 1474 | ||
| 1464 | void mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr) | 1475 | void mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr) | 
| @@ -1664,7 +1675,7 @@ void mem_cgroup_end_migration(struct mem_cgroup *mem, | |||
| 1664 | 1675 | ||
| 1665 | if (!mem) | 1676 | if (!mem) | 
| 1666 | return; | 1677 | return; | 
| 1667 | 1678 | cgroup_exclude_rmdir(&mem->css); | |
| 1668 | /* at migration success, oldpage->mapping is NULL. */ | 1679 | /* at migration success, oldpage->mapping is NULL. */ | 
| 1669 | if (oldpage->mapping) { | 1680 | if (oldpage->mapping) { | 
| 1670 | target = oldpage; | 1681 | target = oldpage; | 
| @@ -1704,6 +1715,12 @@ void mem_cgroup_end_migration(struct mem_cgroup *mem, | |||
| 1704 | */ | 1715 | */ | 
| 1705 | if (ctype == MEM_CGROUP_CHARGE_TYPE_MAPPED) | 1716 | if (ctype == MEM_CGROUP_CHARGE_TYPE_MAPPED) | 
| 1706 | mem_cgroup_uncharge_page(target); | 1717 | mem_cgroup_uncharge_page(target); | 
| 1718 | /* | ||
| 1719 | * At migration, we may charge account against cgroup which has no tasks | ||
| 1720 | * So, rmdir()->pre_destroy() can be called while we do this charge. | ||
| 1721 | * In that case, we need to call pre_destroy() again. check it here. | ||
| 1722 | */ | ||
| 1723 | cgroup_release_and_wakeup_rmdir(&mem->css); | ||
| 1707 | } | 1724 | } | 
| 1708 | 1725 | ||
| 1709 | /* | 1726 | /* | 
