Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp1040124pxf; Thu, 18 Mar 2021 19:01:15 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyvClI6AlQpMOoCj4Msl8H7pI06zdbu0E8MwOZ7W+faArYVfNOmiRSl2HkPimNmd9aEAgfd X-Received: by 2002:a17:906:c1ca:: with SMTP id bw10mr1726351ejb.510.1616119275258; Thu, 18 Mar 2021 19:01:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1616119275; cv=none; d=google.com; s=arc-20160816; b=F2EDI/Un0tAPowZrFqZlUITVFKdAXrfqi/u20LT+HtV2r4ymDQu0E6qS28oFFT35iN 5c+i0aAc+I/tR3yFtIwGK59vk8N1s4Njyx/iUU2rDGq9u2l2QpEoLkN+/+p8jVC0Eyp1 QEIaZT31ZgIg00YfwE2lMAZ0kRzOTRvyWYTDmV8AlOpIj5d81PPuwyzV++A6agU4/B1q cg+ciDwNgVKaaWL9NHPdLjjKv0XLRT43RWI3tfuC1LMbF+pV/TBob7zmVWUcDvJkkBGM VKlXXHUt08Wl87h+qQU/ZWg7flUky057idRkUtav5otYlo0l62g0xy5PXL1yRxE4FFNz ScoQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :ironport-hdrordr; bh=TMV8gftwmWsgGbtQAwy7ZHMQD48OMiEc1WdTzHDOpaE=; b=JMLbw5eLQOwR+l42AVc45rVRAZ/WBgTGUeE/wxrL3krEjVrmDpTLM2SkMsp+Zzxuss 97Dg5+09fxtCQ2fu7s5wMPmsFJ2YPoCGFYH0jIbrvErOS7lS8aasZc5b3hmcvXL7dhiU kP6nkyHgTHpAqdvCIh6orEGi8FSEUFOTmoXWMv8dxFAEO0TD31jRdtoVwzNBbhAmhPCP SJa7rru2pvTcNMK+5pT58qiO5LqYx6LnNtd/NtpiLL5VCB0+V2AP+gb8tHgMGkRBjJdZ A/H2x+Y1g/93G4yd9ysxCJ7FpTq/8k1S+Lq3SQOZUSY/GQMIpqIPQQH41gaxprZkdWnN tLTw== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id u4si2888353ejc.113.2021.03.18.19.00.52; Thu, 18 Mar 2021 19:01:15 -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; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232221AbhCSBxf (ORCPT + 99 others); Thu, 18 Mar 2021 21:53:35 -0400 Received: from mail.cn.fujitsu.com ([183.91.158.132]:41484 "EHLO heian.cn.fujitsu.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S231440AbhCSBxI (ORCPT ); Thu, 18 Mar 2021 21:53:08 -0400 IronPort-HdrOrdr: =?us-ascii?q?A9a23=3AIHRCo65wLKeSV+wgWwPXwCjXdLJzesId70hD?= =?us-ascii?q?6mlaTxtJfsuE0/2/hfhz726RtB89elEF3eqBNq6JXG/G+fdOjLU5EL++UGDd1l?= =?us-ascii?q?eAA41v4IDryT+lOwCWzIRg/Ih6dawWMrzNJHxbqeq/3wWiCdYnx7C8gcWVrMPT?= =?us-ascii?q?1W1kQw0vS4wI1XYbNi+hHkd7RBZLCPMCffLy2uN8uzGidX4LB/7LZEUtYu6rnb?= =?us-ascii?q?32vaOjSRsHKjpi0wOWkA6vgYSQLzGomjsYTBNDqI1PzVT4?= X-IronPort-AV: E=Sophos;i="5.81,259,1610380800"; d="scan'208";a="105876682" Received: from unknown (HELO cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 19 Mar 2021 09:53:06 +0800 Received: from G08CNEXMBPEKD06.g08.fujitsu.local (unknown [10.167.33.206]) by cn.fujitsu.com (Postfix) with ESMTP id 5AB894CEB2B4; Fri, 19 Mar 2021 09:53:06 +0800 (CST) Received: from G08CNEXCHPEKD04.g08.fujitsu.local (10.167.33.200) by G08CNEXMBPEKD06.g08.fujitsu.local (10.167.33.206) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Fri, 19 Mar 2021 09:52:56 +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; Fri, 19 Mar 2021 09:52:55 +0800 From: Shiyang Ruan To: , , , CC: , , , , , , , , , Subject: [PATCH v3 04/10] fsdax: Introduce dax_iomap_cow_copy() Date: Fri, 19 Mar 2021 09:52:31 +0800 Message-ID: <20210319015237.993880-5-ruansy.fnst@fujitsu.com> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210319015237.993880-1-ruansy.fnst@fujitsu.com> References: <20210319015237.993880-1-ruansy.fnst@fujitsu.com> MIME-Version: 1.0 Content-Transfer-Encoding: 7BIT Content-Type: text/plain; charset=US-ASCII X-yoursite-MailScanner-ID: 5AB894CEB2B4.A4A01 X-yoursite-MailScanner: Found to be clean X-yoursite-MailScanner-From: ruansy.fnst@fujitsu.com X-Spam-Status: No Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In the case where the iomap is a write operation and iomap is not equal to srcmap after iomap_begin, we consider it is a CoW operation. The destance extent which iomap indicated is new allocated extent. So, it is needed to copy the data from srcmap to new allocated extent. In theory, it is better to copy the head and tail ranges which is outside of the non-aligned area instead of copying the whole aligned range. But in dax page fault, it will always be an aligned range. So, we have to copy the whole range in this case. Signed-off-by: Shiyang Ruan Reviewed-by: Christoph Hellwig --- fs/dax.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 5 deletions(-) diff --git a/fs/dax.c b/fs/dax.c index a70e6aa285bb..181aad97136a 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -1037,6 +1037,51 @@ static int dax_iomap_direct_access(struct iomap *iomap, loff_t pos, size_t size, return rc; } +/* + * Copy the head and tail part of the pages not included in the write but + * required for CoW, because pos/pos+length are not page aligned. But in dax + * page fault case, the range is page aligned, we need to copy the whole range + * of data. Use copy_edge to distinguish these cases. + */ +static int dax_iomap_cow_copy(loff_t pos, loff_t length, size_t align_size, + struct iomap *srcmap, void *daddr, bool copy_edge) +{ + loff_t head_off = pos & (align_size - 1); + size_t size = ALIGN(head_off + length, align_size); + loff_t end = pos + length; + loff_t pg_end = round_up(end, align_size); + void *saddr = 0; + int ret = 0; + + ret = dax_iomap_direct_access(srcmap, pos, size, &saddr, NULL); + if (ret) + return ret; + + if (!copy_edge) + return copy_mc_to_kernel(daddr, saddr, length); + + /* Copy the head part of the range. Note: we pass offset as length. */ + if (head_off) { + if (saddr) + ret = copy_mc_to_kernel(daddr, saddr, head_off); + else + memset(daddr, 0, head_off); + } + /* Copy the tail part of the range */ + if (end < pg_end) { + loff_t tail_off = head_off + length; + loff_t tail_len = pg_end - end; + + if (saddr) + ret = copy_mc_to_kernel(daddr + tail_off, + saddr + tail_off, tail_len); + else + memset(daddr + tail_off, 0, tail_len); + } + + return ret; +} + /* * The user has performed a load from a hole in the file. Allocating a new * page in the file would cause excessive storage usage for workloads with @@ -1166,11 +1211,12 @@ dax_iomap_actor(struct inode *inode, loff_t pos, loff_t length, void *data, struct dax_device *dax_dev = iomap->dax_dev; struct iov_iter *iter = data; loff_t end = pos + length, done = 0; + bool write = iov_iter_rw(iter) == WRITE; ssize_t ret = 0; size_t xfer; int id; - if (iov_iter_rw(iter) == READ) { + if (!write) { end = min(end, i_size_read(inode)); if (pos >= end) return 0; @@ -1179,7 +1225,8 @@ dax_iomap_actor(struct inode *inode, loff_t pos, loff_t length, void *data, return iov_iter_zero(min(length, end - pos), iter); } - if (WARN_ON_ONCE(iomap->type != IOMAP_MAPPED)) + if (WARN_ON_ONCE(iomap->type != IOMAP_MAPPED && + !(iomap->flags & IOMAP_F_SHARED))) return -EIO; /* @@ -1218,6 +1265,13 @@ dax_iomap_actor(struct inode *inode, loff_t pos, loff_t length, void *data, break; } + if (write && srcmap->addr != iomap->addr) { + ret = dax_iomap_cow_copy(pos, length, PAGE_SIZE, srcmap, + kaddr, true); + if (ret) + break; + } + map_len = PFN_PHYS(map_len); kaddr += offset; map_len -= offset; @@ -1229,7 +1283,7 @@ dax_iomap_actor(struct inode *inode, loff_t pos, loff_t length, void *data, * validated via access_ok() in either vfs_read() or * vfs_write(), depending on which operation we are doing. */ - if (iov_iter_rw(iter) == WRITE) + if (write) xfer = dax_copy_from_iter(dax_dev, pgoff, kaddr, map_len, iter); else @@ -1379,6 +1433,7 @@ static vm_fault_t dax_fault_actor(struct vm_fault *vmf, pfn_t *pfnp, bool sync = dax_fault_is_synchronous(flags, vmf->vma, iomap); int err = 0; pfn_t pfn; + void *kaddr; /* if we are reading UNWRITTEN and HOLE, return a hole. */ if (!write && @@ -1389,18 +1444,24 @@ static vm_fault_t dax_fault_actor(struct vm_fault *vmf, pfn_t *pfnp, return dax_pmd_load_hole(xas, vmf, iomap, &entry); } - if (iomap->type != IOMAP_MAPPED) { + if (iomap->type != IOMAP_MAPPED && !(iomap->flags & IOMAP_F_SHARED)) { WARN_ON_ONCE(1); return VM_FAULT_SIGBUS; } - err = dax_iomap_direct_access(iomap, pos, size, NULL, &pfn); + err = dax_iomap_direct_access(iomap, pos, size, &kaddr, &pfn); if (err) return dax_fault_return(err); entry = dax_insert_entry(xas, mapping, vmf, entry, pfn, 0, write && !sync); + if (write && srcmap->addr != iomap->addr) { + err = dax_iomap_cow_copy(pos, size, size, srcmap, kaddr, false); + if (err) + return dax_fault_return(err); + } + if (sync) return dax_fault_synchronous_pfnp(pfnp, pfn); -- 2.30.1