2024-03-05 08:59:43

by Max Kellermann

[permalink] [raw]
Subject: [PATCH v3 00/14] Fast kernel headers: split linux/mm.h

This patch set aims to clean up the linux/mm.h header and reduce
dependencies on it by moving parts out.

The goal was to eliminate dependencies on linux/mm.h from other
popular headers such as highmem.h and dma-mapping.h, and I started by
checking which symbols were really used and moved those declarations
to separate slim headers.

---
v1 -> v2: added more explanations to commit messages; renamed several
new headers from page_*.h to folio_*.h as suggested by Matthew
Wilcox; rebase on linux-next; fix build failures on architectures
um,nios2,hexagon by adding more missing includes
v2 -> v3: rebase on linux-next

Max Kellermann (14):
drivers: add missing includes on linux/mm.h (and others)
include/drm/drm_gem.h: add poll_table_struct forward declaration
linux/mm.h: move page_kasan_tag() to mm/page_kasan_tag.h
linux/mm.h: move section functions to mm/page_section.h
linux/mm.h: move page_address() and others to mm/page_address.h
linux/mm.h: move folio_size(), ... to mm/folio_size.h
linux/mm.h: move folio_next() to mm/folio_next.h
linux/mm.h: move devmap-related declarations to mm/devmap_managed.h
linux/mm.h: move usage count functions to mm/folio_usage.h
linux/mm.h: move page_zone_id() and more to mm/folio_zone.h
linux/mm.h: move pfmemalloc-related functions to pfmemalloc.h
linux/mm.h: move is_vmalloc_addr() to mm/vmalloc_addr.h
linux/mm.h: move high_memory to mm/high_memory.h
include: reduce dependencies on linux/mm.h

MAINTAINERS | 1 +
arch/arm/include/asm/memory.h | 4 +
arch/arm/include/asm/pgtable.h | 2 +
arch/arm/mm/iomap.c | 3 +
arch/csky/include/asm/page.h | 1 +
arch/hexagon/include/asm/mem-layout.h | 4 +
arch/m68k/include/asm/page_mm.h | 1 +
arch/m68k/include/asm/pgtable_mm.h | 1 +
arch/parisc/include/asm/floppy.h | 1 +
arch/powerpc/include/asm/book3s/32/pgtable.h | 4 +
arch/powerpc/include/asm/nohash/32/pgtable.h | 1 +
arch/powerpc/include/asm/page.h | 1 +
arch/x86/include/asm/floppy.h | 1 +
arch/x86/include/asm/pgtable_32_areas.h | 4 +
drivers/comedi/comedi_buf.c | 1 +
.../qat/qat_common/adf_gen4_pm_debugfs.c | 1 +
drivers/dma/dma-axi-dmac.c | 1 +
drivers/dma/sh/rcar-dmac.c | 1 +
drivers/firmware/qcom/qcom_scm-legacy.c | 1 +
drivers/firmware/qcom/qcom_scm-smc.c | 1 +
drivers/firmware/raspberrypi.c | 1 +
drivers/iio/buffer/industrialio-buffer-dma.c | 1 +
drivers/iommu/iommufd/ioas.c | 2 +
drivers/iommu/iommufd/selftest.c | 1 +
drivers/media/platform/mediatek/vpu/mtk_vpu.c | 1 +
drivers/media/platform/ti/omap/omap_voutlib.c | 1 +
drivers/misc/bcm-vk/bcm_vk_dev.c | 1 +
drivers/misc/fastrpc.c | 1 +
drivers/misc/genwqe/card_dev.c | 1 +
drivers/misc/uacce/uacce.c | 1 +
drivers/mtd/nand/onenand/onenand_samsung.c | 1 +
drivers/mtd/spi-nor/core.h | 2 +
drivers/pci/p2pdma.c | 1 +
drivers/pci/pci.c | 1 +
drivers/remoteproc/remoteproc_core.c | 1 +
drivers/soc/qcom/rmtfs_mem.c | 1 +
drivers/spi/spi-aspeed-smc.c | 1 +
drivers/spi/spi-bcm2835.c | 2 +
drivers/spi/spi-intel.c | 1 +
drivers/virtio/virtio_ring.c | 1 +
include/drm/drm_file.h | 1 +
include/linux/bio.h | 2 +
include/linux/dma-mapping.h | 1 +
include/linux/highmem-internal.h | 2 +
include/linux/highmem.h | 4 +-
include/linux/huge_mm.h | 2 +
include/linux/iommu.h | 1 +
include/linux/mm.h | 583 +-----------------
include/linux/mm/devmap_managed.h | 37 ++
include/linux/mm/folio_next.h | 27 +
include/linux/mm/folio_size.h | 150 +++++
include/linux/mm/folio_usage.h | 182 ++++++
include/linux/mm/folio_zone.h | 36 ++
include/linux/mm/high_memory.h | 7 +
include/linux/mm/page_address.h | 71 +++
include/linux/mm/page_kasan_tag.h | 66 ++
include/linux/mm/page_section.h | 23 +
include/linux/mm/pfmemalloc.h | 52 ++
include/linux/mm/vmalloc_addr.h | 33 +
include/linux/nvme-keyring.h | 2 +
include/linux/scatterlist.h | 8 +-
include/linux/skbuff.h | 4 +
kernel/dma/ops_helpers.c | 1 +
kernel/dma/remap.c | 1 +
lib/scatterlist.c | 1 +
mm/dmapool.c | 1 +
66 files changed, 780 insertions(+), 576 deletions(-)
create mode 100644 include/linux/mm/devmap_managed.h
create mode 100644 include/linux/mm/folio_next.h
create mode 100644 include/linux/mm/folio_size.h
create mode 100644 include/linux/mm/folio_usage.h
create mode 100644 include/linux/mm/folio_zone.h
create mode 100644 include/linux/mm/high_memory.h
create mode 100644 include/linux/mm/page_address.h
create mode 100644 include/linux/mm/page_kasan_tag.h
create mode 100644 include/linux/mm/page_section.h
create mode 100644 include/linux/mm/pfmemalloc.h
create mode 100644 include/linux/mm/vmalloc_addr.h

--
2.39.2



2024-03-05 09:00:01

by Max Kellermann

[permalink] [raw]
Subject: [PATCH v3 01/14] drivers: add missing includes on linux/mm.h (and others)

After developing the other patches in this series, I had lots of build
failures because "#include <linux/mm.h>" was missing. This patch
fixes those build failures by adding the missing "#include" lines. To
allow bisects, it is ordered before the others.

Signed-off-by: Max Kellermann <[email protected]>
---
arch/arm/mm/iomap.c | 3 +++
drivers/comedi/comedi_buf.c | 1 +
drivers/crypto/intel/qat/qat_common/adf_gen4_pm_debugfs.c | 1 +
drivers/dma/dma-axi-dmac.c | 1 +
drivers/dma/sh/rcar-dmac.c | 1 +
drivers/firmware/qcom/qcom_scm-legacy.c | 1 +
drivers/firmware/qcom/qcom_scm-smc.c | 1 +
drivers/firmware/raspberrypi.c | 1 +
drivers/iio/buffer/industrialio-buffer-dma.c | 1 +
drivers/iommu/iommufd/ioas.c | 2 ++
drivers/iommu/iommufd/selftest.c | 1 +
drivers/media/platform/mediatek/vpu/mtk_vpu.c | 1 +
drivers/media/platform/ti/omap/omap_voutlib.c | 1 +
drivers/misc/bcm-vk/bcm_vk_dev.c | 1 +
drivers/misc/fastrpc.c | 1 +
drivers/misc/genwqe/card_dev.c | 1 +
drivers/misc/uacce/uacce.c | 1 +
drivers/mtd/spi-nor/core.h | 2 ++
drivers/pci/p2pdma.c | 1 +
drivers/pci/pci.c | 1 +
drivers/remoteproc/remoteproc_core.c | 1 +
drivers/soc/qcom/rmtfs_mem.c | 1 +
drivers/spi/spi-aspeed-smc.c | 1 +
drivers/spi/spi-bcm2835.c | 2 ++
drivers/spi/spi-intel.c | 1 +
drivers/virtio/virtio_ring.c | 1 +
include/linux/huge_mm.h | 2 ++
include/linux/iommu.h | 1 +
include/linux/nvme-keyring.h | 2 ++
include/linux/scatterlist.h | 6 ++++++
kernel/dma/ops_helpers.c | 1 +
kernel/dma/remap.c | 1 +
mm/dmapool.c | 1 +
33 files changed, 45 insertions(+)

diff --git a/arch/arm/mm/iomap.c b/arch/arm/mm/iomap.c
index 415d0a454237..9873d8156908 100644
--- a/arch/arm/mm/iomap.c
+++ b/arch/arm/mm/iomap.c
@@ -29,6 +29,9 @@ EXPORT_SYMBOL(ioport_unmap);
#endif

#ifdef CONFIG_PCI
+
+#include <asm/pgtable.h> // for VMALLOC_*
+
unsigned long pcibios_min_io = 0x1000;
EXPORT_SYMBOL(pcibios_min_io);

diff --git a/drivers/comedi/comedi_buf.c b/drivers/comedi/comedi_buf.c
index 393966c09740..23b07ebc97ca 100644
--- a/drivers/comedi/comedi_buf.c
+++ b/drivers/comedi/comedi_buf.c
@@ -10,6 +10,7 @@
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/comedi/comedidev.h>
+#include <asm/pgtable.h> // for PAGE_KERNEL*
#include "comedi_internal.h"

#ifdef PAGE_KERNEL_NOCACHE
diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm_debugfs.c b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm_debugfs.c
index ee0b5079de3e..c9b2787baac7 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm_debugfs.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm_debugfs.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2023 Intel Corporation */
#include <linux/dma-mapping.h>
+#include <linux/fs.h> // for simple_read_from_buffer()
#include <linux/kernel.h>
#include <linux/string_helpers.h>
#include <linux/stringify.h>
diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index 4e339c04fc1e..0c98bf0e4b5d 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -15,6 +15,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
+#include <linux/mm.h> // for PAGE_ALIGN()
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_dma.h>
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 40482cb73d79..784da367665c 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -12,6 +12,7 @@
#include <linux/dmaengine.h>
#include <linux/interrupt.h>
#include <linux/list.h>
+#include <linux/mm.h> // for PAGE_ALIGN()
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
diff --git a/drivers/firmware/qcom/qcom_scm-legacy.c b/drivers/firmware/qcom/qcom_scm-legacy.c
index 029e6d117cb8..01e082c7163c 100644
--- a/drivers/firmware/qcom/qcom_scm-legacy.c
+++ b/drivers/firmware/qcom/qcom_scm-legacy.c
@@ -5,6 +5,7 @@

#include <linux/slab.h>
#include <linux/io.h>
+#include <linux/mm.h> // for PAGE_ALIGN()
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/errno.h>
diff --git a/drivers/firmware/qcom/qcom_scm-smc.c b/drivers/firmware/qcom/qcom_scm-smc.c
index 16cf88acfa8e..a5c74d8996fe 100644
--- a/drivers/firmware/qcom/qcom_scm-smc.c
+++ b/drivers/firmware/qcom/qcom_scm-smc.c
@@ -5,6 +5,7 @@
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/delay.h>
+#include <linux/mm.h> // for PAGE_ALIGN()
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/types.h>
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index 322aada20f74..beef5c4afef2 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -9,6 +9,7 @@
#include <linux/dma-mapping.h>
#include <linux/kref.h>
#include <linux/mailbox_client.h>
+#include <linux/mm.h> // for PAGE_ALIGN()
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c b/drivers/iio/buffer/industrialio-buffer-dma.c
index 5610ba67925e..b3ce8c4b101a 100644
--- a/drivers/iio/buffer/industrialio-buffer-dma.c
+++ b/drivers/iio/buffer/industrialio-buffer-dma.c
@@ -6,6 +6,7 @@

#include <linux/slab.h>
#include <linux/kernel.h>
+#include <linux/mm.h> // for PAGE_ALIGN()
#include <linux/module.h>
#include <linux/device.h>
#include <linux/workqueue.h>
diff --git a/drivers/iommu/iommufd/ioas.c b/drivers/iommu/iommufd/ioas.c
index 742248276548..40c4942406cd 100644
--- a/drivers/iommu/iommufd/ioas.c
+++ b/drivers/iommu/iommufd/ioas.c
@@ -5,6 +5,8 @@
#include <linux/interval_tree.h>
#include <linux/iommufd.h>
#include <linux/iommu.h>
+#include <linux/capability.h>
+#include <linux/slab.h>
#include <uapi/linux/iommufd.h>

#include "io_pagetable.h"
diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c
index 7a2199470f31..bcecf44681fe 100644
--- a/drivers/iommu/iommufd/selftest.c
+++ b/drivers/iommu/iommufd/selftest.c
@@ -5,6 +5,7 @@
*/
#include <linux/slab.h>
#include <linux/iommu.h>
+#include <linux/mm.h> // for GUP_PIN_COUNTING_BIAS
#include <linux/xarray.h>
#include <linux/file.h>
#include <linux/anon_inodes.h>
diff --git a/drivers/media/platform/mediatek/vpu/mtk_vpu.c b/drivers/media/platform/mediatek/vpu/mtk_vpu.c
index 7243604a82a5..885b873982e4 100644
--- a/drivers/media/platform/mediatek/vpu/mtk_vpu.c
+++ b/drivers/media/platform/mediatek/vpu/mtk_vpu.c
@@ -8,6 +8,7 @@
#include <linux/firmware.h>
#include <linux/interrupt.h>
#include <linux/iommu.h>
+#include <linux/mm.h> // for totalram_pages()
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
diff --git a/drivers/media/platform/ti/omap/omap_voutlib.c b/drivers/media/platform/ti/omap/omap_voutlib.c
index 0ac46458e41c..3b653b49cc48 100644
--- a/drivers/media/platform/ti/omap/omap_voutlib.c
+++ b/drivers/media/platform/ti/omap/omap_voutlib.c
@@ -18,6 +18,7 @@
*
*/

+#include <linux/mm.h> // for PAGE_ALIGN()
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
diff --git a/drivers/misc/bcm-vk/bcm_vk_dev.c b/drivers/misc/bcm-vk/bcm_vk_dev.c
index d4a96137728d..c5a39a8189bf 100644
--- a/drivers/misc/bcm-vk/bcm_vk_dev.c
+++ b/drivers/misc/bcm-vk/bcm_vk_dev.c
@@ -11,6 +11,7 @@
#include <linux/interrupt.h>
#include <linux/panic_notifier.h>
#include <linux/kref.h>
+#include <linux/mm.h> // for io_remap_pfn_range()
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/pci.h>
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index dbd26c3b245b..35701e9ec28e 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -10,6 +10,7 @@
#include <linux/idr.h>
#include <linux/list.h>
#include <linux/miscdevice.h>
+#include <linux/mm.h> // for find_vma()
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of.h>
diff --git a/drivers/misc/genwqe/card_dev.c b/drivers/misc/genwqe/card_dev.c
index 4441aca2280a..ce3acb938ca6 100644
--- a/drivers/misc/genwqe/card_dev.c
+++ b/drivers/misc/genwqe/card_dev.c
@@ -17,6 +17,7 @@

#include <linux/kernel.h>
#include <linux/types.h>
+#include <linux/mm.h> // for struct vm_operations_struct
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/string.h>
diff --git a/drivers/misc/uacce/uacce.c b/drivers/misc/uacce/uacce.c
index bdc2e6fda782..af815b8a718e 100644
--- a/drivers/misc/uacce/uacce.c
+++ b/drivers/misc/uacce/uacce.c
@@ -2,6 +2,7 @@
#include <linux/compat.h>
#include <linux/dma-mapping.h>
#include <linux/iommu.h>
+#include <linux/mm.h> // for struct vm_operations_struct
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/slab.h>
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 442786685515..c113ed8e8751 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -9,6 +9,8 @@

#include "sfdp.h"

+#include <linux/sizes.h> // for SZ_*
+
#define SPI_NOR_MAX_ID_LEN 6
/*
* 256 bytes is a sane default for most older flashes. Newer flashes will
diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index 4f47a13cb500..ef37ea6c09fc 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/genalloc.h>
#include <linux/memremap.h>
+#include <linux/mm.h> // for VM_MAYSHARE
#include <linux/percpu-refcount.h>
#include <linux/random.h>
#include <linux/seq_buf.h>
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index cfc5b84dc9c9..e2afd992caa7 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -25,6 +25,7 @@
#include <linux/logic_pio.h>
#include <linux/pm_wakeup.h>
#include <linux/device.h>
+#include <linux/pgtable.h> // for pgprot_device()
#include <linux/pm_runtime.h>
#include <linux/pci_hotplug.h>
#include <linux/vmalloc.h>
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index f276956f2c5c..938220fe29f5 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -18,6 +18,7 @@

#include <linux/delay.h>
#include <linux/kernel.h>
+#include <linux/mm.h> // for PAGE_ALIGN()
#include <linux/module.h>
#include <linux/device.h>
#include <linux/panic_notifier.h>
diff --git a/drivers/soc/qcom/rmtfs_mem.c b/drivers/soc/qcom/rmtfs_mem.c
index df850d073102..15c2f6e5eaff 100644
--- a/drivers/soc/qcom/rmtfs_mem.c
+++ b/drivers/soc/qcom/rmtfs_mem.c
@@ -6,6 +6,7 @@
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/err.h>
+#include <linux/mm.h> // for remap_pfn_range()
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c
index bbd417c55e7f..e45f64761e5e 100644
--- a/drivers/spi/spi-aspeed-smc.c
+++ b/drivers/spi/spi-aspeed-smc.c
@@ -11,6 +11,7 @@
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
+#include <linux/sizes.h> // for SZ_*
#include <linux/spi/spi.h>
#include <linux/spi/spi-mem.h>

diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c
index e1b9b1235787..d8ed5575a9c6 100644
--- a/drivers/spi/spi-bcm2835.c
+++ b/drivers/spi/spi-bcm2835.c
@@ -33,6 +33,8 @@
#include <linux/slab.h>
#include <linux/spi/spi.h>

+#include <asm/pgtable.h> // for ZERO_PAGE()
+
/* SPI register offsets */
#define BCM2835_SPI_CS 0x00
#define BCM2835_SPI_FIFO 0x04
diff --git a/drivers/spi/spi-intel.c b/drivers/spi/spi-intel.c
index 3e5dcf2b3c8a..cf8e4f1c4d93 100644
--- a/drivers/spi/spi-intel.c
+++ b/drivers/spi/spi-intel.c
@@ -8,6 +8,7 @@

#include <linux/iopoll.h>
#include <linux/module.h>
+#include <linux/sizes.h> // for SZ_*

#include <linux/mtd/partitions.h>
#include <linux/mtd/spi-nor.h>
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 6f7e5010a673..48f694d1bc46 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -12,6 +12,7 @@
#include <linux/hrtimer.h>
#include <linux/dma-mapping.h>
#include <linux/kmsan.h>
+#include <linux/mm.h> // for PAGE_ALIGN()
#include <linux/spinlock.h>
#include <xen/xen.h>

diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h
index de0c89105076..55b94db3bd5c 100644
--- a/include/linux/huge_mm.h
+++ b/include/linux/huge_mm.h
@@ -7,6 +7,8 @@

#include <linux/fs.h> /* only for vma_is_dax() */

+#include <asm/page.h> // for pmd_t
+
vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf);
int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
pmd_t *dst_pmd, pmd_t *src_pmd, unsigned long addr,
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index af6c367ed673..030820a5639e 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -14,6 +14,7 @@
#include <linux/err.h>
#include <linux/of.h>
#include <linux/iova_bitmap.h>
+#include <linux/uaccess.h> // for copy_struct_from_user()

#define IOMMU_READ (1 << 0)
#define IOMMU_WRITE (1 << 1)
diff --git a/include/linux/nvme-keyring.h b/include/linux/nvme-keyring.h
index e10333d78dbb..9e033850b967 100644
--- a/include/linux/nvme-keyring.h
+++ b/include/linux/nvme-keyring.h
@@ -6,6 +6,8 @@
#ifndef _NVME_KEYRING_H
#define _NVME_KEYRING_H

+#include <linux/key.h>
+
#if IS_ENABLED(CONFIG_NVME_KEYRING)

key_serial_t nvme_tls_psk_default(struct key *keyring,
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index 77df3d7b18a6..0516e64dc03e 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -8,6 +8,12 @@
#include <linux/mm.h>
#include <asm/io.h>

+#ifdef CONFIG_UML
+#include <asm/pgtable.h> // for virt_to_page(), page_to_phys()
+#else
+#include <asm/page.h> // for virt_to_page(), page_to_phys()
+#endif
+
struct scatterlist {
unsigned long page_link;
unsigned int offset;
diff --git a/kernel/dma/ops_helpers.c b/kernel/dma/ops_helpers.c
index af4a6ef48ce0..641363b13bb9 100644
--- a/kernel/dma/ops_helpers.c
+++ b/kernel/dma/ops_helpers.c
@@ -4,6 +4,7 @@
* the allocated memory contains normal pages in the direct kernel mapping.
*/
#include <linux/dma-map-ops.h>
+#include <linux/mm.h> // for PAGE_ALIGN()

static struct page *dma_common_vaddr_to_page(void *cpu_addr)
{
diff --git a/kernel/dma/remap.c b/kernel/dma/remap.c
index 27596f3b4aef..87b3c874d370 100644
--- a/kernel/dma/remap.c
+++ b/kernel/dma/remap.c
@@ -3,6 +3,7 @@
* Copyright (c) 2014 The Linux Foundation
*/
#include <linux/dma-map-ops.h>
+#include <linux/mm.h> // for vmap(), PAGE_ALIGN()
#include <linux/slab.h>
#include <linux/vmalloc.h>

diff --git a/mm/dmapool.c b/mm/dmapool.c
index f0bfc6c490f4..b8e23fdc81d7 100644
--- a/mm/dmapool.c
+++ b/mm/dmapool.c
@@ -25,6 +25,7 @@
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/export.h>
+#include <linux/mm.h> // for want_init_on_alloc()
#include <linux/mutex.h>
#include <linux/poison.h>
#include <linux/sched.h>
--
2.39.2


2024-03-05 09:00:17

by Max Kellermann

[permalink] [raw]
Subject: [PATCH v3 03/14] linux/mm.h: move page_kasan_tag() to mm/page_kasan_tag.h

Prepare to reduce dependencies on linux/mm.h.

page_kasan_tag() is used by the page_to_virt() macro in ARM64 (but
asm/memory.h does not include linux/mm.h). Thus, in order to be able to use
anything that calls page_to_virt(), linux/mm.h needs to be included.

This would prevent us from moving page_address() to a separate header,
because it calls lowmem_page_address() which in turn calls
page_to_virt(). To prepare for this move, we move page_kasan_tag()
out of linux/mm.h into a separate lean header.

A side effect of this patch is that the <linux/kasan.h> include line
is moved inside the "#ifdef CONFIG_KASAN..." block, i.e. it is not
included at all if KASAN is disabled.

Signed-off-by: Max Kellermann <[email protected]>
---
MAINTAINERS | 1 +
include/linux/mm.h | 56 +-------------------------
include/linux/mm/page_kasan_tag.h | 66 +++++++++++++++++++++++++++++++
3 files changed, 68 insertions(+), 55 deletions(-)
create mode 100644 include/linux/mm/page_kasan_tag.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 9e5bb60c55fe..dbfe08329154 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14210,6 +14210,7 @@ F: include/linux/mempolicy.h
F: include/linux/mempool.h
F: include/linux/memremap.h
F: include/linux/mm.h
+F: include/linux/mm/*.h
F: include/linux/mm_*.h
F: include/linux/mmzone.h
F: include/linux/mmu_notifier.h
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 0436b919f1c7..e140ee45f49c 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2,6 +2,7 @@
#ifndef _LINUX_MM_H
#define _LINUX_MM_H

+#include <linux/mm/page_kasan_tag.h>
#include <linux/errno.h>
#include <linux/mmdebug.h>
#include <linux/gfp.h>
@@ -27,7 +28,6 @@
#include <linux/sizes.h>
#include <linux/sched.h>
#include <linux/pgtable.h>
-#include <linux/kasan.h>
#include <linux/memremap.h>
#include <linux/slab.h>

@@ -1818,60 +1818,6 @@ static inline void vma_set_access_pid_bit(struct vm_area_struct *vma)
}
#endif /* CONFIG_NUMA_BALANCING */

-#if defined(CONFIG_KASAN_SW_TAGS) || defined(CONFIG_KASAN_HW_TAGS)
-
-/*
- * KASAN per-page tags are stored xor'ed with 0xff. This allows to avoid
- * setting tags for all pages to native kernel tag value 0xff, as the default
- * value 0x00 maps to 0xff.
- */
-
-static inline u8 page_kasan_tag(const struct page *page)
-{
- u8 tag = KASAN_TAG_KERNEL;
-
- if (kasan_enabled()) {
- tag = (page->flags >> KASAN_TAG_PGSHIFT) & KASAN_TAG_MASK;
- tag ^= 0xff;
- }
-
- return tag;
-}
-
-static inline void page_kasan_tag_set(struct page *page, u8 tag)
-{
- unsigned long old_flags, flags;
-
- if (!kasan_enabled())
- return;
-
- tag ^= 0xff;
- old_flags = READ_ONCE(page->flags);
- do {
- flags = old_flags;
- flags &= ~(KASAN_TAG_MASK << KASAN_TAG_PGSHIFT);
- flags |= (tag & KASAN_TAG_MASK) << KASAN_TAG_PGSHIFT;
- } while (unlikely(!try_cmpxchg(&page->flags, &old_flags, flags)));
-}
-
-static inline void page_kasan_tag_reset(struct page *page)
-{
- if (kasan_enabled())
- page_kasan_tag_set(page, KASAN_TAG_KERNEL);
-}
-
-#else /* CONFIG_KASAN_SW_TAGS || CONFIG_KASAN_HW_TAGS */
-
-static inline u8 page_kasan_tag(const struct page *page)
-{
- return 0xff;
-}
-
-static inline void page_kasan_tag_set(struct page *page, u8 tag) { }
-static inline void page_kasan_tag_reset(struct page *page) { }
-
-#endif /* CONFIG_KASAN_SW_TAGS || CONFIG_KASAN_HW_TAGS */
-
static inline struct zone *page_zone(const struct page *page)
{
return &NODE_DATA(page_to_nid(page))->node_zones[page_zonenum(page)];
diff --git a/include/linux/mm/page_kasan_tag.h b/include/linux/mm/page_kasan_tag.h
new file mode 100644
index 000000000000..1210c62170a3
--- /dev/null
+++ b/include/linux/mm/page_kasan_tag.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_MM_PAGE_KASAN_TAG_H
+#define _LINUX_MM_PAGE_KASAN_TAG_H
+
+#include <linux/types.h>
+
+struct page;
+
+#if defined(CONFIG_KASAN_SW_TAGS) || defined(CONFIG_KASAN_HW_TAGS)
+
+#include <linux/kasan.h>
+#include <linux/mm_types.h> // for struct page
+
+/*
+ * KASAN per-page tags are stored xor'ed with 0xff. This allows to avoid
+ * setting tags for all pages to native kernel tag value 0xff, as the default
+ * value 0x00 maps to 0xff.
+ */
+
+static inline u8 page_kasan_tag(const struct page *page)
+{
+ u8 tag = KASAN_TAG_KERNEL;
+
+ if (kasan_enabled()) {
+ tag = (page->flags >> KASAN_TAG_PGSHIFT) & KASAN_TAG_MASK;
+ tag ^= 0xff;
+ }
+
+ return tag;
+}
+
+static inline void page_kasan_tag_set(struct page *page, u8 tag)
+{
+ unsigned long old_flags, flags;
+
+ if (!kasan_enabled())
+ return;
+
+ tag ^= 0xff;
+ old_flags = READ_ONCE(page->flags);
+ do {
+ flags = old_flags;
+ flags &= ~(KASAN_TAG_MASK << KASAN_TAG_PGSHIFT);
+ flags |= (tag & KASAN_TAG_MASK) << KASAN_TAG_PGSHIFT;
+ } while (unlikely(!try_cmpxchg(&page->flags, &old_flags, flags)));
+}
+
+static inline void page_kasan_tag_reset(struct page *page)
+{
+ if (kasan_enabled())
+ page_kasan_tag_set(page, KASAN_TAG_KERNEL);
+}
+
+#else /* CONFIG_KASAN_SW_TAGS || CONFIG_KASAN_HW_TAGS */
+
+static inline u8 page_kasan_tag(const struct page *page)
+{
+ return 0xff;
+}
+
+static inline void page_kasan_tag_set(struct page *page, u8 tag) { }
+static inline void page_kasan_tag_reset(struct page *page) { }
+
+#endif /* CONFIG_KASAN_SW_TAGS || CONFIG_KASAN_HW_TAGS */
+
+#endif /* _LINUX_MM_PAGE_KASAN_TAG_H */
--
2.39.2


2024-03-05 09:00:29

by Max Kellermann

[permalink] [raw]
Subject: [PATCH v3 04/14] linux/mm.h: move section functions to mm/page_section.h

Prepare to reduce dependencies on linux/mm.h.

page_to_section() is used by __page_to_pfn() (but
asm-generic/memory_model.h does not include linux/mm.h). Thus, in
order to be able to use anything that calls page_to_pfn(), linux/mm.h
needs to be included.

This would prevent us from moving page_address() to a separate header,
because it calls lowmem_page_address() which in turn calls
page_to_virt() and then page_to_pfn(). To prepare for this move, we
move page_to_section() out of linux/mm.h into a separate lean header.

Signed-off-by: Max Kellermann <[email protected]>
---
include/linux/mm.h | 18 +-----------------
include/linux/mm/page_section.h | 23 +++++++++++++++++++++++
2 files changed, 24 insertions(+), 17 deletions(-)
create mode 100644 include/linux/mm/page_section.h

diff --git a/include/linux/mm.h b/include/linux/mm.h
index e140ee45f49c..79c1f924d4b5 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -3,6 +3,7 @@
#define _LINUX_MM_H

#include <linux/mm/page_kasan_tag.h>
+#include <linux/mm/page_section.h>
#include <linux/errno.h>
#include <linux/mmdebug.h>
#include <linux/gfp.h>
@@ -1637,10 +1638,6 @@ static inline bool is_nommu_shared_mapping(vm_flags_t flags)
}
#endif

-#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
-#define SECTION_IN_PAGE_FLAGS
-#endif
-
/*
* The identification function is mainly used by the buddy allocator for
* determining if two pages could be buddies. We are not really identifying
@@ -1838,19 +1835,6 @@ static inline pg_data_t *folio_pgdat(const struct folio *folio)
return page_pgdat(&folio->page);
}

-#ifdef SECTION_IN_PAGE_FLAGS
-static inline void set_page_section(struct page *page, unsigned long section)
-{
- page->flags &= ~(SECTIONS_MASK << SECTIONS_PGSHIFT);
- page->flags |= (section & SECTIONS_MASK) << SECTIONS_PGSHIFT;
-}
-
-static inline unsigned long page_to_section(const struct page *page)
-{
- return (page->flags >> SECTIONS_PGSHIFT) & SECTIONS_MASK;
-}
-#endif
-
/**
* folio_pfn - Return the Page Frame Number of a folio.
* @folio: The folio.
diff --git a/include/linux/mm/page_section.h b/include/linux/mm/page_section.h
new file mode 100644
index 000000000000..e4558c2691b8
--- /dev/null
+++ b/include/linux/mm/page_section.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_MM_PAGE_SECTION_H
+#define _LINUX_MM_PAGE_SECTION_H
+
+#include <linux/mm_types.h> // for struct page
+#include <linux/mmzone.h> // for SECTIONS_*
+
+#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
+#define SECTION_IN_PAGE_FLAGS
+
+static inline void set_page_section(struct page *page, unsigned long section)
+{
+ page->flags &= ~(SECTIONS_MASK << SECTIONS_PGSHIFT);
+ page->flags |= (section & SECTIONS_MASK) << SECTIONS_PGSHIFT;
+}
+
+static inline unsigned long page_to_section(const struct page *page)
+{
+ return (page->flags >> SECTIONS_PGSHIFT) & SECTIONS_MASK;
+}
+#endif
+
+#endif /* _LINUX_MM_PAGE_SECTION_H */
--
2.39.2


2024-03-05 09:01:23

by Max Kellermann

[permalink] [raw]
Subject: [PATCH v3 07/14] linux/mm.h: move folio_next() to mm/folio_next.h

Prepare to reduce dependencies on linux/mm.h.

folio_next() is used by linux/bio.h. Moving it to a separate lean
header will allow us to avoid the dependency on linux/mm.h.

Signed-off-by: Max Kellermann <[email protected]>
---
include/linux/mm.h | 20 +-------------------
include/linux/mm/folio_next.h | 27 +++++++++++++++++++++++++++
2 files changed, 28 insertions(+), 19 deletions(-)
create mode 100644 include/linux/mm/folio_next.h

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 0d291ff61db3..e6c2df977abc 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2,6 +2,7 @@
#ifndef _LINUX_MM_H
#define _LINUX_MM_H

+#include <linux/mm/folio_next.h>
#include <linux/mm/folio_size.h>
#include <linux/mm/page_address.h>
#include <linux/mm/page_section.h>
@@ -1922,25 +1923,6 @@ static inline void set_page_links(struct page *page, enum zone_type zone,
#define MAX_FOLIO_NR_PAGES MAX_ORDER_NR_PAGES
#endif

-/**
- * folio_next - Move to the next physical folio.
- * @folio: The folio we're currently operating on.
- *
- * If you have physically contiguous memory which may span more than
- * one folio (eg a &struct bio_vec), use this function to move from one
- * folio to the next. Do not use it if the memory is only virtually
- * contiguous as the folios are almost certainly not adjacent to each
- * other. This is the folio equivalent to writing ``page++``.
- *
- * Context: We assume that the folios are refcounted and/or locked at a
- * higher level and do not adjust the reference counts.
- * Return: The next struct folio.
- */
-static inline struct folio *folio_next(struct folio *folio)
-{
- return (struct folio *)folio_page(folio, folio_nr_pages(folio));
-}
-
/**
* folio_estimated_sharers - Estimate the number of sharers of a folio.
* @folio: The folio.
diff --git a/include/linux/mm/folio_next.h b/include/linux/mm/folio_next.h
new file mode 100644
index 000000000000..7016e303439c
--- /dev/null
+++ b/include/linux/mm/folio_next.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_MM_FOLIO_NEXT_H
+#define _LINUX_MM_FOLIO_NEXT_H
+
+#include <linux/mm/folio_size.h> // for folio_nr_pages()
+#include <linux/mm/page_address.h> // for nth_page(), needed by folio_page()
+
+/**
+ * folio_next - Move to the next physical folio.
+ * @folio: The folio we're currently operating on.
+ *
+ * If you have physically contiguous memory which may span more than
+ * one folio (eg a &struct bio_vec), use this function to move from one
+ * folio to the next. Do not use it if the memory is only virtually
+ * contiguous as the folios are almost certainly not adjacent to each
+ * other. This is the folio equivalent to writing ``page++``.
+ *
+ * Context: We assume that the folios are refcounted and/or locked at a
+ * higher level and do not adjust the reference counts.
+ * Return: The next struct folio.
+ */
+static inline struct folio *folio_next(struct folio *folio)
+{
+ return (struct folio *)folio_page(folio, folio_nr_pages(folio));
+}
+
+#endif /* _LINUX_MM_FOLIO_NEXT_H */
--
2.39.2


2024-03-05 09:01:25

by Max Kellermann

[permalink] [raw]
Subject: [PATCH v3 05/14] linux/mm.h: move page_address() and others to mm/page_address.h

Prepare to reduce dependencies on linux/mm.h.

page_address() is used by the following popular headers:

- linux/bio.h
- linux/bvec.h
- linux/highmem.h
- linux/scatterlist.h
- linux/skbuff.h

Moving it to a separate lean header will allow us to avoid the
dependency on linux/mm.h.

Signed-off-by: Max Kellermann <[email protected]>
---
include/linux/mm.h | 56 +-------------------------
include/linux/mm/page_address.h | 71 +++++++++++++++++++++++++++++++++
2 files changed, 72 insertions(+), 55 deletions(-)
create mode 100644 include/linux/mm/page_address.h

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 79c1f924d4b5..713cedc03b88 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2,7 +2,7 @@
#ifndef _LINUX_MM_H
#define _LINUX_MM_H

-#include <linux/mm/page_kasan_tag.h>
+#include <linux/mm/page_address.h>
#include <linux/mm/page_section.h>
#include <linux/errno.h>
#include <linux/mmdebug.h>
@@ -104,10 +104,6 @@ extern int mmap_rnd_compat_bits __read_mostly;
#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x), 0))
#endif

-#ifndef page_to_virt
-#define page_to_virt(x) __va(PFN_PHYS(page_to_pfn(x)))
-#endif
-
#ifndef lm_alias
#define lm_alias(x) __va(__pa_symbol(x))
#endif
@@ -211,14 +207,6 @@ int overcommit_kbytes_handler(struct ctl_table *, int, void *, size_t *,
int overcommit_policy_handler(struct ctl_table *, int, void *, size_t *,
loff_t *);

-#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
-#define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n))
-#define folio_page_idx(folio, p) (page_to_pfn(p) - folio_pfn(folio))
-#else
-#define nth_page(page,n) ((page) + (n))
-#define folio_page_idx(folio, p) ((p) - &(folio)->page)
-#endif
-
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE)

@@ -2137,44 +2125,6 @@ static inline int arch_make_folio_accessible(struct folio *folio)
*/
#include <linux/vmstat.h>

-static __always_inline void *lowmem_page_address(const struct page *page)
-{
- return page_to_virt(page);
-}
-
-#if defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL)
-#define HASHED_PAGE_VIRTUAL
-#endif
-
-#if defined(WANT_PAGE_VIRTUAL)
-static inline void *page_address(const struct page *page)
-{
- return page->virtual;
-}
-static inline void set_page_address(struct page *page, void *address)
-{
- page->virtual = address;
-}
-#define page_address_init() do { } while(0)
-#endif
-
-#if defined(HASHED_PAGE_VIRTUAL)
-void *page_address(const struct page *page);
-void set_page_address(struct page *page, void *virtual);
-void page_address_init(void);
-#endif
-
-#if !defined(HASHED_PAGE_VIRTUAL) && !defined(WANT_PAGE_VIRTUAL)
-#define page_address(page) lowmem_page_address(page)
-#define set_page_address(page, address) do { } while(0)
-#define page_address_init() do { } while(0)
-#endif
-
-static inline void *folio_address(const struct folio *folio)
-{
- return page_address(&folio->page);
-}
-
extern pgoff_t __page_file_index(struct page *page);

/*
@@ -2237,10 +2187,6 @@ static inline void clear_page_pfmemalloc(struct page *page)
*/
extern void pagefault_out_of_memory(void);

-#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
-#define offset_in_thp(page, p) ((unsigned long)(p) & (thp_size(page) - 1))
-#define offset_in_folio(folio, p) ((unsigned long)(p) & (folio_size(folio) - 1))
-
/*
* Parameter block passed down to zap_pte_range in exceptional cases.
*/
diff --git a/include/linux/mm/page_address.h b/include/linux/mm/page_address.h
new file mode 100644
index 000000000000..e1aaacc5003f
--- /dev/null
+++ b/include/linux/mm/page_address.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_MM_PAGE_ADDRESS_H
+#define _LINUX_MM_PAGE_ADDRESS_H
+
+#include <linux/mm_types.h> // for struct page
+#include <linux/mm/page_kasan_tag.h> // needed by the page_to_virt() macro on some architectures (e.g. arm64)
+#include <asm/page.h> // for PAGE_MASK, page_to_virt()
+
+#if defined(CONFIG_FLATMEM)
+#include <linux/mmzone.h> // for memmap (used by __pfn_to_page())
+#elif defined(CONFIG_SPARSEMEM_VMEMMAP)
+#include <asm/pgtable.h> // for vmemmap (used by __pfn_to_page())
+#elif defined(CONFIG_SPARSEMEM)
+#include <linux/mm/page_section.h> // for page_to_section() (used by __page_to_pfn())
+#endif
+
+#ifndef page_to_virt
+#define page_to_virt(x) __va(PFN_PHYS(page_to_pfn(x)))
+#endif
+
+#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
+#define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n))
+#define folio_page_idx(folio, p) (page_to_pfn(p) - folio_pfn(folio))
+#else
+#define nth_page(page,n) ((page) + (n))
+#define folio_page_idx(folio, p) ((p) - &(folio)->page)
+#endif
+
+static __always_inline void *lowmem_page_address(const struct page *page)
+{
+ return page_to_virt(page);
+}
+
+#if defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL)
+#define HASHED_PAGE_VIRTUAL
+#endif
+
+#if defined(WANT_PAGE_VIRTUAL)
+static inline void *page_address(const struct page *page)
+{
+ return page->virtual;
+}
+static inline void set_page_address(struct page *page, void *address)
+{
+ page->virtual = address;
+}
+#define page_address_init() do { } while(0)
+#endif
+
+#if defined(HASHED_PAGE_VIRTUAL)
+void *page_address(const struct page *page);
+void set_page_address(struct page *page, void *virtual);
+void page_address_init(void);
+#endif
+
+#if !defined(HASHED_PAGE_VIRTUAL) && !defined(WANT_PAGE_VIRTUAL)
+#define page_address(page) lowmem_page_address(page)
+#define set_page_address(page, address) do { } while(0)
+#define page_address_init() do { } while(0)
+#endif
+
+static inline void *folio_address(const struct folio *folio)
+{
+ return page_address(&folio->page);
+}
+
+#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
+#define offset_in_thp(page, p) ((unsigned long)(p) & (thp_size(page) - 1))
+#define offset_in_folio(folio, p) ((unsigned long)(p) & (folio_size(folio) - 1))
+
+#endif /* _LINUX_MM_PAGE_ADDRESS_H */
--
2.39.2


2024-03-05 09:01:56

by Max Kellermann

[permalink] [raw]
Subject: [PATCH v3 08/14] linux/mm.h: move devmap-related declarations to mm/devmap_managed.h

Prepare to reduce dependencies on linux/mm.h.

put_devmap_managed_page() is called by put_page(). Moving it to a
separate header allows us to move put_page() to a separate lean header
as well.

Signed-off-by: Max Kellermann <[email protected]>
---
include/linux/mm.h | 25 +--------------------
include/linux/mm/devmap_managed.h | 37 +++++++++++++++++++++++++++++++
2 files changed, 38 insertions(+), 24 deletions(-)
create mode 100644 include/linux/mm/devmap_managed.h

diff --git a/include/linux/mm.h b/include/linux/mm.h
index e6c2df977abc..61f1312a626e 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2,6 +2,7 @@
#ifndef _LINUX_MM_H
#define _LINUX_MM_H

+#include <linux/mm/devmap_managed.h>
#include <linux/mm/folio_next.h>
#include <linux/mm/folio_size.h>
#include <linux/mm/page_address.h>
@@ -1357,30 +1358,6 @@ vm_fault_t finish_fault(struct vm_fault *vmf);
* back into memory.
*/

-#if defined(CONFIG_ZONE_DEVICE) && defined(CONFIG_FS_DAX)
-DECLARE_STATIC_KEY_FALSE(devmap_managed_key);
-
-bool __put_devmap_managed_page_refs(struct page *page, int refs);
-static inline bool put_devmap_managed_page_refs(struct page *page, int refs)
-{
- if (!static_branch_unlikely(&devmap_managed_key))
- return false;
- if (!is_zone_device_page(page))
- return false;
- return __put_devmap_managed_page_refs(page, refs);
-}
-#else /* CONFIG_ZONE_DEVICE && CONFIG_FS_DAX */
-static inline bool put_devmap_managed_page_refs(struct page *page, int refs)
-{
- return false;
-}
-#endif /* CONFIG_ZONE_DEVICE && CONFIG_FS_DAX */
-
-static inline bool put_devmap_managed_page(struct page *page)
-{
- return put_devmap_managed_page_refs(page, 1);
-}
-
/* 127: arbitrary random number, small enough to assemble well */
#define folio_ref_zero_or_close_to_overflow(folio) \
((unsigned int) folio_ref_count(folio) + 127u <= 127u)
diff --git a/include/linux/mm/devmap_managed.h b/include/linux/mm/devmap_managed.h
new file mode 100644
index 000000000000..0773529d80b2
--- /dev/null
+++ b/include/linux/mm/devmap_managed.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_MM_DEVMAP_MANAGED_H
+#define _LINUX_MM_DEVMAP_MANAGED_H
+
+#include <linux/types.h> // for bool
+
+struct page;
+
+#if defined(CONFIG_ZONE_DEVICE) && defined(CONFIG_FS_DAX)
+
+#include <linux/jump_label.h> // for DECLARE_STATIC_KEY_FALSE(), static_branch_unlikely()
+#include <linux/mmzone.h> // is_zone_device_page()
+
+DECLARE_STATIC_KEY_FALSE(devmap_managed_key);
+
+bool __put_devmap_managed_page_refs(struct page *page, int refs);
+static inline bool put_devmap_managed_page_refs(struct page *page, int refs)
+{
+ if (!static_branch_unlikely(&devmap_managed_key))
+ return false;
+ if (!is_zone_device_page(page))
+ return false;
+ return __put_devmap_managed_page_refs(page, refs);
+}
+#else /* CONFIG_ZONE_DEVICE && CONFIG_FS_DAX */
+static inline bool put_devmap_managed_page_refs(struct page *page, int refs)
+{
+ return false;
+}
+#endif /* CONFIG_ZONE_DEVICE && CONFIG_FS_DAX */
+
+static inline bool put_devmap_managed_page(struct page *page)
+{
+ return put_devmap_managed_page_refs(page, 1);
+}
+
+#endif /* _LINUX_MM_DEVMAP_MANAGED_H */
--
2.39.2


2024-03-05 09:02:05

by Max Kellermann

[permalink] [raw]
Subject: [PATCH v3 10/14] linux/mm.h: move page_zone_id() and more to mm/folio_zone.h

This is needed to eliminate linux/skbuff.h's dependency on linux/mm.h.

Signed-off-by: Max Kellermann <[email protected]>
---
include/linux/mm.h | 28 +--------------------------
include/linux/mm/folio_zone.h | 36 +++++++++++++++++++++++++++++++++++
2 files changed, 37 insertions(+), 27 deletions(-)
create mode 100644 include/linux/mm/folio_zone.h

diff --git a/include/linux/mm.h b/include/linux/mm.h
index e8a914e7bebd..b3f83fb26aca 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -5,6 +5,7 @@
#include <linux/mm/folio_next.h>
#include <linux/mm/folio_size.h>
#include <linux/mm/folio_usage.h>
+#include <linux/mm/folio_zone.h>
#include <linux/mm/page_address.h>
#include <linux/mm/page_section.h>
#include <linux/errno.h>
@@ -1370,33 +1371,6 @@ static inline bool is_nommu_shared_mapping(vm_flags_t flags)
}
#endif

-/*
- * The identification function is mainly used by the buddy allocator for
- * determining if two pages could be buddies. We are not really identifying
- * the zone since we could be using the section number id if we do not have
- * node id available in page flags.
- * We only guarantee that it will return the same value for two combinable
- * pages in a zone.
- */
-static inline int page_zone_id(struct page *page)
-{
- return (page->flags >> ZONEID_PGSHIFT) & ZONEID_MASK;
-}
-
-#ifdef NODE_NOT_IN_PAGE_FLAGS
-int page_to_nid(const struct page *page);
-#else
-static inline int page_to_nid(const struct page *page)
-{
- return (PF_POISONED_CHECK(page)->flags >> NODES_PGSHIFT) & NODES_MASK;
-}
-#endif
-
-static inline int folio_nid(const struct folio *folio)
-{
- return page_to_nid(&folio->page);
-}
-
#ifdef CONFIG_NUMA_BALANCING
/* page access time bits needs to hold at least 4 seconds */
#define PAGE_ACCESS_TIME_MIN_BITS 12
diff --git a/include/linux/mm/folio_zone.h b/include/linux/mm/folio_zone.h
new file mode 100644
index 000000000000..572fe37068f1
--- /dev/null
+++ b/include/linux/mm/folio_zone.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_MM_FOLIO_ZONE_H
+#define _LINUX_MM_FOLIO_ZONE_H
+
+#include <linux/mm_types.h> // for struct page, struct folio
+#include <linux/mmzone.h> // for ZONEID_*, NODES_*
+#include <linux/page-flags.h> // for PF_POISONED_CHECK()
+
+/*
+ * The identification function is mainly used by the buddy allocator for
+ * determining if two pages could be buddies. We are not really identifying
+ * the zone since we could be using the section number id if we do not have
+ * node id available in page flags.
+ * We only guarantee that it will return the same value for two combinable
+ * pages in a zone.
+ */
+static inline int page_zone_id(struct page *page)
+{
+ return (page->flags >> ZONEID_PGSHIFT) & ZONEID_MASK;
+}
+
+#ifdef NODE_NOT_IN_PAGE_FLAGS
+int page_to_nid(const struct page *page);
+#else
+static inline int page_to_nid(const struct page *page)
+{
+ return (PF_POISONED_CHECK(page)->flags >> NODES_PGSHIFT) & NODES_MASK;
+}
+#endif
+
+static inline int folio_nid(const struct folio *folio)
+{
+ return page_to_nid(&folio->page);
+}
+
+#endif /* _LINUX_MM_FOLIO_ZONE_H */
--
2.39.2


2024-03-05 09:02:48

by Max Kellermann

[permalink] [raw]
Subject: [PATCH v3 12/14] linux/mm.h: move is_vmalloc_addr() to mm/vmalloc_addr.h

This is needed to eliminate linux/dma-mapping.h's dependency on
linux/mm.h.

Signed-off-by: Max Kellermann <[email protected]>
---
include/linux/mm.h | 25 +------------------------
include/linux/mm/vmalloc_addr.h | 33 +++++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+), 24 deletions(-)
create mode 100644 include/linux/mm/vmalloc_addr.h

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 07262ae43c5d..80fc7df2856a 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -9,6 +9,7 @@
#include <linux/mm/page_address.h>
#include <linux/mm/page_section.h>
#include <linux/mm/pfmemalloc.h>
+#include <linux/mm/vmalloc_addr.h>
#include <linux/errno.h>
#include <linux/mmdebug.h>
#include <linux/gfp.h>
@@ -1086,30 +1087,6 @@ enum {
int region_intersects(resource_size_t offset, size_t size, unsigned long flags,
unsigned long desc);

-/* Support for virtually mapped pages */
-struct page *vmalloc_to_page(const void *addr);
-unsigned long vmalloc_to_pfn(const void *addr);
-
-/*
- * Determine if an address is within the vmalloc range
- *
- * On nommu, vmalloc/vfree wrap through kmalloc/kfree directly, so there
- * is no special casing required.
- */
-#ifdef CONFIG_MMU
-extern bool is_vmalloc_addr(const void *x);
-extern int is_vmalloc_or_module_addr(const void *x);
-#else
-static inline bool is_vmalloc_addr(const void *x)
-{
- return false;
-}
-static inline int is_vmalloc_or_module_addr(const void *x)
-{
- return 0;
-}
-#endif
-
/*
* How many times the entire folio is mapped as a single unit (eg by a
* PMD or PUD entry). This is probably not what you want, except for
diff --git a/include/linux/mm/vmalloc_addr.h b/include/linux/mm/vmalloc_addr.h
new file mode 100644
index 000000000000..86ad2dc94960
--- /dev/null
+++ b/include/linux/mm/vmalloc_addr.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_MM_VMALLOC_ADDR_H
+#define _LINUX_MM_VMALLOC_ADDR_H
+
+#include <linux/types.h> // for bool
+
+struct page;
+
+/* Support for virtually mapped pages */
+struct page *vmalloc_to_page(const void *addr);
+unsigned long vmalloc_to_pfn(const void *addr);
+
+/*
+ * Determine if an address is within the vmalloc range
+ *
+ * On nommu, vmalloc/vfree wrap through kmalloc/kfree directly, so there
+ * is no special casing required.
+ */
+#ifdef CONFIG_MMU
+extern bool is_vmalloc_addr(const void *x);
+extern int is_vmalloc_or_module_addr(const void *x);
+#else
+static inline bool is_vmalloc_addr(const void *x)
+{
+ return false;
+}
+static inline int is_vmalloc_or_module_addr(const void *x)
+{
+ return 0;
+}
+#endif
+
+#endif /* _LINUX_MM_VMALLOC_ADDR_H */
--
2.39.2


2024-03-05 09:02:56

by Max Kellermann

[permalink] [raw]
Subject: [PATCH v3 02/14] include/drm/drm_gem.h: add poll_table_struct forward declaration

After eliminating includes of linux/mm.h, the following build failure
occurred:

./include/drm/drm_file.h:443:45: warning: ‘struct poll_table_struct’ declared inside parameter list will not be visible outside of this definition or declaration
443 | __poll_t drm_poll(struct file *filp, struct poll_table_struct *wait);
| ^~~~~~~~~~~~~~~~~
In file included from drivers/gpu/drm/imagination/pvr_gem.h:12,
from drivers/gpu/drm/imagination/pvr_fw.h:9:
./include/drm/drm_gem.h:447:27: error: initialization of ‘__poll_t (*)(struct file *, struct poll_table_struct *)’ {aka ‘unsigned int (*)(struct file *, struct poll_table_struct *)’} from incompatible pointer type ‘__poll_t (*)(struct file *, struct poll_table_struct *)’ {aka ‘unsigned int (*)(struct file *, struct poll_table_struct *)’} [-Werror=incompatible-pointer-types]
447 | .poll = drm_poll,\
| ^~~~~~~~

The compiler is confused, and that can be fixed easily by
forward-declaring the struct expicitly.

Signed-off-by: Max Kellermann <[email protected]>
---
include/drm/drm_file.h | 1 +
1 file changed, 1 insertion(+)

diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h
index ab230d3af138..f24ade9f766f 100644
--- a/include/drm/drm_file.h
+++ b/include/drm/drm_file.h
@@ -44,6 +44,7 @@ struct drm_device;
struct drm_printer;
struct device;
struct file;
+struct poll_table_struct;

/*
* FIXME: Not sure we want to have drm_minor here in the end, but to avoid
--
2.39.2


2024-03-05 09:03:12

by Max Kellermann

[permalink] [raw]
Subject: [PATCH v3 13/14] linux/mm.h: move high_memory to mm/high_memory.h

This variable is used by lots of arch/*/include/asm/ headers, but
these do not (and should not) include the huge linux/mm.h header.
Let's move this "extern" variable to a separate header and include
this one in arch/.

Signed-off-by: Max Kellermann <[email protected]>
---
arch/arm/include/asm/memory.h | 4 ++++
arch/arm/include/asm/pgtable.h | 2 ++
arch/csky/include/asm/page.h | 1 +
arch/hexagon/include/asm/mem-layout.h | 4 ++++
arch/m68k/include/asm/page_mm.h | 1 +
arch/m68k/include/asm/pgtable_mm.h | 1 +
arch/parisc/include/asm/floppy.h | 1 +
arch/powerpc/include/asm/book3s/32/pgtable.h | 4 ++++
arch/powerpc/include/asm/nohash/32/pgtable.h | 1 +
arch/powerpc/include/asm/page.h | 1 +
arch/x86/include/asm/floppy.h | 1 +
arch/x86/include/asm/pgtable_32_areas.h | 4 ++++
drivers/mtd/nand/onenand/onenand_samsung.c | 1 +
include/linux/mm.h | 2 +-
include/linux/mm/high_memory.h | 7 +++++++
15 files changed, 34 insertions(+), 1 deletion(-)
create mode 100644 include/linux/mm/high_memory.h

diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index ef2aa79ece5a..a67afb213e2e 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -387,6 +387,10 @@ static inline unsigned long __virt_to_idmap(unsigned long x)
*/
#define ARCH_PFN_OFFSET PHYS_PFN_OFFSET

+#ifndef __ASSEMBLY__
+#include <linux/mm/high_memory.h>
+#endif
+
#define virt_to_page(kaddr) pfn_to_page(virt_to_pfn(kaddr))
#define virt_addr_valid(kaddr) (((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory) \
&& pfn_valid(virt_to_pfn(kaddr)))
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index be91e376df79..eb80f6a65619 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -11,6 +11,8 @@
#include <asm/proc-fns.h>

#ifndef __ASSEMBLY__
+#include <linux/mm/high_memory.h>
+
/*
* ZERO_PAGE is a global shared page that is always zero: used
* for zero-mapped memory areas etc..
diff --git a/arch/csky/include/asm/page.h b/arch/csky/include/asm/page.h
index 4a0502e324a6..016f722fbe43 100644
--- a/arch/csky/include/asm/page.h
+++ b/arch/csky/include/asm/page.h
@@ -32,6 +32,7 @@

#ifndef __ASSEMBLY__

+#include <linux/mm/high_memory.h>
#include <linux/pfn.h>

#define virt_addr_valid(kaddr) ((void *)(kaddr) >= (void *)PAGE_OFFSET && \
diff --git a/arch/hexagon/include/asm/mem-layout.h b/arch/hexagon/include/asm/mem-layout.h
index e2f99413fe56..a09116c50043 100644
--- a/arch/hexagon/include/asm/mem-layout.h
+++ b/arch/hexagon/include/asm/mem-layout.h
@@ -10,6 +10,10 @@

#include <linux/const.h>

+#ifndef __ASSEMBLY__
+#include <linux/mm/high_memory.h>
+#endif
+
/*
* Have to do this for ginormous numbers, else they get printed as
* negative numbers, which the linker no likey when you try to
diff --git a/arch/m68k/include/asm/page_mm.h b/arch/m68k/include/asm/page_mm.h
index e0ae4d5fc985..f958655d1931 100644
--- a/arch/m68k/include/asm/page_mm.h
+++ b/arch/m68k/include/asm/page_mm.h
@@ -5,6 +5,7 @@
#ifndef __ASSEMBLY__

#include <linux/compiler.h>
+#include <linux/mm/high_memory.h>
#include <asm/module.h>

/*
diff --git a/arch/m68k/include/asm/pgtable_mm.h b/arch/m68k/include/asm/pgtable_mm.h
index dbdf1c2b2f66..ec593656bdc5 100644
--- a/arch/m68k/include/asm/pgtable_mm.h
+++ b/arch/m68k/include/asm/pgtable_mm.h
@@ -13,6 +13,7 @@

#ifndef __ASSEMBLY__
#include <asm/processor.h>
+#include <linux/mm/high_memory.h>
#include <linux/sched.h>
#include <linux/threads.h>

diff --git a/arch/parisc/include/asm/floppy.h b/arch/parisc/include/asm/floppy.h
index b318a7df52f6..98ed37c5dc59 100644
--- a/arch/parisc/include/asm/floppy.h
+++ b/arch/parisc/include/asm/floppy.h
@@ -8,6 +8,7 @@
#ifndef __ASM_PARISC_FLOPPY_H
#define __ASM_PARISC_FLOPPY_H

+#include <linux/mm/high_memory.h>
#include <linux/vmalloc.h>


diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h
index 52971ee30717..03e0a32e1c2c 100644
--- a/arch/powerpc/include/asm/book3s/32/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/32/pgtable.h
@@ -4,6 +4,10 @@

#include <asm-generic/pgtable-nopmd.h>

+#ifndef __ASSEMBLY__
+#include <linux/mm/high_memory.h>
+#endif
+
/*
* The "classic" 32-bit implementation of the PowerPC MMU uses a hash
* table containing PTEs, together with a set of 16 segment registers,
diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h b/arch/powerpc/include/asm/nohash/32/pgtable.h
index 9164a9e41b02..8a9f5b546e4a 100644
--- a/arch/powerpc/include/asm/nohash/32/pgtable.h
+++ b/arch/powerpc/include/asm/nohash/32/pgtable.h
@@ -5,6 +5,7 @@
#include <asm-generic/pgtable-nopmd.h>

#ifndef __ASSEMBLY__
+#include <linux/mm/high_memory.h>
#include <linux/sched.h>
#include <linux/threads.h>
#include <asm/mmu.h> /* For sub-arch specific PPC_PIN_SIZE */
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
index e5fcc79b5bfb..c541e71d3d5c 100644
--- a/arch/powerpc/include/asm/page.h
+++ b/arch/powerpc/include/asm/page.h
@@ -7,6 +7,7 @@
*/

#ifndef __ASSEMBLY__
+#include <linux/mm/high_memory.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/bug.h>
diff --git a/arch/x86/include/asm/floppy.h b/arch/x86/include/asm/floppy.h
index 6ec3fc969ad5..7756e984f146 100644
--- a/arch/x86/include/asm/floppy.h
+++ b/arch/x86/include/asm/floppy.h
@@ -10,6 +10,7 @@
#ifndef _ASM_X86_FLOPPY_H
#define _ASM_X86_FLOPPY_H

+#include <linux/mm/high_memory.h>
#include <linux/vmalloc.h>

/*
diff --git a/arch/x86/include/asm/pgtable_32_areas.h b/arch/x86/include/asm/pgtable_32_areas.h
index b6355416a15a..b339137b4f4e 100644
--- a/arch/x86/include/asm/pgtable_32_areas.h
+++ b/arch/x86/include/asm/pgtable_32_areas.h
@@ -3,6 +3,10 @@

#include <asm/cpu_entry_area.h>

+#ifndef __ASSEMBLY__
+#include <linux/mm/high_memory.h>
+#endif
+
/*
* Just any arbitrary offset to the start of the vmalloc VM area: the
* current 8MB value just means that there will be a 8MB "hole" after the
diff --git a/drivers/mtd/nand/onenand/onenand_samsung.c b/drivers/mtd/nand/onenand/onenand_samsung.c
index fd6890a03d55..7c3cc270386d 100644
--- a/drivers/mtd/nand/onenand/onenand_samsung.c
+++ b/drivers/mtd/nand/onenand/onenand_samsung.c
@@ -15,6 +15,7 @@
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/mm/high_memory.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
#include <linux/mtd/partitions.h>
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 80fc7df2856a..1d7b4c781995 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -6,6 +6,7 @@
#include <linux/mm/folio_size.h>
#include <linux/mm/folio_usage.h>
#include <linux/mm/folio_zone.h>
+#include <linux/mm/high_memory.h>
#include <linux/mm/page_address.h>
#include <linux/mm/page_section.h>
#include <linux/mm/pfmemalloc.h>
@@ -82,7 +83,6 @@ static inline void totalram_pages_add(long count)
atomic_long_add(count, &_totalram_pages);
}

-extern void * high_memory;
extern int page_cluster;
extern const int page_cluster_max;

diff --git a/include/linux/mm/high_memory.h b/include/linux/mm/high_memory.h
new file mode 100644
index 000000000000..e504aafd0d48
--- /dev/null
+++ b/include/linux/mm/high_memory.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_MM_HIGH_MEMORY_H
+#define _LINUX_MM_HIGH_MEMORY_H
+
+extern void * high_memory;
+
+#endif /* _LINUX_MM_HIGH_MEMORY_H */
--
2.39.2


2024-03-05 09:05:01

by Max Kellermann

[permalink] [raw]
Subject: [PATCH v3 06/14] linux/mm.h: move folio_size(), ... to mm/folio_size.h

Prepare to reduce dependencies on linux/mm.h.

folio_size()/page_size() are used by the following popular headers:

- linux/highmem.h
- linux/iov_iter.h
- linux/pagemap.h

Moving them to a separate lean header will allow us to avoid the
dependency on linux/mm.h. Additionally, it allows us to move
folio_next() to a separate header, because it needs folio_nr_pages()
which is also moved to folio_size.h.

Signed-off-by: Max Kellermann <[email protected]>
---
include/linux/mm.h | 140 +------------------------------
include/linux/mm/folio_size.h | 150 ++++++++++++++++++++++++++++++++++
2 files changed, 151 insertions(+), 139 deletions(-)
create mode 100644 include/linux/mm/folio_size.h

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 713cedc03b88..0d291ff61db3 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2,6 +2,7 @@
#ifndef _LINUX_MM_H
#define _LINUX_MM_H

+#include <linux/mm/folio_size.h>
#include <linux/mm/page_address.h>
#include <linux/mm/page_section.h>
#include <linux/errno.h>
@@ -1068,38 +1069,6 @@ int vma_is_stack_for_current(struct vm_area_struct *vma);
struct mmu_gather;
struct inode;

-/*
- * compound_order() can be called without holding a reference, which means
- * that niceties like page_folio() don't work. These callers should be
- * prepared to handle wild return values. For example, PG_head may be
- * set before the order is initialised, or this may be a tail page.
- * See compaction.c for some good examples.
- */
-static inline unsigned int compound_order(struct page *page)
-{
- struct folio *folio = (struct folio *)page;
-
- if (!test_bit(PG_head, &folio->flags))
- return 0;
- return folio->_flags_1 & 0xff;
-}
-
-/**
- * folio_order - The allocation order of a folio.
- * @folio: The folio.
- *
- * A folio is composed of 2^order pages. See get_order() for the definition
- * of order.
- *
- * Return: The order of the folio.
- */
-static inline unsigned int folio_order(struct folio *folio)
-{
- if (!folio_test_large(folio))
- return 0;
- return folio->_flags_1 & 0xff;
-}
-
#include <linux/huge_mm.h>

/*
@@ -1306,39 +1275,6 @@ unsigned long nr_free_buffer_pages(void);

void destroy_large_folio(struct folio *folio);

-/* Returns the number of bytes in this potentially compound page. */
-static inline unsigned long page_size(struct page *page)
-{
- return PAGE_SIZE << compound_order(page);
-}
-
-/* Returns the number of bits needed for the number of bytes in a page */
-static inline unsigned int page_shift(struct page *page)
-{
- return PAGE_SHIFT + compound_order(page);
-}
-
-/**
- * thp_order - Order of a transparent huge page.
- * @page: Head page of a transparent huge page.
- */
-static inline unsigned int thp_order(struct page *page)
-{
- VM_BUG_ON_PGFLAGS(PageTail(page), page);
- return compound_order(page);
-}
-
-/**
- * thp_size - Size of a transparent huge page.
- * @page: Head page of a transparent huge page.
- *
- * Return: Number of bytes in this page.
- */
-static inline unsigned long thp_size(struct page *page)
-{
- return PAGE_SIZE << thp_order(page);
-}
-
#ifdef CONFIG_MMU
/*
* Do pte_mkwrite, but only if the vma says VM_WRITE. We do this when
@@ -1979,23 +1915,6 @@ static inline void set_page_links(struct page *page, enum zone_type zone,
#endif
}

-/**
- * folio_nr_pages - The number of pages in the folio.
- * @folio: The folio.
- *
- * Return: A positive power of two.
- */
-static inline long folio_nr_pages(struct folio *folio)
-{
- if (!folio_test_large(folio))
- return 1;
-#ifdef CONFIG_64BIT
- return folio->_folio_nr_pages;
-#else
- return 1L << (folio->_flags_1 & 0xff);
-#endif
-}
-
/* Only hugetlbfs can allocate folios larger than MAX_ORDER */
#ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE
#define MAX_FOLIO_NR_PAGES (1UL << PUD_ORDER)
@@ -2003,33 +1922,6 @@ static inline long folio_nr_pages(struct folio *folio)
#define MAX_FOLIO_NR_PAGES MAX_ORDER_NR_PAGES
#endif

-/*
- * compound_nr() returns the number of pages in this potentially compound
- * page. compound_nr() can be called on a tail page, and is defined to
- * return 1 in that case.
- */
-static inline unsigned long compound_nr(struct page *page)
-{
- struct folio *folio = (struct folio *)page;
-
- if (!test_bit(PG_head, &folio->flags))
- return 1;
-#ifdef CONFIG_64BIT
- return folio->_folio_nr_pages;
-#else
- return 1L << (folio->_flags_1 & 0xff);
-#endif
-}
-
-/**
- * thp_nr_pages - The number of regular pages in this huge page.
- * @page: The head page of a huge page.
- */
-static inline int thp_nr_pages(struct page *page)
-{
- return folio_nr_pages((struct folio *)page);
-}
-
/**
* folio_next - Move to the next physical folio.
* @folio: The folio we're currently operating on.
@@ -2049,36 +1941,6 @@ static inline struct folio *folio_next(struct folio *folio)
return (struct folio *)folio_page(folio, folio_nr_pages(folio));
}

-/**
- * folio_shift - The size of the memory described by this folio.
- * @folio: The folio.
- *
- * A folio represents a number of bytes which is a power-of-two in size.
- * This function tells you which power-of-two the folio is. See also
- * folio_size() and folio_order().
- *
- * Context: The caller should have a reference on the folio to prevent
- * it from being split. It is not necessary for the folio to be locked.
- * Return: The base-2 logarithm of the size of this folio.
- */
-static inline unsigned int folio_shift(struct folio *folio)
-{
- return PAGE_SHIFT + folio_order(folio);
-}
-
-/**
- * folio_size - The number of bytes in a folio.
- * @folio: The folio.
- *
- * Context: The caller should have a reference on the folio to prevent
- * it from being split. It is not necessary for the folio to be locked.
- * Return: The number of bytes in this folio.
- */
-static inline size_t folio_size(struct folio *folio)
-{
- return PAGE_SIZE << folio_order(folio);
-}
-
/**
* folio_estimated_sharers - Estimate the number of sharers of a folio.
* @folio: The folio.
diff --git a/include/linux/mm/folio_size.h b/include/linux/mm/folio_size.h
new file mode 100644
index 000000000000..dd8af39ef572
--- /dev/null
+++ b/include/linux/mm/folio_size.h
@@ -0,0 +1,150 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_MM_FOLIO_SIZE_H
+#define _LINUX_MM_FOLIO_SIZE_H
+
+#include <linux/bitops.h> // for test_bit()
+#include <linux/mmdebug.h> // for VM_BUG_ON_PGFLAGS()
+#include <linux/mm_types.h> // for struct page
+#include <linux/page-flags.h> // for folio_test_large()
+#include <asm/page.h> // for PAGE_SIZE, PAGE_SHIFT
+
+/*
+ * compound_order() can be called without holding a reference, which means
+ * that niceties like page_folio() don't work. These callers should be
+ * prepared to handle wild return values. For example, PG_head may be
+ * set before the order is initialised, or this may be a tail page.
+ * See compaction.c for some good examples.
+ */
+static inline unsigned int compound_order(struct page *page)
+{
+ struct folio *folio = (struct folio *)page;
+
+ if (!test_bit(PG_head, &folio->flags))
+ return 0;
+ return folio->_flags_1 & 0xff;
+}
+
+/**
+ * folio_order - The allocation order of a folio.
+ * @folio: The folio.
+ *
+ * A folio is composed of 2^order pages. See get_order() for the definition
+ * of order.
+ *
+ * Return: The order of the folio.
+ */
+static inline unsigned int folio_order(struct folio *folio)
+{
+ if (!folio_test_large(folio))
+ return 0;
+ return folio->_flags_1 & 0xff;
+}
+
+/* Returns the number of bytes in this potentially compound page. */
+static inline unsigned long page_size(struct page *page)
+{
+ return PAGE_SIZE << compound_order(page);
+}
+
+/* Returns the number of bits needed for the number of bytes in a page */
+static inline unsigned int page_shift(struct page *page)
+{
+ return PAGE_SHIFT + compound_order(page);
+}
+
+/**
+ * thp_order - Order of a transparent huge page.
+ * @page: Head page of a transparent huge page.
+ */
+static inline unsigned int thp_order(struct page *page)
+{
+ VM_BUG_ON_PGFLAGS(PageTail(page), page);
+ return compound_order(page);
+}
+
+/**
+ * thp_size - Size of a transparent huge page.
+ * @page: Head page of a transparent huge page.
+ *
+ * Return: Number of bytes in this page.
+ */
+static inline unsigned long thp_size(struct page *page)
+{
+ return PAGE_SIZE << thp_order(page);
+}
+
+/**
+ * folio_nr_pages - The number of pages in the folio.
+ * @folio: The folio.
+ *
+ * Return: A positive power of two.
+ */
+static inline long folio_nr_pages(struct folio *folio)
+{
+ if (!folio_test_large(folio))
+ return 1;
+#ifdef CONFIG_64BIT
+ return folio->_folio_nr_pages;
+#else
+ return 1L << (folio->_flags_1 & 0xff);
+#endif
+}
+
+/*
+ * compound_nr() returns the number of pages in this potentially compound
+ * page. compound_nr() can be called on a tail page, and is defined to
+ * return 1 in that case.
+ */
+static inline unsigned long compound_nr(struct page *page)
+{
+ struct folio *folio = (struct folio *)page;
+
+ if (!test_bit(PG_head, &folio->flags))
+ return 1;
+#ifdef CONFIG_64BIT
+ return folio->_folio_nr_pages;
+#else
+ return 1L << (folio->_flags_1 & 0xff);
+#endif
+}
+
+/**
+ * thp_nr_pages - The number of regular pages in this huge page.
+ * @page: The head page of a huge page.
+ */
+static inline int thp_nr_pages(struct page *page)
+{
+ return folio_nr_pages((struct folio *)page);
+}
+
+/**
+ * folio_shift - The size of the memory described by this folio.
+ * @folio: The folio.
+ *
+ * A folio represents a number of bytes which is a power-of-two in size.
+ * This function tells you which power-of-two the folio is. See also
+ * folio_size() and folio_order().
+ *
+ * Context: The caller should have a reference on the folio to prevent
+ * it from being split. It is not necessary for the folio to be locked.
+ * Return: The base-2 logarithm of the size of this folio.
+ */
+static inline unsigned int folio_shift(struct folio *folio)
+{
+ return PAGE_SHIFT + folio_order(folio);
+}
+
+/**
+ * folio_size - The number of bytes in a folio.
+ * @folio: The folio.
+ *
+ * Context: The caller should have a reference on the folio to prevent
+ * it from being split. It is not necessary for the folio to be locked.
+ * Return: The number of bytes in this folio.
+ */
+static inline size_t folio_size(struct folio *folio)
+{
+ return PAGE_SIZE << folio_order(folio);
+}
+
+#endif /* _LINUX_MM_FOLIO_SIZE_H_H */
--
2.39.2


2024-03-05 09:06:46

by Max Kellermann

[permalink] [raw]
Subject: [PATCH v3 09/14] linux/mm.h: move usage count functions to mm/folio_usage.h

Prepare to reduce dependencies on linux/mm.h.

This new header contains wrappers for the low-level functions from
page_ref.h. By having those higher-level functions in a separate
header, we can avoid their additional dependencies in the page_ref.h.

Having these in a separate header will allow eliminating the
dependency on linux/mm.h from these headers:

- linux/skbuff.h
- linux/swap.h

Signed-off-by: Max Kellermann <[email protected]>
---
include/linux/mm.h | 172 +------------------------------
include/linux/mm/folio_usage.h | 182 +++++++++++++++++++++++++++++++++
2 files changed, 183 insertions(+), 171 deletions(-)
create mode 100644 include/linux/mm/folio_usage.h

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 61f1312a626e..e8a914e7bebd 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2,9 +2,9 @@
#ifndef _LINUX_MM_H
#define _LINUX_MM_H

-#include <linux/mm/devmap_managed.h>
#include <linux/mm/folio_next.h>
#include <linux/mm/folio_size.h>
+#include <linux/mm/folio_usage.h>
#include <linux/mm/page_address.h>
#include <linux/mm/page_section.h>
#include <linux/errno.h>
@@ -1073,51 +1073,6 @@ struct inode;

#include <linux/huge_mm.h>

-/*
- * Methods to modify the page usage count.
- *
- * What counts for a page usage:
- * - cache mapping (page->mapping)
- * - private data (page->private)
- * - page mapped in a task's page tables, each mapping
- * is counted separately
- *
- * Also, many kernel routines increase the page count before a critical
- * routine so they can be sure the page doesn't go away from under them.
- */
-
-/*
- * Drop a ref, return true if the refcount fell to zero (the page has no users)
- */
-static inline int put_page_testzero(struct page *page)
-{
- VM_BUG_ON_PAGE(page_ref_count(page) == 0, page);
- return page_ref_dec_and_test(page);
-}
-
-static inline int folio_put_testzero(struct folio *folio)
-{
- return put_page_testzero(&folio->page);
-}
-
-/*
- * Try to grab a ref unless the page has a refcount of zero, return false if
- * that is the case.
- * This can be called when MMU is off so it must not access
- * any of the virtual mappings.
- */
-static inline bool get_page_unless_zero(struct page *page)
-{
- return page_ref_add_unless(page, 1, 0);
-}
-
-static inline struct folio *folio_get_nontail_page(struct page *page)
-{
- if (unlikely(!get_page_unless_zero(page)))
- return NULL;
- return (struct folio *)page;
-}
-
extern int page_is_ram(unsigned long pfn);

enum {
@@ -1266,8 +1221,6 @@ static inline struct folio *virt_to_folio(const void *x)
return page_folio(page);
}

-void __folio_put(struct folio *folio);
-
void put_pages_list(struct list_head *pages);

void split_page(struct page *page, unsigned int order);
@@ -1358,129 +1311,6 @@ vm_fault_t finish_fault(struct vm_fault *vmf);
* back into memory.
*/

-/* 127: arbitrary random number, small enough to assemble well */
-#define folio_ref_zero_or_close_to_overflow(folio) \
- ((unsigned int) folio_ref_count(folio) + 127u <= 127u)
-
-/**
- * folio_get - Increment the reference count on a folio.
- * @folio: The folio.
- *
- * Context: May be called in any context, as long as you know that
- * you have a refcount on the folio. If you do not already have one,
- * folio_try_get() may be the right interface for you to use.
- */
-static inline void folio_get(struct folio *folio)
-{
- VM_BUG_ON_FOLIO(folio_ref_zero_or_close_to_overflow(folio), folio);
- folio_ref_inc(folio);
-}
-
-static inline void get_page(struct page *page)
-{
- folio_get(page_folio(page));
-}
-
-static inline __must_check bool try_get_page(struct page *page)
-{
- page = compound_head(page);
- if (WARN_ON_ONCE(page_ref_count(page) <= 0))
- return false;
- page_ref_inc(page);
- return true;
-}
-
-/**
- * folio_put - Decrement the reference count on a folio.
- * @folio: The folio.
- *
- * If the folio's reference count reaches zero, the memory will be
- * released back to the page allocator and may be used by another
- * allocation immediately. Do not access the memory or the struct folio
- * after calling folio_put() unless you can be sure that it wasn't the
- * last reference.
- *
- * Context: May be called in process or interrupt context, but not in NMI
- * context. May be called while holding a spinlock.
- */
-static inline void folio_put(struct folio *folio)
-{
- if (folio_put_testzero(folio))
- __folio_put(folio);
-}
-
-/**
- * folio_put_refs - Reduce the reference count on a folio.
- * @folio: The folio.
- * @refs: The amount to subtract from the folio's reference count.
- *
- * If the folio's reference count reaches zero, the memory will be
- * released back to the page allocator and may be used by another
- * allocation immediately. Do not access the memory or the struct folio
- * after calling folio_put_refs() unless you can be sure that these weren't
- * the last references.
- *
- * Context: May be called in process or interrupt context, but not in NMI
- * context. May be called while holding a spinlock.
- */
-static inline void folio_put_refs(struct folio *folio, int refs)
-{
- if (folio_ref_sub_and_test(folio, refs))
- __folio_put(folio);
-}
-
-void folios_put_refs(struct folio_batch *folios, unsigned int *refs);
-
-/*
- * union release_pages_arg - an array of pages or folios
- *
- * release_pages() releases a simple array of multiple pages, and
- * accepts various different forms of said page array: either
- * a regular old boring array of pages, an array of folios, or
- * an array of encoded page pointers.
- *
- * The transparent union syntax for this kind of "any of these
- * argument types" is all kinds of ugly, so look away.
- */
-typedef union {
- struct page **pages;
- struct folio **folios;
- struct encoded_page **encoded_pages;
-} release_pages_arg __attribute__ ((__transparent_union__));
-
-void release_pages(release_pages_arg, int nr);
-
-/**
- * folios_put - Decrement the reference count on an array of folios.
- * @folios: The folios.
- *
- * Like folio_put(), but for a batch of folios. This is more efficient
- * than writing the loop yourself as it will optimise the locks which need
- * to be taken if the folios are freed. The folios batch is returned
- * empty and ready to be reused for another batch; there is no need to
- * reinitialise it.
- *
- * Context: May be called in process or interrupt context, but not in NMI
- * context. May be called while holding a spinlock.
- */
-static inline void folios_put(struct folio_batch *folios)
-{
- folios_put_refs(folios, NULL);
-}
-
-static inline void put_page(struct page *page)
-{
- struct folio *folio = page_folio(page);
-
- /*
- * For some devmap managed pages we need to catch refcount transition
- * from 2 to 1:
- */
- if (put_devmap_managed_page(&folio->page))
- return;
- folio_put(folio);
-}
-
/*
* GUP_PIN_COUNTING_BIAS, and the associated functions that use it, overload
* the page's refcount so that two separate items are tracked: the original page
diff --git a/include/linux/mm/folio_usage.h b/include/linux/mm/folio_usage.h
new file mode 100644
index 000000000000..4a7e9cd74909
--- /dev/null
+++ b/include/linux/mm/folio_usage.h
@@ -0,0 +1,182 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_MM_FOLIO_USAGE_H
+#define _LINUX_MM_FOLIO_USAGE_H
+
+#include <linux/mm/devmap_managed.h> // for put_devmap_managed_page()
+#include <linux/mmdebug.h> // for VM_BUG_ON_PAGE()
+#include <linux/mm_types.h> // for struct folio
+#include <linux/page_ref.h>
+
+struct folio_batch;
+
+/*
+ * Methods to modify the page usage count.
+ *
+ * What counts for a page usage:
+ * - cache mapping (page->mapping)
+ * - private data (page->private)
+ * - page mapped in a task's page tables, each mapping
+ * is counted separately
+ *
+ * Also, many kernel routines increase the page count before a critical
+ * routine so they can be sure the page doesn't go away from under them.
+ */
+
+/*
+ * Drop a ref, return true if the refcount fell to zero (the page has no users)
+ */
+static inline int put_page_testzero(struct page *page)
+{
+ VM_BUG_ON_PAGE(page_ref_count(page) == 0, page);
+ return page_ref_dec_and_test(page);
+}
+
+static inline int folio_put_testzero(struct folio *folio)
+{
+ return put_page_testzero(&folio->page);
+}
+
+/*
+ * Try to grab a ref unless the page has a refcount of zero, return false if
+ * that is the case.
+ * This can be called when MMU is off so it must not access
+ * any of the virtual mappings.
+ */
+static inline bool get_page_unless_zero(struct page *page)
+{
+ return page_ref_add_unless(page, 1, 0);
+}
+
+static inline struct folio *folio_get_nontail_page(struct page *page)
+{
+ if (unlikely(!get_page_unless_zero(page)))
+ return NULL;
+ return (struct folio *)page;
+}
+
+void __folio_put(struct folio *folio);
+
+/* 127: arbitrary random number, small enough to assemble well */
+#define folio_ref_zero_or_close_to_overflow(folio) \
+ ((unsigned int) folio_ref_count(folio) + 127u <= 127u)
+
+/**
+ * folio_get - Increment the reference count on a folio.
+ * @folio: The folio.
+ *
+ * Context: May be called in any context, as long as you know that
+ * you have a refcount on the folio. If you do not already have one,
+ * folio_try_get() may be the right interface for you to use.
+ */
+static inline void folio_get(struct folio *folio)
+{
+ VM_BUG_ON_FOLIO(folio_ref_zero_or_close_to_overflow(folio), folio);
+ folio_ref_inc(folio);
+}
+
+static inline void get_page(struct page *page)
+{
+ folio_get(page_folio(page));
+}
+
+static inline __must_check bool try_get_page(struct page *page)
+{
+ page = compound_head(page);
+ if (WARN_ON_ONCE(page_ref_count(page) <= 0))
+ return false;
+ page_ref_inc(page);
+ return true;
+}
+
+/**
+ * folio_put - Decrement the reference count on a folio.
+ * @folio: The folio.
+ *
+ * If the folio's reference count reaches zero, the memory will be
+ * released back to the page allocator and may be used by another
+ * allocation immediately. Do not access the memory or the struct folio
+ * after calling folio_put() unless you can be sure that it wasn't the
+ * last reference.
+ *
+ * Context: May be called in process or interrupt context, but not in NMI
+ * context. May be called while holding a spinlock.
+ */
+static inline void folio_put(struct folio *folio)
+{
+ if (folio_put_testzero(folio))
+ __folio_put(folio);
+}
+
+/**
+ * folio_put_refs - Reduce the reference count on a folio.
+ * @folio: The folio.
+ * @refs: The amount to subtract from the folio's reference count.
+ *
+ * If the folio's reference count reaches zero, the memory will be
+ * released back to the page allocator and may be used by another
+ * allocation immediately. Do not access the memory or the struct folio
+ * after calling folio_put_refs() unless you can be sure that these weren't
+ * the last references.
+ *
+ * Context: May be called in process or interrupt context, but not in NMI
+ * context. May be called while holding a spinlock.
+ */
+static inline void folio_put_refs(struct folio *folio, int refs)
+{
+ if (folio_ref_sub_and_test(folio, refs))
+ __folio_put(folio);
+}
+
+void folios_put_refs(struct folio_batch *folios, unsigned int *refs);
+
+/*
+ * union release_pages_arg - an array of pages or folios
+ *
+ * release_pages() releases a simple array of multiple pages, and
+ * accepts various different forms of said page array: either
+ * a regular old boring array of pages, an array of folios, or
+ * an array of encoded page pointers.
+ *
+ * The transparent union syntax for this kind of "any of these
+ * argument types" is all kinds of ugly, so look away.
+ */
+typedef union {
+ struct page **pages;
+ struct folio **folios;
+ struct encoded_page **encoded_pages;
+} release_pages_arg __attribute__ ((__transparent_union__));
+
+void release_pages(release_pages_arg, int nr);
+
+/**
+ * folios_put - Decrement the reference count on an array of folios.
+ * @folios: The folios.
+ *
+ * Like folio_put(), but for a batch of folios. This is more efficient
+ * than writing the loop yourself as it will optimise the locks which need
+ * to be taken if the folios are freed. The folios batch is returned
+ * empty and ready to be reused for another batch; there is no need to
+ * reinitialise it.
+ *
+ * Context: May be called in process or interrupt context, but not in NMI
+ * context. May be called while holding a spinlock.
+ */
+static inline void folios_put(struct folio_batch *folios)
+{
+ folios_put_refs(folios, NULL);
+}
+
+static inline void put_page(struct page *page)
+{
+ struct folio *folio = page_folio(page);
+
+ /*
+ * For some devmap managed pages we need to catch refcount transition
+ * from 2 to 1:
+ */
+ if (put_devmap_managed_page(&folio->page))
+ return;
+ folio_put(folio);
+}
+
+#endif /* _LINUX_MM_FOLIO_USAGE_H */
--
2.39.2


2024-03-05 09:07:10

by Max Kellermann

[permalink] [raw]
Subject: [PATCH v3 11/14] linux/mm.h: move pfmemalloc-related functions to pfmemalloc.h

This is needed to eliminate linux/skbuff.h's dependency on linux/mm.h.

Signed-off-by: Max Kellermann <[email protected]>
---
include/linux/mm.h | 45 +-----------------------------
include/linux/mm/pfmemalloc.h | 52 +++++++++++++++++++++++++++++++++++
2 files changed, 53 insertions(+), 44 deletions(-)
create mode 100644 include/linux/mm/pfmemalloc.h

diff --git a/include/linux/mm.h b/include/linux/mm.h
index b3f83fb26aca..07262ae43c5d 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -8,6 +8,7 @@
#include <linux/mm/folio_zone.h>
#include <linux/mm/page_address.h>
#include <linux/mm/page_section.h>
+#include <linux/mm/pfmemalloc.h>
#include <linux/errno.h>
#include <linux/mmdebug.h>
#include <linux/gfp.h>
@@ -1763,50 +1764,6 @@ static inline pgoff_t page_index(struct page *page)
return page->index;
}

-/*
- * Return true only if the page has been allocated with
- * ALLOC_NO_WATERMARKS and the low watermark was not
- * met implying that the system is under some pressure.
- */
-static inline bool page_is_pfmemalloc(const struct page *page)
-{
- /*
- * lru.next has bit 1 set if the page is allocated from the
- * pfmemalloc reserves. Callers may simply overwrite it if
- * they do not need to preserve that information.
- */
- return (uintptr_t)page->lru.next & BIT(1);
-}
-
-/*
- * Return true only if the folio has been allocated with
- * ALLOC_NO_WATERMARKS and the low watermark was not
- * met implying that the system is under some pressure.
- */
-static inline bool folio_is_pfmemalloc(const struct folio *folio)
-{
- /*
- * lru.next has bit 1 set if the page is allocated from the
- * pfmemalloc reserves. Callers may simply overwrite it if
- * they do not need to preserve that information.
- */
- return (uintptr_t)folio->lru.next & BIT(1);
-}
-
-/*
- * Only to be called by the page allocator on a freshly allocated
- * page.
- */
-static inline void set_page_pfmemalloc(struct page *page)
-{
- page->lru.next = (void *)BIT(1);
-}
-
-static inline void clear_page_pfmemalloc(struct page *page)
-{
- page->lru.next = NULL;
-}
-
/*
* Can be called by the pagefault handler when it gets a VM_FAULT_OOM.
*/
diff --git a/include/linux/mm/pfmemalloc.h b/include/linux/mm/pfmemalloc.h
new file mode 100644
index 000000000000..345b215a3566
--- /dev/null
+++ b/include/linux/mm/pfmemalloc.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_MM_PFMEMALLOC_H
+#define _LINUX_MM_PFMEMALLOC_H
+
+#include <linux/bits.h> // for BIT()
+#include <linux/mm_types.h> // for struct page
+
+/*
+ * Return true only if the page has been allocated with
+ * ALLOC_NO_WATERMARKS and the low watermark was not
+ * met implying that the system is under some pressure.
+ */
+static inline bool page_is_pfmemalloc(const struct page *page)
+{
+ /*
+ * lru.next has bit 1 set if the page is allocated from the
+ * pfmemalloc reserves. Callers may simply overwrite it if
+ * they do not need to preserve that information.
+ */
+ return (uintptr_t)page->lru.next & BIT(1);
+}
+
+/*
+ * Return true only if the folio has been allocated with
+ * ALLOC_NO_WATERMARKS and the low watermark was not
+ * met implying that the system is under some pressure.
+ */
+static inline bool folio_is_pfmemalloc(const struct folio *folio)
+{
+ /*
+ * lru.next has bit 1 set if the page is allocated from the
+ * pfmemalloc reserves. Callers may simply overwrite it if
+ * they do not need to preserve that information.
+ */
+ return (uintptr_t)folio->lru.next & BIT(1);
+}
+
+/*
+ * Only to be called by the page allocator on a freshly allocated
+ * page.
+ */
+static inline void set_page_pfmemalloc(struct page *page)
+{
+ page->lru.next = (void *)BIT(1);
+}
+
+static inline void clear_page_pfmemalloc(struct page *page)
+{
+ page->lru.next = NULL;
+}
+
+#endif /* _LINUX_MM_PFMEMALLOC_H */
--
2.39.2


2024-03-05 09:08:27

by Max Kellermann

[permalink] [raw]
Subject: [PATCH v3 14/14] include: reduce dependencies on linux/mm.h

Replace <linux/mm.h> with the smaller pieces that were just splitted
out. This affects a few headers that are included by many, e.g. bio.h
and highmem.h, which now no longer depend on the fat <linux/mm.h>
header.

For this, several missing includes need to be added because they are
no longer indirectly included, e.g. <linux/fs.h>.

Signed-off-by: Max Kellermann <[email protected]>
---
include/linux/bio.h | 2 ++
include/linux/dma-mapping.h | 1 +
include/linux/highmem-internal.h | 2 ++
include/linux/highmem.h | 4 +++-
include/linux/scatterlist.h | 2 +-
include/linux/skbuff.h | 4 ++++
lib/scatterlist.c | 1 +
7 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/include/linux/bio.h b/include/linux/bio.h
index 875d792bffff..e2f24d7235d3 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -5,7 +5,9 @@
#ifndef __LINUX_BIO_H
#define __LINUX_BIO_H

+#include <linux/fs.h> // for struct kiocb, IOCB_NOWAIT
#include <linux/mempool.h>
+#include <linux/mm/folio_next.h>
/* struct bio, bio_vec and BIO_* flags are defined in blk_types.h */
#include <linux/blk_types.h>
#include <linux/uio.h>
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 4a658de44ee9..37d5591039c7 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -11,6 +11,7 @@
#include <linux/scatterlist.h>
#include <linux/bug.h>
#include <linux/mem_encrypt.h>
+#include <linux/mm/vmalloc_addr.h>

/**
* List of possible attributes associated with a DMA mapping. The semantics
diff --git a/include/linux/highmem-internal.h b/include/linux/highmem-internal.h
index a3028e400a9c..a479e6b7c54c 100644
--- a/include/linux/highmem-internal.h
+++ b/include/linux/highmem-internal.h
@@ -2,6 +2,8 @@
#ifndef _LINUX_HIGHMEM_INTERNAL_H
#define _LINUX_HIGHMEM_INTERNAL_H

+#include <linux/mm/page_address.h>
+
/*
* Outside of CONFIG_HIGHMEM to support X86 32bit iomap_atomic() cruft.
*/
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 00341b56d291..10a165a913ad 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -7,7 +7,9 @@
#include <linux/bug.h>
#include <linux/cacheflush.h>
#include <linux/kmsan.h>
-#include <linux/mm.h>
+#include <linux/mm/folio_size.h> // for page_size()
+#include <linux/mm/folio_usage.h> // for folio_put()
+#include <linux/mm/page_address.h>
#include <linux/uaccess.h>
#include <linux/hardirq.h>

diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index 0516e64dc03e..9221bba82b23 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -5,7 +5,7 @@
#include <linux/string.h>
#include <linux/types.h>
#include <linux/bug.h>
-#include <linux/mm.h>
+#include <linux/mm/page_address.h>
#include <asm/io.h>

#ifdef CONFIG_UML
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index d577e0bee18d..ac121262bedb 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -16,6 +16,10 @@
#include <linux/bug.h>
#include <linux/bvec.h>
#include <linux/cache.h>
+#include <linux/gfp.h> // for alloc_pages_node()
+#include <linux/mm/folio_usage.h> // for get_page(), put_page()
+#include <linux/mm/folio_zone.h> // for page_to_nid()
+#include <linux/mm/pfmemalloc.h> // for page_is_pfmemalloc()
#include <linux/rbtree.h>
#include <linux/socket.h>
#include <linux/refcount.h>
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index 68b45c82c37a..03599396f15d 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -9,6 +9,7 @@
#include <linux/scatterlist.h>
#include <linux/highmem.h>
#include <linux/kmemleak.h>
+#include <linux/mm.h>
#include <linux/bvec.h>
#include <linux/uio.h>

--
2.39.2


2024-03-07 15:56:16

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v3 06/14] linux/mm.h: move folio_size(), ... to mm/folio_size.h

Hi Max,

kernel test robot noticed the following build errors:

[auto build test ERROR on next-20240305]
[cannot apply to akpm-mm/mm-everything char-misc/char-misc-testing char-misc/char-misc-next char-misc/char-misc-linus joro-iommu/next broonie-spi/for-next powerpc/next powerpc/fixes linus/master v6.8-rc7 v6.8-rc6 v6.8-rc5 v6.8-rc7]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Max-Kellermann/drivers-add-missing-includes-on-linux-mm-h-and-others/20240305-170312
base: next-20240305
patch link: https://lore.kernel.org/r/20240305085919.1601395-7-max.kellermann%40ionos.com
patch subject: [PATCH v3 06/14] linux/mm.h: move folio_size(), ... to mm/folio_size.h
config: loongarch-defconfig (https://download.01.org/0day-ci/archive/20240307/[email protected]/config)
compiler: loongarch64-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240307/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All error/warnings (new ones prefixed by >>):

In file included from include/linux/mm/folio_size.h:8,
from include/linux/mm.h:5,
from arch/loongarch/include/asm/vdso.h:10,
from arch/loongarch/vdso/vgetcpu.c:6:
>> include/linux/page-flags.h:202:1: warning: data definition has no type or storage class
202 | DECLARE_STATIC_KEY_FALSE(hugetlb_optimize_vmemmap_key);
| ^~~~~~~~~~~~~~~~~~~~~~~~
>> include/linux/page-flags.h:202:1: error: type defaults to 'int' in declaration of 'DECLARE_STATIC_KEY_FALSE' [-Werror=implicit-int]
>> include/linux/page-flags.h:202:1: warning: parameter names (without types) in function declaration
In file included from include/linux/mm/folio_size.h:8,
from include/linux/mm.h:5,
from arch/loongarch/include/asm/vdso.h:10,
from arch/loongarch/include/asm/vdso/vdso.h:11,
from arch/loongarch/include/asm/vdso/gettimeofday.h:13,
from include/vdso/datapage.h:151,
from lib/vdso/gettimeofday.c:5,
from <command-line>:
>> include/linux/page-flags.h:202:1: warning: data definition has no type or storage class
202 | DECLARE_STATIC_KEY_FALSE(hugetlb_optimize_vmemmap_key);
| ^~~~~~~~~~~~~~~~~~~~~~~~
>> include/linux/page-flags.h:202:1: error: type defaults to 'int' in declaration of 'DECLARE_STATIC_KEY_FALSE' [-Werror=implicit-int]
>> include/linux/page-flags.h:202:1: warning: parameter names (without types) in function declaration
include/linux/page-flags.h: In function 'page_fixed_fake_head':
>> include/linux/page-flags.h:210:14: error: implicit declaration of function 'static_branch_unlikely' [-Werror=implicit-function-declaration]
210 | if (!static_branch_unlikely(&hugetlb_optimize_vmemmap_key))
| ^~~~~~~~~~~~~~~~~~~~~~
include/linux/page-flags.h: In function 'page_fixed_fake_head':
>> include/linux/page-flags.h:210:14: error: implicit declaration of function 'static_branch_unlikely' [-Werror=implicit-function-declaration]
210 | if (!static_branch_unlikely(&hugetlb_optimize_vmemmap_key))
| ^~~~~~~~~~~~~~~~~~~~~~
>> include/linux/page-flags.h:210:38: error: 'hugetlb_optimize_vmemmap_key' undeclared (first use in this function)
210 | if (!static_branch_unlikely(&hugetlb_optimize_vmemmap_key))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/page-flags.h:210:38: note: each undeclared identifier is reported only once for each function it appears in
>> include/linux/page-flags.h:210:38: error: 'hugetlb_optimize_vmemmap_key' undeclared (first use in this function)
210 | if (!static_branch_unlikely(&hugetlb_optimize_vmemmap_key))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/page-flags.h:210:38: note: each undeclared identifier is reported only once for each function it appears in
cc1: some warnings being treated as errors
cc1: some warnings being treated as errors
make[3]: *** [scripts/Makefile.build:244: arch/loongarch/vdso/vgetcpu.o] Error 1
make[3]: *** [scripts/Makefile.build:244: arch/loongarch/vdso/vgettimeofday.o] Error 1
make[3]: Target 'include/generated/vdso-offsets.h' not remade because of errors.
make[2]: *** [arch/loongarch/Makefile:163: vdso_prepare] Error 2
make[2]: Target 'prepare' not remade because of errors.
make[1]: *** [Makefile:240: __sub-make] Error 2
make[1]: Target 'prepare' not remade because of errors.
make: *** [Makefile:240: __sub-make] Error 2
make: Target 'prepare' not remade because of errors.


vim +202 include/linux/page-flags.h

9223b4190fa129 Christoph Lameter 2008-04-28 200
47010c040dec8a Muchun Song 2022-04-28 201 #ifdef CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP
cf5472e5611338 Muchun Song 2022-06-28 @202 DECLARE_STATIC_KEY_FALSE(hugetlb_optimize_vmemmap_key);
a6b40850c442bf Muchun Song 2022-03-22 203
e7d324850bfcb3 Muchun Song 2022-03-22 204 /*
838691a1c0ec44 Muchun Song 2022-06-28 205 * Return the real head page struct iff the @page is a fake head page, otherwise
838691a1c0ec44 Muchun Song 2022-06-28 206 * return the @page itself. See Documentation/mm/vmemmap_dedup.rst.
e7d324850bfcb3 Muchun Song 2022-03-22 207 */
e7d324850bfcb3 Muchun Song 2022-03-22 208 static __always_inline const struct page *page_fixed_fake_head(const struct page *page)
e7d324850bfcb3 Muchun Song 2022-03-22 209 {
cf5472e5611338 Muchun Song 2022-06-28 @210 if (!static_branch_unlikely(&hugetlb_optimize_vmemmap_key))
e7d324850bfcb3 Muchun Song 2022-03-22 211 return page;
e7d324850bfcb3 Muchun Song 2022-03-22 212
e7d324850bfcb3 Muchun Song 2022-03-22 213 /*
e7d324850bfcb3 Muchun Song 2022-03-22 214 * Only addresses aligned with PAGE_SIZE of struct page may be fake head
e7d324850bfcb3 Muchun Song 2022-03-22 215 * struct page. The alignment check aims to avoid access the fields (
e7d324850bfcb3 Muchun Song 2022-03-22 216 * e.g. compound_head) of the @page[1]. It can avoid touch a (possibly)
e7d324850bfcb3 Muchun Song 2022-03-22 217 * cold cacheline in some cases.
e7d324850bfcb3 Muchun Song 2022-03-22 218 */
e7d324850bfcb3 Muchun Song 2022-03-22 219 if (IS_ALIGNED((unsigned long)page, PAGE_SIZE) &&
e7d324850bfcb3 Muchun Song 2022-03-22 220 test_bit(PG_head, &page->flags)) {
e7d324850bfcb3 Muchun Song 2022-03-22 221 /*
e7d324850bfcb3 Muchun Song 2022-03-22 222 * We can safely access the field of the @page[1] with PG_head
e7d324850bfcb3 Muchun Song 2022-03-22 223 * because the @page is a compound page composed with at least
e7d324850bfcb3 Muchun Song 2022-03-22 224 * two contiguous pages.
e7d324850bfcb3 Muchun Song 2022-03-22 225 */
e7d324850bfcb3 Muchun Song 2022-03-22 226 unsigned long head = READ_ONCE(page[1].compound_head);
e7d324850bfcb3 Muchun Song 2022-03-22 227
e7d324850bfcb3 Muchun Song 2022-03-22 228 if (likely(head & 1))
e7d324850bfcb3 Muchun Song 2022-03-22 229 return (const struct page *)(head - 1);
e7d324850bfcb3 Muchun Song 2022-03-22 230 }
e7d324850bfcb3 Muchun Song 2022-03-22 231 return page;
e7d324850bfcb3 Muchun Song 2022-03-22 232 }
e7d324850bfcb3 Muchun Song 2022-03-22 233 #else
e7d324850bfcb3 Muchun Song 2022-03-22 234 static inline const struct page *page_fixed_fake_head(const struct page *page)
e7d324850bfcb3 Muchun Song 2022-03-22 235 {
e7d324850bfcb3 Muchun Song 2022-03-22 236 return page;
e7d324850bfcb3 Muchun Song 2022-03-22 237 }
e7d324850bfcb3 Muchun Song 2022-03-22 238 #endif
e7d324850bfcb3 Muchun Song 2022-03-22 239

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki