aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2012-01-31 11:14:54 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-02-01 17:39:01 -0500
commit572d34b946bae070debd42db1143034d9687e13f (patch)
treeb913d612090e8ec25e92451120ef64692c802264 /fs/proc
parent71879d3cb3dd8f2dfdefb252775c1b3ea04a3dd4 (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.c90
1 files changed, 32 insertions, 58 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index c3617ea7830..be190904168 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
721static ssize_t mem_read(struct file * file, char __user * buf, 721static 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
765static 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
768static 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
774static 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
806loff_t mem_lseek(struct file *file, loff_t offset, int orig) 780loff_t mem_lseek(struct file *file, loff_t offset, int orig)
807{ 781{
808 switch (orig) { 782 switch (orig) {