Received: by 2002:a05:6a10:1287:0:0:0:0 with SMTP id d7csp3614406pxv; Mon, 26 Jul 2021 08:00:19 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxT8k0OO1GFLj/e1EMWNYj5/ZSXDFiFClQQmJfzCkb1aza70godUcRd0pAjjJUfGvKbhw35 X-Received: by 2002:a17:907:a072:: with SMTP id ia18mr17461237ejc.72.1627311619365; Mon, 26 Jul 2021 08:00:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1627311619; cv=none; d=google.com; s=arc-20160816; b=RMzLr4dfhHSVzgaYLbtFNgcUuR5LydhgIYLEK4VUBJtNj5NdX6ZT/IxWNXIPOLatN0 9wmPkeAKyXtl2wJpT78NiJmksuxTpS0nWBI1gRLjehxupp+mj4W7fy+MJYhO8R2dXwfW n5Ab2zrea1To24GEqBQeb332NqMWi+NSIb2j7fm5z/7f+wSEDT+Sd7Iy32CeexMYS3sz vRhgyacY0rGSWRwyTSkXZrs6+qePsrxYNqnpEIWXuhJroM4GMgEyMjyRN3XRxwD3ie9o DfN97ggDdrABkuK68k8z45IfvvfksHsu4XkcJK1tLHT9XY7ziH/NbN5BGllbvzkgVL2u YlYA== 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 :message-id:date:subject:cc:to:from; bh=Zvun9T1OFq5grsJdX3WK4sOOxI9UsWrbfVw4HoqsgOI=; b=Ul/4eSoiLb2b4huR50TTzqiNDjLmCcBjqEs1ErP2U5ghHnhlUGe7kW6Cyc4T5VJXNL J+BNMRyNvXR0NhEPLGC+a8oMamNAatmm97MMRe87jQFyClruPdio4n2maAtNK2pqqUEy C3aqnW8lFtfTpKsUSLiyB4fY4cnpkVq9/sgi3lgQ7XY2Hs14Slv66jTkAyH3uJx7nIkz gZIkMcc4ov32R+OxxB91hsjEgTFSP0qYP1aleEfkycYE5sM7k/jEl0ZKsIQp6RoMCwoW DVusLjZF77S9mcnSGZG9GlYuFNjA929N/bgjY0bSmKuThvb8bGhrYc2LiVESNMcP/fbg VxNg== 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=alibaba.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id nb18si146836ejc.113.2021.07.26.07.59.56; Mon, 26 Jul 2021 08:00:19 -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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=alibaba.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235030AbhGZORQ (ORCPT + 99 others); Mon, 26 Jul 2021 10:17:16 -0400 Received: from out30-132.freemail.mail.aliyun.com ([115.124.30.132]:55082 "EHLO out30-132.freemail.mail.aliyun.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234762AbhGZORP (ORCPT ); Mon, 26 Jul 2021 10:17:15 -0400 X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R121e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=e01e04426;MF=hsiangkao@linux.alibaba.com;NM=1;PH=DS;RN=10;SR=0;TI=SMTPD_---0Uh49OZI_1627311456; Received: from e18g09479.et15sqa.tbsite.net(mailfrom:hsiangkao@linux.alibaba.com fp:SMTPD_---0Uh49OZI_1627311456) by smtp.aliyun-inc.com(127.0.0.1); Mon, 26 Jul 2021 22:57:40 +0800 From: Gao Xiang To: linux-erofs@lists.ozlabs.org, linux-fsdevel@vger.kernel.org Cc: LKML , Huang Jianan , Joseph Qi , Gao Xiang , Christoph Hellwig , "Darrick J . Wong" , Matthew Wilcox , Andreas Gruenbacher Subject: [PATCH v8] iomap: make inline data support more flexible Date: Mon, 26 Jul 2021 22:57:34 +0800 Message-Id: <20210726145734.214295-1-hsiangkao@linux.alibaba.com> X-Mailer: git-send-email 2.24.4 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The existing inline data support only works for cases where the entire file is stored as inline data. For larger files, EROFS stores the initial blocks separately and then can pack a small tail adjacent to the inode. Generalise inline data to allow for tail packing. Tails may not cross a page boundary in memory. We currently have no filesystems that support tail packing and writing, so that case is currently disabled (see iomap_write_begin_inline). Cc: Christoph Hellwig Cc: Darrick J. Wong Cc: Matthew Wilcox Signed-off-by: Andreas Gruenbacher Signed-off-by: Gao Xiang --- v7: https://lore.kernel.org/r/20210723174131.180813-1-hsiangkao@linux.alibaba.com changes since v7: - This version is based on Andreas's patch, the main difference is to avoid using "iomap->length" in iomap_read_inline_data(). more details see: https://lore.kernel.org/r/CAHpGcMJhuSApy4eg9jKe2pYq4d7bY-Lg-Bmo9tOANghQ2Hxo-A@mail.gmail.com The rest are similar (some renaming and return type changes.) - with update according to Christoph's comments: https://lore.kernel.org/r/20210726121702.GA528@lst.de/ except that " I think we should fix that now that we have the srcmap concept. That is or IOMAP_WRITE|IOMAP_ZERO return the inline map as the soure map, and return the actual block map we plan to write into as the main iomap. " Hopefully it could be addressed with a new gfs2-related patch. - it passes gfs2 fstests and no strange on my side. Hopefully I don't miss anything (already many inputs), and everyone is happy with this version. fs/iomap/buffered-io.c | 40 ++++++++++++++++++++++++++++------------ fs/iomap/direct-io.c | 10 ++++++---- include/linux/iomap.h | 18 ++++++++++++++++++ 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c index 87ccb3438bec..0d9f161ecb7e 100644 --- a/fs/iomap/buffered-io.c +++ b/fs/iomap/buffered-io.c @@ -205,25 +205,30 @@ struct iomap_readpage_ctx { struct readahead_control *rac; }; -static void -iomap_read_inline_data(struct inode *inode, struct page *page, +static int iomap_read_inline_data(struct inode *inode, struct page *page, struct iomap *iomap) { - size_t size = i_size_read(inode); + size_t size = i_size_read(inode) - iomap->offset; void *addr; if (PageUptodate(page)) - return; + return 0; - BUG_ON(page_has_private(page)); - BUG_ON(page->index); - BUG_ON(size > PAGE_SIZE - offset_in_page(iomap->inline_data)); + /* inline data must start page aligned in the file */ + if (WARN_ON_ONCE(offset_in_page(iomap->offset))) + return -EIO; + if (WARN_ON_ONCE(size > PAGE_SIZE - + offset_in_page(iomap->inline_data))) + return -EIO; + if (WARN_ON_ONCE(page_has_private(page))) + return -EIO; addr = kmap_atomic(page); memcpy(addr, iomap->inline_data, size); memset(addr + size, 0, PAGE_SIZE - size); kunmap_atomic(addr); SetPageUptodate(page); + return 0; } static inline bool iomap_block_needs_zeroing(struct inode *inode, @@ -247,8 +252,10 @@ iomap_readpage_actor(struct inode *inode, loff_t pos, loff_t length, void *data, sector_t sector; if (iomap->type == IOMAP_INLINE) { - WARN_ON_ONCE(pos); - iomap_read_inline_data(inode, page, iomap); + int ret = iomap_read_inline_data(inode, page, iomap); + + if (ret) + return ret; return PAGE_SIZE; } @@ -589,6 +596,15 @@ __iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, int flags, return 0; } +static int iomap_write_begin_inline(struct inode *inode, + struct page *page, struct iomap *srcmap) +{ + /* needs more work for the tailpacking case, disable for now */ + if (WARN_ON_ONCE(srcmap->offset != 0)) + return -EIO; + return iomap_read_inline_data(inode, page, srcmap); +} + static int iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags, struct page **pagep, struct iomap *iomap, struct iomap *srcmap) @@ -618,7 +634,7 @@ iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags, } if (srcmap->type == IOMAP_INLINE) - iomap_read_inline_data(inode, page, srcmap); + status = iomap_write_begin_inline(inode, page, srcmap); else if (iomap->flags & IOMAP_F_BUFFER_HEAD) status = __block_write_begin_int(page, pos, len, NULL, srcmap); else @@ -671,11 +687,11 @@ static size_t iomap_write_end_inline(struct inode *inode, struct page *page, void *addr; WARN_ON_ONCE(!PageUptodate(page)); - BUG_ON(pos + copied > PAGE_SIZE - offset_in_page(iomap->inline_data)); + BUG_ON(!iomap_inline_data_valid(iomap)); flush_dcache_page(page); addr = kmap_atomic(page); - memcpy(iomap->inline_data + pos, addr + pos, copied); + memcpy(iomap_inline_data(iomap, pos), addr + pos, copied); kunmap_atomic(addr); mark_inode_dirty(inode); diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c index 9398b8c31323..41ccbfc9dc82 100644 --- a/fs/iomap/direct-io.c +++ b/fs/iomap/direct-io.c @@ -378,23 +378,25 @@ iomap_dio_inline_actor(struct inode *inode, loff_t pos, loff_t length, struct iomap_dio *dio, struct iomap *iomap) { struct iov_iter *iter = dio->submit.iter; + void *inline_data = iomap_inline_data(iomap, pos); size_t copied; - BUG_ON(pos + length > PAGE_SIZE - offset_in_page(iomap->inline_data)); + if (WARN_ON_ONCE(!iomap_inline_data_valid(iomap))) + return -EIO; if (dio->flags & IOMAP_DIO_WRITE) { loff_t size = inode->i_size; if (pos > size) - memset(iomap->inline_data + size, 0, pos - size); - copied = copy_from_iter(iomap->inline_data + pos, length, iter); + memset(iomap_inline_data(iomap, size), 0, pos - size); + copied = copy_from_iter(inline_data, length, iter); if (copied) { if (pos + copied > size) i_size_write(inode, pos + copied); mark_inode_dirty(inode); } } else { - copied = copy_to_iter(iomap->inline_data + pos, length, iter); + copied = copy_to_iter(inline_data, length, iter); } dio->size += copied; return copied; diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 479c1da3e221..b8ec145b2975 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -97,6 +97,24 @@ iomap_sector(struct iomap *iomap, loff_t pos) return (iomap->addr + pos - iomap->offset) >> SECTOR_SHIFT; } +/* + * Returns the inline data pointer for logical offset @pos. + */ +static inline void *iomap_inline_data(struct iomap *iomap, loff_t pos) +{ + return iomap->inline_data + pos - iomap->offset; +} + +/* + * Check if the mapping's length is within the valid range for inline data. + * This is used to guard against accessing data beyond the page inline_data + * points at. + */ +static inline bool iomap_inline_data_valid(struct iomap *iomap) +{ + return iomap->length <= PAGE_SIZE - offset_in_page(iomap->inline_data); +} + /* * When a filesystem sets page_ops in an iomap mapping it returns, page_prepare * and page_done will be called for each page written to. This only applies to -- 2.24.4