diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/mem.c | 51 |
1 files changed, 15 insertions, 36 deletions
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 01b3c17ca851..b64108dd765b 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/highmem.h> | 26 | #include <linux/highmem.h> |
27 | #include <linux/crash_dump.h> | 27 | #include <linux/crash_dump.h> |
28 | #include <linux/backing-dev.h> | 28 | #include <linux/backing-dev.h> |
29 | #include <linux/bootmem.h> | ||
29 | 30 | ||
30 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
31 | #include <asm/io.h> | 32 | #include <asm/io.h> |
@@ -278,55 +279,33 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma) | |||
278 | #ifdef CONFIG_CRASH_DUMP | 279 | #ifdef CONFIG_CRASH_DUMP |
279 | /* | 280 | /* |
280 | * Read memory corresponding to the old kernel. | 281 | * Read memory corresponding to the old kernel. |
281 | * If we are reading from the reserved section, which is | ||
282 | * actually used by the current kernel, we just return zeroes. | ||
283 | * Or if we are reading from the first 640k, we return from the | ||
284 | * backed up area. | ||
285 | */ | 282 | */ |
286 | static ssize_t read_oldmem(struct file * file, char * buf, | 283 | static ssize_t read_oldmem(struct file *file, char __user *buf, |
287 | size_t count, loff_t *ppos) | 284 | size_t count, loff_t *ppos) |
288 | { | 285 | { |
289 | unsigned long pfn; | 286 | unsigned long pfn, offset; |
290 | unsigned backup_start, backup_end, relocate_start; | 287 | size_t read = 0, csize; |
291 | size_t read=0, csize; | 288 | int rc = 0; |
292 | |||
293 | backup_start = CRASH_BACKUP_BASE / PAGE_SIZE; | ||
294 | backup_end = backup_start + (CRASH_BACKUP_SIZE / PAGE_SIZE); | ||
295 | relocate_start = (CRASH_BACKUP_BASE + CRASH_BACKUP_SIZE) / PAGE_SIZE; | ||
296 | 289 | ||
297 | while(count) { | 290 | while(count) { |
298 | pfn = *ppos / PAGE_SIZE; | 291 | pfn = *ppos / PAGE_SIZE; |
292 | if (pfn > saved_max_pfn) | ||
293 | return read; | ||
299 | 294 | ||
300 | csize = (count > PAGE_SIZE) ? PAGE_SIZE : count; | 295 | offset = (unsigned long)(*ppos % PAGE_SIZE); |
301 | 296 | if (count > PAGE_SIZE - offset) | |
302 | /* Perform translation (see comment above) */ | 297 | csize = PAGE_SIZE - offset; |
303 | if ((pfn >= backup_start) && (pfn < backup_end)) { | 298 | else |
304 | if (clear_user(buf, csize)) { | 299 | csize = count; |
305 | read = -EFAULT; | ||
306 | goto done; | ||
307 | } | ||
308 | |||
309 | goto copy_done; | ||
310 | } else if (pfn < (CRASH_RELOCATE_SIZE / PAGE_SIZE)) | ||
311 | pfn += relocate_start; | ||
312 | |||
313 | if (pfn > saved_max_pfn) { | ||
314 | read = 0; | ||
315 | goto done; | ||
316 | } | ||
317 | |||
318 | if (copy_oldmem_page(pfn, buf, csize, 1)) { | ||
319 | read = -EFAULT; | ||
320 | goto done; | ||
321 | } | ||
322 | 300 | ||
323 | copy_done: | 301 | rc = copy_oldmem_page(pfn, buf, csize, offset, 1); |
302 | if (rc < 0) | ||
303 | return rc; | ||
324 | buf += csize; | 304 | buf += csize; |
325 | *ppos += csize; | 305 | *ppos += csize; |
326 | read += csize; | 306 | read += csize; |
327 | count -= csize; | 307 | count -= csize; |
328 | } | 308 | } |
329 | done: | ||
330 | return read; | 309 | return read; |
331 | } | 310 | } |
332 | #endif | 311 | #endif |