diff options
author | Oleg Nesterov <oleg@redhat.com> | 2012-01-31 11:14:54 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-02-01 17:39:01 -0500 |
commit | 572d34b946bae070debd42db1143034d9687e13f (patch) | |
tree | b913d612090e8ec25e92451120ef64692c802264 /fs/proc | |
parent | 71879d3cb3dd8f2dfdefb252775c1b3ea04a3dd4 (diff) |
proc: unify mem_read() and mem_write()
No functional changes, cleanup and preparation.
mem_read() and mem_write() are very similar. Move this code into the
new common helper, mem_rw(), which takes the additional "int write"
argument.
Cc: stable@kernel.org
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/base.c | 90 |
1 files changed, 32 insertions, 58 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index c3617ea7830b..be1909041685 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -718,57 +718,13 @@ static int mem_open(struct inode* inode, struct file* file) | |||
718 | return 0; | 718 | return 0; |
719 | } | 719 | } |
720 | 720 | ||
721 | static ssize_t mem_read(struct file * file, char __user * buf, | 721 | static ssize_t mem_rw(struct file *file, char __user *buf, |
722 | size_t count, loff_t *ppos) | 722 | size_t count, loff_t *ppos, int write) |
723 | { | 723 | { |
724 | int ret; | ||
725 | char *page; | ||
726 | unsigned long src = *ppos; | ||
727 | struct mm_struct *mm = file->private_data; | 724 | struct mm_struct *mm = file->private_data; |
728 | 725 | unsigned long addr = *ppos; | |
729 | if (!mm) | 726 | ssize_t copied; |
730 | return 0; | ||
731 | |||
732 | page = (char *)__get_free_page(GFP_TEMPORARY); | ||
733 | if (!page) | ||
734 | return -ENOMEM; | ||
735 | |||
736 | ret = 0; | ||
737 | |||
738 | while (count > 0) { | ||
739 | int this_len, retval; | ||
740 | |||
741 | this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; | ||
742 | retval = access_remote_vm(mm, src, page, this_len, 0); | ||
743 | if (!retval) { | ||
744 | if (!ret) | ||
745 | ret = -EIO; | ||
746 | break; | ||
747 | } | ||
748 | |||
749 | if (copy_to_user(buf, page, retval)) { | ||
750 | ret = -EFAULT; | ||
751 | break; | ||
752 | } | ||
753 | |||
754 | ret += retval; | ||
755 | src += retval; | ||
756 | buf += retval; | ||
757 | count -= retval; | ||
758 | } | ||
759 | *ppos = src; | ||
760 | |||
761 | free_page((unsigned long) page); | ||
762 | return ret; | ||
763 | } | ||
764 | |||
765 | static ssize_t mem_write(struct file * file, const char __user *buf, | ||
766 | size_t count, loff_t *ppos) | ||
767 | { | ||
768 | int copied; | ||
769 | char *page; | 727 | char *page; |
770 | unsigned long dst = *ppos; | ||
771 | struct mm_struct *mm = file->private_data; | ||
772 | 728 | ||
773 | if (!mm) | 729 | if (!mm) |
774 | return 0; | 730 | return 0; |
@@ -779,30 +735,48 @@ static ssize_t mem_write(struct file * file, const char __user *buf, | |||
779 | 735 | ||
780 | copied = 0; | 736 | copied = 0; |
781 | while (count > 0) { | 737 | while (count > 0) { |
782 | int this_len, retval; | 738 | int this_len = min_t(int, count, PAGE_SIZE); |
783 | 739 | ||
784 | this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; | 740 | if (write && copy_from_user(page, buf, this_len)) { |
785 | if (copy_from_user(page, buf, this_len)) { | ||
786 | copied = -EFAULT; | 741 | copied = -EFAULT; |
787 | break; | 742 | break; |
788 | } | 743 | } |
789 | retval = access_remote_vm(mm, dst, page, this_len, 1); | 744 | |
790 | if (!retval) { | 745 | this_len = access_remote_vm(mm, addr, page, this_len, write); |
746 | if (!this_len) { | ||
791 | if (!copied) | 747 | if (!copied) |
792 | copied = -EIO; | 748 | copied = -EIO; |
793 | break; | 749 | break; |
794 | } | 750 | } |
795 | copied += retval; | 751 | |
796 | buf += retval; | 752 | if (!write && copy_to_user(buf, page, this_len)) { |
797 | dst += retval; | 753 | copied = -EFAULT; |
798 | count -= retval; | 754 | break; |
755 | } | ||
756 | |||
757 | buf += this_len; | ||
758 | addr += this_len; | ||
759 | copied += this_len; | ||
760 | count -= this_len; | ||
799 | } | 761 | } |
800 | *ppos = dst; | 762 | *ppos = addr; |
801 | 763 | ||
802 | free_page((unsigned long) page); | 764 | free_page((unsigned long) page); |
803 | return copied; | 765 | return copied; |
804 | } | 766 | } |
805 | 767 | ||
768 | static ssize_t mem_read(struct file *file, char __user *buf, | ||
769 | size_t count, loff_t *ppos) | ||
770 | { | ||
771 | return mem_rw(file, buf, count, ppos, 0); | ||
772 | } | ||
773 | |||
774 | static ssize_t mem_write(struct file *file, const char __user *buf, | ||
775 | size_t count, loff_t *ppos) | ||
776 | { | ||
777 | return mem_rw(file, (char __user*)buf, count, ppos, 1); | ||
778 | } | ||
779 | |||
806 | loff_t mem_lseek(struct file *file, loff_t offset, int orig) | 780 | loff_t mem_lseek(struct file *file, loff_t offset, int orig) |
807 | { | 781 | { |
808 | switch (orig) { | 782 | switch (orig) { |