From patchwork Tue Nov 7 21:26:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Matthew Wilcox (Oracle)" X-Patchwork-Id: 13449309 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AF77FC4332F for ; Tue, 7 Nov 2023 21:26:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234888AbjKGV06 (ORCPT ); Tue, 7 Nov 2023 16:26:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33988 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235267AbjKGV0x (ORCPT ); Tue, 7 Nov 2023 16:26:53 -0500 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 97E8E10D5; Tue, 7 Nov 2023 13:26:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=lkRC7Bno9DMh6U/8dcyjn2uoQxPsQ9ZkkBeHr6QdQXc=; b=qvaEl+OnLXfSQi27oJIuxxgw/f pcHChr1doAR5IJsp57EmVuuypKh5J7C1t3dACGsq4kXC74yDDP4rRy5irG0n8jE9/IRBodPRqZ/2z aGo3EOiIfNoUSsA68+IU7JLv9+7Zpbrp1CEif/NZ5UH30jwe0Ix5qg3LVU/FTxt/8J587B+hEaBGj YCIA2GgcwDNw1o7c+WriS4JuWbB8zQ1OdnlUB+dahdQBY2SHI1acyDtpR+gWNXm1hy0XWdewtIdNt hTsTvoWdSvGz7CSS6+3DAlR8yBBwAGNHYExaun3WAkutpeFQwLEn/+lKq/FC8VhwgEZ+5tEsdCKoa yrhLKNmQ==; Received: from willy by casper.infradead.org with local (Exim 4.94.2 #2 (Red Hat Linux)) id 1r0Tav-00Ee0V-3c; Tue, 07 Nov 2023 21:26:45 +0000 From: "Matthew Wilcox (Oracle)" To: Andrew Morton Cc: "Matthew Wilcox (Oracle)" , linux-ext4@vger.kernel.org, gfs2@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org, "Darrick J . Wong" , linux-erofs@lists.ozlabs.org, "Theodore Ts'o" , Andreas Dilger , Andreas Gruenbacher Subject: [PATCH 1/3] mm: Add folio_zero_tail() and use it in ext4 Date: Tue, 7 Nov 2023 21:26:40 +0000 Message-Id: <20231107212643.3490372-2-willy@infradead.org> X-Mailer: git-send-email 2.37.1 In-Reply-To: <20231107212643.3490372-1-willy@infradead.org> References: <20231107212643.3490372-1-willy@infradead.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org Instead of unmapping the folio after copying the data to it, then mapping it again to zero the tail, provide folio_zero_tail() to zero the tail of an already-mapped folio. Signed-off-by: Matthew Wilcox (Oracle) Reviewed-by: Andreas Gruenbacher --- fs/ext4/inline.c | 3 +-- include/linux/highmem.h | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 9a84a5f9fef4..d5bd1e3a5d36 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -502,9 +502,8 @@ static int ext4_read_inline_folio(struct inode *inode, struct folio *folio) BUG_ON(len > PAGE_SIZE); kaddr = kmap_local_folio(folio, 0); ret = ext4_read_inline_data(inode, kaddr, len, &iloc); - flush_dcache_folio(folio); + kaddr = folio_zero_tail(folio, len, kaddr + len); kunmap_local(kaddr); - folio_zero_segment(folio, len, folio_size(folio)); folio_mark_uptodate(folio); brelse(iloc.bh); diff --git a/include/linux/highmem.h b/include/linux/highmem.h index 4cacc0e43b51..1b81416196dd 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -483,6 +483,44 @@ static inline void memcpy_to_folio(struct folio *folio, size_t offset, flush_dcache_folio(folio); } +/** + * folio_zero_tail - Zero the tail of a folio. + * @folio: The folio to zero. + * @kaddr: The address the folio is currently mapped to. + * @offset: The byte offset in the folio to start zeroing at. + * + * If you have already used kmap_local_folio() to map a folio, written + * some data to it and now need to zero the end of the folio (and flush + * the dcache), you can use this function. If you do not have the + * folio kmapped (eg the folio has been partially populated by DMA), + * use folio_zero_range() or folio_zero_segment() instead. + * + * Return: An address which can be passed to kunmap_local(). + */ +static inline __must_check void *folio_zero_tail(struct folio *folio, + size_t offset, void *kaddr) +{ + size_t len = folio_size(folio) - offset; + + if (folio_test_highmem(folio)) { + size_t max = PAGE_SIZE - offset_in_page(offset); + + while (len > max) { + memset(kaddr, 0, max); + kunmap_local(kaddr); + len -= max; + offset += max; + max = PAGE_SIZE; + kaddr = kmap_local_folio(folio, offset); + } + } + + memset(kaddr, 0, len); + flush_dcache_folio(folio); + + return kaddr; +} + /** * memcpy_from_file_folio - Copy some bytes from a file folio. * @to: The destination buffer. From patchwork Tue Nov 7 21:26:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Matthew Wilcox (Oracle)" X-Patchwork-Id: 13449310 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 15DCAC04A92 for ; Tue, 7 Nov 2023 21:26:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235260AbjKGV06 (ORCPT ); Tue, 7 Nov 2023 16:26:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34040 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235306AbjKGV04 (ORCPT ); Tue, 7 Nov 2023 16:26:56 -0500 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A1FE610E4; Tue, 7 Nov 2023 13:26:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=YwVh6l/W1yK7KiZyEJlfwu5hHInPV2A4ijrPzoQDwKI=; b=NXRUiGQ1reyOncWjpC1pyDdJ+t Goyz1m7qTUWS0PRa/Dqn9ZSWvv43hjble24CYNoFlr32oR55XcZH/Jj7lZQw8H4+QtgUfaFWb6Bg1 lpy32NyNeBhJIQLv69u6pNYFuraoYFPTBVud2E0OB81JpP2aCBnk5F2SXfKYn/TYkAPXbX45LWjEv YCQF5Jur5FhRtADhxyVqfdjtTQx6DYyn2v2lOleAdnTl5BIhR+cLF3aK8GnlceSt41tUQrOjOw4lI ZvudLz1DMbRYtjOxKV1MhQMqsYpI2wVlhYaf8W7OMT9qySFBUL0TJZCGfq07whhAZ9PNya5D8c2Z7 QNM1r6Iw==; Received: from willy by casper.infradead.org with local (Exim 4.94.2 #2 (Red Hat Linux)) id 1r0Tav-00Ee0X-6a; Tue, 07 Nov 2023 21:26:45 +0000 From: "Matthew Wilcox (Oracle)" To: Andrew Morton Cc: "Matthew Wilcox (Oracle)" , linux-ext4@vger.kernel.org, gfs2@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org, "Darrick J . Wong" , linux-erofs@lists.ozlabs.org, "Theodore Ts'o" , Andreas Dilger , Andreas Gruenbacher Subject: [PATCH 2/3] mm: Add folio_fill_tail() and use it in iomap Date: Tue, 7 Nov 2023 21:26:41 +0000 Message-Id: <20231107212643.3490372-3-willy@infradead.org> X-Mailer: git-send-email 2.37.1 In-Reply-To: <20231107212643.3490372-1-willy@infradead.org> References: <20231107212643.3490372-1-willy@infradead.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org The iomap code was limited to PAGE_SIZE bytes; generalise it to cover an arbitrary-sized folio, and move it to be a common helper. Signed-off-by: Matthew Wilcox (Oracle) Reviewed-by: Andreas Gruenbacher --- fs/iomap/buffered-io.c | 14 ++------------ include/linux/highmem.h | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c index f72df2babe56..093c4515b22a 100644 --- a/fs/iomap/buffered-io.c +++ b/fs/iomap/buffered-io.c @@ -305,28 +305,18 @@ static int iomap_read_inline_data(const struct iomap_iter *iter, { const struct iomap *iomap = iomap_iter_srcmap(iter); size_t size = i_size_read(iter->inode) - iomap->offset; - size_t poff = offset_in_page(iomap->offset); size_t offset = offset_in_folio(folio, iomap->offset); - void *addr; if (folio_test_uptodate(folio)) return 0; - if (WARN_ON_ONCE(size > PAGE_SIZE - poff)) - return -EIO; - if (WARN_ON_ONCE(size > PAGE_SIZE - - offset_in_page(iomap->inline_data))) - return -EIO; if (WARN_ON_ONCE(size > iomap->length)) return -EIO; if (offset > 0) ifs_alloc(iter->inode, folio, iter->flags); - addr = kmap_local_folio(folio, offset); - memcpy(addr, iomap->inline_data, size); - memset(addr + size, 0, PAGE_SIZE - poff - size); - kunmap_local(addr); - iomap_set_range_uptodate(folio, offset, PAGE_SIZE - poff); + folio_fill_tail(folio, offset, iomap->inline_data, size); + iomap_set_range_uptodate(folio, offset, folio_size(folio) - offset); return 0; } diff --git a/include/linux/highmem.h b/include/linux/highmem.h index 1b81416196dd..0fbb60ffefc9 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -521,6 +521,44 @@ static inline __must_check void *folio_zero_tail(struct folio *folio, return kaddr; } +/** + * folio_fill_tail - Copy some data to a folio and pad with zeroes. + * @folio: The destination folio. + * @offset: The offset into @folio at which to start copying. + * @from: The data to copy. + * @len: How many bytes of data to copy. + * + * This function is most useful for filesystems which support inline data. + * When they want to copy data from the inode into the page cache, this + * function does everything for them. It supports large folios even on + * HIGHMEM configurations. + */ +static inline void folio_fill_tail(struct folio *folio, size_t offset, + const char *from, size_t len) +{ + char *to = kmap_local_folio(folio, offset); + + VM_BUG_ON(offset + len > folio_size(folio)); + + if (folio_test_highmem(folio)) { + size_t max = PAGE_SIZE - offset_in_page(offset); + + while (len > max) { + memcpy(to, from, max); + kunmap_local(to); + len -= max; + from += max; + offset += max; + max = PAGE_SIZE; + to = kmap_local_folio(folio, offset); + } + } + + memcpy(to, from, len); + to = folio_zero_tail(folio, offset, to); + kunmap_local(to); +} + /** * memcpy_from_file_folio - Copy some bytes from a file folio. * @to: The destination buffer. From patchwork Tue Nov 7 21:26:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Matthew Wilcox (Oracle)" X-Patchwork-Id: 13449308 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EA975C4167D for ; Tue, 7 Nov 2023 21:26:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235210AbjKGV0v (ORCPT ); Tue, 7 Nov 2023 16:26:51 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33914 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235264AbjKGV0t (ORCPT ); Tue, 7 Nov 2023 16:26:49 -0500 Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:8b0:10b:1236::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C3E5AD7A; Tue, 7 Nov 2023 13:26:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=iNDYg8DRsvaObfvTpWqtERvBTstUV4Ejndj13obP+9Q=; b=N7ZxMqoKgjDdJKGIqzDX461pjq 5Wh7Vxea9VO5l3vU4Kl0EiGsyC34H9WII34u3+a2H4RBok4fD260MYcv7joOkcq8LffDD1qC+zS7U dwyvka6mV8jDJ60fvK6vbFmIm+z7vP0Ek3KGHSpECTOaSiXSyil4snlVPw+mKpLnaif6UGv0SJKi2 xnKTDWn8D+dqdHylomhQACisCLSi7iQ0xYe8B6PMfy4nrU22HdmMLVa1kRu7I+zdz2zJ1LGuInYxv OrmU9FeQP8nfyn242lzo3tpUN9Ct2/ecJMI9fBmo0gFPy84UMZ8wEnFUs9pN8qfVuRNE1fpzfNKkt 0zwZzg2w==; Received: from willy by casper.infradead.org with local (Exim 4.94.2 #2 (Red Hat Linux)) id 1r0Tav-00Ee0Z-9K; Tue, 07 Nov 2023 21:26:45 +0000 From: "Matthew Wilcox (Oracle)" To: Andrew Morton Cc: "Matthew Wilcox (Oracle)" , linux-ext4@vger.kernel.org, gfs2@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-xfs@vger.kernel.org, "Darrick J . Wong" , linux-erofs@lists.ozlabs.org, "Theodore Ts'o" , Andreas Dilger , Andreas Gruenbacher Subject: [PATCH 3/3] gfs2: Convert stuffed_readpage() to stuffed_read_folio() Date: Tue, 7 Nov 2023 21:26:42 +0000 Message-Id: <20231107212643.3490372-4-willy@infradead.org> X-Mailer: git-send-email 2.37.1 In-Reply-To: <20231107212643.3490372-1-willy@infradead.org> References: <20231107212643.3490372-1-willy@infradead.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org Use folio_fill_tail() to implement the unstuffing and folio_end_read() to simultaneously mark the folio uptodate and unlock it. Unifies a couple of code paths. Signed-off-by: Matthew Wilcox (Oracle) Reviewed-by: Andreas Gruenbacher --- fs/gfs2/aops.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 9611bfceda4b..ba8742dc91f8 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c @@ -403,18 +403,18 @@ static int gfs2_jdata_writepages(struct address_space *mapping, } /** - * stuffed_readpage - Fill in a Linux folio with stuffed file data + * stuffed_read_folio - Fill in a Linux folio with stuffed file data * @ip: the inode * @folio: the folio * * Returns: errno */ -static int stuffed_readpage(struct gfs2_inode *ip, struct folio *folio) +static int stuffed_read_folio(struct gfs2_inode *ip, struct folio *folio) { - struct buffer_head *dibh; - size_t i_size = i_size_read(&ip->i_inode); - void *data; - int error; + struct buffer_head *dibh = NULL; + size_t dsize = i_size_read(&ip->i_inode); + void *from = NULL; + int error = 0; /* * Due to the order of unstuffing files and ->fault(), we can be @@ -422,22 +422,20 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct folio *folio) * so we need to supply one here. It doesn't happen often. */ if (unlikely(folio->index)) { - folio_zero_range(folio, 0, folio_size(folio)); - folio_mark_uptodate(folio); - return 0; + dsize = 0; + } else { + error = gfs2_meta_inode_buffer(ip, &dibh); + if (error) + goto out; + from = dibh->b_data + sizeof(struct gfs2_dinode); } - error = gfs2_meta_inode_buffer(ip, &dibh); - if (error) - return error; - - data = dibh->b_data + sizeof(struct gfs2_dinode); - memcpy_to_folio(folio, 0, data, i_size); - folio_zero_range(folio, i_size, folio_size(folio) - i_size); + folio_fill_tail(folio, 0, from, dsize); brelse(dibh); - folio_mark_uptodate(folio); +out: + folio_end_read(folio, error == 0); - return 0; + return error; } /** @@ -456,8 +454,7 @@ static int gfs2_read_folio(struct file *file, struct folio *folio) (i_blocksize(inode) == PAGE_SIZE && !folio_buffers(folio))) { error = iomap_read_folio(folio, &gfs2_iomap_ops); } else if (gfs2_is_stuffed(ip)) { - error = stuffed_readpage(ip, folio); - folio_unlock(folio); + error = stuffed_read_folio(ip, folio); } else { error = mpage_read_folio(folio, gfs2_block_map); }