Skip to content

Commit

Permalink
mempolicy: write lock mmap_sem while changing task mempolicy
Browse files Browse the repository at this point in the history
A read of /proc/<pid>/numa_maps holds the target task's mmap_sem for read
while examining each vma's mempolicy.  A vma's mempolicy can fall back to the
task's policy.  However, the task could be changing it's task policy and free
the one that the show_numa_maps() is examining.

To prevent this, grab the mmap_sem for write when updating task mempolicy.
Pointed out to me by Christoph Lameter and extracted and reworked from
Christoph's alternative mempol reference counting patch.

This is analogous to the way that do_mbind() and do_get_mempolicy() prevent
races between task's sharing an mm_struct [a.k.a.  threads] setting and
querying a mempolicy for a particular address.

Note: this is necessary, but not sufficient, to allow us to stop taking an
extra reference on "other task's mempolicy" in get_vma_policy.  Subsequent
patches will complete this update, allowing us to simplify the tests for
whether we need to unref a mempolicy at various points in the code.

Signed-off-by: Lee Schermerhorn <lee.schermerhorn@hp.com>
Cc: Christoph Lameter <clameter@sgi.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Lee Schermerhorn authored and Linus Torvalds committed Apr 28, 2008
1 parent 846a16b commit f4e53d9
Showing 1 changed file with 13 additions and 0 deletions.
13 changes: 13 additions & 0 deletions mm/mempolicy.c
Original file line number Diff line number Diff line change
Expand Up @@ -591,16 +591,29 @@ static long do_set_mempolicy(unsigned short mode, unsigned short flags,
nodemask_t *nodes)
{
struct mempolicy *new;
struct mm_struct *mm = current->mm;

new = mpol_new(mode, flags, nodes);
if (IS_ERR(new))
return PTR_ERR(new);

/*
* prevent changing our mempolicy while show_numa_maps()
* is using it.
* Note: do_set_mempolicy() can be called at init time
* with no 'mm'.
*/
if (mm)
down_write(&mm->mmap_sem);
mpol_put(current->mempolicy);
current->mempolicy = new;
mpol_set_task_struct_flag();
if (new && new->policy == MPOL_INTERLEAVE &&
nodes_weight(new->v.nodes))
current->il_next = first_node(new->v.nodes);
if (mm)
up_write(&mm->mmap_sem);

return 0;
}

Expand Down

0 comments on commit f4e53d9

Please sign in to comment.