From patchwork Mon Jan 11 21:07:30 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bob Peterson X-Patchwork-Id: 8011471 Return-Path: X-Original-To: patchwork-linux-fsdevel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 104DD9F1CC for ; Mon, 11 Jan 2016 21:08:09 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 07873200D6 for ; Mon, 11 Jan 2016 21:08:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D3E5220121 for ; Mon, 11 Jan 2016 21:07:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1760743AbcAKVHj (ORCPT ); Mon, 11 Jan 2016 16:07:39 -0500 Received: from mx1.redhat.com ([209.132.183.28]:36965 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1760186AbcAKVHe (ORCPT ); Mon, 11 Jan 2016 16:07:34 -0500 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (Postfix) with ESMTPS id 79FA3A203B for ; Mon, 11 Jan 2016 21:07:34 +0000 (UTC) Received: from loki.redhat.com (ovpn-113-31.phx2.redhat.com [10.3.113.31]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u0BL7X0d020507 for ; Mon, 11 Jan 2016 16:07:34 -0500 From: Bob Peterson To: linux-fsdevel Subject: [vfs PATCH 2/4] VFS: Add new __generic_iomap_fiemap interface Date: Mon, 11 Jan 2016 16:07:30 -0500 Message-Id: <1452546452-18531-3-git-send-email-rpeterso@redhat.com> In-Reply-To: <1452546452-18531-1-git-send-email-rpeterso@redhat.com> References: <1452546452-18531-1-git-send-email-rpeterso@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds a new function __generic_iomap_fiemap similar to __generic_block_fiemap, but it uses the new iomap interface. Signed-off-by: Bob Peterson --- fs/ioctl.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 6 ++++ 2 files changed, 103 insertions(+) diff --git a/fs/ioctl.c b/fs/ioctl.c index 29466c3..1b80e84 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -15,6 +15,8 @@ #include #include #include +#include + #include "internal.h" #include @@ -251,6 +253,101 @@ static inline loff_t blk_to_logical(struct inode *inode, sector_t blk) } /** + * __generic_iomap_fiemap - FIEMAP for iomap based inodes (no locking) + * @inode: the inode to map + * @fieinfo: the fiemap info struct that will be passed back to userspace + * @start: where to start mapping in the inode + * @len: how much space to map + * + * This does FIEMAP for iomap based inodes. Basically it will just loop + * through iomap until we hit the number of extents we want to map, or we + * go past the end of the file and hit a hole. + * + * If it is possible to have data blocks beyond a hole past @inode->i_size, then + * please do not use this function, it will stop at the first unmapped block + * beyond i_size. + * + * If you use this function directly, you need to do your own locking. Use + * generic_iomap_fiemap if you want the locking done for you. + */ + +int __generic_iomap_fiemap(struct inode *inode, + struct fiemap_extent_info *fieinfo, loff_t start, + loff_t len) +{ + struct iomap iom, prev_iom; + loff_t isize = i_size_read(inode); + int ret = 0; + + ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC); + memset(&prev_iom, 0, sizeof(prev_iom)); + if (len >= isize) + len = isize; + + while ((ret == 0) && (start < isize) && len) { + memset(&iom, 0, sizeof(iom)); + ret = inode->i_mapping->a_ops->iomap(inode->i_mapping, start, + len, &iom, IOMAP_READ); + if (ret) + break; + + if (!iomap_needs_allocation(&iom)) { + if (prev_iom.blkno) + ret = fiemap_fill_next_extent(fieinfo, + prev_iom.offset, + blk_to_logical(inode, + prev_iom.blkno), + prev_iom.length, + FIEMAP_EXTENT_MERGED); + prev_iom = iom; + } + start += iom.length; + if (len < iom.length) + break; + len -= iom.length; + cond_resched(); + } + + if (prev_iom.blkno) + ret = fiemap_fill_next_extent(fieinfo, prev_iom.offset, + blk_to_logical(inode, + prev_iom.blkno), + prev_iom.length, + FIEMAP_EXTENT_MERGED | + FIEMAP_EXTENT_LAST); + /* If ret is 1 then we just hit the end of the extent array */ + if (ret == 1) + ret = 0; + + return ret; +} +EXPORT_SYMBOL(__generic_iomap_fiemap); + +/** + * generic_iomap_fiemap - FIEMAP for block based inodes + * @inode: The inode to map + * @fieinfo: The mapping information + * @start: The initial block to map + * @len: The length of the extect to attempt to map + * @get_block: The block mapping function for the fs + * + * Calls __generic_block_fiemap to map the inode, after taking + * the inode's mutex lock. + */ + +int generic_iomap_fiemap(struct inode *inode, + struct fiemap_extent_info *fieinfo, u64 start, + u64 len) +{ + int ret; + mutex_lock(&inode->i_mutex); + ret = __generic_iomap_fiemap(inode, fieinfo, start, len); + mutex_unlock(&inode->i_mutex); + return ret; +} +EXPORT_SYMBOL(generic_iomap_fiemap); + +/** * __generic_block_fiemap - FIEMAP for block based inodes (no locking) * @inode: the inode to map * @fieinfo: the fiemap info struct that will be passed back to userspace diff --git a/include/linux/fs.h b/include/linux/fs.h index 8bafb11..093e9e5 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2781,6 +2781,12 @@ extern int vfs_lstat(const char __user *, struct kstat *); extern int vfs_fstat(unsigned int, struct kstat *); extern int vfs_fstatat(int , const char __user *, struct kstat *, int); +extern int __generic_iomap_fiemap(struct inode *inode, + struct fiemap_extent_info *fieinfo, + loff_t start, loff_t len); +extern int generic_iomap_fiemap(struct inode *inode, + struct fiemap_extent_info *fieinfo, u64 start, + u64 len); extern int __generic_block_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, loff_t start, loff_t len,