diff options
| author | Oleg Nesterov <oleg@redhat.com> | 2012-01-31 17:14:54 +0100 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-02-01 14:39:01 -0800 | 
| commit | 572d34b946bae070debd42db1143034d9687e13f (patch) | |
| tree | b913d612090e8ec25e92451120ef64692c802264 /fs/proc | |
| parent | 71879d3cb3dd8f2dfdefb252775c1b3ea04a3dd4 (diff) | |
| download | linux-572d34b946bae070debd42db1143034d9687e13f.tar.bz2 | |
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)  	return 0;  } -static ssize_t mem_read(struct file * file, char __user * buf, -			size_t count, loff_t *ppos) +static ssize_t mem_rw(struct file *file, char __user *buf, +			size_t count, loff_t *ppos, int write)  { -	int ret; -	char *page; -	unsigned long src = *ppos;  	struct mm_struct *mm = file->private_data; - -	if (!mm) -		return 0; - -	page = (char *)__get_free_page(GFP_TEMPORARY); -	if (!page) -		return -ENOMEM; - -	ret = 0; -  -	while (count > 0) { -		int this_len, retval; - -		this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; -		retval = access_remote_vm(mm, src, page, this_len, 0); -		if (!retval) { -			if (!ret) -				ret = -EIO; -			break; -		} - -		if (copy_to_user(buf, page, retval)) { -			ret = -EFAULT; -			break; -		} -  -		ret += retval; -		src += retval; -		buf += retval; -		count -= retval; -	} -	*ppos = src; - -	free_page((unsigned long) page); -	return ret; -} - -static ssize_t mem_write(struct file * file, const char __user *buf, -			 size_t count, loff_t *ppos) -{ -	int copied; +	unsigned long addr = *ppos; +	ssize_t copied;  	char *page; -	unsigned long dst = *ppos; -	struct mm_struct *mm = file->private_data;  	if (!mm)  		return 0; @@ -779,30 +735,48 @@ static ssize_t mem_write(struct file * file, const char __user *buf,  	copied = 0;  	while (count > 0) { -		int this_len, retval; +		int this_len = min_t(int, count, PAGE_SIZE); -		this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; -		if (copy_from_user(page, buf, this_len)) { +		if (write && copy_from_user(page, buf, this_len)) {  			copied = -EFAULT;  			break;  		} -		retval = access_remote_vm(mm, dst, page, this_len, 1); -		if (!retval) { + +		this_len = access_remote_vm(mm, addr, page, this_len, write); +		if (!this_len) {  			if (!copied)  				copied = -EIO;  			break;  		} -		copied += retval; -		buf += retval; -		dst += retval; -		count -= retval;			 + +		if (!write && copy_to_user(buf, page, this_len)) { +			copied = -EFAULT; +			break; +		} + +		buf += this_len; +		addr += this_len; +		copied += this_len; +		count -= this_len;  	} -	*ppos = dst; +	*ppos = addr;  	free_page((unsigned long) page);  	return copied;  } +static ssize_t mem_read(struct file *file, char __user *buf, +			size_t count, loff_t *ppos) +{ +	return mem_rw(file, buf, count, ppos, 0); +} + +static ssize_t mem_write(struct file *file, const char __user *buf, +			 size_t count, loff_t *ppos) +{ +	return mem_rw(file, (char __user*)buf, count, ppos, 1); +} +  loff_t mem_lseek(struct file *file, loff_t offset, int orig)  {  	switch (orig) { |