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 | |
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')
-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__ |