Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1694039 > unrolled thread
| Started by | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| First post | 2017-07-22 00:50 +0200 |
| Last post | 2017-07-24 13:50 +0200 |
| Articles | 12 — 3 participants |
Back to article view | Back to linux.kernel
[PATCH v4 0/5] DAX common 4k zero page Ross Zwisler <ross.zwisler@linux.intel.com> - 2017-07-22 00:50 +0200
[PATCH v4 2/5] dax: relocate some dax functions Ross Zwisler <ross.zwisler@linux.intel.com> - 2017-07-22 00:50 +0200
Re: [PATCH v4 2/5] dax: relocate some dax functions Jan Kara <jack@suse.cz> - 2017-07-24 13:40 +0200
[PATCH v4 1/5] mm: add mkwrite param to vm_insert_mixed() Ross Zwisler <ross.zwisler@linux.intel.com> - 2017-07-22 00:50 +0200
Re: [PATCH v4 1/5] mm: add mkwrite param to vm_insert_mixed() Dan Williams <dan.j.williams@gmail.com> - 2017-07-22 18:30 +0200
Re: [PATCH v4 1/5] mm: add mkwrite param to vm_insert_mixed() Jan Kara <jack@suse.cz> - 2017-07-24 13:20 +0200
Re: [PATCH v4 1/5] mm: add mkwrite param to vm_insert_mixed() Ross Zwisler <ross.zwisler@linux.intel.com> - 2017-07-24 17:20 +0200
Re: [PATCH v4 1/5] mm: add mkwrite param to vm_insert_mixed() Jan Kara <jack@suse.cz> - 2017-07-24 13:30 +0200
Re: [PATCH v4 1/5] mm: add mkwrite param to vm_insert_mixed() Ross Zwisler <ross.zwisler@linux.intel.com> - 2017-07-24 17:30 +0200
Re: [PATCH v4 1/5] mm: add mkwrite param to vm_insert_mixed() Jan Kara <jack@suse.cz> - 2017-07-24 18:00 +0200
[PATCH v4 4/5] dax: remove DAX code from page_cache_tree_insert() Ross Zwisler <ross.zwisler@linux.intel.com> - 2017-07-22 00:50 +0200
Re: [PATCH v4 4/5] dax: remove DAX code from page_cache_tree_insert() Jan Kara <jack@suse.cz> - 2017-07-24 13:50 +0200
| From | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| Date | 2017-07-22 00:50 +0200 |
| Subject | [PATCH v4 0/5] DAX common 4k zero page |
| Message-ID | <u5OU9-2dk-3@gated-at.bofh.it> |
Changes since v3: - Rebased onto the current linux/master which is based on v4.13-rc1. - Instead of adding vm_insert_mkwrite_mixed() and duplicating code from vm_insert_mixed(), instead just add a 'mkwrite' parameter to vm_insert_mixed() and update all call sites. (Vivek) - Added a sanity check to the mkwrite case of insert_pfn() to be sure the pfn for the pte we are about to make writable matches the pfn for our fault. (Jan) - Fixed up some changelog wording for clarity. (Jan) --- When servicing mmap() reads from file holes the current DAX code allocates a page cache page of all zeroes and places the struct page pointer in the mapping->page_tree radix tree. This has three major drawbacks: 1) It consumes memory unnecessarily. For every 4k page that is read via a DAX mmap() over a hole, we allocate a new page cache page. This means that if you read 1GiB worth of pages, you end up using 1GiB of zeroed memory. 2) It is slower than using a common zero page because each page fault has more work to do. Instead of just inserting a common zero page we have to allocate a page cache page, zero it, and then insert it. 3) The fact that we had to check for both DAX exceptional entries and for page cache pages in the radix tree made the DAX code more complex. This series solves these issues by following the lead of the DAX PMD code and using a common 4k zero page instead. This reduces memory usage and decreases latencies for some workloads, and it simplifies the DAX code, removing over 100 lines in total. This series has passed my targeted testing and a full xfstests run on both XFS and ext4. Ross Zwisler (5): mm: add mkwrite param to vm_insert_mixed() dax: relocate some dax functions dax: use common 4k zero page for dax mmap reads dax: remove DAX code from page_cache_tree_insert() dax: move all DAX radix tree defs to fs/dax.c Documentation/filesystems/dax.txt | 5 +- drivers/dax/device.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_gem.c | 3 +- drivers/gpu/drm/gma500/framebuffer.c | 2 +- drivers/gpu/drm/msm/msm_gem.c | 3 +- drivers/gpu/drm/omapdrm/omap_gem.c | 6 +- drivers/gpu/drm/ttm/ttm_bo_vm.c | 2 +- fs/dax.c | 342 +++++++++++++------------------- fs/ext2/file.c | 25 +-- fs/ext4/file.c | 32 +-- fs/xfs/xfs_file.c | 2 +- include/linux/dax.h | 45 ----- include/linux/mm.h | 2 +- include/trace/events/fs_dax.h | 2 - mm/filemap.c | 13 +- mm/memory.c | 27 ++- 16 files changed, 181 insertions(+), 332 deletions(-) -- 2.9.4
[toc] | [next] | [standalone]
| From | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| Date | 2017-07-22 00:50 +0200 |
| Subject | [PATCH v4 2/5] dax: relocate some dax functions |
| Message-ID | <u5OUa-2dk-19@gated-at.bofh.it> |
| In reply to | #1694039 |
dax_load_hole() will soon need to call dax_insert_mapping_entry(), so it
needs to be moved lower in dax.c so the definition exists.
dax_wake_mapping_entry_waiter() will soon be removed from dax.h and be made
static to dax.c, so we need to move its definition above all its callers.
Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
---
fs/dax.c | 138 +++++++++++++++++++++++++++++++--------------------------------
1 file changed, 69 insertions(+), 69 deletions(-)
diff --git a/fs/dax.c b/fs/dax.c
index c844a51..779dc5e 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -121,6 +121,31 @@ static int wake_exceptional_entry_func(wait_queue_entry_t *wait, unsigned int mo
}
/*
+ * We do not necessarily hold the mapping->tree_lock when we call this
+ * function so it is possible that 'entry' is no longer a valid item in the
+ * radix tree. This is okay because all we really need to do is to find the
+ * correct waitqueue where tasks might be waiting for that old 'entry' and
+ * wake them.
+ */
+void dax_wake_mapping_entry_waiter(struct address_space *mapping,
+ pgoff_t index, void *entry, bool wake_all)
+{
+ struct exceptional_entry_key key;
+ wait_queue_head_t *wq;
+
+ wq = dax_entry_waitqueue(mapping, index, entry, &key);
+
+ /*
+ * Checking for locked entry and prepare_to_wait_exclusive() happens
+ * under mapping->tree_lock, ditto for entry handling in our callers.
+ * So at this point all tasks that could have seen our entry locked
+ * must be in the waitqueue and the following check will see them.
+ */
+ if (waitqueue_active(wq))
+ __wake_up(wq, TASK_NORMAL, wake_all ? 0 : 1, &key);
+}
+
+/*
* Check whether the given slot is locked. The function must be called with
* mapping->tree_lock held
*/
@@ -392,31 +417,6 @@ static void *grab_mapping_entry(struct address_space *mapping, pgoff_t index,
return entry;
}
-/*
- * We do not necessarily hold the mapping->tree_lock when we call this
- * function so it is possible that 'entry' is no longer a valid item in the
- * radix tree. This is okay because all we really need to do is to find the
- * correct waitqueue where tasks might be waiting for that old 'entry' and
- * wake them.
- */
-void dax_wake_mapping_entry_waiter(struct address_space *mapping,
- pgoff_t index, void *entry, bool wake_all)
-{
- struct exceptional_entry_key key;
- wait_queue_head_t *wq;
-
- wq = dax_entry_waitqueue(mapping, index, entry, &key);
-
- /*
- * Checking for locked entry and prepare_to_wait_exclusive() happens
- * under mapping->tree_lock, ditto for entry handling in our callers.
- * So at this point all tasks that could have seen our entry locked
- * must be in the waitqueue and the following check will see them.
- */
- if (waitqueue_active(wq))
- __wake_up(wq, TASK_NORMAL, wake_all ? 0 : 1, &key);
-}
-
static int __dax_invalidate_mapping_entry(struct address_space *mapping,
pgoff_t index, bool trunc)
{
@@ -468,50 +468,6 @@ int dax_invalidate_mapping_entry_sync(struct address_space *mapping,
return __dax_invalidate_mapping_entry(mapping, index, false);
}
-/*
- * The user has performed a load from a hole in the file. Allocating
- * a new page in the file would cause excessive storage usage for
- * workloads with sparse files. We allocate a page cache page instead.
- * We'll kick it out of the page cache if it's ever written to,
- * otherwise it will simply fall out of the page cache under memory
- * pressure without ever having been dirtied.
- */
-static int dax_load_hole(struct address_space *mapping, void **entry,
- struct vm_fault *vmf)
-{
- struct inode *inode = mapping->host;
- struct page *page;
- int ret;
-
- /* Hole page already exists? Return it... */
- if (!radix_tree_exceptional_entry(*entry)) {
- page = *entry;
- goto finish_fault;
- }
-
- /* This will replace locked radix tree entry with a hole page */
- page = find_or_create_page(mapping, vmf->pgoff,
- vmf->gfp_mask | __GFP_ZERO);
- if (!page) {
- ret = VM_FAULT_OOM;
- goto out;
- }
-
-finish_fault:
- vmf->page = page;
- ret = finish_fault(vmf);
- vmf->page = NULL;
- *entry = page;
- if (!ret) {
- /* Grab reference for PTE that is now referencing the page */
- get_page(page);
- ret = VM_FAULT_NOPAGE;
- }
-out:
- trace_dax_load_hole(inode, vmf, ret);
- return ret;
-}
-
static int copy_user_dax(struct block_device *bdev, struct dax_device *dax_dev,
sector_t sector, size_t size, struct page *to,
unsigned long vaddr)
@@ -938,6 +894,50 @@ int dax_pfn_mkwrite(struct vm_fault *vmf)
}
EXPORT_SYMBOL_GPL(dax_pfn_mkwrite);
+/*
+ * The user has performed a load from a hole in the file. Allocating
+ * a new page in the file would cause excessive storage usage for
+ * workloads with sparse files. We allocate a page cache page instead.
+ * We'll kick it out of the page cache if it's ever written to,
+ * otherwise it will simply fall out of the page cache under memory
+ * pressure without ever having been dirtied.
+ */
+static int dax_load_hole(struct address_space *mapping, void **entry,
+ struct vm_fault *vmf)
+{
+ struct inode *inode = mapping->host;
+ struct page *page;
+ int ret;
+
+ /* Hole page already exists? Return it... */
+ if (!radix_tree_exceptional_entry(*entry)) {
+ page = *entry;
+ goto finish_fault;
+ }
+
+ /* This will replace locked radix tree entry with a hole page */
+ page = find_or_create_page(mapping, vmf->pgoff,
+ vmf->gfp_mask | __GFP_ZERO);
+ if (!page) {
+ ret = VM_FAULT_OOM;
+ goto out;
+ }
+
+finish_fault:
+ vmf->page = page;
+ ret = finish_fault(vmf);
+ vmf->page = NULL;
+ *entry = page;
+ if (!ret) {
+ /* Grab reference for PTE that is now referencing the page */
+ get_page(page);
+ ret = VM_FAULT_NOPAGE;
+ }
+out:
+ trace_dax_load_hole(inode, vmf, ret);
+ return ret;
+}
+
static bool dax_range_is_aligned(struct block_device *bdev,
unsigned int offset, unsigned int length)
{
--
2.9.4
[toc] | [prev] | [next] | [standalone]
| From | Jan Kara <jack@suse.cz> |
|---|---|
| Date | 2017-07-24 13:40 +0200 |
| Subject | Re: [PATCH v4 2/5] dax: relocate some dax functions |
| Message-ID | <u6JSq-4bx-7@gated-at.bofh.it> |
| In reply to | #1694040 |
On Fri 21-07-17 16:39:52, Ross Zwisler wrote:
> dax_load_hole() will soon need to call dax_insert_mapping_entry(), so it
> needs to be moved lower in dax.c so the definition exists.
>
> dax_wake_mapping_entry_waiter() will soon be removed from dax.h and be made
> static to dax.c, so we need to move its definition above all its callers.
>
> Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
Looks good. You can add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> fs/dax.c | 138 +++++++++++++++++++++++++++++++--------------------------------
> 1 file changed, 69 insertions(+), 69 deletions(-)
>
> diff --git a/fs/dax.c b/fs/dax.c
> index c844a51..779dc5e 100644
> --- a/fs/dax.c
> +++ b/fs/dax.c
> @@ -121,6 +121,31 @@ static int wake_exceptional_entry_func(wait_queue_entry_t *wait, unsigned int mo
> }
>
> /*
> + * We do not necessarily hold the mapping->tree_lock when we call this
> + * function so it is possible that 'entry' is no longer a valid item in the
> + * radix tree. This is okay because all we really need to do is to find the
> + * correct waitqueue where tasks might be waiting for that old 'entry' and
> + * wake them.
> + */
> +void dax_wake_mapping_entry_waiter(struct address_space *mapping,
> + pgoff_t index, void *entry, bool wake_all)
> +{
> + struct exceptional_entry_key key;
> + wait_queue_head_t *wq;
> +
> + wq = dax_entry_waitqueue(mapping, index, entry, &key);
> +
> + /*
> + * Checking for locked entry and prepare_to_wait_exclusive() happens
> + * under mapping->tree_lock, ditto for entry handling in our callers.
> + * So at this point all tasks that could have seen our entry locked
> + * must be in the waitqueue and the following check will see them.
> + */
> + if (waitqueue_active(wq))
> + __wake_up(wq, TASK_NORMAL, wake_all ? 0 : 1, &key);
> +}
> +
> +/*
> * Check whether the given slot is locked. The function must be called with
> * mapping->tree_lock held
> */
> @@ -392,31 +417,6 @@ static void *grab_mapping_entry(struct address_space *mapping, pgoff_t index,
> return entry;
> }
>
> -/*
> - * We do not necessarily hold the mapping->tree_lock when we call this
> - * function so it is possible that 'entry' is no longer a valid item in the
> - * radix tree. This is okay because all we really need to do is to find the
> - * correct waitqueue where tasks might be waiting for that old 'entry' and
> - * wake them.
> - */
> -void dax_wake_mapping_entry_waiter(struct address_space *mapping,
> - pgoff_t index, void *entry, bool wake_all)
> -{
> - struct exceptional_entry_key key;
> - wait_queue_head_t *wq;
> -
> - wq = dax_entry_waitqueue(mapping, index, entry, &key);
> -
> - /*
> - * Checking for locked entry and prepare_to_wait_exclusive() happens
> - * under mapping->tree_lock, ditto for entry handling in our callers.
> - * So at this point all tasks that could have seen our entry locked
> - * must be in the waitqueue and the following check will see them.
> - */
> - if (waitqueue_active(wq))
> - __wake_up(wq, TASK_NORMAL, wake_all ? 0 : 1, &key);
> -}
> -
> static int __dax_invalidate_mapping_entry(struct address_space *mapping,
> pgoff_t index, bool trunc)
> {
> @@ -468,50 +468,6 @@ int dax_invalidate_mapping_entry_sync(struct address_space *mapping,
> return __dax_invalidate_mapping_entry(mapping, index, false);
> }
>
> -/*
> - * The user has performed a load from a hole in the file. Allocating
> - * a new page in the file would cause excessive storage usage for
> - * workloads with sparse files. We allocate a page cache page instead.
> - * We'll kick it out of the page cache if it's ever written to,
> - * otherwise it will simply fall out of the page cache under memory
> - * pressure without ever having been dirtied.
> - */
> -static int dax_load_hole(struct address_space *mapping, void **entry,
> - struct vm_fault *vmf)
> -{
> - struct inode *inode = mapping->host;
> - struct page *page;
> - int ret;
> -
> - /* Hole page already exists? Return it... */
> - if (!radix_tree_exceptional_entry(*entry)) {
> - page = *entry;
> - goto finish_fault;
> - }
> -
> - /* This will replace locked radix tree entry with a hole page */
> - page = find_or_create_page(mapping, vmf->pgoff,
> - vmf->gfp_mask | __GFP_ZERO);
> - if (!page) {
> - ret = VM_FAULT_OOM;
> - goto out;
> - }
> -
> -finish_fault:
> - vmf->page = page;
> - ret = finish_fault(vmf);
> - vmf->page = NULL;
> - *entry = page;
> - if (!ret) {
> - /* Grab reference for PTE that is now referencing the page */
> - get_page(page);
> - ret = VM_FAULT_NOPAGE;
> - }
> -out:
> - trace_dax_load_hole(inode, vmf, ret);
> - return ret;
> -}
> -
> static int copy_user_dax(struct block_device *bdev, struct dax_device *dax_dev,
> sector_t sector, size_t size, struct page *to,
> unsigned long vaddr)
> @@ -938,6 +894,50 @@ int dax_pfn_mkwrite(struct vm_fault *vmf)
> }
> EXPORT_SYMBOL_GPL(dax_pfn_mkwrite);
>
> +/*
> + * The user has performed a load from a hole in the file. Allocating
> + * a new page in the file would cause excessive storage usage for
> + * workloads with sparse files. We allocate a page cache page instead.
> + * We'll kick it out of the page cache if it's ever written to,
> + * otherwise it will simply fall out of the page cache under memory
> + * pressure without ever having been dirtied.
> + */
> +static int dax_load_hole(struct address_space *mapping, void **entry,
> + struct vm_fault *vmf)
> +{
> + struct inode *inode = mapping->host;
> + struct page *page;
> + int ret;
> +
> + /* Hole page already exists? Return it... */
> + if (!radix_tree_exceptional_entry(*entry)) {
> + page = *entry;
> + goto finish_fault;
> + }
> +
> + /* This will replace locked radix tree entry with a hole page */
> + page = find_or_create_page(mapping, vmf->pgoff,
> + vmf->gfp_mask | __GFP_ZERO);
> + if (!page) {
> + ret = VM_FAULT_OOM;
> + goto out;
> + }
> +
> +finish_fault:
> + vmf->page = page;
> + ret = finish_fault(vmf);
> + vmf->page = NULL;
> + *entry = page;
> + if (!ret) {
> + /* Grab reference for PTE that is now referencing the page */
> + get_page(page);
> + ret = VM_FAULT_NOPAGE;
> + }
> +out:
> + trace_dax_load_hole(inode, vmf, ret);
> + return ret;
> +}
> +
> static bool dax_range_is_aligned(struct block_device *bdev,
> unsigned int offset, unsigned int length)
> {
> --
> 2.9.4
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
[toc] | [prev] | [next] | [standalone]
| From | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| Date | 2017-07-22 00:50 +0200 |
| Subject | [PATCH v4 1/5] mm: add mkwrite param to vm_insert_mixed() |
| Message-ID | <u5OUa-2dk-21@gated-at.bofh.it> |
| In reply to | #1694039 |
To be able to use the common 4k zero page in DAX we need to have our PTE
fault path look more like our PMD fault path where a PTE entry can be
marked as dirty and writeable as it is first inserted, rather than waiting
for a follow-up dax_pfn_mkwrite() => finish_mkwrite_fault() call.
Right now we can rely on having a dax_pfn_mkwrite() call because we can
distinguish between these two cases in do_wp_page():
case 1: 4k zero page => writable DAX storage
case 2: read-only DAX storage => writeable DAX storage
This distinction is made by via vm_normal_page(). vm_normal_page() returns
false for the common 4k zero page, though, just as it does for DAX ptes.
Instead of special casing the DAX + 4k zero page case, we will simplify our
DAX PTE page fault sequence so that it matches our DAX PMD sequence, and
get rid of the dax_pfn_mkwrite() helper. We will instead use
dax_iomap_fault() to handle write-protection faults.
This means that insert_pfn() needs to follow the lead of insert_pfn_pmd()
and allow us to pass in a 'mkwrite' flag. If 'mkwrite' is set insert_pfn()
will do the work that was previously done by wp_page_reuse() as part of the
dax_pfn_mkwrite() call path.
Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
---
drivers/dax/device.c | 2 +-
drivers/gpu/drm/exynos/exynos_drm_gem.c | 3 ++-
drivers/gpu/drm/gma500/framebuffer.c | 2 +-
drivers/gpu/drm/msm/msm_gem.c | 3 ++-
drivers/gpu/drm/omapdrm/omap_gem.c | 6 ++++--
drivers/gpu/drm/ttm/ttm_bo_vm.c | 2 +-
fs/dax.c | 2 +-
include/linux/mm.h | 2 +-
mm/memory.c | 27 +++++++++++++++++++++------
9 files changed, 34 insertions(+), 15 deletions(-)
diff --git a/drivers/dax/device.c b/drivers/dax/device.c
index e9f3b3e..3973521 100644
--- a/drivers/dax/device.c
+++ b/drivers/dax/device.c
@@ -273,7 +273,7 @@ static int __dev_dax_pte_fault(struct dev_dax *dev_dax, struct vm_fault *vmf)
pfn = phys_to_pfn_t(phys, dax_region->pfn_flags);
- rc = vm_insert_mixed(vmf->vma, vmf->address, pfn);
+ rc = vm_insert_mixed(vmf->vma, vmf->address, pfn, false);
if (rc == -ENOMEM)
return VM_FAULT_OOM;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index c23479b..bfa6648 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -466,7 +466,8 @@ int exynos_drm_gem_fault(struct vm_fault *vmf)
}
pfn = page_to_pfn(exynos_gem->pages[page_offset]);
- ret = vm_insert_mixed(vma, vmf->address, __pfn_to_pfn_t(pfn, PFN_DEV));
+ ret = vm_insert_mixed(vma, vmf->address, __pfn_to_pfn_t(pfn, PFN_DEV),
+ false);
out:
switch (ret) {
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
index 7da70b6..6dd865f 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c
@@ -134,7 +134,7 @@ static int psbfb_vm_fault(struct vm_fault *vmf)
pfn = (phys_addr >> PAGE_SHIFT);
ret = vm_insert_mixed(vma, address,
- __pfn_to_pfn_t(pfn, PFN_DEV));
+ __pfn_to_pfn_t(pfn, PFN_DEV), false);
if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0)))
break;
else if (unlikely(ret != 0)) {
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 65f3554..c187fd1 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -249,7 +249,8 @@ int msm_gem_fault(struct vm_fault *vmf)
VERB("Inserting %p pfn %lx, pa %lx", (void *)vmf->address,
pfn, pfn << PAGE_SHIFT);
- ret = vm_insert_mixed(vma, vmf->address, __pfn_to_pfn_t(pfn, PFN_DEV));
+ ret = vm_insert_mixed(vma, vmf->address, __pfn_to_pfn_t(pfn, PFN_DEV),
+ false);
out_unlock:
mutex_unlock(&msm_obj->lock);
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c
index 5c5c86d..26eebcd 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -393,7 +393,8 @@ static int fault_1d(struct drm_gem_object *obj,
VERB("Inserting %p pfn %lx, pa %lx", (void *)vmf->address,
pfn, pfn << PAGE_SHIFT);
- return vm_insert_mixed(vma, vmf->address, __pfn_to_pfn_t(pfn, PFN_DEV));
+ return vm_insert_mixed(vma, vmf->address, __pfn_to_pfn_t(pfn, PFN_DEV),
+ false);
}
/* Special handling for the case of faulting in 2d tiled buffers */
@@ -486,7 +487,8 @@ static int fault_2d(struct drm_gem_object *obj,
pfn, pfn << PAGE_SHIFT);
for (i = n; i > 0; i--) {
- vm_insert_mixed(vma, vaddr, __pfn_to_pfn_t(pfn, PFN_DEV));
+ vm_insert_mixed(vma, vaddr, __pfn_to_pfn_t(pfn, PFN_DEV),
+ false);
pfn += priv->usergart[fmt].stride_pfn;
vaddr += PAGE_SIZE * m;
}
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
index b442d12..e85bfa7 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
@@ -248,7 +248,7 @@ static int ttm_bo_vm_fault(struct vm_fault *vmf)
if (vma->vm_flags & VM_MIXEDMAP)
ret = vm_insert_mixed(&cvma, address,
- __pfn_to_pfn_t(pfn, PFN_DEV));
+ __pfn_to_pfn_t(pfn, PFN_DEV), false);
else
ret = vm_insert_pfn(&cvma, address, pfn);
diff --git a/fs/dax.c b/fs/dax.c
index 306c2b6..c844a51 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -899,7 +899,7 @@ static int dax_insert_mapping(struct address_space *mapping,
*entryp = ret;
trace_dax_insert_mapping(mapping->host, vmf, ret);
- return vm_insert_mixed(vma, vaddr, pfn);
+ return vm_insert_mixed(vma, vaddr, pfn, false);
}
/**
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 46b9ac5..3eabc40 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2292,7 +2292,7 @@ int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
int vm_insert_pfn_prot(struct vm_area_struct *vma, unsigned long addr,
unsigned long pfn, pgprot_t pgprot);
int vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr,
- pfn_t pfn);
+ pfn_t pfn, bool mkwrite);
int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long len);
diff --git a/mm/memory.c b/mm/memory.c
index 0e517be..d351911 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1646,7 +1646,7 @@ int vm_insert_page(struct vm_area_struct *vma, unsigned long addr,
EXPORT_SYMBOL(vm_insert_page);
static int insert_pfn(struct vm_area_struct *vma, unsigned long addr,
- pfn_t pfn, pgprot_t prot)
+ pfn_t pfn, pgprot_t prot, bool mkwrite)
{
struct mm_struct *mm = vma->vm_mm;
int retval;
@@ -1658,14 +1658,28 @@ static int insert_pfn(struct vm_area_struct *vma, unsigned long addr,
if (!pte)
goto out;
retval = -EBUSY;
- if (!pte_none(*pte))
- goto out_unlock;
+ if (!pte_none(*pte)) {
+ if (mkwrite) {
+ if (WARN_ON_ONCE(pte_pfn(*pte) != pfn_t_to_pfn(pfn)))
+ goto out_unlock;
+ entry = *pte;
+ goto out_mkwrite;
+ } else
+ goto out_unlock;
+ }
/* Ok, finally just insert the thing.. */
if (pfn_t_devmap(pfn))
entry = pte_mkdevmap(pfn_t_pte(pfn, prot));
else
entry = pte_mkspecial(pfn_t_pte(pfn, prot));
+
+out_mkwrite:
+ if (mkwrite) {
+ entry = pte_mkyoung(entry);
+ entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+ }
+
set_pte_at(mm, addr, pte, entry);
update_mmu_cache(vma, addr, pte); /* XXX: why not for insert_page? */
@@ -1736,14 +1750,15 @@ int vm_insert_pfn_prot(struct vm_area_struct *vma, unsigned long addr,
track_pfn_insert(vma, &pgprot, __pfn_to_pfn_t(pfn, PFN_DEV));
- ret = insert_pfn(vma, addr, __pfn_to_pfn_t(pfn, PFN_DEV), pgprot);
+ ret = insert_pfn(vma, addr, __pfn_to_pfn_t(pfn, PFN_DEV), pgprot,
+ false);
return ret;
}
EXPORT_SYMBOL(vm_insert_pfn_prot);
int vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr,
- pfn_t pfn)
+ pfn_t pfn, bool mkwrite)
{
pgprot_t pgprot = vma->vm_page_prot;
@@ -1772,7 +1787,7 @@ int vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr,
page = pfn_to_page(pfn_t_to_pfn(pfn));
return insert_page(vma, addr, page, pgprot);
}
- return insert_pfn(vma, addr, pfn, pgprot);
+ return insert_pfn(vma, addr, pfn, pgprot, mkwrite);
}
EXPORT_SYMBOL(vm_insert_mixed);
--
2.9.4
[toc] | [prev] | [next] | [standalone]
| From | Dan Williams <dan.j.williams@gmail.com> |
|---|---|
| Date | 2017-07-22 18:30 +0200 |
| Subject | Re: [PATCH v4 1/5] mm: add mkwrite param to vm_insert_mixed() |
| Message-ID | <u65rX-4aW-11@gated-at.bofh.it> |
| In reply to | #1694041 |
On Fri, Jul 21, 2017 at 3:39 PM, Ross Zwisler
<ross.zwisler@linux.intel.com> wrote:
> To be able to use the common 4k zero page in DAX we need to have our PTE
> fault path look more like our PMD fault path where a PTE entry can be
> marked as dirty and writeable as it is first inserted, rather than waiting
> for a follow-up dax_pfn_mkwrite() => finish_mkwrite_fault() call.
>
> Right now we can rely on having a dax_pfn_mkwrite() call because we can
> distinguish between these two cases in do_wp_page():
>
> case 1: 4k zero page => writable DAX storage
> case 2: read-only DAX storage => writeable DAX storage
>
> This distinction is made by via vm_normal_page(). vm_normal_page() returns
> false for the common 4k zero page, though, just as it does for DAX ptes.
> Instead of special casing the DAX + 4k zero page case, we will simplify our
> DAX PTE page fault sequence so that it matches our DAX PMD sequence, and
> get rid of the dax_pfn_mkwrite() helper. We will instead use
> dax_iomap_fault() to handle write-protection faults.
>
> This means that insert_pfn() needs to follow the lead of insert_pfn_pmd()
> and allow us to pass in a 'mkwrite' flag. If 'mkwrite' is set insert_pfn()
> will do the work that was previously done by wp_page_reuse() as part of the
> dax_pfn_mkwrite() call path.
>
> Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
> ---
> drivers/dax/device.c | 2 +-
> drivers/gpu/drm/exynos/exynos_drm_gem.c | 3 ++-
> drivers/gpu/drm/gma500/framebuffer.c | 2 +-
> drivers/gpu/drm/msm/msm_gem.c | 3 ++-
> drivers/gpu/drm/omapdrm/omap_gem.c | 6 ++++--
> drivers/gpu/drm/ttm/ttm_bo_vm.c | 2 +-
> fs/dax.c | 2 +-
> include/linux/mm.h | 2 +-
> mm/memory.c | 27 +++++++++++++++++++++------
> 9 files changed, 34 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/dax/device.c b/drivers/dax/device.c
> index e9f3b3e..3973521 100644
> --- a/drivers/dax/device.c
> +++ b/drivers/dax/device.c
> @@ -273,7 +273,7 @@ static int __dev_dax_pte_fault(struct dev_dax *dev_dax, struct vm_fault *vmf)
>
> pfn = phys_to_pfn_t(phys, dax_region->pfn_flags);
>
> - rc = vm_insert_mixed(vmf->vma, vmf->address, pfn);
> + rc = vm_insert_mixed(vmf->vma, vmf->address, pfn, false);
Ugh, I generally find bool flags unreadable. They place a tax on
jumping to function definition to recall what true and false mean. If
we want to go this 'add an argument' route can we at least add an enum
like:
enum {
PTE_MKDIRTY,
PTE_MKCLEAN,
};
...to differentiate the two cases?
[toc] | [prev] | [next] | [standalone]
| From | Jan Kara <jack@suse.cz> |
|---|---|
| Date | 2017-07-24 13:20 +0200 |
| Subject | Re: [PATCH v4 1/5] mm: add mkwrite param to vm_insert_mixed() |
| Message-ID | <u6Jz3-42s-5@gated-at.bofh.it> |
| In reply to | #1694171 |
On Sat 22-07-17 09:21:31, Dan Williams wrote:
> On Fri, Jul 21, 2017 at 3:39 PM, Ross Zwisler
> <ross.zwisler@linux.intel.com> wrote:
> > To be able to use the common 4k zero page in DAX we need to have our PTE
> > fault path look more like our PMD fault path where a PTE entry can be
> > marked as dirty and writeable as it is first inserted, rather than waiting
> > for a follow-up dax_pfn_mkwrite() => finish_mkwrite_fault() call.
> >
> > Right now we can rely on having a dax_pfn_mkwrite() call because we can
> > distinguish between these two cases in do_wp_page():
> >
> > case 1: 4k zero page => writable DAX storage
> > case 2: read-only DAX storage => writeable DAX storage
> >
> > This distinction is made by via vm_normal_page(). vm_normal_page() returns
> > false for the common 4k zero page, though, just as it does for DAX ptes.
> > Instead of special casing the DAX + 4k zero page case, we will simplify our
> > DAX PTE page fault sequence so that it matches our DAX PMD sequence, and
> > get rid of the dax_pfn_mkwrite() helper. We will instead use
> > dax_iomap_fault() to handle write-protection faults.
> >
> > This means that insert_pfn() needs to follow the lead of insert_pfn_pmd()
> > and allow us to pass in a 'mkwrite' flag. If 'mkwrite' is set insert_pfn()
> > will do the work that was previously done by wp_page_reuse() as part of the
> > dax_pfn_mkwrite() call path.
> >
> > Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
> > ---
> > drivers/dax/device.c | 2 +-
> > drivers/gpu/drm/exynos/exynos_drm_gem.c | 3 ++-
> > drivers/gpu/drm/gma500/framebuffer.c | 2 +-
> > drivers/gpu/drm/msm/msm_gem.c | 3 ++-
> > drivers/gpu/drm/omapdrm/omap_gem.c | 6 ++++--
> > drivers/gpu/drm/ttm/ttm_bo_vm.c | 2 +-
> > fs/dax.c | 2 +-
> > include/linux/mm.h | 2 +-
> > mm/memory.c | 27 +++++++++++++++++++++------
> > 9 files changed, 34 insertions(+), 15 deletions(-)
> >
> > diff --git a/drivers/dax/device.c b/drivers/dax/device.c
> > index e9f3b3e..3973521 100644
> > --- a/drivers/dax/device.c
> > +++ b/drivers/dax/device.c
> > @@ -273,7 +273,7 @@ static int __dev_dax_pte_fault(struct dev_dax *dev_dax, struct vm_fault *vmf)
> >
> > pfn = phys_to_pfn_t(phys, dax_region->pfn_flags);
> >
> > - rc = vm_insert_mixed(vmf->vma, vmf->address, pfn);
> > + rc = vm_insert_mixed(vmf->vma, vmf->address, pfn, false);
>
> Ugh, I generally find bool flags unreadable. They place a tax on
> jumping to function definition to recall what true and false mean. If
> we want to go this 'add an argument' route can we at least add an enum
> like:
>
> enum {
> PTE_MKDIRTY,
> PTE_MKCLEAN,
> };
>
> ...to differentiate the two cases?
So how I usually deal with this is that I create e.g.:
__vm_insert_mixed() that takes the bool argument, make vm_insert_mixed()
pass false, and vm_insert_mixed_mkwrite() pass true. That way there's no
code duplication, old call sites can stay unchanged, the naming clearly
says what's going on...
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
[toc] | [prev] | [next] | [standalone]
| From | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| Date | 2017-07-24 17:20 +0200 |
| Subject | Re: [PATCH v4 1/5] mm: add mkwrite param to vm_insert_mixed() |
| Message-ID | <u6Njj-6DL-11@gated-at.bofh.it> |
| In reply to | #1694646 |
On Mon, Jul 24, 2017 at 01:15:31PM +0200, Jan Kara wrote:
> On Sat 22-07-17 09:21:31, Dan Williams wrote:
> > On Fri, Jul 21, 2017 at 3:39 PM, Ross Zwisler
> > <ross.zwisler@linux.intel.com> wrote:
> > > To be able to use the common 4k zero page in DAX we need to have our PTE
> > > fault path look more like our PMD fault path where a PTE entry can be
> > > marked as dirty and writeable as it is first inserted, rather than waiting
> > > for a follow-up dax_pfn_mkwrite() => finish_mkwrite_fault() call.
> > >
> > > Right now we can rely on having a dax_pfn_mkwrite() call because we can
> > > distinguish between these two cases in do_wp_page():
> > >
> > > case 1: 4k zero page => writable DAX storage
> > > case 2: read-only DAX storage => writeable DAX storage
> > >
> > > This distinction is made by via vm_normal_page(). vm_normal_page() returns
> > > false for the common 4k zero page, though, just as it does for DAX ptes.
> > > Instead of special casing the DAX + 4k zero page case, we will simplify our
> > > DAX PTE page fault sequence so that it matches our DAX PMD sequence, and
> > > get rid of the dax_pfn_mkwrite() helper. We will instead use
> > > dax_iomap_fault() to handle write-protection faults.
> > >
> > > This means that insert_pfn() needs to follow the lead of insert_pfn_pmd()
> > > and allow us to pass in a 'mkwrite' flag. If 'mkwrite' is set insert_pfn()
> > > will do the work that was previously done by wp_page_reuse() as part of the
> > > dax_pfn_mkwrite() call path.
> > >
> > > Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
> > > ---
> > > drivers/dax/device.c | 2 +-
> > > drivers/gpu/drm/exynos/exynos_drm_gem.c | 3 ++-
> > > drivers/gpu/drm/gma500/framebuffer.c | 2 +-
> > > drivers/gpu/drm/msm/msm_gem.c | 3 ++-
> > > drivers/gpu/drm/omapdrm/omap_gem.c | 6 ++++--
> > > drivers/gpu/drm/ttm/ttm_bo_vm.c | 2 +-
> > > fs/dax.c | 2 +-
> > > include/linux/mm.h | 2 +-
> > > mm/memory.c | 27 +++++++++++++++++++++------
> > > 9 files changed, 34 insertions(+), 15 deletions(-)
> > >
> > > diff --git a/drivers/dax/device.c b/drivers/dax/device.c
> > > index e9f3b3e..3973521 100644
> > > --- a/drivers/dax/device.c
> > > +++ b/drivers/dax/device.c
> > > @@ -273,7 +273,7 @@ static int __dev_dax_pte_fault(struct dev_dax *dev_dax, struct vm_fault *vmf)
> > >
> > > pfn = phys_to_pfn_t(phys, dax_region->pfn_flags);
> > >
> > > - rc = vm_insert_mixed(vmf->vma, vmf->address, pfn);
> > > + rc = vm_insert_mixed(vmf->vma, vmf->address, pfn, false);
> >
> > Ugh, I generally find bool flags unreadable. They place a tax on
> > jumping to function definition to recall what true and false mean. If
> > we want to go this 'add an argument' route can we at least add an enum
> > like:
> >
> > enum {
> > PTE_MKDIRTY,
> > PTE_MKCLEAN,
> > };
> >
> > ...to differentiate the two cases?
>
> So how I usually deal with this is that I create e.g.:
>
> __vm_insert_mixed() that takes the bool argument, make vm_insert_mixed()
> pass false, and vm_insert_mixed_mkwrite() pass true. That way there's no
> code duplication, old call sites can stay unchanged, the naming clearly
> says what's going on...
Ah, that does seem cleaner. I'll try that for v5.
[toc] | [prev] | [next] | [standalone]
| From | Jan Kara <jack@suse.cz> |
|---|---|
| Date | 2017-07-24 13:30 +0200 |
| Subject | Re: [PATCH v4 1/5] mm: add mkwrite param to vm_insert_mixed() |
| Message-ID | <u6JIJ-47M-7@gated-at.bofh.it> |
| In reply to | #1694041 |
> @@ -1658,14 +1658,28 @@ static int insert_pfn(struct vm_area_struct *vma, unsigned long addr,
> if (!pte)
> goto out;
> retval = -EBUSY;
> - if (!pte_none(*pte))
> - goto out_unlock;
> + if (!pte_none(*pte)) {
> + if (mkwrite) {
> + if (WARN_ON_ONCE(pte_pfn(*pte) != pfn_t_to_pfn(pfn)))
Is the WARN_ON_ONCE() really appropriate here? Your testcase with private
mappings has triggered this situation if I'm right...
Otherwise the patch looks good to me.
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
[toc] | [prev] | [next] | [standalone]
| From | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| Date | 2017-07-24 17:30 +0200 |
| Subject | Re: [PATCH v4 1/5] mm: add mkwrite param to vm_insert_mixed() |
| Message-ID | <u6Nt1-6HD-33@gated-at.bofh.it> |
| In reply to | #1694650 |
On Mon, Jul 24, 2017 at 01:25:30PM +0200, Jan Kara wrote:
> > @@ -1658,14 +1658,28 @@ static int insert_pfn(struct vm_area_struct *vma, unsigned long addr,
> > if (!pte)
> > goto out;
> > retval = -EBUSY;
> > - if (!pte_none(*pte))
> > - goto out_unlock;
> > + if (!pte_none(*pte)) {
> > + if (mkwrite) {
> > + if (WARN_ON_ONCE(pte_pfn(*pte) != pfn_t_to_pfn(pfn)))
>
> Is the WARN_ON_ONCE() really appropriate here? Your testcase with private
> mappings has triggered this situation if I'm right...
Yep, I think this WARN_ON_ONCE() is correct. The test with private mappings
had collisions between read-only DAX mappings which were being faulted in via
insert_pfn(), and read/write COW page cache mappings which were being faulted
in by wp_page_copy().
I was hitting a false-positive warning when I had the WARN_ON_ONCE() in
insert_pfn() outside of the mkwrite case, i.e.:
if (!pte_none(*pte)) {
if (WARN_ON_ONCE(pte_pfn(*pte) != pfn_t_to_pfn(pfn)))
goto out_unlock;
if (mkwrite) {
entry = *pte;
goto out_mkwrite;
} else
goto out_unlock;
}
This was triggering when one thread was faulting in a read-only DAX mapping
when another thread had already faulted in a read-write COW page cache page.
The patches I sent out have the warning in the mkwrite case, which would mean
that we were getting a fault for a read/write PTE in insert_pfn() and the PFN
didn't match what was already in the PTE.
This can't ever happen in the private mapping case because we will never
install a read/write PTE for normal storage, only for COW page cache pages.
Essentially I don't think we should ever be able to hit this warning, and if
we do I'd like to get the bug report so that I can track down how it was
happening and make sure that it's safe. It is in the mkwrite path of
insert_pfn() which is currently only used by the DAX code.
Does that make sense to you, or would you recommend leaving it out? (If so,
why?)
[toc] | [prev] | [next] | [standalone]
| From | Jan Kara <jack@suse.cz> |
|---|---|
| Date | 2017-07-24 18:00 +0200 |
| Subject | Re: [PATCH v4 1/5] mm: add mkwrite param to vm_insert_mixed() |
| Message-ID | <u6NW3-6Tk-35@gated-at.bofh.it> |
| In reply to | #1694815 |
On Mon 24-07-17 09:23:57, Ross Zwisler wrote:
> On Mon, Jul 24, 2017 at 01:25:30PM +0200, Jan Kara wrote:
> > > @@ -1658,14 +1658,28 @@ static int insert_pfn(struct vm_area_struct *vma, unsigned long addr,
> > > if (!pte)
> > > goto out;
> > > retval = -EBUSY;
> > > - if (!pte_none(*pte))
> > > - goto out_unlock;
> > > + if (!pte_none(*pte)) {
> > > + if (mkwrite) {
> > > + if (WARN_ON_ONCE(pte_pfn(*pte) != pfn_t_to_pfn(pfn)))
> >
> > Is the WARN_ON_ONCE() really appropriate here? Your testcase with private
> > mappings has triggered this situation if I'm right...
>
> Yep, I think this WARN_ON_ONCE() is correct. The test with private mappings
> had collisions between read-only DAX mappings which were being faulted in via
> insert_pfn(), and read/write COW page cache mappings which were being faulted
> in by wp_page_copy().
>
> I was hitting a false-positive warning when I had the WARN_ON_ONCE() in
> insert_pfn() outside of the mkwrite case, i.e.:
>
> if (!pte_none(*pte)) {
> if (WARN_ON_ONCE(pte_pfn(*pte) != pfn_t_to_pfn(pfn)))
> goto out_unlock;
> if (mkwrite) {
> entry = *pte;
> goto out_mkwrite;
> } else
> goto out_unlock;
> }
>
> This was triggering when one thread was faulting in a read-only DAX mapping
> when another thread had already faulted in a read-write COW page cache page.
>
> The patches I sent out have the warning in the mkwrite case, which would mean
> that we were getting a fault for a read/write PTE in insert_pfn() and the PFN
> didn't match what was already in the PTE.
>
> This can't ever happen in the private mapping case because we will never
> install a read/write PTE for normal storage, only for COW page cache pages.
> Essentially I don't think we should ever be able to hit this warning, and if
> we do I'd like to get the bug report so that I can track down how it was
> happening and make sure that it's safe. It is in the mkwrite path of
> insert_pfn() which is currently only used by the DAX code.
>
> Does that make sense to you, or would you recommend leaving it out? (If so,
> why?)
Ah, OK, makes sense. So feel free to add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
[toc] | [prev] | [next] | [standalone]
| From | Ross Zwisler <ross.zwisler@linux.intel.com> |
|---|---|
| Date | 2017-07-22 00:50 +0200 |
| Subject | [PATCH v4 4/5] dax: remove DAX code from page_cache_tree_insert() |
| Message-ID | <u5OUa-2dk-27@gated-at.bofh.it> |
| In reply to | #1694039 |
Now that we no longer insert struct page pointers in DAX radix trees we can
remove the special casing for DAX in page_cache_tree_insert(). This also
allows us to make dax_wake_mapping_entry_waiter() local to fs/dax.c,
removing it from dax.h.
Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
Suggested-by: Jan Kara <jack@suse.cz>
---
fs/dax.c | 2 +-
include/linux/dax.h | 2 --
mm/filemap.c | 13 ++-----------
3 files changed, 3 insertions(+), 14 deletions(-)
diff --git a/fs/dax.c b/fs/dax.c
index fb0e4c1..0e27d90 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -127,7 +127,7 @@ static int wake_exceptional_entry_func(wait_queue_entry_t *wait, unsigned int mo
* correct waitqueue where tasks might be waiting for that old 'entry' and
* wake them.
*/
-void dax_wake_mapping_entry_waiter(struct address_space *mapping,
+static void dax_wake_mapping_entry_waiter(struct address_space *mapping,
pgoff_t index, void *entry, bool wake_all)
{
struct exceptional_entry_key key;
diff --git a/include/linux/dax.h b/include/linux/dax.h
index 29cced8..afa99bb 100644
--- a/include/linux/dax.h
+++ b/include/linux/dax.h
@@ -122,8 +122,6 @@ int dax_iomap_fault(struct vm_fault *vmf, enum page_entry_size pe_size,
int dax_delete_mapping_entry(struct address_space *mapping, pgoff_t index);
int dax_invalidate_mapping_entry_sync(struct address_space *mapping,
pgoff_t index);
-void dax_wake_mapping_entry_waiter(struct address_space *mapping,
- pgoff_t index, void *entry, bool wake_all);
#ifdef CONFIG_FS_DAX
int __dax_zero_page_range(struct block_device *bdev,
diff --git a/mm/filemap.c b/mm/filemap.c
index a497024..1bf1265 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -130,17 +130,8 @@ static int page_cache_tree_insert(struct address_space *mapping,
return -EEXIST;
mapping->nrexceptional--;
- if (!dax_mapping(mapping)) {
- if (shadowp)
- *shadowp = p;
- } else {
- /* DAX can replace empty locked entry with a hole */
- WARN_ON_ONCE(p !=
- dax_radix_locked_entry(0, RADIX_DAX_EMPTY));
- /* Wakeup waiters for exceptional entry lock */
- dax_wake_mapping_entry_waiter(mapping, page->index, p,
- true);
- }
+ if (shadowp)
+ *shadowp = p;
}
__radix_tree_replace(&mapping->page_tree, node, slot, page,
workingset_update_node, mapping);
--
2.9.4
[toc] | [prev] | [next] | [standalone]
| From | Jan Kara <jack@suse.cz> |
|---|---|
| Date | 2017-07-24 13:50 +0200 |
| Subject | Re: [PATCH v4 4/5] dax: remove DAX code from page_cache_tree_insert() |
| Message-ID | <u6K26-4ff-11@gated-at.bofh.it> |
| In reply to | #1694042 |
On Fri 21-07-17 16:39:54, Ross Zwisler wrote:
> Now that we no longer insert struct page pointers in DAX radix trees we can
> remove the special casing for DAX in page_cache_tree_insert(). This also
> allows us to make dax_wake_mapping_entry_waiter() local to fs/dax.c,
> removing it from dax.h.
>
> Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
> Suggested-by: Jan Kara <jack@suse.cz>
Looks good. You can add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
> ---
> fs/dax.c | 2 +-
> include/linux/dax.h | 2 --
> mm/filemap.c | 13 ++-----------
> 3 files changed, 3 insertions(+), 14 deletions(-)
>
> diff --git a/fs/dax.c b/fs/dax.c
> index fb0e4c1..0e27d90 100644
> --- a/fs/dax.c
> +++ b/fs/dax.c
> @@ -127,7 +127,7 @@ static int wake_exceptional_entry_func(wait_queue_entry_t *wait, unsigned int mo
> * correct waitqueue where tasks might be waiting for that old 'entry' and
> * wake them.
> */
> -void dax_wake_mapping_entry_waiter(struct address_space *mapping,
> +static void dax_wake_mapping_entry_waiter(struct address_space *mapping,
> pgoff_t index, void *entry, bool wake_all)
> {
> struct exceptional_entry_key key;
> diff --git a/include/linux/dax.h b/include/linux/dax.h
> index 29cced8..afa99bb 100644
> --- a/include/linux/dax.h
> +++ b/include/linux/dax.h
> @@ -122,8 +122,6 @@ int dax_iomap_fault(struct vm_fault *vmf, enum page_entry_size pe_size,
> int dax_delete_mapping_entry(struct address_space *mapping, pgoff_t index);
> int dax_invalidate_mapping_entry_sync(struct address_space *mapping,
> pgoff_t index);
> -void dax_wake_mapping_entry_waiter(struct address_space *mapping,
> - pgoff_t index, void *entry, bool wake_all);
>
> #ifdef CONFIG_FS_DAX
> int __dax_zero_page_range(struct block_device *bdev,
> diff --git a/mm/filemap.c b/mm/filemap.c
> index a497024..1bf1265 100644
> --- a/mm/filemap.c
> +++ b/mm/filemap.c
> @@ -130,17 +130,8 @@ static int page_cache_tree_insert(struct address_space *mapping,
> return -EEXIST;
>
> mapping->nrexceptional--;
> - if (!dax_mapping(mapping)) {
> - if (shadowp)
> - *shadowp = p;
> - } else {
> - /* DAX can replace empty locked entry with a hole */
> - WARN_ON_ONCE(p !=
> - dax_radix_locked_entry(0, RADIX_DAX_EMPTY));
> - /* Wakeup waiters for exceptional entry lock */
> - dax_wake_mapping_entry_waiter(mapping, page->index, p,
> - true);
> - }
> + if (shadowp)
> + *shadowp = p;
> }
> __radix_tree_replace(&mapping->page_tree, node, slot, page,
> workingset_update_node, mapping);
> --
> 2.9.4
>
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web