diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-10-08 09:11:48 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-11-09 00:16:26 -0500 |
commit | 2507a4fbd48a96bc4236e584252635f8539079df (patch) | |
tree | d31719bcacb80dc5b3ccfa99c28e5a2c92602aa6 /fs/coredump.c | |
parent | 1ad67015e619ba4e0b15ed0482d464292fedf263 (diff) |
make dump_emit() use vfs_write() instead of banging at ->f_op->write directly
... and deal with short writes properly - the output might be to pipe, after
all; as it is, e.g. no-MMU case of elf_fdpic coredump can write a whole lot
more than a page worth of data at one call.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/coredump.c')
-rw-r--r-- | fs/coredump.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/fs/coredump.c b/fs/coredump.c index 319f973bab72..2472ed9e682c 100644 --- a/fs/coredump.c +++ b/fs/coredump.c | |||
@@ -696,13 +696,20 @@ EXPORT_SYMBOL(dump_write); | |||
696 | int dump_emit(struct coredump_params *cprm, const void *addr, int nr) | 696 | int dump_emit(struct coredump_params *cprm, const void *addr, int nr) |
697 | { | 697 | { |
698 | struct file *file = cprm->file; | 698 | struct file *file = cprm->file; |
699 | if (dump_interrupted() || !access_ok(VERIFY_READ, addr, nr)) | 699 | loff_t pos = file->f_pos; |
700 | return 0; | 700 | ssize_t n; |
701 | if (cprm->written + nr > cprm->limit) | 701 | if (cprm->written + nr > cprm->limit) |
702 | return 0; | 702 | return 0; |
703 | if (file->f_op->write(file, addr, nr, &file->f_pos) != nr) | 703 | while (nr) { |
704 | return 0; | 704 | if (dump_interrupted()) |
705 | cprm->written += nr; | 705 | return 0; |
706 | n = vfs_write(file, addr, nr, &pos); | ||
707 | if (n <= 0) | ||
708 | return 0; | ||
709 | file->f_pos = pos; | ||
710 | cprm->written += n; | ||
711 | nr -= n; | ||
712 | } | ||
706 | return 1; | 713 | return 1; |
707 | } | 714 | } |
708 | EXPORT_SYMBOL(dump_emit); | 715 | EXPORT_SYMBOL(dump_emit); |