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 <behlendorf1@llnl.gov>
Signed-off-by: Brian Atkinson <batkinson@lanl.gov>
Closes #13199
This commit is contained in:
parent
dad2b19fff
commit
becc717f61
|
@ -0,0 +1,27 @@
|
||||||
|
dnl #
|
||||||
|
dnl # ZERO_PAGE() is an alias for emtpy_zero_page. On certain architectures
|
||||||
|
dnl # this is a GPL exported variable.
|
||||||
|
dnl #
|
||||||
|
|
||||||
|
dnl #
|
||||||
|
dnl # Checking if ZERO_PAGE is exported GPL-only
|
||||||
|
dnl #
|
||||||
|
AC_DEFUN([ZFS_AC_KERNEL_SRC_ZERO_PAGE], [
|
||||||
|
ZFS_LINUX_TEST_SRC([zero_page], [
|
||||||
|
#include <asm/pgtable.h>
|
||||||
|
], [
|
||||||
|
struct page *p __attribute__ ((unused));
|
||||||
|
p = ZERO_PAGE(0);
|
||||||
|
], [], [ZFS_META_LICENSE])
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_DEFUN([ZFS_AC_KERNEL_ZERO_PAGE], [
|
||||||
|
AC_MSG_CHECKING([whether ZERO_PAGE() is GPL-only])
|
||||||
|
ZFS_LINUX_TEST_RESULT([zero_page_license], [
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
], [
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
AC_DEFINE(HAVE_ZERO_PAGE_GPL_ONLY, 1,
|
||||||
|
[ZERO_PAGE() is GPL-only])
|
||||||
|
])
|
||||||
|
])
|
|
@ -137,6 +137,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
|
||||||
ZFS_AC_KERNEL_SRC_PAGEMAP_FOLIO_WAIT_BIT
|
ZFS_AC_KERNEL_SRC_PAGEMAP_FOLIO_WAIT_BIT
|
||||||
ZFS_AC_KERNEL_SRC_ADD_DISK
|
ZFS_AC_KERNEL_SRC_ADD_DISK
|
||||||
ZFS_AC_KERNEL_SRC_KTHREAD
|
ZFS_AC_KERNEL_SRC_KTHREAD
|
||||||
|
ZFS_AC_KERNEL_SRC_ZERO_PAGE
|
||||||
|
|
||||||
AC_MSG_CHECKING([for available kernel interfaces])
|
AC_MSG_CHECKING([for available kernel interfaces])
|
||||||
ZFS_LINUX_TEST_COMPILE_ALL([kabi])
|
ZFS_LINUX_TEST_COMPILE_ALL([kabi])
|
||||||
|
@ -247,6 +248,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
|
||||||
ZFS_AC_KERNEL_PAGEMAP_FOLIO_WAIT_BIT
|
ZFS_AC_KERNEL_PAGEMAP_FOLIO_WAIT_BIT
|
||||||
ZFS_AC_KERNEL_ADD_DISK
|
ZFS_AC_KERNEL_ADD_DISK
|
||||||
ZFS_AC_KERNEL_KTHREAD
|
ZFS_AC_KERNEL_KTHREAD
|
||||||
|
ZFS_AC_KERNEL_ZERO_PAGE
|
||||||
])
|
])
|
||||||
|
|
||||||
dnl #
|
dnl #
|
||||||
|
|
|
@ -182,8 +182,11 @@ abd_t *abd_zero_scatter = NULL;
|
||||||
|
|
||||||
struct page;
|
struct page;
|
||||||
/*
|
/*
|
||||||
* abd_zero_page we will be an allocated zero'd PAGESIZE buffer, which is
|
* _KERNEL - Will point to ZERO_PAGE if it is available or it will be
|
||||||
* assigned to set each of the pages of abd_zero_scatter.
|
* 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;
|
static struct page *abd_zero_page = NULL;
|
||||||
|
|
||||||
|
@ -466,15 +469,19 @@ abd_alloc_zero_scatter(void)
|
||||||
struct scatterlist *sg = NULL;
|
struct scatterlist *sg = NULL;
|
||||||
struct sg_table table;
|
struct sg_table table;
|
||||||
gfp_t gfp = __GFP_NOWARN | GFP_NOIO;
|
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 nr_pages = abd_chunkcnt_for_bytes(SPA_MAXBLOCKSIZE);
|
||||||
int i = 0;
|
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) {
|
while ((abd_zero_page = __page_cache_alloc(gfp_zero_page)) == NULL) {
|
||||||
ABDSTAT_BUMP(abdstat_scatter_page_alloc_retry);
|
ABDSTAT_BUMP(abdstat_scatter_page_alloc_retry);
|
||||||
schedule_timeout_interruptible(1);
|
schedule_timeout_interruptible(1);
|
||||||
}
|
}
|
||||||
abd_mark_zfs_page(abd_zero_page);
|
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)) {
|
while (sg_alloc_table(&table, nr_pages, gfp)) {
|
||||||
ABDSTAT_BUMP(abdstat_scatter_sg_table_retry);
|
ABDSTAT_BUMP(abdstat_scatter_sg_table_retry);
|
||||||
|
@ -695,8 +702,10 @@ abd_free_zero_scatter(void)
|
||||||
abd_zero_scatter = NULL;
|
abd_zero_scatter = NULL;
|
||||||
ASSERT3P(abd_zero_page, !=, NULL);
|
ASSERT3P(abd_zero_page, !=, NULL);
|
||||||
#if defined(_KERNEL)
|
#if defined(_KERNEL)
|
||||||
|
#if defined(HAVE_ZERO_PAGE_GPL_ONLY)
|
||||||
abd_unmark_zfs_page(abd_zero_page);
|
abd_unmark_zfs_page(abd_zero_page);
|
||||||
__free_page(abd_zero_page);
|
__free_page(abd_zero_page);
|
||||||
|
#endif /* HAVE_ZERO_PAGE_GPL_ONLY */
|
||||||
#else
|
#else
|
||||||
umem_free(abd_zero_page, PAGESIZE);
|
umem_free(abd_zero_page, PAGESIZE);
|
||||||
#endif /* _KERNEL */
|
#endif /* _KERNEL */
|
||||||
|
|
Loading…
Reference in New Issue