aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2013-10-05 22:24:29 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2013-11-09 00:16:24 -0500
commitcdc3d5627d5f7c4e6b6372b9fb39cba0fe6a9b2a (patch)
treea171558a3396fbcf89a82a065d4f0742ddc22076
parente6c1baa9b562ca296d57178c44f3894795d13d32 (diff)
switch elf_coredump_extra_notes_write() to dump_emit()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--arch/powerpc/include/asm/spu.h3
-rw-r--r--arch/powerpc/platforms/cell/spu_syscalls.c5
-rw-r--r--arch/powerpc/platforms/cell/spufs/coredump.c44
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h3
-rw-r--r--fs/binfmt_elf.c7
-rw-r--r--include/linux/elf.h6
6 files changed, 30 insertions, 38 deletions
diff --git a/arch/powerpc/include/asm/spu.h b/arch/powerpc/include/asm/spu.h
index 93f280e23279..37b7ca39ec9f 100644
--- a/arch/powerpc/include/asm/spu.h
+++ b/arch/powerpc/include/asm/spu.h
@@ -235,6 +235,7 @@ extern long spu_sys_callback(struct spu_syscall_block *s);
235 235
236/* syscalls implemented in spufs */ 236/* syscalls implemented in spufs */
237struct file; 237struct file;
238struct coredump_params;
238struct spufs_calls { 239struct spufs_calls {
239 long (*create_thread)(const char __user *name, 240 long (*create_thread)(const char __user *name,
240 unsigned int flags, umode_t mode, 241 unsigned int flags, umode_t mode,
@@ -242,7 +243,7 @@ struct spufs_calls {
242 long (*spu_run)(struct file *filp, __u32 __user *unpc, 243 long (*spu_run)(struct file *filp, __u32 __user *unpc,
243 __u32 __user *ustatus); 244 __u32 __user *ustatus);
244 int (*coredump_extra_notes_size)(void); 245 int (*coredump_extra_notes_size)(void);
245 int (*coredump_extra_notes_write)(struct file *file, loff_t *foffset); 246 int (*coredump_extra_notes_write)(struct coredump_params *cprm);
246 void (*notify_spus_active)(void); 247 void (*notify_spus_active)(void);
247 struct module *owner; 248 struct module *owner;
248}; 249};
diff --git a/arch/powerpc/platforms/cell/spu_syscalls.c b/arch/powerpc/platforms/cell/spu_syscalls.c
index db4e638cf408..3844f1397fc3 100644
--- a/arch/powerpc/platforms/cell/spu_syscalls.c
+++ b/arch/powerpc/platforms/cell/spu_syscalls.c
@@ -25,6 +25,7 @@
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/syscalls.h> 26#include <linux/syscalls.h>
27#include <linux/rcupdate.h> 27#include <linux/rcupdate.h>
28#include <linux/binfmts.h>
28 29
29#include <asm/spu.h> 30#include <asm/spu.h>
30 31
@@ -126,7 +127,7 @@ int elf_coredump_extra_notes_size(void)
126 return ret; 127 return ret;
127} 128}
128 129
129int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset) 130int elf_coredump_extra_notes_write(struct coredump_params *cprm)
130{ 131{
131 struct spufs_calls *calls; 132 struct spufs_calls *calls;
132 int ret; 133 int ret;
@@ -135,7 +136,7 @@ int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset)
135 if (!calls) 136 if (!calls)
136 return 0; 137 return 0;
137 138
138 ret = calls->coredump_extra_notes_write(file, foffset); 139 ret = calls->coredump_extra_notes_write(cprm);
139 140
140 spufs_calls_put(calls); 141 spufs_calls_put(calls);
141 142
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index c9500ea7be2f..5d9b0a288f36 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -27,6 +27,8 @@
27#include <linux/gfp.h> 27#include <linux/gfp.h>
28#include <linux/list.h> 28#include <linux/list.h>
29#include <linux/syscalls.h> 29#include <linux/syscalls.h>
30#include <linux/coredump.h>
31#include <linux/binfmts.h>
30 32
31#include <asm/uaccess.h> 33#include <asm/uaccess.h>
32 34
@@ -52,35 +54,24 @@ static ssize_t do_coredump_read(int num, struct spu_context *ctx, void *buffer,
52 * These are the only things you should do on a core-file: use only these 54 * These are the only things you should do on a core-file: use only these
53 * functions to write out all the necessary info. 55 * functions to write out all the necessary info.
54 */ 56 */
55static int spufs_dump_write(struct file *file, const void *addr, int nr, loff_t *foffset) 57static int spufs_dump_write(struct coredump_params *cprm, const void *addr, int nr)
56{ 58{
57 unsigned long limit = rlimit(RLIMIT_CORE); 59 if (!dump_emit(cprm, addr, nr))
58 ssize_t written;
59
60 if (*foffset + nr > limit)
61 return -EIO; 60 return -EIO;
62
63 written = file->f_op->write(file, addr, nr, &file->f_pos);
64 *foffset += written;
65
66 if (written != nr)
67 return -EIO;
68
69 return 0; 61 return 0;
70} 62}
71 63
72static int spufs_dump_align(struct file *file, char *buf, loff_t new_off, 64static int spufs_dump_align(struct coredump_params *cprm, char *buf, loff_t new_off)
73 loff_t *foffset)
74{ 65{
75 int rc, size; 66 int rc, size;
76 67
77 size = min((loff_t)PAGE_SIZE, new_off - *foffset); 68 size = min((loff_t)PAGE_SIZE, new_off - cprm->written);
78 memset(buf, 0, size); 69 memset(buf, 0, size);
79 70
80 rc = 0; 71 rc = 0;
81 while (rc == 0 && new_off > *foffset) { 72 while (rc == 0 && new_off > cprm->written) {
82 size = min((loff_t)PAGE_SIZE, new_off - *foffset); 73 size = min((loff_t)PAGE_SIZE, new_off - cprm->written);
83 rc = spufs_dump_write(file, buf, size, foffset); 74 rc = spufs_dump_write(cprm, buf, size);
84 } 75 }
85 76
86 return rc; 77 return rc;
@@ -165,7 +156,7 @@ int spufs_coredump_extra_notes_size(void)
165} 156}
166 157
167static int spufs_arch_write_note(struct spu_context *ctx, int i, 158static int spufs_arch_write_note(struct spu_context *ctx, int i,
168 struct file *file, int dfd, loff_t *foffset) 159 struct coredump_params *cprm, int dfd)
169{ 160{
170 loff_t pos = 0; 161 loff_t pos = 0;
171 int sz, rc, nread, total = 0; 162 int sz, rc, nread, total = 0;
@@ -186,22 +177,22 @@ static int spufs_arch_write_note(struct spu_context *ctx, int i,
186 en.n_descsz = sz; 177 en.n_descsz = sz;
187 en.n_type = NT_SPU; 178 en.n_type = NT_SPU;
188 179
189 rc = spufs_dump_write(file, &en, sizeof(en), foffset); 180 rc = spufs_dump_write(cprm, &en, sizeof(en));
190 if (rc) 181 if (rc)
191 goto out; 182 goto out;
192 183
193 rc = spufs_dump_write(file, fullname, en.n_namesz, foffset); 184 rc = spufs_dump_write(cprm, fullname, en.n_namesz);
194 if (rc) 185 if (rc)
195 goto out; 186 goto out;
196 187
197 rc = spufs_dump_align(file, buf, roundup(*foffset, 4), foffset); 188 rc = spufs_dump_align(cprm, buf, roundup(cprm->written, 4));
198 if (rc) 189 if (rc)
199 goto out; 190 goto out;
200 191
201 do { 192 do {
202 nread = do_coredump_read(i, ctx, buf, bufsz, &pos); 193 nread = do_coredump_read(i, ctx, buf, bufsz, &pos);
203 if (nread > 0) { 194 if (nread > 0) {
204 rc = spufs_dump_write(file, buf, nread, foffset); 195 rc = spufs_dump_write(cprm, buf, nread);
205 if (rc) 196 if (rc)
206 goto out; 197 goto out;
207 total += nread; 198 total += nread;
@@ -213,15 +204,14 @@ static int spufs_arch_write_note(struct spu_context *ctx, int i,
213 goto out; 204 goto out;
214 } 205 }
215 206
216 rc = spufs_dump_align(file, buf, roundup(*foffset - total + sz, 4), 207 rc = spufs_dump_align(cprm, buf, roundup(cprm->written - total + sz, 4));
217 foffset);
218 208
219out: 209out:
220 free_page((unsigned long)buf); 210 free_page((unsigned long)buf);
221 return rc; 211 return rc;
222} 212}
223 213
224int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset) 214int spufs_coredump_extra_notes_write(struct coredump_params *cprm)
225{ 215{
226 struct spu_context *ctx; 216 struct spu_context *ctx;
227 int fd, j, rc; 217 int fd, j, rc;
@@ -233,7 +223,7 @@ int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset)
233 return rc; 223 return rc;
234 224
235 for (j = 0; spufs_coredump_read[j].name != NULL; j++) { 225 for (j = 0; spufs_coredump_read[j].name != NULL; j++) {
236 rc = spufs_arch_write_note(ctx, j, file, fd, foffset); 226 rc = spufs_arch_write_note(ctx, j, cprm, fd);
237 if (rc) { 227 if (rc) {
238 spu_release_saved(ctx); 228 spu_release_saved(ctx);
239 return rc; 229 return rc;
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 67852ade4c01..0ba3c9598358 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -247,12 +247,13 @@ extern const struct spufs_tree_descr spufs_dir_debug_contents[];
247 247
248/* system call implementation */ 248/* system call implementation */
249extern struct spufs_calls spufs_calls; 249extern struct spufs_calls spufs_calls;
250struct coredump_params;
250long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *status); 251long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *status);
251long spufs_create(struct path *nd, struct dentry *dentry, unsigned int flags, 252long spufs_create(struct path *nd, struct dentry *dentry, unsigned int flags,
252 umode_t mode, struct file *filp); 253 umode_t mode, struct file *filp);
253/* ELF coredump callbacks for writing SPU ELF notes */ 254/* ELF coredump callbacks for writing SPU ELF notes */
254extern int spufs_coredump_extra_notes_size(void); 255extern int spufs_coredump_extra_notes_size(void);
255extern int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset); 256extern int spufs_coredump_extra_notes_write(struct coredump_params *cprm);
256 257
257extern const struct file_operations spufs_context_fops; 258extern const struct file_operations spufs_context_fops;
258 259
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index ddab40d3d828..3bf75d767a4a 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -2037,7 +2037,7 @@ static int elf_core_dump(struct coredump_params *cprm)
2037 size_t size = 0; 2037 size_t size = 0;
2038 struct vm_area_struct *vma, *gate_vma; 2038 struct vm_area_struct *vma, *gate_vma;
2039 struct elfhdr *elf = NULL; 2039 struct elfhdr *elf = NULL;
2040 loff_t offset = 0, dataoff, foffset; 2040 loff_t offset = 0, dataoff;
2041 struct elf_note_info info = { }; 2041 struct elf_note_info info = { };
2042 struct elf_phdr *phdr4note = NULL; 2042 struct elf_phdr *phdr4note = NULL;
2043 struct elf_shdr *shdr4extnum = NULL; 2043 struct elf_shdr *shdr4extnum = NULL;
@@ -2160,12 +2160,11 @@ static int elf_core_dump(struct coredump_params *cprm)
2160 if (!write_note_info(&info, cprm)) 2160 if (!write_note_info(&info, cprm))
2161 goto end_coredump; 2161 goto end_coredump;
2162 2162
2163 foffset = cprm->written; 2163 if (elf_coredump_extra_notes_write(cprm))
2164 if (elf_coredump_extra_notes_write(cprm->file, &foffset))
2165 goto end_coredump; 2164 goto end_coredump;
2166 2165
2167 /* Align to page */ 2166 /* Align to page */
2168 if (!dump_seek(cprm->file, dataoff - foffset)) 2167 if (!dump_seek(cprm->file, dataoff - cprm->written))
2169 goto end_coredump; 2168 goto end_coredump;
2170 2169
2171 cprm->written = size; 2170 cprm->written = size;
diff --git a/include/linux/elf.h b/include/linux/elf.h
index 40a3c0e01b2b..67a5fa7830c4 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -39,13 +39,13 @@ extern Elf64_Dyn _DYNAMIC [];
39 39
40/* Optional callbacks to write extra ELF notes. */ 40/* Optional callbacks to write extra ELF notes. */
41struct file; 41struct file;
42struct coredump_params;
42 43
43#ifndef ARCH_HAVE_EXTRA_ELF_NOTES 44#ifndef ARCH_HAVE_EXTRA_ELF_NOTES
44static inline int elf_coredump_extra_notes_size(void) { return 0; } 45static inline int elf_coredump_extra_notes_size(void) { return 0; }
45static inline int elf_coredump_extra_notes_write(struct file *file, 46static inline int elf_coredump_extra_notes_write(struct coredump_params *cprm) { return 0; }
46 loff_t *foffset) { return 0; }
47#else 47#else
48extern int elf_coredump_extra_notes_size(void); 48extern int elf_coredump_extra_notes_size(void);
49extern int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset); 49extern int elf_coredump_extra_notes_write(struct coredump_params *cprm);
50#endif 50#endif
51#endif /* _LINUX_ELF_H */ 51#endif /* _LINUX_ELF_H */