Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932229Ab3GYR7v (ORCPT ); Thu, 25 Jul 2013 13:59:51 -0400 Received: from aserp1040.oracle.com ([141.146.126.69]:43459 "EHLO aserp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757000Ab3GYRwE (ORCPT ); Thu, 25 Jul 2013 13:52:04 -0400 From: Dave Kleikamp To: linux-kernel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, Andrew Morton , "Maxim V. Patlasov" , Zach Brown , Hugh Dickins , Dave Kleikamp Subject: [PATCH V8 33/33] tmpfs: add support for read_iter and write_iter Date: Thu, 25 Jul 2013 12:50:59 -0500 Message-Id: <1374774659-13121-34-git-send-email-dave.kleikamp@oracle.com> X-Mailer: git-send-email 1.8.3.4 In-Reply-To: <1374774659-13121-1-git-send-email-dave.kleikamp@oracle.com> References: <1374774659-13121-1-git-send-email-dave.kleikamp@oracle.com> X-Source-IP: acsinet21.oracle.com [141.146.126.237] Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6883 Lines: 212 From: Hugh Dickins 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 --- include/linux/fs.h | 5 +++-- mm/filemap.c | 42 ++----------------------------------- mm/shmem.c | 61 +++++++++++++++++------------------------------------- 3 files changed, 24 insertions(+), 84 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index 269ef07..48209c8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2499,8 +2499,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 41b9672..45cfcfc 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1313,44 +1313,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 @@ -1390,8 +1352,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 a87990c..67cd5e5 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, @@ -2721,8 +2698,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, -- 1.8.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/