Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 110086
b: refs/heads/master
c: 31a78f2
h: refs/heads/master
v: v3
  • Loading branch information
Balbir Singh authored and Linus Torvalds committed Sep 29, 2008
1 parent af33ce0 commit e5b3128
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 6 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: bf5cb66447e7d9f7f111c1d0ebb6d7c90ec24b4d
refs/heads/master: 31a78f23bac0069004e69f98808b6988baccb6b6
2 changes: 1 addition & 1 deletion trunk/fs/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -752,11 +752,11 @@ static int exec_mmap(struct mm_struct *mm)
tsk->active_mm = mm;
activate_mm(active_mm, mm);
task_unlock(tsk);
mm_update_next_owner(old_mm);
arch_pick_mmap_layout(mm);
if (old_mm) {
up_read(&old_mm->mmap_sem);
BUG_ON(active_mm != old_mm);
mm_update_next_owner(old_mm);
mmput(old_mm);
return 0;
}
Expand Down
5 changes: 3 additions & 2 deletions trunk/kernel/cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -2738,14 +2738,15 @@ void cgroup_fork_callbacks(struct task_struct *child)
*/
void cgroup_mm_owner_callbacks(struct task_struct *old, struct task_struct *new)
{
struct cgroup *oldcgrp, *newcgrp;
struct cgroup *oldcgrp, *newcgrp = NULL;

if (need_mm_owner_callback) {
int i;
for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
struct cgroup_subsys *ss = subsys[i];
oldcgrp = task_cgroup(old, ss->subsys_id);
newcgrp = task_cgroup(new, ss->subsys_id);
if (new)
newcgrp = task_cgroup(new, ss->subsys_id);
if (oldcgrp == newcgrp)
continue;
if (ss->mm_owner_changed)
Expand Down
12 changes: 10 additions & 2 deletions trunk/kernel/exit.c
Original file line number Diff line number Diff line change
Expand Up @@ -583,8 +583,6 @@ mm_need_new_owner(struct mm_struct *mm, struct task_struct *p)
* If there are other users of the mm and the owner (us) is exiting
* we need to find a new owner to take on the responsibility.
*/
if (!mm)
return 0;
if (atomic_read(&mm->mm_users) <= 1)
return 0;
if (mm->owner != p)
Expand Down Expand Up @@ -627,6 +625,16 @@ void mm_update_next_owner(struct mm_struct *mm)
} while_each_thread(g, c);

read_unlock(&tasklist_lock);
/*
* We found no owner yet mm_users > 1: this implies that we are
* most likely racing with swapoff (try_to_unuse()) or /proc or
* ptrace or page migration (get_task_mm()). Mark owner as NULL,
* so that subsystems can understand the callback and take action.
*/
down_write(&mm->mmap_sem);
cgroup_mm_owner_callbacks(mm->owner, NULL);
mm->owner = NULL;
up_write(&mm->mmap_sem);
return;

assign_new_owner:
Expand Down
17 changes: 17 additions & 0 deletions trunk/mm/memcontrol.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,14 @@ static struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont)

struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p)
{
/*
* mm_update_next_owner() may clear mm->owner to NULL
* if it races with swapoff, page migration, etc.
* So this can be called with p == NULL.
*/
if (unlikely(!p))
return NULL;

return container_of(task_subsys_state(p, mem_cgroup_subsys_id),
struct mem_cgroup, css);
}
Expand Down Expand Up @@ -549,6 +557,11 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm,
if (likely(!memcg)) {
rcu_read_lock();
mem = mem_cgroup_from_task(rcu_dereference(mm->owner));
if (unlikely(!mem)) {
rcu_read_unlock();
kmem_cache_free(page_cgroup_cache, pc);
return 0;
}
/*
* For every charge from the cgroup, increment reference count
*/
Expand Down Expand Up @@ -801,6 +814,10 @@ int mem_cgroup_shrink_usage(struct mm_struct *mm, gfp_t gfp_mask)

rcu_read_lock();
mem = mem_cgroup_from_task(rcu_dereference(mm->owner));
if (unlikely(!mem)) {
rcu_read_unlock();
return 0;
}
css_get(&mem->css);
rcu_read_unlock();

Expand Down

0 comments on commit e5b3128

Please sign in to comment.