Commit 5a3b4e80 authored by Davidlohr Bueso's avatar Davidlohr Bueso Committed by Chris Metcalf

tile/elf: reorganize notify_exec()

In the future mm->exe_file will be done without mmap_sem
serialization, thus isolate and reorganize the tile elf
code to make the transition easier. Good users will, make
use of the more standard get_mm_exe_file(), requiring only
holding the mmap_sem to read the value, and relying on reference
counting to make sure that the exe file won't dissappear
underneath us.

The visible effects of this patch are:

   o We now take and drop the mmap_sem more often. Instead of
     just in arch_setup_additional_pages(), we also do it in:

     1) get_mm_exe_file()
     2) to get the mm->vm_file and notify the simulator.

    [Note that 1) will disappear once we change the locking
     rules for exe_file.]

   o We avoid getting a free page and doing d_path() while
     holding the mmap_sem. This requires reordering the checks.
Signed-off-by: default avatarDavidlohr Bueso <dbueso@suse.de>
Signed-off-by: default avatarChris Metcalf <cmetcalf@ezchip.com>
parent 89067c2d
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/binfmts.h> #include <linux/binfmts.h>
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/mman.h> #include <linux/mman.h>
#include <linux/file.h>
#include <linux/elf.h> #include <linux/elf.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
...@@ -39,30 +40,34 @@ static void sim_notify_exec(const char *binary_name) ...@@ -39,30 +40,34 @@ static void sim_notify_exec(const char *binary_name)
static int notify_exec(struct mm_struct *mm) static int notify_exec(struct mm_struct *mm)
{ {
int ret = 0;
char *buf, *path; char *buf, *path;
struct vm_area_struct *vma; struct vm_area_struct *vma;
struct file *exe_file;
if (!sim_is_simulator()) if (!sim_is_simulator())
return 1; return 1;
if (mm->exe_file == NULL)
return 0;
for (vma = current->mm->mmap; ; vma = vma->vm_next) {
if (vma == NULL)
return 0;
if (vma->vm_file == mm->exe_file)
break;
}
buf = (char *) __get_free_page(GFP_KERNEL); buf = (char *) __get_free_page(GFP_KERNEL);
if (buf == NULL) if (buf == NULL)
return 0; return 0;
path = d_path(&mm->exe_file->f_path, buf, PAGE_SIZE); exe_file = get_mm_exe_file(mm);
if (IS_ERR(path)) { if (exe_file == NULL)
free_page((unsigned long)buf); goto done_free;
return 0;
path = d_path(&exe_file->f_path, buf, PAGE_SIZE);
if (IS_ERR(path))
goto done_put;
down_read(&mm->mmap_sem);
for (vma = current->mm->mmap; ; vma = vma->vm_next) {
if (vma == NULL) {
up_read(&mm->mmap_sem);
goto done_put;
}
if (vma->vm_file == exe_file)
break;
} }
/* /*
...@@ -80,14 +85,20 @@ static int notify_exec(struct mm_struct *mm) ...@@ -80,14 +85,20 @@ static int notify_exec(struct mm_struct *mm)
__insn_mtspr(SPR_SIM_CONTROL, __insn_mtspr(SPR_SIM_CONTROL,
(SIM_CONTROL_DLOPEN (SIM_CONTROL_DLOPEN
| (c << _SIM_CONTROL_OPERATOR_BITS))); | (c << _SIM_CONTROL_OPERATOR_BITS)));
if (c == '\0') if (c == '\0') {
ret = 1; /* success */
break; break;
}
} }
} }
up_read(&mm->mmap_sem);
sim_notify_exec(path); sim_notify_exec(path);
done_put:
fput(exe_file);
done_free:
free_page((unsigned long)buf); free_page((unsigned long)buf);
return 1; return ret;
} }
/* Notify a running simulator, if any, that we loaded an interpreter. */ /* Notify a running simulator, if any, that we loaded an interpreter. */
...@@ -109,8 +120,6 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, ...@@ -109,8 +120,6 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
struct mm_struct *mm = current->mm; struct mm_struct *mm = current->mm;
int retval = 0; int retval = 0;
down_write(&mm->mmap_sem);
/* /*
* Notify the simulator that an exec just occurred. * Notify the simulator that an exec just occurred.
* If we can't find the filename of the mapping, just use * If we can't find the filename of the mapping, just use
...@@ -119,6 +128,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, ...@@ -119,6 +128,8 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
if (!notify_exec(mm)) if (!notify_exec(mm))
sim_notify_exec(bprm->filename); sim_notify_exec(bprm->filename);
down_write(&mm->mmap_sem);
retval = setup_vdso_pages(); retval = setup_vdso_pages();
#ifndef __tilegx__ #ifndef __tilegx__
......
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