In preparation for device-dax to use the same mapping machinery as fsdax, add support for device-dax compound pages. Presently this is handled by dax_set_mapping() which is careful to only update page->mapping for head pages. However, it does that by looking at properties in the 'struct dev_dax' instance associated with the page. Switch to just checking PageHead() directly. Cc: Matthew Wilcox <willy@xxxxxxxxxxxxx> Cc: Jan Kara <jack@xxxxxxx> Cc: "Darrick J. Wong" <djwong@xxxxxxxxxx> Cc: Jason Gunthorpe <jgg@xxxxxxxxxx> Cc: Christoph Hellwig <hch@xxxxxx> Cc: John Hubbard <jhubbard@xxxxxxxxxx> Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx> --- drivers/dax/Kconfig | 1 + drivers/dax/mapping.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/drivers/dax/Kconfig b/drivers/dax/Kconfig index 3ed4da3935e5..2dcc8744277d 100644 --- a/drivers/dax/Kconfig +++ b/drivers/dax/Kconfig @@ -10,6 +10,7 @@ if DAX config DEV_DAX tristate "Device DAX: direct access mapping device" depends on TRANSPARENT_HUGEPAGE + depends on !FS_DAX_LIMITED help Support raw access to differentiated (persistence, bandwidth, latency...) memory via an mmap(2) capable character diff --git a/drivers/dax/mapping.c b/drivers/dax/mapping.c index 0810af7d9503..6bd38ddba2cb 100644 --- a/drivers/dax/mapping.c +++ b/drivers/dax/mapping.c @@ -351,6 +351,8 @@ static vm_fault_t dax_associate_entry(void *entry, for_each_mapped_pfn(entry, pfn) { struct page *page = pfn_to_page(pfn); + page = compound_head(page); + if (flags & DAX_COW) { dax_mapping_set_cow(page); } else { @@ -358,6 +360,13 @@ static vm_fault_t dax_associate_entry(void *entry, page->mapping = mapping; page->index = index + i++; } + + /* + * page->mapping and page->index are only manipulated on + * head pages + */ + if (PageHead(page)) + break; } return 0; @@ -380,6 +389,8 @@ static void dax_disassociate_entry(void *entry, struct address_space *mapping, for_each_mapped_pfn(entry, pfn) { page = pfn_to_page(pfn); + page = compound_head(page); + WARN_ON_ONCE(trunc && page_maybe_dma_pinned(page)); if (dax_mapping_is_cow(page->mapping)) { /* keep the CoW flag if this page is still shared */ @@ -389,6 +400,13 @@ static void dax_disassociate_entry(void *entry, struct address_space *mapping, WARN_ON_ONCE(page->mapping && page->mapping != mapping); page->mapping = NULL; page->index = 0; + + /* + * page->mapping and page->index are only manipulated on + * head pages + */ + if (PageHead(page)) + break; } }