aboutsummaryrefslogtreecommitdiffstats
path: root/module/os
diff options
context:
space:
mode:
authorBrian Atkinson <[email protected]>2022-03-14 13:37:39 -0600
committerGitHub <[email protected]>2022-03-14 12:37:39 -0700
commitbecc717f6143caf80bad6879b6c6402538ecae89 (patch)
treebfca8c4127635dbb2041877808991a71c75b25ea /module/os
parentdad2b19fffda43894a005a042055e268fe6b32e3 (diff)
Adding ZERO_PAGE detection
On some architectures ZERO_PAGE is unavailable because it references a GPL exported symbol of empty_zero_page. Originally e08b993 removed the call to PAGE_ZERO(0) for assignment to the abd_zero_page. However, a simple check can be done to avoid a kernel allocation and free for the abd_zero_page if ZERO_PAGE is available. Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Brian Atkinson <[email protected]> Closes #13199
Diffstat (limited to 'module/os')
-rw-r--r--module/os/linux/zfs/abd_os.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/module/os/linux/zfs/abd_os.c b/module/os/linux/zfs/abd_os.c
index 113aee585..688458621 100644
--- a/module/os/linux/zfs/abd_os.c
+++ b/module/os/linux/zfs/abd_os.c
@@ -182,8 +182,11 @@ abd_t *abd_zero_scatter = NULL;
struct page;
/*
- * abd_zero_page we will be an allocated zero'd PAGESIZE buffer, which is
- * assigned to set each of the pages of abd_zero_scatter.
+ * _KERNEL - Will point to ZERO_PAGE if it is available or it will be
+ * an allocated zero'd PAGESIZE buffer.
+ * Userspace - Will be an allocated zero'ed PAGESIZE buffer.
+ *
+ * abd_zero_page is assigned to each of the pages of abd_zero_scatter.
*/
static struct page *abd_zero_page = NULL;
@@ -466,15 +469,19 @@ abd_alloc_zero_scatter(void)
struct scatterlist *sg = NULL;
struct sg_table table;
gfp_t gfp = __GFP_NOWARN | GFP_NOIO;
- gfp_t gfp_zero_page = gfp | __GFP_ZERO;
int nr_pages = abd_chunkcnt_for_bytes(SPA_MAXBLOCKSIZE);
int i = 0;
+#if defined(HAVE_ZERO_PAGE_GPL_ONLY)
+ gfp_t gfp_zero_page = gfp | __GFP_ZERO;
while ((abd_zero_page = __page_cache_alloc(gfp_zero_page)) == NULL) {
ABDSTAT_BUMP(abdstat_scatter_page_alloc_retry);
schedule_timeout_interruptible(1);
}
abd_mark_zfs_page(abd_zero_page);
+#else
+ abd_zero_page = ZERO_PAGE(0);
+#endif /* HAVE_ZERO_PAGE_GPL_ONLY */
while (sg_alloc_table(&table, nr_pages, gfp)) {
ABDSTAT_BUMP(abdstat_scatter_sg_table_retry);
@@ -695,8 +702,10 @@ abd_free_zero_scatter(void)
abd_zero_scatter = NULL;
ASSERT3P(abd_zero_page, !=, NULL);
#if defined(_KERNEL)
+#if defined(HAVE_ZERO_PAGE_GPL_ONLY)
abd_unmark_zfs_page(abd_zero_page);
__free_page(abd_zero_page);
+#endif /* HAVE_ZERO_PAGE_GPL_ONLY */
#else
umem_free(abd_zero_page, PAGESIZE);
#endif /* _KERNEL */