From patchwork Fri Jan 20 14:57:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Wilcox X-Patchwork-Id: 13110058 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1E6F1C25B4E for ; Fri, 20 Jan 2023 14:58:02 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 918646B0075; Fri, 20 Jan 2023 09:58:01 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 8C8446B0078; Fri, 20 Jan 2023 09:58:01 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 791FA6B007B; Fri, 20 Jan 2023 09:58:01 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id 6894B6B0075 for ; Fri, 20 Jan 2023 09:58:01 -0500 (EST) Received: from smtpin05.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id 25B681A0E19 for ; Fri, 20 Jan 2023 14:58:01 +0000 (UTC) X-FDA: 80375482362.05.38FB2FF Received: from casper.infradead.org (casper.infradead.org [90.155.50.34]) by imf10.hostedemail.com (Postfix) with ESMTP id DD9D1C000B for ; Fri, 20 Jan 2023 14:57:58 +0000 (UTC) Authentication-Results: imf10.hostedemail.com; dkim=pass header.d=infradead.org header.s=casper.20170209 header.b="Hyed/f0G"; spf=none (imf10.hostedemail.com: domain of willy@infradead.org has no SPF policy when checking 90.155.50.34) smtp.mailfrom=willy@infradead.org; dmarc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1674226679; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:content-transfer-encoding:in-reply-to: references:dkim-signature; bh=d+qxOFTo64MexSqtQ3SnPnYCe3GWPcwdD4xngzdKZlA=; b=eDS/Gizjjq46tLSiV4kVVr88ordKVPbp9ou5a3X/9iRCkXiTYWbn5DEbRSfORCh33y4KVT lX2bdEGZZjDBvhlPWEykDMSIINlh4S6EHeZ6mnPAN5O8ut0h4TY2rsTs28FEKM/fgQiUXI rgcvFo5C//et6+VLKYML4ewdXQOISog= ARC-Authentication-Results: i=1; imf10.hostedemail.com; dkim=pass header.d=infradead.org header.s=casper.20170209 header.b="Hyed/f0G"; spf=none (imf10.hostedemail.com: domain of willy@infradead.org has no SPF policy when checking 90.155.50.34) smtp.mailfrom=willy@infradead.org; dmarc=none ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1674226679; a=rsa-sha256; cv=none; b=bm0JwxoJ8iWVCNJQG23OPvJXIVFMP09ua7TlbYjx4Fr1c64jsXznfSnwp7qOZIesnO8hOo G4qG+elxRXvEzWcjOSLWZmKrrxHCPwfwt5kaF10FKh9gSIWXkI0q7j66zaDCKAH4isvhgj ANEXozhgAhaH4aTqlCYabPSUElEUVqo= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Type:MIME-Version:Message-ID: Subject:Cc:To:From:Date:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:In-Reply-To:References; bh=d+qxOFTo64MexSqtQ3SnPnYCe3GWPcwdD4xngzdKZlA=; b=Hyed/f0GU4ys5keUjxYlS1UGau k83DbyEH40qNuIFij0TWpQzFSqyQNAO55CU8F/h1YQPwHPcNET0NiZY2ET/VLhaw/dhYyrxfpsxD0 y7L10XYeJm7LvQKCOgnChqakhCgkds5jsqpjRPIdjmN3bBcLhwzX+jtwMmEdN9RMZpR0VsdQFVCNw Bh7G863GDlB0kd1MSYXibhfLPOAaZLkoIiFyP6PGrp+oGKgyaYGfLDOH3fo11KI7a20svWqcT75NO qE3POwaiwFpJInt06LFF5M7GhrJ5NWas4k7jcQNcpu9qYf2moU7hzJOlCWF1N+0+JDBSw5UPASEJb 3q9/xDaw==; Received: from willy by casper.infradead.org with local (Exim 4.94.2 #2 (Red Hat Linux)) id 1pIsq1-0022sG-Az; Fri, 20 Jan 2023 14:57:53 +0000 Date: Fri, 20 Jan 2023 14:57:53 +0000 From: Matthew Wilcox To: linux-mm@kvack.org, linux-fsdevel@vger.kernel.org Cc: Ira Weiny , "Fabio M. De Francesco" Subject: [RFC] memcpy_from_folio() Message-ID: MIME-Version: 1.0 Content-Disposition: inline X-Rspam-User: X-Rspamd-Server: rspam03 X-Stat-Signature: y9f1whtamws7685nodq54i8uh6xmmxrd X-Rspamd-Queue-Id: DD9D1C000B X-HE-Tag: 1674226678-645165 X-HE-Meta: U2FsdGVkX19M1lkLT81mKKVnGR4VlCoVB9zCo5oCkGX7a/bl8bpSOVKNC8TQTI2ghSfZov60gdhc5iKYiSXRTYWdXGYYMjtW+4wuM7UVoLGciHpeYDxxivnyasIllX4jWAcvWIq5C0Lj2QAX/zKgJJTEwngY6avuyu0nqrX2Uv1hvtdfH8acWYItDTPmPE8TUQKnGNcTpD+/WbVQHk0+9vYK0CuqrnmwkydPEQWl5hHlkBk+vn5CAIHD2iImG/GEaO1+RqaN6MsCyG01yOLiflwv0qPB3x1/ZxEBk7fUixBvtO2+r8QwbeZ1KYeT0rH34IhiC+hnGuT0X2qrsM3iMIkvogiYkGe1bA1IRA7Su6PBo7Gnhe42MVNRboJs/hQNVtAq/8Zo1C71B9e6dGD7J+PnbpCZuCV7sVo7ZAVh9MS7bxQntHFXwIgW6XqalrRnm6PnrMILSRO6mkKYXoN2ETMZAzTUBeswrju9jYvCLARgmnkvPkna+gAY9tizQvw3LksrWZsf3HmOmK2x+J74cAabPwbg2aTSAq8aoAE4HCYIYb3b2tBYKc7CDWxTKZfpVf+93wTjmgzZ8XJpK3fP7rSCZKFteRhmBQEjVQx44bhwxjgmlSGsMuK57iTGDyoHF7pd6ETuS+2zC1FXcouDQ2yw3oroEe6LTi0sp2Hvx2ABfYHTjSHVcpxvVVfHQiCG4ZVQYF0KkI7OIYcFJIrcEYFouRShC9ZR9/4/8RR3Cl6l+OaM8/IVsw9aXG0WJLJIHSBthVneqkzdzENyVmqOOiq6XWggrb4Y7ALEGDEZJAQQ5/2I/IPam+9KVGBx8N5fLoRaptps8s2YGegokwLlzI141bg7N5pW83duD0DvcmVeXMpFbCJF+G7p3lILUpK4npuu90j+aItlhdQcyFV6JzahhkJqJ/ZeN5ENgHekSv/rsEPPRPh7xVU8MHw8RtsR1aevIGTjW/J3FYpaT1N qgz3XqvG 9y/PKEdAuy4PJup54Wyy188KDvjwPiS9tnoV0CO2TyXYSDw2R8EAtLtBrWYC+OhCFv/Mr0s1wVcfzW13NPtVgGnrNCdv4f7C3/HQp69KVKv7JYytjyTk4BuyndZcUs1mDM9pPUwmvxfZxnswQaoWIrM3wNjeIAWVtj9CKWMQpqlyaEH/D+kRIT98/M4pVfp7nDg43Vk3xwpAiUrw= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: I think I have a good folio replacement for memcpy_from_page(). One of the annoying things about dealing with multi-page folios is that you can't kmap the entire folio, yet on systems without highmem, you don't need to. It's also somewhat annoying in the caller to keep track of n/len/offset/pos/... I think this is probably the best option. We could have a loop that kmaps each page in the folio, but that seems like excessive complexity. I'm happy to have highmem systems be less efficient, since they are anyway. Another potential area of concern is that folios can be quite large and maybe having preemption disabled while we copy 2MB of data might be a bad thing. If so, the API is fine with limiting the amount of data we copy, we just need to find out that it is a problem and decide what the correct limit is, if it's not folio_size(). fs/ext4/verity.c | 16 +++++++--------- include/linux/highmem.h | 29 +++++++++++++++++++++++++++++ include/linux/page-flags.h | 1 + 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/fs/ext4/verity.c b/fs/ext4/verity.c index e4da1704438e..afe847c967a4 100644 --- a/fs/ext4/verity.c +++ b/fs/ext4/verity.c @@ -42,18 +42,16 @@ static int pagecache_read(struct inode *inode, void *buf, size_t count, loff_t pos) { while (count) { - size_t n = min_t(size_t, count, - PAGE_SIZE - offset_in_page(pos)); - struct page *page; + struct folio *folio; + size_t n; - page = read_mapping_page(inode->i_mapping, pos >> PAGE_SHIFT, + folio = read_mapping_folio(inode->i_mapping, pos >> PAGE_SHIFT, NULL); - if (IS_ERR(page)) - return PTR_ERR(page); - - memcpy_from_page(buf, page, offset_in_page(pos), n); + if (IS_ERR(folio)) + return PTR_ERR(folio); - put_page(page); + n = memcpy_from_file_folio(buf, folio, pos, count); + folio_put(folio); buf += n; pos += n; diff --git a/include/linux/highmem.h b/include/linux/highmem.h index 9fa462561e05..9917357b9e8f 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -414,6 +414,35 @@ static inline void memzero_page(struct page *page, size_t offset, size_t len) kunmap_local(addr); } +/** + * memcpy_from_file_folio - Copy some bytes from a file folio. + * @to: The destination buffer. + * @folio: The folio to copy from. + * @pos: The position in the file. + * @len: The maximum number of bytes to copy. + * + * Copy up to @len bytes from this folio. This may be limited by PAGE_SIZE + * if the folio comes from HIGHMEM, and by the size of the folio. + * + * Return: The number of bytes copied from the folio. + */ +static inline size_t memcpy_from_file_folio(char *to, struct folio *folio, + loff_t pos, size_t len) +{ + size_t offset = offset_in_folio(folio, pos); + char *from = kmap_local_folio(folio, offset); + + if (folio_test_highmem(folio)) + len = min(len, PAGE_SIZE - offset); + else + len = min(len, folio_size(folio) - offset); + + memcpy(to, from, len); + kunmap_local(from); + + return len; +} + /** * folio_zero_segments() - Zero two byte ranges in a folio. * @folio: The folio to write to. diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index bc09194d372f..bba2a32031a2 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -531,6 +531,7 @@ PAGEFLAG(Readahead, readahead, PF_NO_COMPOUND) * available at this point. */ #define PageHighMem(__p) is_highmem_idx(page_zonenum(__p)) +#define folio_test_highmem(__f) is_highmem_idx(folio_zonenum(__f)) #else PAGEFLAG_FALSE(HighMem, highmem) #endif