diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/mem.c | 49 |
1 files changed, 22 insertions, 27 deletions
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 192af59afc13..868ff2ce1675 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -440,19 +440,18 @@ static ssize_t read_kmem(struct file *file, char __user *buf, | |||
440 | if (!kbuf) | 440 | if (!kbuf) |
441 | return -ENOMEM; | 441 | return -ENOMEM; |
442 | while (count > 0) { | 442 | while (count > 0) { |
443 | int len = size_inside_page(p, count); | 443 | sz = size_inside_page(p, count); |
444 | 444 | sz = vread(kbuf, (char *)p, sz); | |
445 | len = vread(kbuf, (char *)p, len); | 445 | if (!sz) |
446 | if (!len) | ||
447 | break; | 446 | break; |
448 | if (copy_to_user(buf, kbuf, len)) { | 447 | if (copy_to_user(buf, kbuf, sz)) { |
449 | free_page((unsigned long)kbuf); | 448 | free_page((unsigned long)kbuf); |
450 | return -EFAULT; | 449 | return -EFAULT; |
451 | } | 450 | } |
452 | count -= len; | 451 | count -= sz; |
453 | buf += len; | 452 | buf += sz; |
454 | read += len; | 453 | read += sz; |
455 | p += len; | 454 | p += sz; |
456 | } | 455 | } |
457 | free_page((unsigned long)kbuf); | 456 | free_page((unsigned long)kbuf); |
458 | } | 457 | } |
@@ -522,19 +521,14 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, | |||
522 | unsigned long p = *ppos; | 521 | unsigned long p = *ppos; |
523 | ssize_t wrote = 0; | 522 | ssize_t wrote = 0; |
524 | ssize_t virtr = 0; | 523 | ssize_t virtr = 0; |
525 | ssize_t written; | ||
526 | char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ | 524 | char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ |
527 | 525 | ||
528 | if (p < (unsigned long) high_memory) { | 526 | if (p < (unsigned long) high_memory) { |
529 | 527 | unsigned long to_write = min_t(unsigned long, count, | |
530 | wrote = count; | 528 | (unsigned long)high_memory - p); |
531 | if (count > (unsigned long) high_memory - p) | 529 | wrote = do_write_kmem((void *)p, p, buf, to_write, ppos); |
532 | wrote = (unsigned long) high_memory - p; | 530 | if (wrote != to_write) |
533 | 531 | return wrote; | |
534 | written = do_write_kmem((void*)p, p, buf, wrote, ppos); | ||
535 | if (written != wrote) | ||
536 | return written; | ||
537 | wrote = written; | ||
538 | p += wrote; | 532 | p += wrote; |
539 | buf += wrote; | 533 | buf += wrote; |
540 | count -= wrote; | 534 | count -= wrote; |
@@ -545,20 +539,21 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, | |||
545 | if (!kbuf) | 539 | if (!kbuf) |
546 | return wrote ? wrote : -ENOMEM; | 540 | return wrote ? wrote : -ENOMEM; |
547 | while (count > 0) { | 541 | while (count > 0) { |
548 | int len = size_inside_page(p, count); | 542 | unsigned long sz = size_inside_page(p, count); |
543 | unsigned long n; | ||
549 | 544 | ||
550 | written = copy_from_user(kbuf, buf, len); | 545 | n = copy_from_user(kbuf, buf, sz); |
551 | if (written) { | 546 | if (n) { |
552 | if (wrote + virtr) | 547 | if (wrote + virtr) |
553 | break; | 548 | break; |
554 | free_page((unsigned long)kbuf); | 549 | free_page((unsigned long)kbuf); |
555 | return -EFAULT; | 550 | return -EFAULT; |
556 | } | 551 | } |
557 | len = vwrite(kbuf, (char *)p, len); | 552 | sz = vwrite(kbuf, (char *)p, sz); |
558 | count -= len; | 553 | count -= sz; |
559 | buf += len; | 554 | buf += sz; |
560 | virtr += len; | 555 | virtr += sz; |
561 | p += len; | 556 | p += sz; |
562 | } | 557 | } |
563 | free_page((unsigned long)kbuf); | 558 | free_page((unsigned long)kbuf); |
564 | } | 559 | } |