From patchwork Sun Feb 7 17:09:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ruan Shiyang X-Patchwork-Id: 12076049 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 454EBC433E9 for ; Mon, 8 Feb 2021 16:54:13 +0000 (UTC) Received: from aserp2120.oracle.com (aserp2120.oracle.com [141.146.126.78]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B48EF64E9C for ; Mon, 8 Feb 2021 16:54:12 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B48EF64E9C Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=cn.fujitsu.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=ocfs2-devel-bounces@oss.oracle.com Received: from pps.filterd (aserp2120.oracle.com [127.0.0.1]) by aserp2120.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 118GZR81184720; Mon, 8 Feb 2021 16:54:11 GMT Received: from userp3030.oracle.com (userp3030.oracle.com [156.151.31.80]) by aserp2120.oracle.com with ESMTP id 36hk2kck15-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 08 Feb 2021 16:54:11 +0000 Received: from pps.filterd (userp3030.oracle.com [127.0.0.1]) by userp3030.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 118GYvTb010119; Mon, 8 Feb 2021 16:54:10 GMT Received: from oss.oracle.com (oss-old-reserved.oracle.com [137.254.22.2]) by userp3030.oracle.com with ESMTP id 36j51uwv6v-1 (version=TLSv1 cipher=AES256-SHA bits=256 verify=NO); Mon, 08 Feb 2021 16:54:10 +0000 Received: from localhost ([127.0.0.1] helo=lb-oss.oracle.com) by oss.oracle.com with esmtp (Exim 4.63) (envelope-from ) id 1l99nd-0005jE-6B; Mon, 08 Feb 2021 08:54:09 -0800 Received: from userp3020.oracle.com ([156.151.31.79]) by oss.oracle.com with esmtp (Exim 4.63) (envelope-from ) id 1l8nZ9-0007Oc-Ht for ocfs2-devel@oss.oracle.com; Sun, 07 Feb 2021 09:09:43 -0800 Received: from pps.filterd (userp3020.oracle.com [127.0.0.1]) by userp3020.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 117H0WaM015964 for ; Sun, 7 Feb 2021 17:09:43 GMT Received: from userp2030.oracle.com (userp2030.oracle.com [156.151.31.89]) by userp3020.oracle.com with ESMTP id 36j4vp0twp-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Sun, 07 Feb 2021 17:09:43 +0000 Received: from pps.filterd (userp2030.oracle.com [127.0.0.1]) by userp2030.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 117H4DDR022151 for ; Sun, 7 Feb 2021 17:09:42 GMT Received: from heian.cn.fujitsu.com (mail.cn.fujitsu.com [183.91.158.132]) by userp2030.oracle.com with ESMTP id 36hh5gj0pd-4 for ; Sun, 07 Feb 2021 17:09:42 +0000 X-IronPort-AV: E=Sophos;i="5.81,160,1610380800"; d="scan'208";a="104299372" Received: from unknown (HELO cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 08 Feb 2021 01:09:38 +0800 Received: from G08CNEXMBPEKD04.g08.fujitsu.local (unknown [10.167.33.201]) by cn.fujitsu.com (Postfix) with ESMTP id EE5B64CE6033; Mon, 8 Feb 2021 01:09:33 +0800 (CST) Received: from G08CNEXCHPEKD04.g08.fujitsu.local (10.167.33.200) by G08CNEXMBPEKD04.g08.fujitsu.local (10.167.33.201) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 8 Feb 2021 01:09:36 +0800 Received: from irides.mr.mr.mr (10.167.225.141) by G08CNEXCHPEKD04.g08.fujitsu.local (10.167.33.209) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 8 Feb 2021 01:09:35 +0800 From: Shiyang Ruan To: , , , Date: Mon, 8 Feb 2021 01:09:22 +0800 Message-ID: <20210207170924.2933035-6-ruansy.fnst@cn.fujitsu.com> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210207170924.2933035-1-ruansy.fnst@cn.fujitsu.com> References: <20210207170924.2933035-1-ruansy.fnst@cn.fujitsu.com> MIME-Version: 1.0 X-yoursite-MailScanner-ID: EE5B64CE6033.AF9D0 X-yoursite-MailScanner: Found to be clean X-yoursite-MailScanner-From: ruansy.fnst@cn.fujitsu.com X-PDR: PASS X-Source-IP: 183.91.158.132 X-ServerName: mail.cn.fujitsu.com X-Proofpoint-SPF-Result: None X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=9888 signatures=668683 X-Proofpoint-Spam-Details: rule=tap_notspam policy=tap score=0 phishscore=0 malwarescore=0 mlxscore=0 adultscore=0 spamscore=0 lowpriorityscore=0 priorityscore=95 suspectscore=0 clxscore=239 bulkscore=0 mlxlogscore=999 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2009150000 definitions=main-2102070121 X-Spam: Clean X-Mailman-Approved-At: Mon, 08 Feb 2021 08:54:07 -0800 Cc: jack@suse.cz, darrick.wong@oracle.com, david@fromorbit.com, ocfs2-devel@oss.oracle.com, viro@zeniv.linux.org.uk, Goldwyn Rodrigues , dan.j.williams@intel.com, linux-btrfs@vger.kernel.org Subject: [Ocfs2-devel] [PATCH 5/7] fsdax: Dedup file range to use a compare function X-BeenThere: ocfs2-devel@oss.oracle.com X-Mailman-Version: 2.1.9 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: ocfs2-devel-bounces@oss.oracle.com Errors-To: ocfs2-devel-bounces@oss.oracle.com X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=9889 signatures=668683 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 suspectscore=0 spamscore=0 phishscore=0 mlxscore=0 malwarescore=0 mlxlogscore=999 bulkscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2009150000 definitions=main-2102080107 X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=9889 signatures=668683 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 mlxscore=0 malwarescore=0 priorityscore=1501 clxscore=1034 impostorscore=0 lowpriorityscore=0 bulkscore=0 suspectscore=0 spamscore=0 mlxlogscore=999 adultscore=0 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2009150000 definitions=main-2102080107 With dax we cannot deal with readpage() etc. So, we create a funciton callback to perform the file data comparison and pass it to generic_remap_file_range_prep() so it can use iomap-based functions. Signed-off-by: Goldwyn Rodrigues Signed-off-by: Shiyang Ruan --- fs/btrfs/reflink.c | 3 +- fs/dax.c | 67 ++++++++++++++++++++++++++++++++++++++++++++ fs/ocfs2/file.c | 2 +- fs/remap_range.c | 14 +++++---- fs/xfs/xfs_reflink.c | 2 +- include/linux/dax.h | 5 ++++ include/linux/fs.h | 9 +++++- 7 files changed, 92 insertions(+), 10 deletions(-) diff --git a/fs/btrfs/reflink.c b/fs/btrfs/reflink.c index 99aa87c08912..efe094f7f748 100644 --- a/fs/btrfs/reflink.c +++ b/fs/btrfs/reflink.c @@ -783,7 +783,8 @@ static int btrfs_remap_file_range_prep(struct file *file_in, loff_t pos_in, return ret; return generic_remap_file_range_prep(file_in, pos_in, file_out, pos_out, - len, remap_flags); + len, remap_flags, + vfs_dedupe_file_range_compare); } loff_t btrfs_remap_file_range(struct file *src_file, loff_t off, diff --git a/fs/dax.c b/fs/dax.c index 29698a3d2e37..6e9391845057 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -30,6 +30,8 @@ #define CREATE_TRACE_POINTS #include +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + static inline unsigned int pe_order(enum page_entry_size pe_size) { if (pe_size == PE_SIZE_PTE) @@ -1827,3 +1829,68 @@ vm_fault_t dax_finish_sync_fault(struct vm_fault *vmf, return dax_insert_pfn_mkwrite(vmf, pfn, order); } EXPORT_SYMBOL_GPL(dax_finish_sync_fault); + +int dax_file_range_compare(struct inode *src, loff_t srcoff, struct inode *dest, + loff_t destoff, loff_t len, bool *is_same, + const struct iomap_ops *ops) +{ + void *saddr, *daddr; + struct iomap smap = { 0 }; + struct iomap dmap = { 0 }; + bool same = false; + loff_t cmp_len; + int id, ret = 0; + + id = dax_read_lock(); + while (len) { + ret = ops->iomap_begin(src, srcoff, len, 0, &smap, NULL); + if (ret < 0) + goto out_src; + cmp_len = MIN(len, smap.offset + smap.length - srcoff); + + ret = ops->iomap_begin(dest, destoff, cmp_len, 0, &dmap, NULL); + if (ret < 0) + goto out_dest; + cmp_len = MIN(cmp_len, dmap.offset + dmap.length - destoff); + + if (smap.type == IOMAP_HOLE && dmap.type == IOMAP_HOLE) + goto next; + + if (smap.type == IOMAP_HOLE || dmap.type == IOMAP_HOLE) { + same = false; + goto next; + } + + ret = dax_iomap_direct_access(&smap, srcoff, + ALIGN(srcoff + cmp_len, PAGE_SIZE), &saddr, NULL); + if (ret < 0) + goto out_dest; + + ret = dax_iomap_direct_access(&dmap, destoff, + ALIGN(destoff + cmp_len, PAGE_SIZE), &daddr, NULL); + if (ret < 0) + goto out_dest; + + same = !memcmp(saddr, daddr, cmp_len); + if (!same) + break; +next: + len -= cmp_len; + srcoff += cmp_len; + destoff += cmp_len; +out_dest: + if (ops->iomap_end) + ops->iomap_end(dest, destoff, cmp_len, 0, 0, &dmap); +out_src: + if (ops->iomap_end) + ops->iomap_end(src, srcoff, len, 0, 0, &smap); + + if (ret < 0) + goto out; + } + *is_same = same; +out: + dax_read_unlock(id); + return ret; +} +EXPORT_SYMBOL_GPL(dax_file_range_compare); diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 85979e2214b3..9d101f129d16 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -2591,7 +2591,7 @@ static loff_t ocfs2_remap_file_range(struct file *file_in, loff_t pos_in, goto out_unlock; ret = generic_remap_file_range_prep(file_in, pos_in, file_out, pos_out, - &len, remap_flags); + &len, remap_flags, vfs_dedupe_file_range_compare); if (ret < 0 || len == 0) goto out_unlock; diff --git a/fs/remap_range.c b/fs/remap_range.c index e6099beefa97..fc64f7e2af5a 100644 --- a/fs/remap_range.c +++ b/fs/remap_range.c @@ -199,9 +199,9 @@ static void vfs_unlock_two_pages(struct page *page1, struct page *page2) * Compare extents of two files to see if they are the same. * Caller must have locked both inodes to prevent write races. */ -static int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff, - struct inode *dest, loff_t destoff, - loff_t len, bool *is_same) +int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff, + struct inode *dest, loff_t destoff, + loff_t len, bool *is_same) { loff_t src_poff; loff_t dest_poff; @@ -280,6 +280,7 @@ static int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff, out_error: return error; } +EXPORT_SYMBOL(vfs_dedupe_file_range_compare); /* * Check that the two inodes are eligible for cloning, the ranges make @@ -291,7 +292,8 @@ static int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff, */ int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, - loff_t *len, unsigned int remap_flags) + loff_t *len, unsigned int remap_flags, + compare_range_t compare_range_fn) { struct inode *inode_in = file_inode(file_in); struct inode *inode_out = file_inode(file_out); @@ -351,8 +353,8 @@ int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in, if (remap_flags & REMAP_FILE_DEDUP) { bool is_same = false; - ret = vfs_dedupe_file_range_compare(inode_in, pos_in, - inode_out, pos_out, *len, &is_same); + ret = compare_range_fn(inode_in, pos_in, inode_out, pos_out, + *len, &is_same); if (ret) return ret; if (!is_same) diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 6fa05fb78189..26708c01fd78 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -1309,7 +1309,7 @@ xfs_reflink_remap_prep( goto out_unlock; ret = generic_remap_file_range_prep(file_in, pos_in, file_out, pos_out, - len, remap_flags); + len, remap_flags, vfs_dedupe_file_range_compare); if (ret || *len == 0) goto out_unlock; diff --git a/include/linux/dax.h b/include/linux/dax.h index b52f084aa643..183e084c2ac7 100644 --- a/include/linux/dax.h +++ b/include/linux/dax.h @@ -238,6 +238,11 @@ int dax_delete_mapping_entry(struct address_space *mapping, pgoff_t index); int dax_invalidate_mapping_entry_sync(struct address_space *mapping, pgoff_t index); s64 dax_iomap_zero(loff_t pos, u64 length, struct iomap *iomap); +int dax_file_range_compare(struct inode *src, loff_t srcoff, + struct inode *dest, loff_t destoff, + loff_t len, bool *is_same, + const struct iomap_ops *ops); + static inline bool dax_mapping(struct address_space *mapping) { return mapping->host && IS_DAX(mapping->host); diff --git a/include/linux/fs.h b/include/linux/fs.h index 8667d0cdc71e..159ec755e47b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1912,13 +1912,20 @@ extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *); extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *); extern ssize_t vfs_copy_file_range(struct file *, loff_t , struct file *, loff_t, size_t, unsigned int); +extern int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff, + struct inode *dest, loff_t destoff, + loff_t len, bool *is_same); +typedef int (*compare_range_t)(struct inode *src, loff_t srcpos, + struct inode *dest, loff_t destpos, + loff_t len, bool *is_same); extern ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, size_t len, unsigned int flags); extern int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, loff_t *count, - unsigned int remap_flags); + unsigned int remap_flags, + compare_range_t compare_range_fn); extern loff_t do_clone_file_range(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, loff_t len, unsigned int remap_flags);