Commit 65d33ad6 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] simple_read_buffer() helper function

A number of drivers or special virtual devices really just want their
"read()" function to populate user space from some internal buffer.

This adds such a helper function - "simple_read_from_buffer()" - and
converts several ->read() instances to use it.
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 1cc9f865
......@@ -426,8 +426,6 @@ salinfo_log_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
struct inode *inode = file->f_dentry->d_inode;
struct proc_dir_entry *entry = PDE(inode);
struct salinfo_data *data = entry->data;
void *saldata;
size_t size;
u8 *buf;
u64 bufsize;
......@@ -441,18 +439,7 @@ salinfo_log_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
buf = NULL;
bufsize = 0;
}
if (*ppos >= bufsize)
return 0;
saldata = buf + file->f_pos;
size = bufsize - file->f_pos;
if (size > count)
size = count;
if (copy_to_user(buffer, saldata, size))
return -EFAULT;
*ppos += size;
return size;
return simple_read_from_buffer(buffer, count, ppos, buf, bufsize);
}
static void
......
......@@ -161,21 +161,10 @@ static loff_t page_map_seek( struct file *file, loff_t off, int whence)
return (file->f_pos = new);
}
static ssize_t page_map_read( struct file *file, char *buf, size_t nbytes, loff_t *ppos)
static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
{
unsigned pos = *ppos;
struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
if ( pos >= dp->size )
return 0;
if ( nbytes >= dp->size )
nbytes = dp->size;
if ( pos + nbytes > dp->size )
nbytes = dp->size - pos;
copy_to_user( buf, (char *)dp->data + pos, nbytes );
*ppos = pos + nbytes;
return nbytes;
return simple_read_from_buffer(buf, nbytes, ppos, dp->data, dp->size);
}
static int page_map_mmap( struct file *file, struct vm_area_struct *vma )
......
......@@ -92,8 +92,7 @@ acpi_system_read_dsdt (
{
acpi_status status = AE_OK;
struct acpi_buffer dsdt = {ACPI_ALLOCATE_BUFFER, NULL};
void *data = NULL;
size_t size = 0;
ssize_t res;
ACPI_FUNCTION_TRACE("acpi_system_read_dsdt");
......@@ -101,22 +100,11 @@ acpi_system_read_dsdt (
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
if (*ppos < dsdt.length) {
data = dsdt.pointer + file->f_pos;
size = dsdt.length - file->f_pos;
if (size > count)
size = count;
if (copy_to_user(buffer, data, size)) {
res = simple_read_from_buffer(buffer, count, ppos,
dsdt.pointer, dsdt.length);
acpi_os_free(dsdt.pointer);
return_VALUE(-EFAULT);
}
}
acpi_os_free(dsdt.pointer);
*ppos += size;
return_VALUE(size);
return_VALUE(res);
}
......@@ -135,8 +123,7 @@ acpi_system_read_fadt (
{
acpi_status status = AE_OK;
struct acpi_buffer fadt = {ACPI_ALLOCATE_BUFFER, NULL};
void *data = NULL;
size_t size = 0;
ssize_t res;
ACPI_FUNCTION_TRACE("acpi_system_read_fadt");
......@@ -144,22 +131,11 @@ acpi_system_read_fadt (
if (ACPI_FAILURE(status))
return_VALUE(-ENODEV);
if (*ppos < fadt.length) {
data = fadt.pointer + file->f_pos;
size = fadt.length - file->f_pos;
if (size > count)
size = count;
if (copy_to_user(buffer, data, size)) {
res = simple_read_from_buffer(buffer, count, ppos,
fadt.pointer, fadt.length);
acpi_os_free(fadt.pointer);
return_VALUE(-EFAULT);
}
}
acpi_os_free(fadt.pointer);
*ppos += size;
return_VALUE(size);
return_VALUE(res);
}
......
......@@ -47,23 +47,7 @@ static struct super_operations s_ops = {
ssize_t oprofilefs_str_to_user(char const * str, char __user * buf, size_t count, loff_t * offset)
{
size_t len = strlen(str);
if (!count)
return 0;
if (*offset > len)
return 0;
if (count > len - *offset)
count = len - *offset;
if (copy_to_user(buf, str + *offset, count))
return -EFAULT;
*offset += count;
return count;
return simple_read_from_buffer(buf, count, offset, str, strlen(str));
}
......@@ -72,29 +56,10 @@ ssize_t oprofilefs_str_to_user(char const * str, char __user * buf, size_t count
ssize_t oprofilefs_ulong_to_user(unsigned long val, char __user * buf, size_t count, loff_t * offset)
{
char tmpbuf[TMPBUFSIZE];
size_t maxlen;
if (!count)
return 0;
spin_lock(&oprofilefs_lock);
maxlen = snprintf(tmpbuf, TMPBUFSIZE, "%lu\n", val);
spin_unlock(&oprofilefs_lock);
size_t maxlen = snprintf(tmpbuf, TMPBUFSIZE, "%lu\n", val);
if (maxlen > TMPBUFSIZE)
maxlen = TMPBUFSIZE;
if (*offset > maxlen)
return 0;
if (count > maxlen - *offset)
count = maxlen - *offset;
if (copy_to_user(buf, tmpbuf + *offset, count))
return -EFAULT;
*offset += count;
return count;
return simple_read_from_buffer(buf, count, offset, tmpbuf, maxlen);
}
......
......@@ -571,22 +571,7 @@ static ssize_t uhci_proc_read(struct file *file, char __user *buf,
size_t nbytes, loff_t *ppos)
{
struct uhci_proc *up = file->private_data;
unsigned int pos;
unsigned int size;
pos = *ppos;
size = up->size;
if (pos >= size)
return 0;
if (nbytes > size - pos)
nbytes = size - pos;
if (copy_to_user(buf, up->data + pos, nbytes))
return -EFAULT;
*ppos += nbytes;
return nbytes;
return simple_read_from_buffer(buf, nbytes, ppos, up->data, up->size);
}
static int uhci_proc_release(struct inode *inode, struct file *file)
......
......@@ -7,6 +7,7 @@
#include <linux/pagemap.h>
#include <linux/mount.h>
#include <linux/vfs.h>
#include <asm/uaccess.h>
int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat)
......@@ -439,6 +440,22 @@ void simple_release_fs(struct vfsmount **mount, int *count)
mntput(mnt);
}
ssize_t simple_read_from_buffer(void __user *to, size_t count, loff_t *ppos,
void *from, size_t available)
{
loff_t pos = *ppos;
if (pos < 0)
return -EINVAL;
if (pos >= available)
return 0;
if (count > available - pos)
count = available - pos;
if (copy_to_user(to, from + pos, count))
return -EFAULT;
*ppos = pos + count;
return count;
}
EXPORT_SYMBOL(dcache_dir_close);
EXPORT_SYMBOL(dcache_dir_lseek);
EXPORT_SYMBOL(dcache_dir_open);
......@@ -461,3 +478,4 @@ EXPORT_SYMBOL(simple_rmdir);
EXPORT_SYMBOL(simple_statfs);
EXPORT_SYMBOL(simple_sync_file);
EXPORT_SYMBOL(simple_unlink);
EXPORT_SYMBOL(simple_read_from_buffer);
......@@ -1527,6 +1527,8 @@ extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
extern int simple_pin_fs(char *name, struct vfsmount **mount, int *count);
extern void simple_release_fs(struct vfsmount **mount, int *count);
extern ssize_t simple_read_from_buffer(void __user *, size_t, loff_t *, void *, size_t);
extern int inode_change_ok(struct inode *, struct iattr *);
extern int __must_check inode_setattr(struct inode *, struct iattr *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment