unsigned flags = IOMAP_FAULT;
        int error, major = 0;
        bool write = vmf->flags & FAULT_FLAG_WRITE;
+       bool sync;
        int vmf_ret = 0;
        void *entry;
        pfn_t pfn;
                goto finish_iomap;
        }
 
+       sync = (vma->vm_flags & VM_SYNC) && (iomap.flags & IOMAP_F_DIRTY);
+
        switch (iomap.type) {
        case IOMAP_MAPPED:
                if (iomap.flags & IOMAP_F_NEW) {
 
                entry = dax_insert_mapping_entry(mapping, vmf, entry,
                                                 dax_iomap_sector(&iomap, pos),
-                                                0, write);
+                                                0, write && !sync);
                if (IS_ERR(entry)) {
                        error = PTR_ERR(entry);
                        goto error_finish_iomap;
                }
 
+               /*
+                * If we are doing synchronous page fault and inode needs fsync,
+                * we can insert PTE into page tables only after that happens.
+                * Skip insertion for now and return the pfn so that caller can
+                * insert it after fsync is done.
+                */
+               if (sync) {
+                       if (WARN_ON_ONCE(!pfnp)) {
+                               error = -EIO;
+                               goto error_finish_iomap;
+                       }
+                       *pfnp = pfn;
+                       vmf_ret = VM_FAULT_NEEDDSYNC | major;
+                       goto finish_iomap;
+               }
                trace_dax_insert_mapping(inode, vmf, entry);
                if (write)
                        error = vm_insert_mixed_mkwrite(vma, vaddr, pfn);
        struct address_space *mapping = vma->vm_file->f_mapping;
        unsigned long pmd_addr = vmf->address & PMD_MASK;
        bool write = vmf->flags & FAULT_FLAG_WRITE;
+       bool sync;
        unsigned int iomap_flags = (write ? IOMAP_WRITE : 0) | IOMAP_FAULT;
        struct inode *inode = mapping->host;
        int result = VM_FAULT_FALLBACK;
        if (iomap.offset + iomap.length < pos + PMD_SIZE)
                goto finish_iomap;
 
+       sync = (vma->vm_flags & VM_SYNC) && (iomap.flags & IOMAP_F_DIRTY);
+
        switch (iomap.type) {
        case IOMAP_MAPPED:
                error = dax_iomap_pfn(&iomap, pos, PMD_SIZE, &pfn);
 
                entry = dax_insert_mapping_entry(mapping, vmf, entry,
                                                dax_iomap_sector(&iomap, pos),
-                                               RADIX_DAX_PMD, write);
+                                               RADIX_DAX_PMD, write && !sync);
                if (IS_ERR(entry))
                        goto finish_iomap;
 
+               /*
+                * If we are doing synchronous page fault and inode needs fsync,
+                * we can insert PMD into page tables only after that happens.
+                * Skip insertion for now and return the pfn so that caller can
+                * insert it after fsync is done.
+                */
+               if (sync) {
+                       if (WARN_ON_ONCE(!pfnp))
+                               goto finish_iomap;
+                       *pfnp = pfn;
+                       result = VM_FAULT_NEEDDSYNC;
+                       goto finish_iomap;
+               }
+
                trace_dax_pmd_insert_mapping(inode, vmf, PMD_SIZE, pfn, entry);
                result = vmf_insert_pfn_pmd(vma, vmf->address, vmf->pmd, pfn,
                                            write);
 
 #define VM_FAULT_RETRY 0x0400  /* ->fault blocked, must retry */
 #define VM_FAULT_FALLBACK 0x0800       /* huge page fault failed, fall back to small */
 #define VM_FAULT_DONE_COW   0x1000     /* ->fault has fully handled COW */
+#define VM_FAULT_NEEDDSYNC  0x2000     /* ->fault did not modify page tables
+                                        * and needs fsync() to complete (for
+                                        * synchronous page faults in DAX) */
 
 #define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \
                         VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE | \
        { VM_FAULT_LOCKED,              "LOCKED" }, \
        { VM_FAULT_RETRY,               "RETRY" }, \
        { VM_FAULT_FALLBACK,            "FALLBACK" }, \
-       { VM_FAULT_DONE_COW,            "DONE_COW" }
+       { VM_FAULT_DONE_COW,            "DONE_COW" }, \
+       { VM_FAULT_NEEDDSYNC,           "NEEDDSYNC" }
 
 /* Encode hstate index for a hwpoisoned large page */
 #define VM_FAULT_SET_HINDEX(x) ((x) << 12)