Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1231139 > unrolled thread
| Started by | Dan Williams <dan.j.williams@intel.com> |
|---|---|
| First post | 2015-09-23 06:50 +0200 |
| Last post | 2015-10-03 01:00 +0200 |
| Articles | 6 — 2 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
[PATCH 14/15] mm, dax, pmem: introduce {get|put}_dev_pagemap() for dax-gup Dan Williams <dan.j.williams@intel.com> - 2015-09-23 06:50 +0200
Re: [PATCH 14/15] mm, dax, pmem: introduce {get|put}_dev_pagemap() for dax-gup Logan Gunthorpe <logang@deltatee.com> - 2015-10-03 00:00 +0200
Re: [PATCH 14/15] mm, dax, pmem: introduce {get|put}_dev_pagemap() for dax-gup Dan Williams <dan.j.williams@intel.com> - 2015-10-03 00:00 +0200
Re: [PATCH 14/15] mm, dax, pmem: introduce {get|put}_dev_pagemap() for dax-gup Logan Gunthorpe <logang@deltatee.com> - 2015-10-03 00:20 +0200
Re: [PATCH 14/15] mm, dax, pmem: introduce {get|put}_dev_pagemap() for dax-gup Logan Gunthorpe <logang@deltatee.com> - 2015-10-03 00:50 +0200
Re: [PATCH 14/15] mm, dax, pmem: introduce {get|put}_dev_pagemap() for dax-gup Dan Williams <dan.j.williams@intel.com> - 2015-10-03 01:00 +0200
| From | Dan Williams <dan.j.williams@intel.com> |
|---|---|
| Date | 2015-09-23 06:50 +0200 |
| Subject | [PATCH 14/15] mm, dax, pmem: introduce {get|put}_dev_pagemap() for dax-gup |
| Message-ID | <qbKae-20h-13@gated-at.bofh.it> |
get_dev_page() enables paths like get_user_pages() to pin a dynamically
mapped pfn-range (devm_memremap_pages()) while the resulting struct page
objects are in use. Unlike get_page() it may fail if the device is, or
is in the process of being, disabled. While the initial lookup of the
range may be an expensive list walk, the result is cached to speed up
subsequent lookups which are likely to be in the same mapped range.
Cc: Dave Hansen <dave@sr71.net>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Matthew Wilcox <willy@linux.intel.com>
Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/nvdimm/pmem.c | 2 +
include/linux/io.h | 17 -----------
include/linux/mm.h | 62 ++++++++++++++++++++++++++++++++++++++++
include/linux/mm_types.h | 6 +++-
kernel/memremap.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 140 insertions(+), 18 deletions(-)
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index 1c670775129b..ac581a2e20e2 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -184,6 +184,7 @@ static void pmem_detach_disk(struct pmem_device *pmem)
static int pmem_attach_disk(struct device *dev,
struct nd_namespace_common *ndns, struct pmem_device *pmem)
{
+ struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
int nid = dev_to_node(dev);
struct gendisk *disk;
@@ -191,6 +192,7 @@ static int pmem_attach_disk(struct device *dev,
if (!pmem->pmem_queue)
return -ENOMEM;
+ devm_register_pagemap(dev, &nsio->res, &pmem->pmem_queue->dax_ref.count);
blk_queue_make_request(pmem->pmem_queue, pmem_make_request);
blk_queue_physical_block_size(pmem->pmem_queue, PAGE_SIZE);
blk_queue_max_hw_sectors(pmem->pmem_queue, UINT_MAX);
diff --git a/include/linux/io.h b/include/linux/io.h
index de64c1e53612..2f2f8859abd9 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -87,23 +87,6 @@ void *devm_memremap(struct device *dev, resource_size_t offset,
size_t size, unsigned long flags);
void devm_memunmap(struct device *dev, void *addr);
-void *__devm_memremap_pages(struct device *dev, struct resource *res);
-
-#ifdef CONFIG_ZONE_DEVICE
-void *devm_memremap_pages(struct device *dev, struct resource *res);
-#else
-static inline void *devm_memremap_pages(struct device *dev, struct resource *res)
-{
- /*
- * Fail attempts to call devm_memremap_pages() without
- * ZONE_DEVICE support enabled, this requires callers to fall
- * back to plain devm_memremap() based on config
- */
- WARN_ON_ONCE(1);
- return ERR_PTR(-ENXIO);
-}
-#endif
-
/*
* Some systems do not have legacy ISA devices.
* /dev/port is not a valid interface on these systems.
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 989c5459bee7..6183549a854c 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -15,12 +15,14 @@
#include <linux/debug_locks.h>
#include <linux/mm_types.h>
#include <linux/range.h>
+#include <linux/percpu-refcount.h>
#include <linux/pfn.h>
#include <linux/bit_spinlock.h>
#include <linux/shrinker.h>
#include <linux/resource.h>
#include <linux/page_ext.h>
#include <linux/err.h>
+#include <linux/ioport.h>
struct mempolicy;
struct anon_vma;
@@ -558,6 +560,28 @@ static inline void init_page_count(struct page *page)
void put_page(struct page *page);
void put_pages_list(struct list_head *pages);
+#ifdef CONFIG_ZONE_DEVICE
+void *devm_memremap_pages(struct device *dev, struct resource *res);
+void devm_register_pagemap(struct device *dev, struct resource *res,
+ struct percpu_ref *ref);
+#else
+static inline void *devm_memremap_pages(struct device *dev, struct resource *res)
+{
+ /*
+ * Fail attempts to call devm_memremap_pages() without
+ * ZONE_DEVICE support enabled, this requires callers to fall
+ * back to plain devm_memremap() based on config
+ */
+ WARN_ON_ONCE(1);
+ return ERR_PTR(-ENXIO);
+}
+
+static inline void devm_register_pagemap(struct device *dev, struct resource *res,
+ struct percpu_ref *ref)
+{
+}
+#endif
+
void split_page(struct page *page, unsigned int order);
int split_free_page(struct page *page);
@@ -717,6 +741,44 @@ static inline enum zone_type page_zonenum(const struct page *page)
return (page->flags >> ZONES_PGSHIFT) & ZONES_MASK;
}
+/**
+ * struct dev_pagemap - reference count for a devm_memremap_pages mapping
+ * @res: physical address range covered by @ref
+ * @ref: reference count that pins the devm_memremap_pages() mapping
+ * @dev: host device of the mapping for debug
+ */
+struct dev_pagemap {
+ const struct resource *res;
+ struct percpu_ref *ref;
+ struct device *dev;
+};
+
+struct dev_pagemap *__get_dev_pagemap(resource_size_t phys);
+
+static inline struct dev_pagemap *get_dev_pagemap(unsigned long pfn,
+ struct dev_pagemap *pgmap)
+{
+ resource_size_t phys = PFN_PHYS(pfn);
+
+ /*
+ * In the cached case we're already holding a reference so we can
+ * simply do a blind increment
+ */
+ if (pgmap && phys >= pgmap->res->start && phys <= pgmap->res->end) {
+ percpu_ref_get(pgmap->ref);
+ return pgmap;
+ }
+
+ /* fall back to slow path lookup */
+ return __get_dev_pagemap(phys);
+}
+
+static inline void put_dev_pagemap(struct dev_pagemap *pgmap)
+{
+ if (pgmap)
+ percpu_ref_put(pgmap->ref);
+}
+
#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
#define SECTION_IN_PAGE_FLAGS
#endif
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 3d6baa7d4534..20097e7b679a 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -49,12 +49,16 @@ struct page {
* updated asynchronously */
union {
struct address_space *mapping; /* If low bit clear, points to
- * inode address_space, or NULL.
+ * inode address_space, unless
+ * the page is in ZONE_DEVICE
+ * then it points to its parent
+ * dev_pagemap, otherwise NULL.
* If page mapped as anonymous
* memory, low bit is set, and
* it points to anon_vma object:
* see PAGE_MAPPING_ANON below.
*/
+ struct dev_pagemap *pgmap;
void *s_mem; /* slab first object */
};
diff --git a/kernel/memremap.c b/kernel/memremap.c
index 0d818ce04129..74344dc8c31e 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>
@@ -137,16 +138,86 @@ 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 devm_memremap_pages_release(struct device *dev, void *res)
{
struct page_map *page_map = res;
+ struct dev_pagemap *pgmap = &page_map->pgmap;
/* pages are dead and unused, undo the arch mapping */
arch_remove_memory(page_map->res.start, resource_size(&page_map->res));
+
+ if (pgmap->res) {
+ spin_lock(&range_lock);
+ list_del_rcu(&page_map->list);
+ spin_unlock(&range_lock);
+ dev_WARN_ONCE(dev, !percpu_ref_is_zero(pgmap->ref),
+ "page mapping not idle in %s\n", __func__);
+ }
+}
+
+static int page_map_match(struct device *dev, void *res, void *match_data)
+{
+ struct page_map *page_map = res;
+ resource_size_t phys = *(resource_size_t *) match_data;
+
+ return page_map->res.start == phys;
+}
+
+void devm_register_pagemap(struct device *dev, struct resource *res,
+ struct percpu_ref *ref)
+{
+ struct page_map *page_map;
+ struct dev_pagemap *pgmap;
+ unsigned long pfn;
+
+ page_map = devres_find(dev, devm_memremap_pages_release,
+ page_map_match, &res->start);
+ dev_WARN_ONCE(dev, !page_map, "%s: no mapping found for %pa\n",
+ __func__, &res->start);
+ if (!page_map)
+ return;
+
+ pgmap = &page_map->pgmap;
+ pgmap->dev = dev;
+ pgmap->res = &page_map->res;
+ pgmap->ref = ref;
+ INIT_LIST_HEAD(&page_map->list);
+ spin_lock(&range_lock);
+ list_add_rcu(&page_map->list, &ranges);
+ spin_unlock(&range_lock);
+
+ for (pfn = res->start >> PAGE_SHIFT;
+ pfn < res->end >> PAGE_SHIFT; pfn++) {
+ struct page *page = pfn_to_page(pfn);
+
+ page->pgmap = pgmap;
+ }
+}
+EXPORT_SYMBOL(devm_register_pagemap);
+
+struct dev_pagemap *__get_dev_pagemap(resource_size_t phys)
+{
+ struct page_map *page_map;
+ struct dev_pagemap *pgmap = NULL;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(page_map, &ranges, list)
+ if (phys >= page_map->res.start && phys <= page_map->res.end) {
+ if (percpu_ref_tryget_live(page_map->pgmap.ref))
+ pgmap = &page_map->pgmap;
+ break;
+ }
+ rcu_read_unlock();
+ return pgmap;
}
void *devm_memremap_pages(struct device *dev, struct resource *res)
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Logan Gunthorpe <logang@deltatee.com> |
|---|---|
| Date | 2015-10-03 00:00 +0200 |
| Subject | Re: [PATCH 14/15] mm, dax, pmem: introduce {get|put}_dev_pagemap() for dax-gup |
| Message-ID | <qfgwW-7vm-3@gated-at.bofh.it> |
| In reply to | #1231139 |
Hi Dan,
We've been doing some experimenting and testing with this patchset.
Specifically, we are trying to use you're ZONE_DEVICE work to enable
peer to peer PCIe transfers. This is actually working pretty well
(though we're still testing and working through some things).
However, we've found a couple of issues:
On Wed, Sep 23, 2015 at 12:42:27AM -0400, Dan Williams wrote:
> diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
> index 3d6baa7d4534..20097e7b679a 100644
> --- a/include/linux/mm_types.h
> +++ b/include/linux/mm_types.h
> @@ -49,12 +49,16 @@ struct page {
> * updated asynchronously */
> union {
> struct address_space *mapping; /* If low bit clear, points to
> - * inode address_space, or NULL.
> + * inode address_space, unless
> + * the page is in ZONE_DEVICE
> + * then it points to its parent
> + * dev_pagemap, otherwise NULL.
> * If page mapped as anonymous
> * memory, low bit is set, and
> * it points to anon_vma object:
> * see PAGE_MAPPING_ANON below.
> */
> + struct dev_pagemap *pgmap;
> void *s_mem; /* slab first object */
> };
When you add to this union and overide the mapping value, we see bugs
in calls to set_page_dirty when it tries to dereference mapping. I believe
a change to page_mapping is required such as the patch that's at the end of
this email.
> diff --git a/mm/gup.c b/mm/gup.c
> index a798293fc648..1064e9a489a4 100644
> --- a/mm/gup.c
> +++ b/mm/gup.c
> @@ -98,7 +98,16 @@ retry:
> }
>
> page = vm_normal_page(vma, address, pte);
> - if (unlikely(!page)) {
> + if (!page && pte_devmap(pte) && (flags & FOLL_GET)) {
> + /*
> + * Only return device mapping pages in the FOLL_GET case since
> + * they are only valid while holding the pgmap reference.
> + */
> + if (get_dev_pagemap(pte_pfn(pte), NULL))
> + page = pte_page(pte);
> + else
> + goto no_page;
> + } else if (unlikely(!page)) {
I've found that if a driver creates a ZONE_DEVICE mapping but doesn't
create the pagemap (using devm_register_pagemap) then the get_user_pages code
will go into an infinite loop. I'm not really sure if this as an issue or
not but it seems a bit undesirable for a buggy driver to be able to cause this.
My thoughts are that either devm_register_pagemap needs to be done by
devm_memremap_pages so a driver cannot use one without the other,
or the GUP code needs to return EFAULT if no pagemap was registered so
it doesn't loop forever.
Thanks!
Logan
diff --git a/mm/util.c b/mm/util.c
index 68ff8a5..19af683 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -368,6 +368,9 @@ struct address_space *page_mapping(struct page *page)
return swap_address_space(entry);
}
+ if (unlikely(is_zone_device_page(page)))
+ return NULL;
+
mapping = (unsigned long)page->mapping;
if (mapping & PAGE_MAPPING_FLAGS)
return NULL;
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Dan Williams <dan.j.williams@intel.com> |
|---|---|
| Date | 2015-10-03 00:00 +0200 |
| Subject | Re: [PATCH 14/15] mm, dax, pmem: introduce {get|put}_dev_pagemap() for dax-gup |
| Message-ID | <qfgwW-7vm-11@gated-at.bofh.it> |
| In reply to | #1238636 |
On Fri, Oct 2, 2015 at 2:21 PM, Logan Gunthorpe <logang@deltatee.com> wrote:
> Hi Dan,
>
> We've been doing some experimenting and testing with this patchset.
> Specifically, we are trying to use you're ZONE_DEVICE work to enable
> peer to peer PCIe transfers. This is actually working pretty well
> (though we're still testing and working through some things).
Hmm, I didn't have peer-to-peer PCI-E in mind for this mechanism, but
the test report is welcome nonetheless. The definition of dma_addr_t
is the device view of host memory, not necessarily the device view of
a peer device's memory range, so I expect you'll run into issues with
IOMMUs and other parts of the kernel that assume this definition.
>
> However, we've found a couple of issues:
>
> On Wed, Sep 23, 2015 at 12:42:27AM -0400, Dan Williams wrote:
>> diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
>> index 3d6baa7d4534..20097e7b679a 100644
>> --- a/include/linux/mm_types.h
>> +++ b/include/linux/mm_types.h
>> @@ -49,12 +49,16 @@ struct page {
>> * updated asynchronously */
>> union {
>> struct address_space *mapping; /* If low bit clear, points to
>> - * inode address_space, or NULL.
>> + * inode address_space, unless
>> + * the page is in ZONE_DEVICE
>> + * then it points to its parent
>> + * dev_pagemap, otherwise NULL.
>> * If page mapped as anonymous
>> * memory, low bit is set, and
>> * it points to anon_vma object:
>> * see PAGE_MAPPING_ANON below.
>> */
>> + struct dev_pagemap *pgmap;
>> void *s_mem; /* slab first object */
>> };
>
>
> When you add to this union and overide the mapping value, we see bugs
> in calls to set_page_dirty when it tries to dereference mapping. I believe
> a change to page_mapping is required such as the patch that's at the end of
> this email.
Yes, this location for dev_pagemap will not work. I've since moved it
to a union with the lru list_head since ZONE_DEVICE pages memory
should always have an elevated page count and never land on a slab
allocator lru.
>> diff --git a/mm/gup.c b/mm/gup.c
>> index a798293fc648..1064e9a489a4 100644
>> --- a/mm/gup.c
>> +++ b/mm/gup.c
>> @@ -98,7 +98,16 @@ retry:
>> }
>>
>> page = vm_normal_page(vma, address, pte);
>> - if (unlikely(!page)) {
>> + if (!page && pte_devmap(pte) && (flags & FOLL_GET)) {
>> + /*
>> + * Only return device mapping pages in the FOLL_GET case since
>> + * they are only valid while holding the pgmap reference.
>> + */
>> + if (get_dev_pagemap(pte_pfn(pte), NULL))
>> + page = pte_page(pte);
>> + else
>> + goto no_page;
>> + } else if (unlikely(!page)) {
>
> I've found that if a driver creates a ZONE_DEVICE mapping but doesn't
> create the pagemap (using devm_register_pagemap) then the get_user_pages code
> will go into an infinite loop. I'm not really sure if this as an issue or
> not but it seems a bit undesirable for a buggy driver to be able to cause this.
>
> My thoughts are that either devm_register_pagemap needs to be done by
> devm_memremap_pages so a driver cannot use one without the other,
> or the GUP code needs to return EFAULT if no pagemap was registered so
> it doesn't loop forever.
Exactly, we should fail (-EFAULT) get_user_pages() in that case since
we don't have a mechanism to pin down the mapping. I'll track down
what's causing the loop.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Logan Gunthorpe <logang@deltatee.com> |
|---|---|
| Date | 2015-10-03 00:20 +0200 |
| Subject | Re: [PATCH 14/15] mm, dax, pmem: introduce {get|put}_dev_pagemap() for dax-gup |
| Message-ID | <qfgQi-87k-9@gated-at.bofh.it> |
| In reply to | #1238638 |
Hi Dan, Good to know you've already addressed the struct page issue. We'll watch out for an updated patchset to try. On 02/10/15 03:53 PM, Dan Williams wrote: > Hmm, I didn't have peer-to-peer PCI-E in mind for this mechanism, but > the test report is welcome nonetheless. The definition of dma_addr_t > is the device view of host memory, not necessarily the device view of > a peer device's memory range, so I expect you'll run into issues with > IOMMUs and other parts of the kernel that assume this definition. Yeah, we've actually been doing this with a number of more "hacky" techniques for some time. ZONE_DEVICE just provides us with a much cleaner way to set this up that doesn't require patching around get_user_pages in various places in the kernel. We've never had any issues with the IOMMU getting in the way (at least on Intel x86). My understanding always was that the IOMMU sits between a PCI card and main memory; it doesn't get in the way of peer-to-peer transfers. Though admittedly, I don't have a complete understanding of how the IOMMU works in the kernel. I'm just speaking from experimental experience. We've never actually tried this on other architectures. Thanks, Logan -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Logan Gunthorpe <logang@deltatee.com> |
|---|---|
| Date | 2015-10-03 00:50 +0200 |
| Subject | Re: [PATCH 14/15] mm, dax, pmem: introduce {get|put}_dev_pagemap() for dax-gup |
| Message-ID | <qfhjk-de-11@gated-at.bofh.it> |
| In reply to | #1238638 |
On 02/10/15 03:53 PM, Dan Williams wrote: > Yes, this location for dev_pagemap will not work. I've since moved it > to a union with the lru list_head since ZONE_DEVICE pages memory > should always have an elevated page count and never land on a slab > allocator lru. Oh, also, I was actually hoping to make use of the lru list_head in the future with ZONE_DEVICE memory. One thought I had was once we have a PCIe device with a BAR space, we'd then need to have a way of allocating these buffers when user space needs them. The simple way I was thinking was to just use the lru list head to store lists of used and unused pages -- though there are probably other solutions to this that don't require using struct pages. Thanks, Logan -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Dan Williams <dan.j.williams@intel.com> |
|---|---|
| Date | 2015-10-03 01:00 +0200 |
| Subject | Re: [PATCH 14/15] mm, dax, pmem: introduce {get|put}_dev_pagemap() for dax-gup |
| Message-ID | <qfht1-oF-31@gated-at.bofh.it> |
| In reply to | #1238676 |
On Fri, Oct 2, 2015 at 3:42 PM, Logan Gunthorpe <logang@deltatee.com> wrote: > > > On 02/10/15 03:53 PM, Dan Williams wrote: >> >> Yes, this location for dev_pagemap will not work. I've since moved it >> to a union with the lru list_head since ZONE_DEVICE pages memory >> should always have an elevated page count and never land on a slab >> allocator lru. > > > Oh, also, I was actually hoping to make use of the lru list_head in the > future with ZONE_DEVICE memory. One thought I had was once we have a PCIe > device with a BAR space, we'd then need to have a way of allocating these > buffers when user space needs them. The simple way I was thinking was to > just use the lru list head to store lists of used and unused pages -- though > there are probably other solutions to this that don't require using struct > pages. > The current assumption is the ZONE_DEVICE ranges are being managed by a physical address allocator. In the case of persistent memory this is the block allocator of the filesystem sitting on top of a pmem block device. The struct page is really only there to facilitate in-flight I/O requests. If it weren't for complexity we'd allocate them on demand. So you're "unused" case should be a raw pfn and then for the time-limited duration it is in use as a struct page it should hold a reference against the mapping. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web