diff options
author | Michael Ellerman <michael@ellerman.id.au> | 2007-09-19 04:38:12 (GMT) |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-09-19 05:12:17 (GMT) |
commit | f9b7bbe7a803c6f10e7b3a354c5d97f632060320 (patch) | |
tree | 185d60f1b2c4a708a11851b0bf0522adc9f144cb /arch/powerpc/platforms/cell/spufs/coredump.c | |
parent | a595ed662c96dcd920415bea3135ff1af60e9a00 (diff) | |
download | linux-fsl-qoriq-f9b7bbe7a803c6f10e7b3a354c5d97f632060320.tar.xz |
[POWERPC] spufs: Remove ctx_info and ctx_info_list
Remove the ctx_info struct entirely, and also the ctx_info_list. This
fixes a race where two processes can clobber each other's ctx_info structs.
Instead of using the list, we just repeat the search through the file
descriptor table.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/cell/spufs/coredump.c')
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/coredump.c | 79 |
1 files changed, 19 insertions, 60 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c index 99f8e0b..6663669 100644 --- a/arch/powerpc/platforms/cell/spufs/coredump.c +++ b/arch/powerpc/platforms/cell/spufs/coredump.c @@ -31,15 +31,6 @@ #include "spufs.h" -struct spufs_ctx_info { - struct list_head list; - int dfd; - int memsize; /* in bytes */ - struct spu_context *ctx; -}; - -static LIST_HEAD(ctx_info_list); - static ssize_t do_coredump_read(int num, struct spu_context *ctx, void __user *buffer, size_t size, loff_t *off) { @@ -73,25 +64,17 @@ static int spufs_dump_seek(struct file *file, loff_t off) return 1; } -static void spufs_fill_memsize(struct spufs_ctx_info *ctx_info) +static u64 ctx_ls_size(struct spu_context *ctx) { - struct spu_context *ctx; - unsigned long long lslr; - - ctx = ctx_info->ctx; - lslr = ctx->csa.priv2.spu_lslr_RW; - ctx_info->memsize = lslr + 1; + return ctx->csa.priv2.spu_lslr_RW + 1; } -static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info) +static int spufs_ctx_note_size(struct spu_context *ctx, int dfd) { - int dfd, memsize, i, sz, total = 0; + int i, sz, total = 0; char *name; char fullname[80]; - dfd = ctx_info->dfd; - memsize = ctx_info->memsize; - for (i = 0; spufs_coredump_read[i].name; i++) { name = spufs_coredump_read[i].name; sz = spufs_coredump_read[i].size; @@ -101,7 +84,7 @@ static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info) total += sizeof(struct elf_note); total += roundup(strlen(fullname) + 1, 4); if (!strcmp(name, "mem")) - total += roundup(memsize, 4); + total += roundup(ctx_ls_size(ctx), 4); else total += roundup(sz, 4); } @@ -109,25 +92,6 @@ static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info) return total; } -static int spufs_add_one_context(struct spu_context *ctx, int dfd) -{ - struct spufs_ctx_info *ctx_info; - int size; - - ctx_info = kzalloc(sizeof(*ctx_info), GFP_KERNEL); - if (unlikely(!ctx_info)) - return -ENOMEM; - - ctx_info->dfd = dfd; - ctx_info->ctx = ctx; - - spufs_fill_memsize(ctx_info); - - size = spufs_ctx_note_size(ctx_info); - list_add(&ctx_info->list, &ctx_info_list); - return size; -} - /* * The additional architecture-specific notes for Cell are various * context files in the spu context. @@ -171,7 +135,7 @@ static int spufs_arch_notes_size(void) fd = 0; while ((ctx = coredump_next_context(&fd)) != NULL) { - rc = spufs_add_one_context(ctx, fd); + rc = spufs_ctx_note_size(ctx, fd); if (rc < 0) break; @@ -181,12 +145,11 @@ static int spufs_arch_notes_size(void) return size; } -static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i, - struct file *file) +static void spufs_arch_write_note(struct spu_context *ctx, int i, + struct file *file, int dfd) { - struct spu_context *ctx; loff_t pos = 0; - int sz, dfd, rc, total = 0; + int sz, rc, total = 0; const int bufsz = PAGE_SIZE; char *name; char fullname[80], *buf; @@ -196,18 +159,13 @@ static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i, if (!buf) return; - dfd = ctx_info->dfd; name = spufs_coredump_read[i].name; if (!strcmp(name, "mem")) - sz = ctx_info->memsize; + sz = ctx_ls_size(ctx); else sz = spufs_coredump_read[i].size; - ctx = ctx_info->ctx; - if (!ctx) - goto out; - sprintf(fullname, "SPU/%d/%s", dfd, name); en.n_namesz = strlen(fullname) + 1; en.n_descsz = sz; @@ -237,16 +195,17 @@ out: static void spufs_arch_write_notes(struct file *file) { - int j; - struct spufs_ctx_info *ctx_info, *next; + struct spu_context *ctx; + int fd, j; + + fd = 0; + while ((ctx = coredump_next_context(&fd)) != NULL) { + spu_acquire_saved(ctx); - list_for_each_entry_safe(ctx_info, next, &ctx_info_list, list) { - spu_acquire_saved(ctx_info->ctx); for (j = 0; j < spufs_coredump_num_notes; j++) - spufs_arch_write_note(ctx_info, j, file); - spu_release_saved(ctx_info->ctx); - list_del(&ctx_info->list); - kfree(ctx_info); + spufs_arch_write_note(ctx, j, file, fd); + + spu_release_saved(ctx); } } |