diff options
| author | Davidlohr Bueso <dave@stgolabs.net> | 2015-02-25 16:58:35 -0500 |
|---|---|---|
| committer | Chris Metcalf <cmetcalf@ezchip.com> | 2015-04-17 12:58:31 -0400 |
| commit | 5a3b4e8000c1ce476f5e8babd62c580457561f34 (patch) | |
| tree | 9ee106a764964508ce11beff4b06b9727a7e8381 /arch/tile/mm | |
| parent | 89067c2daf3d9e0ce51c768589e79e845e6fda42 (diff) | |
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: Davidlohr Bueso <dbueso@suse.de>
Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com>
Diffstat (limited to 'arch/tile/mm')
| -rw-r--r-- | arch/tile/mm/elf.c | 47 |
1 files changed, 29 insertions, 18 deletions
diff --git a/arch/tile/mm/elf.c b/arch/tile/mm/elf.c index 23f044e8a7ab..f7ddae3725a4 100644 --- a/arch/tile/mm/elf.c +++ b/arch/tile/mm/elf.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/binfmts.h> | 17 | #include <linux/binfmts.h> |
| 18 | #include <linux/compat.h> | 18 | #include <linux/compat.h> |
| 19 | #include <linux/mman.h> | 19 | #include <linux/mman.h> |
| 20 | #include <linux/file.h> | ||
| 20 | #include <linux/elf.h> | 21 | #include <linux/elf.h> |
| 21 | #include <asm/pgtable.h> | 22 | #include <asm/pgtable.h> |
| 22 | #include <asm/pgalloc.h> | 23 | #include <asm/pgalloc.h> |
| @@ -39,30 +40,34 @@ static void sim_notify_exec(const char *binary_name) | |||
| 39 | 40 | ||
| 40 | static int notify_exec(struct mm_struct *mm) | 41 | static int notify_exec(struct mm_struct *mm) |
| 41 | { | 42 | { |
| 43 | int ret = 0; | ||
| 42 | char *buf, *path; | 44 | char *buf, *path; |
| 43 | struct vm_area_struct *vma; | 45 | struct vm_area_struct *vma; |
| 46 | struct file *exe_file; | ||
| 44 | 47 | ||
| 45 | if (!sim_is_simulator()) | 48 | if (!sim_is_simulator()) |
| 46 | return 1; | 49 | return 1; |
| 47 | 50 | ||
| 48 | if (mm->exe_file == NULL) | ||
| 49 | return 0; | ||
| 50 | |||
| 51 | for (vma = current->mm->mmap; ; vma = vma->vm_next) { | ||
| 52 | if (vma == NULL) | ||
| 53 | return 0; | ||
| 54 | if (vma->vm_file == mm->exe_file) | ||
| 55 | break; | ||
| 56 | } | ||
| 57 | |||
| 58 | buf = (char *) __get_free_page(GFP_KERNEL); | 51 | buf = (char *) __get_free_page(GFP_KERNEL); |
| 59 | if (buf == NULL) | 52 | if (buf == NULL) |
| 60 | return 0; | 53 | return 0; |
| 61 | 54 | ||
| 62 | path = d_path(&mm->exe_file->f_path, buf, PAGE_SIZE); | 55 | exe_file = get_mm_exe_file(mm); |
| 63 | if (IS_ERR(path)) { | 56 | if (exe_file == NULL) |
| 64 | free_page((unsigned long)buf); | 57 | goto done_free; |
| 65 | return 0; | 58 | |
| 59 | path = d_path(&exe_file->f_path, buf, PAGE_SIZE); | ||
| 60 | if (IS_ERR(path)) | ||
| 61 | goto done_put; | ||
| 62 | |||
| 63 | down_read(&mm->mmap_sem); | ||
| 64 | for (vma = current->mm->mmap; ; vma = vma->vm_next) { | ||
| 65 | if (vma == NULL) { | ||
| 66 | up_read(&mm->mmap_sem); | ||
| 67 | goto done_put; | ||
| 68 | } | ||
| 69 | if (vma->vm_file == exe_file) | ||
| 70 | break; | ||
| 66 | } | 71 | } |
| 67 | 72 | ||
| 68 | /* | 73 | /* |
| @@ -80,14 +85,20 @@ static int notify_exec(struct mm_struct *mm) | |||
| 80 | __insn_mtspr(SPR_SIM_CONTROL, | 85 | __insn_mtspr(SPR_SIM_CONTROL, |
| 81 | (SIM_CONTROL_DLOPEN | 86 | (SIM_CONTROL_DLOPEN |
| 82 | | (c << _SIM_CONTROL_OPERATOR_BITS))); | 87 | | (c << _SIM_CONTROL_OPERATOR_BITS))); |
| 83 | if (c == '\0') | 88 | if (c == '\0') { |
| 89 | ret = 1; /* success */ | ||
| 84 | break; | 90 | break; |
| 91 | } | ||
| 85 | } | 92 | } |
| 86 | } | 93 | } |
| 94 | up_read(&mm->mmap_sem); | ||
| 87 | 95 | ||
| 88 | sim_notify_exec(path); | 96 | sim_notify_exec(path); |
| 97 | done_put: | ||
| 98 | fput(exe_file); | ||
| 99 | done_free: | ||
| 89 | free_page((unsigned long)buf); | 100 | free_page((unsigned long)buf); |
| 90 | return 1; | 101 | return ret; |
| 91 | } | 102 | } |
| 92 | 103 | ||
| 93 | /* Notify a running simulator, if any, that we loaded an interpreter. */ | 104 | /* 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 | struct mm_struct *mm = current->mm; | 120 | struct mm_struct *mm = current->mm; |
| 110 | int retval = 0; | 121 | int retval = 0; |
| 111 | 122 | ||
| 112 | down_write(&mm->mmap_sem); | ||
| 113 | |||
| 114 | /* | 123 | /* |
| 115 | * Notify the simulator that an exec just occurred. | 124 | * Notify the simulator that an exec just occurred. |
| 116 | * If we can't find the filename of the mapping, just use | 125 | * 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 | if (!notify_exec(mm)) | 128 | if (!notify_exec(mm)) |
| 120 | sim_notify_exec(bprm->filename); | 129 | sim_notify_exec(bprm->filename); |
| 121 | 130 | ||
| 131 | down_write(&mm->mmap_sem); | ||
| 132 | |||
| 122 | retval = setup_vdso_pages(); | 133 | retval = setup_vdso_pages(); |
| 123 | 134 | ||
| 124 | #ifndef __tilegx__ | 135 | #ifndef __tilegx__ |
