Received: by 2002:a05:6a10:f347:0:0:0:0 with SMTP id d7csp2754795pxu; Mon, 7 Dec 2020 15:01:46 -0800 (PST) X-Google-Smtp-Source: ABdhPJyDb6U/mWOziQBSLZibhT8d32XJCCHaz2TxSIfM9viUdvIeCNJ+TGHAhttX4c/1uAQ3I4D+ X-Received: by 2002:aa7:d459:: with SMTP id q25mr22005144edr.279.1607382105969; Mon, 07 Dec 2020 15:01:45 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1607382105; cv=none; d=google.com; s=arc-20160816; b=1Bnr+M3wUMUWHtEvkdlwy69odBS+qc8tVOYHgzgvuM3MrUu8EkeNT/m3Qt8VOxced1 Y5dZQjBNWCnlwzZMf5lMPzQPiR6MYkCZnA8GFa/xkomUbEO0hh0xodWHielmJt8bBxGK l7jyoP4U2LxTQRrMHojLOP/VPM4I7BhN5Tc0Y8np2R/BFlpSIuLB93KcG9h1gtqHai4B yCy2m4i/mVsTMy40VLGo/AXQrKKwGAzMxygO76gN02Z8Wvx12NlP36nJsP+lI+XSxglQ MGzcrHjPkGquKtN3fUhIC/BWmw2DEMi/wPri2iN4tBzgsH2qknYoFIzy/xtgiBv12xep 3ycQ== 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-sdr:ironport-sdr; bh=6CjCVj6M8GQueT/ur7cdK2YgMyBif+deKYgCYcbkPjQ=; b=wJ0KKfDnu4UjUS0EfLKoxjr12X9SUwXa3v1F2oQr4LfKqiQDj5NJH71Zg3ZY8FRBiQ 96luNKwRU634IaqL7U5tzlkWinEPDtnnyjjePcrWnBMfvkRqfV6CfOFezUmEjSeHbZj5 x9RetiYEYpUENRFf1Jx3ZFFT5eW6xU73lvJsWg5hHPHVrskEM6dL3k9fqPGldcuOoffZ 3dC/Xm526kJ+IzI6Ra78tmqP9MkGlYPNs3V80nilJXLMEGLv6WEEml0/Ci5fhqFK18SQ Ng6TeMlGLL9m8CQYceVzXc/u5V8Eg7wXUOMjB+YwCwJG5Vsg59C7R89y/Z3dK/afAbSF 1ryQ== 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=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id ce8si7159810ejb.147.2020.12.07.15.01.23; Mon, 07 Dec 2020 15:01:45 -0800 (PST) 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=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727916AbgLGW6B (ORCPT + 99 others); Mon, 7 Dec 2020 17:58:01 -0500 Received: from mga05.intel.com ([192.55.52.43]:30904 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726429AbgLGW6B (ORCPT ); Mon, 7 Dec 2020 17:58:01 -0500 IronPort-SDR: cmjfE5o6yErC0svfiwh2WX7jE/WSC7jkFXC2mTas5j5KNGNaxKZY42Melw5mtvIOMSQGojextK TolMkGiub59g== X-IronPort-AV: E=McAfee;i="6000,8403,9828"; a="258503446" X-IronPort-AV: E=Sophos;i="5.78,401,1599548400"; d="scan'208";a="258503446" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Dec 2020 14:57:20 -0800 IronPort-SDR: e9d6KgSN55dDPcjiPioCnlFbID2IDa8Hm1l+x2GSqdCoALUss9l/+rB7tpSry9HRuk+hJghrwP l+868QZHa2pA== X-IronPort-AV: E=Sophos;i="5.78,401,1599548400"; d="scan'208";a="317433222" Received: from iweiny-desk2.sc.intel.com (HELO localhost) ([10.3.52.147]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Dec 2020 14:57:20 -0800 From: ira.weiny@intel.com To: Thomas Gleixner , Andrew Morton Cc: Ira Weiny , Dave Hansen , Matthew Wilcox , Christoph Hellwig , Dan Williams , Al Viro , Eric Biggers , Joonas Lahtinen , linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH V2 2/2] mm/highmem: Lift memcpy_[to|from]_page to core Date: Mon, 7 Dec 2020 14:57:03 -0800 Message-Id: <20201207225703.2033611-3-ira.weiny@intel.com> X-Mailer: git-send-email 2.28.0.rc0.12.gb6a658bd00c9 In-Reply-To: <20201207225703.2033611-1-ira.weiny@intel.com> References: <20201207225703.2033611-1-ira.weiny@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Ira Weiny Working through a conversion to a call such as kmap_thread() revealed many places where the pattern kmap/memcpy/kunmap occurred. Eric Biggers, Matthew Wilcox, Christoph Hellwig, Dan Williams, and Al Viro all suggested putting this code into helper functions. Al Viro further pointed out that these functions already existed in the iov_iter code.[1] Placing these functions in 'highmem.h' is suboptimal especially with the changes being proposed in the functionality of kmap. From a caller perspective including/using 'highmem.h' implies that the functions defined in that header are only required when highmem is in use which is increasingly not the case with modern processors. Some headers like mm.h or string.h seem ok but don't really portray the functionality well. 'pagemap.h', on the other hand, makes sense and is already included in many of the places we want to convert. Another alternative would be to create a new header for the promoted memcpy functions, but it masks the fact that these are designed to copy to/from pages using the kernel direct mappings and complicates matters with a new header. Lift memcpy_to_page() and memcpy_from_page() to pagemap.h. Remove memzero_page() in favor of zero_user() to zero a page. Add a memcpy_page(), memmove_page, and memset_page() to cover more kmap/mem*/kunmap. patterns. Finally use kmap_local_page() in all the new calls. [1] https://lore.kernel.org/lkml/20201013200149.GI3576660@ZenIV.linux.org.uk/ https://lore.kernel.org/lkml/20201013112544.GA5249@infradead.org/ Cc: Dave Hansen Suggested-by: Matthew Wilcox Suggested-by: Christoph Hellwig Suggested-by: Dan Williams Suggested-by: Al Viro Suggested-by: Eric Biggers Signed-off-by: Ira Weiny --- Changes for V2: From Thomas Gleixner Change kmap_atomic() to kmap_local_page() after basing on tip/core/mm From Joonas Lahtinen Reverse offset/val in memset_page() --- include/linux/pagemap.h | 44 +++++++++++++++++++++++++++++++++++++++++ lib/iov_iter.c | 26 +++--------------------- 2 files changed, 47 insertions(+), 23 deletions(-) diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index c77b7c31b2e4..9141e5b7b9df 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -1028,4 +1028,48 @@ unsigned int i_blocks_per_page(struct inode *inode, struct page *page) { return thp_size(page) >> inode->i_blkbits; } + +static inline void memcpy_page(struct page *dst_page, size_t dst_off, + struct page *src_page, size_t src_off, + size_t len) +{ + char *dst = kmap_local_page(dst_page); + char *src = kmap_local_page(src_page); + memcpy(dst + dst_off, src + src_off, len); + kunmap_local(src); + kunmap_local(dst); +} + +static inline void memmove_page(struct page *dst_page, size_t dst_off, + struct page *src_page, size_t src_off, + size_t len) +{ + char *dst = kmap_local_page(dst_page); + char *src = kmap_local_page(src_page); + memmove(dst + dst_off, src + src_off, len); + kunmap_local(src); + kunmap_local(dst); +} + +static inline void memcpy_from_page(char *to, struct page *page, size_t offset, size_t len) +{ + char *from = kmap_local_page(page); + memcpy(to, from + offset, len); + kunmap_local(from); +} + +static inline void memcpy_to_page(struct page *page, size_t offset, const char *from, size_t len) +{ + char *to = kmap_local_page(page); + memcpy(to + offset, from, len); + kunmap_local(to); +} + +static inline void memset_page(struct page *page, size_t offset, int val, size_t len) +{ + char *addr = kmap_local_page(page); + memset(addr + offset, val, len); + kunmap_local(addr); +} + #endif /* _LINUX_PAGEMAP_H */ diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 1635111c5bd2..8ed1f846fcc3 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -466,27 +467,6 @@ void iov_iter_init(struct iov_iter *i, unsigned int direction, } EXPORT_SYMBOL(iov_iter_init); -static void memcpy_from_page(char *to, struct page *page, size_t offset, size_t len) -{ - char *from = kmap_atomic(page); - memcpy(to, from + offset, len); - kunmap_atomic(from); -} - -static void memcpy_to_page(struct page *page, size_t offset, const char *from, size_t len) -{ - char *to = kmap_atomic(page); - memcpy(to + offset, from, len); - kunmap_atomic(to); -} - -static void memzero_page(struct page *page, size_t offset, size_t len) -{ - char *addr = kmap_atomic(page); - memset(addr + offset, 0, len); - kunmap_atomic(addr); -} - static inline bool allocated(struct pipe_buffer *buf) { return buf->ops == &default_pipe_buf_ops; @@ -964,7 +944,7 @@ static size_t pipe_zero(size_t bytes, struct iov_iter *i) do { size_t chunk = min_t(size_t, n, PAGE_SIZE - off); - memzero_page(pipe->bufs[i_head & p_mask].page, off, chunk); + zero_user(pipe->bufs[i_head & p_mask].page, off, chunk); i->head = i_head; i->iov_offset = off + chunk; n -= chunk; @@ -981,7 +961,7 @@ size_t iov_iter_zero(size_t bytes, struct iov_iter *i) return pipe_zero(bytes, i); iterate_and_advance(i, bytes, v, clear_user(v.iov_base, v.iov_len), - memzero_page(v.bv_page, v.bv_offset, v.bv_len), + zero_user(v.bv_page, v.bv_offset, v.bv_len), memset(v.iov_base, 0, v.iov_len) ) -- 2.28.0.rc0.12.gb6a658bd00c9