From: Dan Williams <dan.j.williams@intel.com>
To: linux-nvdimm@lists.01.org
Cc: Dave Chinner <david@fromorbit.com>,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
ross.zwisler@linux.intel.com,
Andrew Morton <akpm@linux-foundation.org>,
hch@lst.de
Subject: [PATCH v2 04/20] mm: introduce __get_dev_pagemap()
Date: Fri, 09 Oct 2015 20:55:44 -0400 [thread overview]
Message-ID: <20151010005544.17221.69747.stgit@dwillia2-desk3.jf.intel.com> (raw)
In-Reply-To: <20151010005522.17221.87557.stgit@dwillia2-desk3.jf.intel.com>
There are several scenarios where we need to retrieve and update
metadata associated with a given devm_memremap_pages() mapping, and the
only lookup key available is a pfn in the range:
1/ We want to augment vmemmap_populate() (called via arch_add_memory())
to allocate memmap storage from pre-allocated pages reserved by the
device driver. At vmemmap_alloc_block_buf() time it grabs device pages
rather than page allocator pages. This is in support of
devm_memremap_pages() mappings where the memmap is too large to fit in
main memory (i.e. large persistent memory devices).
2/ Taking a reference against the mapping when inserting device pages
into the address_space radix of a given inode. This facilitates
unmap_mapping_range() and truncate_inode_pages() operations when the
driver is tearing down the mapping.
3/ get_user_pages() operations on ZONE_DEVICE memory require taking a
reference against the mapping so that the driver teardown path can
revoke and drain usage of device pages.
Cc: Christoph Hellwig <hch@lst.de>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
include/linux/mm.h | 18 ++++++++++++++++++
kernel/memremap.c | 40 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 58 insertions(+)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 80001de019ba..30c3c8764649 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -717,6 +717,24 @@ static inline enum zone_type page_zonenum(const struct page *page)
return (page->flags >> ZONES_PGSHIFT) & ZONES_MASK;
}
+/**
+ * struct dev_pagemap - metadata for ZONE_DEVICE mappings
+ * @dev: host device of the mapping for debug
+ */
+struct dev_pagemap {
+ /* TODO: vmem_altmap and percpu_ref count */
+ struct device *dev;
+};
+
+#ifdef CONFIG_ZONE_DEVICE
+struct dev_pagemap *__get_dev_pagemap(resource_size_t phys);
+#else
+static inline struct dev_pagemap *get_dev_pagemap(resource_size_t phys)
+{
+ return NULL;
+}
+#endif
+
#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
#define SECTION_IN_PAGE_FLAGS
#endif
diff --git a/kernel/memremap.c b/kernel/memremap.c
index 3218e8b1fc28..64bfd9fa93aa 100644
--- a/kernel/memremap.c
+++ b/kernel/memremap.c
@@ -10,6 +10,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
+#include <linux/rculist.h>
#include <linux/device.h>
#include <linux/types.h>
#include <linux/io.h>
@@ -138,18 +139,52 @@ void devm_memunmap(struct device *dev, void *addr)
EXPORT_SYMBOL(devm_memunmap);
#ifdef CONFIG_ZONE_DEVICE
+static LIST_HEAD(ranges);
+static DEFINE_SPINLOCK(range_lock);
+
struct page_map {
struct resource res;
+ struct dev_pagemap pgmap;
+ struct list_head list;
};
+static void add_page_map(struct page_map *page_map)
+{
+ spin_lock(&range_lock);
+ list_add_rcu(&page_map->list, &ranges);
+ spin_unlock(&range_lock);
+}
+
+static void del_page_map(struct page_map *page_map)
+{
+ spin_lock(&range_lock);
+ list_del_rcu(&page_map->list);
+ spin_unlock(&range_lock);
+}
+
static void devm_memremap_pages_release(struct device *dev, void *res)
{
struct page_map *page_map = res;
+ del_page_map(page_map);
+
/* pages are dead and unused, undo the arch mapping */
arch_remove_memory(page_map->res.start, resource_size(&page_map->res));
}
+/* assumes rcu_read_lock() held at entry */
+struct dev_pagemap *__get_dev_pagemap(resource_size_t phys)
+{
+ struct page_map *page_map;
+
+ WARN_ON_ONCE(!rcu_read_lock_held());
+
+ list_for_each_entry_rcu(page_map, &ranges, list)
+ if (phys >= page_map->res.start && phys <= page_map->res.end)
+ return &page_map->pgmap;
+ return NULL;
+}
+
void *devm_memremap_pages(struct device *dev, struct resource *res)
{
int is_ram = region_intersects(res->start, resource_size(res),
@@ -173,12 +208,17 @@ void *devm_memremap_pages(struct device *dev, struct resource *res)
memcpy(&page_map->res, res, sizeof(*res));
+ page_map->pgmap.dev = dev;
+ INIT_LIST_HEAD(&page_map->list);
+ add_page_map(page_map);
+
nid = dev_to_node(dev);
if (nid < 0)
nid = numa_mem_id();
error = arch_add_memory(nid, res->start, resource_size(res), true);
if (error) {
+ del_page_map(page_map);
devres_free(page_map);
return ERR_PTR(error);
}
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2015-10-10 1:01 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-10-10 0:55 [PATCH v2 00/20] get_user_pages() for dax mappings Dan Williams
2015-10-10 0:55 ` [PATCH v2 01/20] block: generic request_queue reference counting Dan Williams
2015-10-11 12:59 ` Christoph Hellwig
2015-10-13 0:09 ` Dan Williams
2015-10-10 0:55 ` [PATCH v2 02/20] dax: increase granularity of dax_clear_blocks() operations Dan Williams
2015-10-10 0:55 ` [PATCH v2 03/20] block, dax: fix lifetime of in-kernel dax mappings with dax_map_atomic() Dan Williams
2015-10-10 0:55 ` Dan Williams [this message]
2015-10-10 0:55 ` [PATCH v2 05/20] x86, mm: introduce vmem_altmap to augment vmemmap_populate() Dan Williams
2015-10-19 22:53 ` Williams, Dan J
2015-10-10 0:55 ` [PATCH v2 06/20] libnvdimm, pfn, pmem: allocate memmap array in persistent memory Dan Williams
2015-10-10 0:56 ` [PATCH v2 07/20] avr32: convert to asm-generic/memory_model.h Dan Williams
2015-10-10 0:56 ` [PATCH v2 08/20] hugetlb: fix compile error on tile Dan Williams
2015-10-10 0:56 ` [PATCH v2 09/20] frv: fix compiler warning from definition of __pmd() Dan Williams
2015-10-10 0:56 ` [PATCH v2 10/20] um: kill pfn_t Dan Williams
2015-10-10 0:56 ` [PATCH v2 11/20] kvm: rename pfn_t to kvm_pfn_t Dan Williams
2015-10-10 15:35 ` Christoffer Dall
2015-10-10 20:35 ` Paolo Bonzini
2015-10-10 20:57 ` Dan Williams
2015-10-12 12:51 ` Paolo Bonzini
2015-10-12 16:16 ` Dan Williams
2015-10-10 0:56 ` [PATCH v2 12/20] mips: fix PAGE_MASK definition Dan Williams
2015-10-10 0:56 ` [PATCH v2 13/20] mm, dax, pmem: introduce pfn_t Dan Williams
2015-10-10 0:56 ` [PATCH v2 14/20] mm, dax, gpu: convert vm_insert_mixed to pfn_t, introduce _PAGE_DEVMAP Dan Williams
2015-10-10 0:56 ` [PATCH v2 15/20] mm, dax: convert vmf_insert_pfn_pmd() to pfn_t Dan Williams
2015-10-10 0:56 ` [PATCH v2 16/20] list: introduce list_poison() and LIST_POISON3 Dan Williams
2015-10-10 0:56 ` [PATCH v2 17/20] mm, dax, pmem: introduce {get|put}_dev_pagemap() for dax-gup Dan Williams
2015-10-10 0:57 ` [PATCH v2 18/20] block: notify queue death confirmation Dan Williams
2015-10-10 0:57 ` [PATCH v2 19/20] mm, pmem: devm_memunmap_pages(), truncate and unmap ZONE_DEVICE pages Dan Williams
2015-10-10 0:57 ` [PATCH v2 20/20] mm, x86: get_user_pages() for dax mappings Dan Williams
2015-10-23 21:06 ` [PATCH v2 00/20] " Logan Gunthorpe
2015-11-30 22:15 ` Dan Williams
2015-12-02 22:02 ` Logan Gunthorpe
2015-12-02 22:04 ` Dan Williams
2015-12-04 2:16 ` Dan Williams
2015-12-05 1:58 ` Logan Gunthorpe
2015-12-08 0:00 ` Logan Gunthorpe
2015-12-08 0:48 ` Dan Williams
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20151010005544.17221.69747.stgit@dwillia2-desk3.jf.intel.com \
--to=dan.j.williams@intel.com \
--cc=akpm@linux-foundation.org \
--cc=david@fromorbit.com \
--cc=hch@lst.de \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-nvdimm@lists.01.org \
--cc=ross.zwisler@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).