In preparation for dax_insert_entry() to start taking page and pgmap
references ensure that page->pgmap is valid by holding the
dax_read_lock() over both dax_direct_access() and dax_insert_entry().

I.e. the code that wants to elevate the reference count of a pgmap page
from 0 -> 1 must ensure that the pgmap is not exiting and will not start
exiting until the proper references have been taken.

Cc: Matthew Wilcox <[email protected]>
Cc: Jan Kara <[email protected]>
Cc: "Darrick J. Wong" <[email protected]>
Cc: Jason Gunthorpe <[email protected]>
Cc: Christoph Hellwig <[email protected]>
Cc: John Hubbard <[email protected]>
Signed-off-by: Dan Williams <[email protected]>
---
 fs/dax.c |   12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/fs/dax.c b/fs/dax.c
index 1d4f0072e58d..6990a6e7df9f 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -1107,10 +1107,9 @@ static int dax_iomap_direct_access(const struct iomap 
*iomap, loff_t pos,
                size_t size, void **kaddr, pfn_t *pfnp)
 {
        pgoff_t pgoff = dax_iomap_pgoff(iomap, pos);
-       int id, rc = 0;
        long length;
+       int rc = 0;
 
-       id = dax_read_lock();
        length = dax_direct_access(iomap->dax_dev, pgoff, PHYS_PFN(size),
                                   DAX_ACCESS, kaddr, pfnp);
        if (length < 0) {
@@ -1135,7 +1134,6 @@ static int dax_iomap_direct_access(const struct iomap 
*iomap, loff_t pos,
        if (!*kaddr)
                rc = -EFAULT;
 out:
-       dax_read_unlock(id);
        return rc;
 }
 
@@ -1588,7 +1586,7 @@ static vm_fault_t dax_fault_iter(struct vm_fault *vmf,
        loff_t pos = (loff_t)xas->xa_index << PAGE_SHIFT;
        bool write = iter->flags & IOMAP_WRITE;
        unsigned long entry_flags = pmd ? DAX_PMD : 0;
-       int err = 0;
+       int err = 0, id;
        pfn_t pfn;
        void *kaddr;
 
@@ -1608,11 +1606,15 @@ static vm_fault_t dax_fault_iter(struct vm_fault *vmf,
                return pmd ? VM_FAULT_FALLBACK : VM_FAULT_SIGBUS;
        }
 
+       id = dax_read_lock();
        err = dax_iomap_direct_access(iomap, pos, size, &kaddr, &pfn);
-       if (err)
+       if (err) {
+               dax_read_unlock(id);
                return pmd ? VM_FAULT_FALLBACK : dax_fault_return(err);
+       }
 
        *entry = dax_insert_entry(xas, vmf, iter, *entry, pfn, entry_flags);
+       dax_read_unlock(id);
 
        if (write &&
            srcmap->type != IOMAP_HOLE && srcmap->addr != iomap->addr) {


Reply via email to