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) ...@@ -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 inode *inode = file->f_dentry->d_inode;
struct proc_dir_entry *entry = PDE(inode); struct proc_dir_entry *entry = PDE(inode);
struct salinfo_data *data = entry->data; struct salinfo_data *data = entry->data;
void *saldata;
size_t size;
u8 *buf; u8 *buf;
u64 bufsize; u64 bufsize;
...@@ -441,18 +439,7 @@ salinfo_log_read(struct file *file, char *buffer, size_t count, loff_t *ppos) ...@@ -441,18 +439,7 @@ salinfo_log_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
buf = NULL; buf = NULL;
bufsize = 0; bufsize = 0;
} }
if (*ppos >= bufsize) return simple_read_from_buffer(buffer, count, ppos, buf, 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;
} }
static void static void
......
...@@ -161,21 +161,10 @@ static loff_t page_map_seek( struct file *file, loff_t off, int whence) ...@@ -161,21 +161,10 @@ static loff_t page_map_seek( struct file *file, loff_t off, int whence)
return (file->f_pos = new); 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); struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
return simple_read_from_buffer(buf, nbytes, ppos, dp->data, dp->size);
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;
} }
static int page_map_mmap( struct file *file, struct vm_area_struct *vma ) static int page_map_mmap( struct file *file, struct vm_area_struct *vma )
......
...@@ -92,8 +92,7 @@ acpi_system_read_dsdt ( ...@@ -92,8 +92,7 @@ acpi_system_read_dsdt (
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
struct acpi_buffer dsdt = {ACPI_ALLOCATE_BUFFER, NULL}; struct acpi_buffer dsdt = {ACPI_ALLOCATE_BUFFER, NULL};
void *data = NULL; ssize_t res;
size_t size = 0;
ACPI_FUNCTION_TRACE("acpi_system_read_dsdt"); ACPI_FUNCTION_TRACE("acpi_system_read_dsdt");
...@@ -101,22 +100,11 @@ acpi_system_read_dsdt ( ...@@ -101,22 +100,11 @@ acpi_system_read_dsdt (
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
if (*ppos < dsdt.length) { res = simple_read_from_buffer(buffer, count, ppos,
data = dsdt.pointer + file->f_pos; dsdt.pointer, dsdt.length);
size = dsdt.length - file->f_pos;
if (size > count)
size = count;
if (copy_to_user(buffer, data, size)) {
acpi_os_free(dsdt.pointer); acpi_os_free(dsdt.pointer);
return_VALUE(-EFAULT);
}
}
acpi_os_free(dsdt.pointer); return_VALUE(res);
*ppos += size;
return_VALUE(size);
} }
...@@ -135,8 +123,7 @@ acpi_system_read_fadt ( ...@@ -135,8 +123,7 @@ acpi_system_read_fadt (
{ {
acpi_status status = AE_OK; acpi_status status = AE_OK;
struct acpi_buffer fadt = {ACPI_ALLOCATE_BUFFER, NULL}; struct acpi_buffer fadt = {ACPI_ALLOCATE_BUFFER, NULL};
void *data = NULL; ssize_t res;
size_t size = 0;
ACPI_FUNCTION_TRACE("acpi_system_read_fadt"); ACPI_FUNCTION_TRACE("acpi_system_read_fadt");
...@@ -144,22 +131,11 @@ acpi_system_read_fadt ( ...@@ -144,22 +131,11 @@ acpi_system_read_fadt (
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
return_VALUE(-ENODEV); return_VALUE(-ENODEV);
if (*ppos < fadt.length) { res = simple_read_from_buffer(buffer, count, ppos,
data = fadt.pointer + file->f_pos; fadt.pointer, fadt.length);
size = fadt.length - file->f_pos;
if (size > count)
size = count;
if (copy_to_user(buffer, data, size)) {
acpi_os_free(fadt.pointer); acpi_os_free(fadt.pointer);
return_VALUE(-EFAULT);
}
}
acpi_os_free(fadt.pointer); return_VALUE(res);
*ppos += size;
return_VALUE(size);
} }
......
...@@ -47,23 +47,7 @@ static struct super_operations s_ops = { ...@@ -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) ssize_t oprofilefs_str_to_user(char const * str, char __user * buf, size_t count, loff_t * offset)
{ {
size_t len = strlen(str); return simple_read_from_buffer(buf, count, offset, str, 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;
} }
...@@ -72,29 +56,10 @@ ssize_t oprofilefs_str_to_user(char const * str, char __user * buf, size_t count ...@@ -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) ssize_t oprofilefs_ulong_to_user(unsigned long val, char __user * buf, size_t count, loff_t * offset)
{ {
char tmpbuf[TMPBUFSIZE]; char tmpbuf[TMPBUFSIZE];
size_t maxlen; size_t maxlen = snprintf(tmpbuf, TMPBUFSIZE, "%lu\n", val);
if (!count)
return 0;
spin_lock(&oprofilefs_lock);
maxlen = snprintf(tmpbuf, TMPBUFSIZE, "%lu\n", val);
spin_unlock(&oprofilefs_lock);
if (maxlen > TMPBUFSIZE) if (maxlen > TMPBUFSIZE)
maxlen = TMPBUFSIZE; maxlen = TMPBUFSIZE;
return simple_read_from_buffer(buf, count, offset, tmpbuf, maxlen);
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;
} }
......
...@@ -571,22 +571,7 @@ static ssize_t uhci_proc_read(struct file *file, char __user *buf, ...@@ -571,22 +571,7 @@ static ssize_t uhci_proc_read(struct file *file, char __user *buf,
size_t nbytes, loff_t *ppos) size_t nbytes, loff_t *ppos)
{ {
struct uhci_proc *up = file->private_data; struct uhci_proc *up = file->private_data;
unsigned int pos; return simple_read_from_buffer(buf, nbytes, ppos, up->data, up->size);
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;
} }
static int uhci_proc_release(struct inode *inode, struct file *file) static int uhci_proc_release(struct inode *inode, struct file *file)
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/vfs.h> #include <linux/vfs.h>
#include <asm/uaccess.h>
int simple_getattr(struct vfsmount *mnt, struct dentry *dentry, int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat) struct kstat *stat)
...@@ -439,6 +440,22 @@ void simple_release_fs(struct vfsmount **mount, int *count) ...@@ -439,6 +440,22 @@ void simple_release_fs(struct vfsmount **mount, int *count)
mntput(mnt); 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_close);
EXPORT_SYMBOL(dcache_dir_lseek); EXPORT_SYMBOL(dcache_dir_lseek);
EXPORT_SYMBOL(dcache_dir_open); EXPORT_SYMBOL(dcache_dir_open);
...@@ -461,3 +478,4 @@ EXPORT_SYMBOL(simple_rmdir); ...@@ -461,3 +478,4 @@ EXPORT_SYMBOL(simple_rmdir);
EXPORT_SYMBOL(simple_statfs); EXPORT_SYMBOL(simple_statfs);
EXPORT_SYMBOL(simple_sync_file); EXPORT_SYMBOL(simple_sync_file);
EXPORT_SYMBOL(simple_unlink); 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 *); ...@@ -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 int simple_pin_fs(char *name, struct vfsmount **mount, int *count);
extern void simple_release_fs(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 inode_change_ok(struct inode *, struct iattr *);
extern int __must_check inode_setattr(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