From: Hugh Dickins Date: Tue, 15 Oct 2013 18:44:42 +0000 (-0500) Subject: tmpfs: add support for read_iter and write_iter X-Git-Tag: next-20131017~92^2 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=99030da3fbf530177cf88780e60ee6a27c2df832;p=karo-tx-linux.git tmpfs: add support for read_iter and write_iter Convert tmpfs do_shmem_file_read() to shmem_file_read_iter(). Make file_read_iter_actor() global so tmpfs can use it too: delete file_read_actor(), which was made global in 2.4.4 for use by tmpfs. Replace tmpfs generic_file_aio_write() by generic_file_write_iter(). Signed-off-by: Hugh Dickins Signed-off-by: Dave Kleikamp --- diff --git a/include/linux/fs.h b/include/linux/fs.h index 9e29beb60a13..6f1384c12a69 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2504,8 +2504,9 @@ extern int sb_min_blocksize(struct super_block *, int); extern int generic_file_mmap(struct file *, struct vm_area_struct *); extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *); extern int generic_file_remap_pages(struct vm_area_struct *, unsigned long addr, - unsigned long size, pgoff_t pgoff); -extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size); + unsigned long size, pgoff_t pgoff); +extern int file_read_iter_actor(read_descriptor_t *desc, struct page *page, + unsigned long offset, unsigned long size); int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk); extern ssize_t generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t); extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *, diff --git a/mm/filemap.c b/mm/filemap.c index 1ac1ceeb4d9a..9b0b85223d5c 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1315,44 +1315,6 @@ out: file_accessed(filp); } -int file_read_actor(read_descriptor_t *desc, struct page *page, - unsigned long offset, unsigned long size) -{ - char *kaddr; - unsigned long left, count = desc->count; - - if (size > count) - size = count; - - /* - * Faults on the destination of a read are common, so do it before - * taking the kmap. - */ - if (!fault_in_pages_writeable(desc->arg.buf, size)) { - kaddr = kmap_atomic(page); - left = __copy_to_user_inatomic(desc->arg.buf, - kaddr + offset, size); - kunmap_atomic(kaddr); - if (left == 0) - goto success; - } - - /* Do it the slow way */ - kaddr = kmap(page); - left = __copy_to_user(desc->arg.buf, kaddr + offset, size); - kunmap(page); - - if (left) { - size -= left; - desc->error = -EFAULT; - } -success: - desc->count = count - size; - desc->written += size; - desc->arg.buf += size; - return size; -} - /* * Performs necessary checks before doing a write * @iov: io vector request @@ -1392,8 +1354,8 @@ int generic_segment_checks(const struct iovec *iov, } EXPORT_SYMBOL(generic_segment_checks); -static int file_read_iter_actor(read_descriptor_t *desc, struct page *page, - unsigned long offset, unsigned long size) +int file_read_iter_actor(read_descriptor_t *desc, struct page *page, + unsigned long offset, unsigned long size) { struct iov_iter *iter = desc->arg.data; unsigned long copied = 0; diff --git a/mm/shmem.c b/mm/shmem.c index 8297623fcaed..8612a95d7d7e 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1464,14 +1464,23 @@ shmem_write_end(struct file *file, struct address_space *mapping, return copied; } -static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_t *desc, read_actor_t actor) +static ssize_t shmem_file_read_iter(struct kiocb *iocb, + struct iov_iter *iter, loff_t pos) { + read_descriptor_t desc; + loff_t *ppos = &iocb->ki_pos; + struct file *filp = iocb->ki_filp; struct inode *inode = file_inode(filp); struct address_space *mapping = inode->i_mapping; pgoff_t index; unsigned long offset; enum sgp_type sgp = SGP_READ; + desc.written = 0; + desc.count = iov_iter_count(iter); + desc.arg.data = iter; + desc.error = 0; + /* * Might this read be for a stacking filesystem? Then when reading * holes of a sparse file, we actually need to allocate those pages, @@ -1498,10 +1507,10 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_ break; } - desc->error = shmem_getpage(inode, index, &page, sgp, NULL); - if (desc->error) { - if (desc->error == -EINVAL) - desc->error = 0; + desc.error = shmem_getpage(inode, index, &page, sgp, NULL); + if (desc.error) { + if (desc.error == -EINVAL) + desc.error = 0; break; } if (page) @@ -1552,13 +1561,13 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_ * "pos" here (the actor routine has to update the user buffer * pointers and the remaining count). */ - ret = actor(desc, page, offset, nr); + ret = file_read_iter_actor(&desc, page, offset, nr); offset += ret; index += offset >> PAGE_CACHE_SHIFT; offset &= ~PAGE_CACHE_MASK; page_cache_release(page); - if (ret != nr || !desc->count) + if (ret != nr || !desc.count) break; cond_resched(); @@ -1566,40 +1575,8 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_ *ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset; file_accessed(filp); -} - -static ssize_t shmem_file_aio_read(struct kiocb *iocb, - const struct iovec *iov, unsigned long nr_segs, loff_t pos) -{ - struct file *filp = iocb->ki_filp; - ssize_t retval; - unsigned long seg; - size_t count; - loff_t *ppos = &iocb->ki_pos; - retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE); - if (retval) - return retval; - - for (seg = 0; seg < nr_segs; seg++) { - read_descriptor_t desc; - - desc.written = 0; - desc.arg.buf = iov[seg].iov_base; - desc.count = iov[seg].iov_len; - if (desc.count == 0) - continue; - desc.error = 0; - do_shmem_file_read(filp, ppos, &desc, file_read_actor); - retval += desc.written; - if (desc.error) { - retval = retval ?: desc.error; - break; - } - if (desc.count > 0) - break; - } - return retval; + return desc.written ? desc.written : desc.error; } static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, @@ -2724,8 +2701,8 @@ static const struct file_operations shmem_file_operations = { .llseek = shmem_file_llseek, .read = do_sync_read, .write = do_sync_write, - .aio_read = shmem_file_aio_read, - .aio_write = generic_file_aio_write, + .read_iter = shmem_file_read_iter, + .write_iter = generic_file_write_iter, .fsync = noop_fsync, .splice_read = shmem_file_splice_read, .splice_write = generic_file_splice_write,