Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp889443pxf; Thu, 8 Apr 2021 15:34:40 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzTVoxI5baXHgoldfBtVDQHg9Vo6j2urXFVKOC9OHvvpK7DHvPxUzYUpQNhylmCR+Cmbgrf X-Received: by 2002:a65:4582:: with SMTP id o2mr10240756pgq.93.1617921280228; Thu, 08 Apr 2021 15:34:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1617921280; cv=none; d=google.com; s=arc-20160816; b=t/HkxUXOqj5H6JxJnqONjGO6V2AAEKiARIiLYh/7TsFpzbimjOV6B+jOCUx3JsoMRr u7BmC9vhXrg3R4HlFxfFOSqKA1GJ2K39+zao0FTAJSZiSU9wqoSRjZv5Ew9rhRk2/RX/ RwbqNHmqqVqD7XF2ntuMUpK9BpqLERD6/gVIKmotg+toBfEOheVHfH3YHF5i4ekbPnOn KONixsxl2GYKEh7wMcKv0qr962e8Jw800GBmgOGZIPo84lI3JhhbN3hIlGyRbx9uWyob +YDk/66nsi4YJOMwUEaL91+674VYFSRPpZayIvE+UU+Dx51D7uZbOUrHq2wDcwJcAX9K uwiQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :references:message-id:subject:cc:to:from:date:dkim-signature; bh=yrxmQLM/CEgDjqYo/NYBe2FDumLJHaKJiIGHl1FAbH8=; b=IgDbCPRuN8jQC4/hMb0TJ7Ahu8YWu8dMlRB513rmxCSnBnSYGmlbBzJcGncKOXQtUX Q3r6OsKItczi+qQeV7gimHA9Sj8aO9VrZ34zvAL93p+SnsDWORfcgnuvPm/ZuFwYEpUD BbeLedr2aCIEqzjlpGlEtPLuRqXKEyv+cnqAcQdA1Cwi3XrQvnkv4pUG2NgZ1YAoxzqK /8aMsq8sR84F3gRCh0hPK+74qi2MG2RynrFOQV55BQLkSqt4DJ4wR9iVhfEQ7r1l/3g8 +Limre/q8zvwMuoNev/2aMUm7Acq+DvHweCit8FHCYakbyeeOvKtJ4sg68O1kyi4yv5K cI9A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=WOIr5mS5; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id m14si910056pjq.134.2021.04.08.15.34.26; Thu, 08 Apr 2021 15:34:40 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=WOIr5mS5; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232733AbhDHWdt (ORCPT + 99 others); Thu, 8 Apr 2021 18:33:49 -0400 Received: from mail.kernel.org ([198.145.29.99]:47050 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232265AbhDHWdt (ORCPT ); Thu, 8 Apr 2021 18:33:49 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id D714D61159; Thu, 8 Apr 2021 22:33:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1617921217; bh=pIXAWdF4etfveY6DyHQCkA+BjDO7SA9GuyWMh9fzC0g=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=WOIr5mS5WEysTPC18xj8DCO8gqONd0fl/7BAVpA1SonKsPea6YsWA9r7wgozZn/oe hDE4LIv9N0OfEBSRSLN8nBew5ZVuBm1LOc97wE4Z9A3YU/GzcTekvpEBdp7RZKxSjZ deA7+2v5wNS373EGXYYDVQRNixHDHpp+MYpGcAssTawo3UjHY+CEFadwOGwMVaRQD3 PFaBgQU9s5teamwtSyMBAfLe5OcJEKOuG42sQzeqrdpQilq2nA+lrvHl2TJKawHo3p AxQoTgqItF9KSb8PI2gxOv4XDZ32vNf6sEj4Y5oOZJS/tXvR2Zjnpk+E4TBe7d3uSC 7unxF5liYi5Ng== Date: Thu, 8 Apr 2021 15:33:36 -0700 From: "Darrick J. Wong" To: Shiyang Ruan Cc: linux-kernel@vger.kernel.org, linux-xfs@vger.kernel.org, linux-nvdimm@lists.01.org, linux-fsdevel@vger.kernel.org, darrick.wong@oracle.com, dan.j.williams@intel.com, willy@infradead.org, jack@suse.cz, viro@zeniv.linux.org.uk, linux-btrfs@vger.kernel.org, david@fromorbit.com, hch@lst.de, rgoldwyn@suse.de, Goldwyn Rodrigues Subject: Re: [PATCH v4 5/7] fsdax: Dedup file range to use a compare function Message-ID: <20210408223336.GB3957620@magnolia> References: <20210408120432.1063608-1-ruansy.fnst@fujitsu.com> <20210408120432.1063608-6-ruansy.fnst@fujitsu.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20210408120432.1063608-6-ruansy.fnst@fujitsu.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, Apr 08, 2021 at 08:04:30PM +0800, Shiyang Ruan wrote: > With dax we cannot deal with readpage() etc. So, we create a dax > comparison funciton which is similar with > vfs_dedupe_file_range_compare(). > And introduce dax_remap_file_range_prep() for filesystem use. > > Signed-off-by: Goldwyn Rodrigues > Signed-off-by: Shiyang Ruan > --- > fs/dax.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ > fs/remap_range.c | 45 ++++++++++++++++++++++++++++------- > fs/xfs/xfs_reflink.c | 9 +++++-- > include/linux/dax.h | 4 ++++ > include/linux/fs.h | 12 ++++++---- > 5 files changed, 112 insertions(+), 14 deletions(-) > > diff --git a/fs/dax.c b/fs/dax.c > index fcd1e932716e..ba924b6629a6 100644 > --- a/fs/dax.c > +++ b/fs/dax.c > @@ -1849,3 +1849,59 @@ 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); > + > +static loff_t dax_range_compare_actor(struct inode *ino1, loff_t pos1, > + struct inode *ino2, loff_t pos2, loff_t len, void *data, > + struct iomap *smap, struct iomap *dmap) > +{ > + void *saddr, *daddr; > + bool *same = data; > + int ret; > + > + if (smap->type == IOMAP_HOLE && dmap->type == IOMAP_HOLE) { > + *same = true; > + return len; > + } > + > + if (smap->type == IOMAP_HOLE || dmap->type == IOMAP_HOLE) { > + *same = false; > + return 0; > + } > + > + ret = dax_iomap_direct_access(smap, pos1, ALIGN(pos1 + len, PAGE_SIZE), > + &saddr, NULL); > + if (ret < 0) > + return -EIO; > + > + ret = dax_iomap_direct_access(dmap, pos2, ALIGN(pos2 + len, PAGE_SIZE), > + &daddr, NULL); > + if (ret < 0) > + return -EIO; > + > + *same = !memcmp(saddr, daddr, len); > + return len; > +} > + > +int dax_dedupe_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) > +{ > + int id, ret = 0; > + > + id = dax_read_lock(); > + while (len) { > + ret = iomap_apply2(src, srcoff, dest, destoff, len, 0, ops, > + is_same, dax_range_compare_actor); > + if (ret < 0 || !*is_same) > + goto out; > + > + len -= ret; > + srcoff += ret; > + destoff += ret; > + } > + ret = 0; > +out: > + dax_read_unlock(id); > + return ret; > +} > +EXPORT_SYMBOL_GPL(dax_dedupe_file_range_compare); > diff --git a/fs/remap_range.c b/fs/remap_range.c > index e4a5fdd7ad7b..1fab0db49c68 100644 > --- a/fs/remap_range.c > +++ b/fs/remap_range.c > @@ -14,6 +14,7 @@ > #include > #include > #include > +#include > #include "internal.h" > > #include > @@ -199,9 +200,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 +281,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 > @@ -289,9 +291,11 @@ static int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff, > * If there's an error, then the usual negative error code is returned. > * Otherwise returns 0 with *len set to the request length. > */ > -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) > +static 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, > + const struct iomap_ops *ops) Can we rename @ops to @dax_read_ops instead? > { > struct inode *inode_in = file_inode(file_in); > struct inode *inode_out = file_inode(file_out); > @@ -351,8 +355,15 @@ 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); > + if (!IS_DAX(inode_in) && !IS_DAX(inode_out)) If we already checked that IS_DAX(inode_in) == IS_DAX(inode_out), then can we only check one of these? if (!IS_DAX(inode_in)) ret = vfs_dedupe_file_range_compare(...); else if (dax_compare_ops) ret = dax_dedupe_file_range_compare(...); else ret = -EINVAL; > + ret = vfs_dedupe_file_range_compare(inode_in, pos_in, > + inode_out, pos_out, *len, &is_same); > + else if (IS_DAX(inode_in) && IS_DAX(inode_out) && ops) > + ret = dax_dedupe_file_range_compare(inode_in, pos_in, > + inode_out, pos_out, *len, &is_same, > + ops); > + else > + return -EINVAL; > if (ret) > return ret; > if (!is_same) > @@ -370,6 +381,24 @@ int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in, > > return ret; > } > + > +int dax_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, > + const struct iomap_ops *ops) > +{ > + return __generic_remap_file_range_prep(file_in, pos_in, file_out, > + pos_out, len, remap_flags, ops); > +} > +EXPORT_SYMBOL(dax_remap_file_range_prep); > + > +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) > +{ > + return __generic_remap_file_range_prep(file_in, pos_in, file_out, > + pos_out, len, remap_flags, NULL); > +} > EXPORT_SYMBOL(generic_remap_file_range_prep); > > loff_t do_clone_file_range(struct file *file_in, loff_t pos_in, > diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c > index 725c7d8e4438..9ef9f98725a2 100644 > --- a/fs/xfs/xfs_reflink.c > +++ b/fs/xfs/xfs_reflink.c > @@ -1329,8 +1329,13 @@ xfs_reflink_remap_prep( > if (IS_DAX(inode_in) || IS_DAX(inode_out)) > goto out_unlock; > > - ret = generic_remap_file_range_prep(file_in, pos_in, file_out, pos_out, > - len, remap_flags); > + if (!IS_DAX(inode_in)) > + ret = generic_remap_file_range_prep(file_in, pos_in, file_out, > + pos_out, len, remap_flags); > + else > + ret = dax_remap_file_range_prep(file_in, pos_in, file_out, > + pos_out, len, remap_flags, > + &xfs_read_iomap_ops); > if (ret || *len == 0) > goto out_unlock; > > diff --git a/include/linux/dax.h b/include/linux/dax.h > index 3275e01ed33d..32e1c34349f2 100644 > --- a/include/linux/dax.h > +++ b/include/linux/dax.h > @@ -239,6 +239,10 @@ 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, > struct iomap *srcmap); > +int dax_dedupe_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); What happens if dax isn't enabled in the kernel build? --D > 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 ec8f3ddf4a6a..28861e334dac 100644 > --- a/include/linux/fs.h > +++ b/include/linux/fs.h > @@ -70,6 +70,7 @@ struct fsverity_info; > struct fsverity_operations; > struct fs_context; > struct fs_parameter_spec; > +struct iomap_ops; > > extern void __init inode_init(void); > extern void __init inode_init_early(void); > @@ -1989,10 +1990,13 @@ extern ssize_t vfs_copy_file_range(struct file *, loff_t , struct file *, > 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); > +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); > +int dax_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, > + const struct iomap_ops *ops); > 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); > -- > 2.31.0 > > >