Commit a0a7ec30 authored by JANAK DESAI's avatar JANAK DESAI Committed by Linus Torvalds

[PATCH] unshare system call -v5: unshare vm

If vm structure is being shared, allocate a new one and copy information from
the current, shared, structure.
Signed-off-by: default avatarJanak Desai <janak@us.ibm.com>
Cc: Al Viro <viro@ftp.linux.org.uk>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Michael Kerrisk <mtk-manpages@gmx.net>
Cc: Andi Kleen <ak@muc.de>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 741a2951
...@@ -446,6 +446,55 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm) ...@@ -446,6 +446,55 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm)
} }
} }
/*
* Allocate a new mm structure and copy contents from the
* mm structure of the passed in task structure.
*/
static struct mm_struct *dup_mm(struct task_struct *tsk)
{
struct mm_struct *mm, *oldmm = current->mm;
int err;
if (!oldmm)
return NULL;
mm = allocate_mm();
if (!mm)
goto fail_nomem;
memcpy(mm, oldmm, sizeof(*mm));
if (!mm_init(mm))
goto fail_nomem;
if (init_new_context(tsk, mm))
goto fail_nocontext;
err = dup_mmap(mm, oldmm);
if (err)
goto free_pt;
mm->hiwater_rss = get_mm_rss(mm);
mm->hiwater_vm = mm->total_vm;
return mm;
free_pt:
mmput(mm);
fail_nomem:
return NULL;
fail_nocontext:
/*
* If init_new_context() failed, we cannot use mmput() to free the mm
* because it calls destroy_context()
*/
mm_free_pgd(mm);
free_mm(mm);
return NULL;
}
static int copy_mm(unsigned long clone_flags, struct task_struct * tsk) static int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
{ {
struct mm_struct * mm, *oldmm; struct mm_struct * mm, *oldmm;
...@@ -473,43 +522,17 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * tsk) ...@@ -473,43 +522,17 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
} }
retval = -ENOMEM; retval = -ENOMEM;
mm = allocate_mm(); mm = dup_mm(tsk);
if (!mm) if (!mm)
goto fail_nomem; goto fail_nomem;
/* Copy the current MM stuff.. */
memcpy(mm, oldmm, sizeof(*mm));
if (!mm_init(mm))
goto fail_nomem;
if (init_new_context(tsk,mm))
goto fail_nocontext;
retval = dup_mmap(mm, oldmm);
if (retval)
goto free_pt;
mm->hiwater_rss = get_mm_rss(mm);
mm->hiwater_vm = mm->total_vm;
good_mm: good_mm:
tsk->mm = mm; tsk->mm = mm;
tsk->active_mm = mm; tsk->active_mm = mm;
return 0; return 0;
free_pt:
mmput(mm);
fail_nomem: fail_nomem:
return retval; return retval;
fail_nocontext:
/*
* If init_new_context() failed, we cannot use mmput() to free the mm
* because it calls destroy_context()
*/
mm_free_pgd(mm);
free_mm(mm);
return retval;
} }
static inline struct fs_struct *__copy_fs_struct(struct fs_struct *old) static inline struct fs_struct *__copy_fs_struct(struct fs_struct *old)
...@@ -1423,18 +1446,20 @@ static int unshare_sighand(unsigned long unshare_flags, struct sighand_struct ** ...@@ -1423,18 +1446,20 @@ static int unshare_sighand(unsigned long unshare_flags, struct sighand_struct **
} }
/* /*
* Unsharing of vm for tasks created with CLONE_VM is not supported yet * Unshare vm if it is being shared
*/ */
static int unshare_vm(unsigned long unshare_flags, struct mm_struct **new_mmp) static int unshare_vm(unsigned long unshare_flags, struct mm_struct **new_mmp)
{ {
struct mm_struct *mm = current->mm; struct mm_struct *mm = current->mm;
if ((unshare_flags & CLONE_VM) && if ((unshare_flags & CLONE_VM) &&
(mm && atomic_read(&mm->mm_users) > 1)) (mm && atomic_read(&mm->mm_users) > 1)) {
return -EINVAL; *new_mmp = dup_mm(current);
if (!*new_mmp)
return -ENOMEM;
}
return 0; return 0;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment