diff options
| author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-10-19 09:13:00 +0100 |
|---|---|---|
| committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-10-19 09:14:50 +0100 |
| commit | fb9a90f7c674f3ddef6baf55cb1612dadd8ea752 (patch) | |
| tree | f25cf2ce17449ba34cdfdfb948134eb3464e400e /fs/exec.c | |
| parent | 2d7b8366ae4a9ec2183c30e432a4a9a495c82bcd (diff) | |
| parent | 21c74a8ea8b47eb6c3c621e36578f6e27f65c5c7 (diff) | |
Merge remote branch 'airlied/drm-core-next' into tmp
Diffstat (limited to 'fs/exec.c')
| -rw-r--r-- | fs/exec.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/fs/exec.c b/fs/exec.c index 828dd2461d6b..6d2b6f936858 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -2014,3 +2014,43 @@ fail_creds: fail: return; } + +/* + * Core dumping helper functions. These are the only things you should + * do on a core-file: use only these functions to write out all the + * necessary info. + */ +int dump_write(struct file *file, const void *addr, int nr) +{ + return access_ok(VERIFY_READ, addr, nr) && file->f_op->write(file, addr, nr, &file->f_pos) == nr; +} +EXPORT_SYMBOL(dump_write); + +int dump_seek(struct file *file, loff_t off) +{ + int ret = 1; + + if (file->f_op->llseek && file->f_op->llseek != no_llseek) { + if (file->f_op->llseek(file, off, SEEK_CUR) < 0) + return 0; + } else { + char *buf = (char *)get_zeroed_page(GFP_KERNEL); + + if (!buf) + return 0; + while (off > 0) { + unsigned long n = off; + + if (n > PAGE_SIZE) + n = PAGE_SIZE; + if (!dump_write(file, buf, n)) { + ret = 0; + break; + } + off -= n; + } + free_page((unsigned long)buf); + } + return ret; +} +EXPORT_SYMBOL(dump_seek); |
