|
Jan Kara |
ef57d1 |
From 71eab6dfd91eabf06fe782a590c07e8a0795f5ea Mon Sep 17 00:00:00 2001
|
|
Jan Kara |
ef57d1 |
From: Jan Kara <jack@suse.cz>
|
|
Jan Kara |
ef57d1 |
Date: Wed, 1 Nov 2017 16:36:43 +0100
|
|
Jan Kara |
ef57d1 |
Subject: [PATCH 15/20] dax: Implement dax_finish_sync_fault()
|
|
Jan Kara |
ef57d1 |
Git-commit: 71eab6dfd91eabf06fe782a590c07e8a0795f5ea
|
|
Jan Kara |
ef57d1 |
Patch-mainline: v4.15-rc1
|
|
Jan Kara |
ef57d1 |
References: fate#322879
|
|
Jan Kara |
ef57d1 |
|
|
Jan Kara |
ef57d1 |
Implement a function that filesystems can call to finish handling of
|
|
Jan Kara |
ef57d1 |
synchronous page faults. It takes care of syncing appropriare file range
|
|
Jan Kara |
ef57d1 |
and insertion of page table entry.
|
|
Jan Kara |
ef57d1 |
|
|
Jan Kara |
ef57d1 |
Reviewed-by: Ross Zwisler <ross.zwisler@linux.intel.com>
|
|
Jan Kara |
ef57d1 |
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
|
Jan Kara |
ef57d1 |
Signed-off-by: Jan Kara <jack@suse.cz>
|
|
Jan Kara |
ef57d1 |
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
|
Jan Kara |
ef57d1 |
Acked-by: Jan Kara <jack@suse.cz>
|
|
Jan Kara |
ef57d1 |
|
|
Jan Kara |
ef57d1 |
---
|
|
Jan Kara |
ef57d1 |
fs/dax.c | 83 +++++++++++++++++++++++++++++++++++++++++++
|
|
Jan Kara |
ef57d1 |
include/linux/dax.h | 2 ++
|
|
Jan Kara |
ef57d1 |
include/trace/events/fs_dax.h | 2 ++
|
|
Jan Kara |
ef57d1 |
3 files changed, 87 insertions(+)
|
|
Jan Kara |
ef57d1 |
|
|
Jan Kara |
ef57d1 |
diff --git a/fs/dax.c b/fs/dax.c
|
|
Jan Kara |
ef57d1 |
index bb9ff907738c..78233c716757 100644
|
|
Jan Kara |
ef57d1 |
--- a/fs/dax.c
|
|
Jan Kara |
ef57d1 |
+++ b/fs/dax.c
|
|
Jan Kara |
ef57d1 |
@@ -1492,3 +1492,86 @@ int dax_iomap_fault(struct vm_fault *vmf, enum page_entry_size pe_size,
|
|
Jan Kara |
ef57d1 |
}
|
|
Jan Kara |
ef57d1 |
}
|
|
Jan Kara |
ef57d1 |
EXPORT_SYMBOL_GPL(dax_iomap_fault);
|
|
Jan Kara |
ef57d1 |
+
|
|
Jan Kara |
ef57d1 |
+/**
|
|
Jan Kara |
ef57d1 |
+ * dax_insert_pfn_mkwrite - insert PTE or PMD entry into page tables
|
|
Jan Kara |
ef57d1 |
+ * @vmf: The description of the fault
|
|
Jan Kara |
ef57d1 |
+ * @pe_size: Size of entry to be inserted
|
|
Jan Kara |
ef57d1 |
+ * @pfn: PFN to insert
|
|
Jan Kara |
ef57d1 |
+ *
|
|
Jan Kara |
ef57d1 |
+ * This function inserts writeable PTE or PMD entry into page tables for mmaped
|
|
Jan Kara |
ef57d1 |
+ * DAX file. It takes care of marking corresponding radix tree entry as dirty
|
|
Jan Kara |
ef57d1 |
+ * as well.
|
|
Jan Kara |
ef57d1 |
+ */
|
|
Jan Kara |
ef57d1 |
+static int dax_insert_pfn_mkwrite(struct vm_fault *vmf,
|
|
Jan Kara |
ef57d1 |
+ enum page_entry_size pe_size,
|
|
Jan Kara |
ef57d1 |
+ pfn_t pfn)
|
|
Jan Kara |
ef57d1 |
+{
|
|
Jan Kara |
ef57d1 |
+ struct address_space *mapping = vmf->vma->vm_file->f_mapping;
|
|
Jan Kara |
ef57d1 |
+ void *entry, **slot;
|
|
Jan Kara |
ef57d1 |
+ pgoff_t index = vmf->pgoff;
|
|
Jan Kara |
ef57d1 |
+ int vmf_ret, error;
|
|
Jan Kara |
ef57d1 |
+
|
|
Jan Kara |
ef57d1 |
+ spin_lock_irq(&mapping->tree_lock);
|
|
Jan Kara |
ef57d1 |
+ entry = get_unlocked_mapping_entry(mapping, index, &slot);
|
|
Jan Kara |
ef57d1 |
+ /* Did we race with someone splitting entry or so? */
|
|
Jan Kara |
ef57d1 |
+ if (!entry ||
|
|
Jan Kara |
ef57d1 |
+ (pe_size == PE_SIZE_PTE && !dax_is_pte_entry(entry)) ||
|
|
Jan Kara |
ef57d1 |
+ (pe_size == PE_SIZE_PMD && !dax_is_pmd_entry(entry))) {
|
|
Jan Kara |
ef57d1 |
+ put_unlocked_mapping_entry(mapping, index, entry);
|
|
Jan Kara |
ef57d1 |
+ spin_unlock_irq(&mapping->tree_lock);
|
|
Jan Kara |
ef57d1 |
+ trace_dax_insert_pfn_mkwrite_no_entry(mapping->host, vmf,
|
|
Jan Kara |
ef57d1 |
+ VM_FAULT_NOPAGE);
|
|
Jan Kara |
ef57d1 |
+ return VM_FAULT_NOPAGE;
|
|
Jan Kara |
ef57d1 |
+ }
|
|
Jan Kara |
ef57d1 |
+ radix_tree_tag_set(&mapping->page_tree, index, PAGECACHE_TAG_DIRTY);
|
|
Jan Kara |
ef57d1 |
+ entry = lock_slot(mapping, slot);
|
|
Jan Kara |
ef57d1 |
+ spin_unlock_irq(&mapping->tree_lock);
|
|
Jan Kara |
ef57d1 |
+ switch (pe_size) {
|
|
Jan Kara |
ef57d1 |
+ case PE_SIZE_PTE:
|
|
Jan Kara |
ef57d1 |
+ error = vm_insert_mixed_mkwrite(vmf->vma, vmf->address, pfn);
|
|
Jan Kara |
ef57d1 |
+ vmf_ret = dax_fault_return(error);
|
|
Jan Kara |
ef57d1 |
+ break;
|
|
Jan Kara |
ef57d1 |
+#ifdef CONFIG_FS_DAX_PMD
|
|
Jan Kara |
ef57d1 |
+ case PE_SIZE_PMD:
|
|
Jan Kara |
ef57d1 |
+ vmf_ret = vmf_insert_pfn_pmd(vmf->vma, vmf->address, vmf->pmd,
|
|
Jan Kara |
ef57d1 |
+ pfn, true);
|
|
Jan Kara |
ef57d1 |
+ break;
|
|
Jan Kara |
ef57d1 |
+#endif
|
|
Jan Kara |
ef57d1 |
+ default:
|
|
Jan Kara |
ef57d1 |
+ vmf_ret = VM_FAULT_FALLBACK;
|
|
Jan Kara |
ef57d1 |
+ }
|
|
Jan Kara |
ef57d1 |
+ put_locked_mapping_entry(mapping, index);
|
|
Jan Kara |
ef57d1 |
+ trace_dax_insert_pfn_mkwrite(mapping->host, vmf, vmf_ret);
|
|
Jan Kara |
ef57d1 |
+ return vmf_ret;
|
|
Jan Kara |
ef57d1 |
+}
|
|
Jan Kara |
ef57d1 |
+
|
|
Jan Kara |
ef57d1 |
+/**
|
|
Jan Kara |
ef57d1 |
+ * dax_finish_sync_fault - finish synchronous page fault
|
|
Jan Kara |
ef57d1 |
+ * @vmf: The description of the fault
|
|
Jan Kara |
ef57d1 |
+ * @pe_size: Size of entry to be inserted
|
|
Jan Kara |
ef57d1 |
+ * @pfn: PFN to insert
|
|
Jan Kara |
ef57d1 |
+ *
|
|
Jan Kara |
ef57d1 |
+ * This function ensures that the file range touched by the page fault is
|
|
Jan Kara |
ef57d1 |
+ * stored persistently on the media and handles inserting of appropriate page
|
|
Jan Kara |
ef57d1 |
+ * table entry.
|
|
Jan Kara |
ef57d1 |
+ */
|
|
Jan Kara |
ef57d1 |
+int dax_finish_sync_fault(struct vm_fault *vmf, enum page_entry_size pe_size,
|
|
Jan Kara |
ef57d1 |
+ pfn_t pfn)
|
|
Jan Kara |
ef57d1 |
+{
|
|
Jan Kara |
ef57d1 |
+ int err;
|
|
Jan Kara |
ef57d1 |
+ loff_t start = ((loff_t)vmf->pgoff) << PAGE_SHIFT;
|
|
Jan Kara |
ef57d1 |
+ size_t len = 0;
|
|
Jan Kara |
ef57d1 |
+
|
|
Jan Kara |
ef57d1 |
+ if (pe_size == PE_SIZE_PTE)
|
|
Jan Kara |
ef57d1 |
+ len = PAGE_SIZE;
|
|
Jan Kara |
ef57d1 |
+ else if (pe_size == PE_SIZE_PMD)
|
|
Jan Kara |
ef57d1 |
+ len = PMD_SIZE;
|
|
Jan Kara |
ef57d1 |
+ else
|
|
Jan Kara |
ef57d1 |
+ WARN_ON_ONCE(1);
|
|
Jan Kara |
ef57d1 |
+ err = vfs_fsync_range(vmf->vma->vm_file, start, start + len - 1, 1);
|
|
Jan Kara |
ef57d1 |
+ if (err)
|
|
Jan Kara |
ef57d1 |
+ return VM_FAULT_SIGBUS;
|
|
Jan Kara |
ef57d1 |
+ return dax_insert_pfn_mkwrite(vmf, pe_size, pfn);
|
|
Jan Kara |
ef57d1 |
+}
|
|
Jan Kara |
ef57d1 |
+EXPORT_SYMBOL_GPL(dax_finish_sync_fault);
|
|
Jan Kara |
ef57d1 |
diff --git a/include/linux/dax.h b/include/linux/dax.h
|
|
Jan Kara |
ef57d1 |
index e7fa4b8f45bc..d403f78b706c 100644
|
|
Jan Kara |
ef57d1 |
--- a/include/linux/dax.h
|
|
Jan Kara |
ef57d1 |
+++ b/include/linux/dax.h
|
|
Jan Kara |
ef57d1 |
@@ -96,6 +96,8 @@ ssize_t dax_iomap_rw(struct kiocb *iocb, struct iov_iter *iter,
|
|
Jan Kara |
ef57d1 |
const struct iomap_ops *ops);
|
|
Jan Kara |
ef57d1 |
int dax_iomap_fault(struct vm_fault *vmf, enum page_entry_size pe_size,
|
|
Jan Kara |
ef57d1 |
pfn_t *pfnp, const struct iomap_ops *ops);
|
|
Jan Kara |
ef57d1 |
+int dax_finish_sync_fault(struct vm_fault *vmf, enum page_entry_size pe_size,
|
|
Jan Kara |
ef57d1 |
+ pfn_t pfn);
|
|
Jan Kara |
ef57d1 |
int dax_delete_mapping_entry(struct address_space *mapping, pgoff_t index);
|
|
Jan Kara |
ef57d1 |
int dax_invalidate_mapping_entry_sync(struct address_space *mapping,
|
|
Jan Kara |
ef57d1 |
pgoff_t index);
|
|
Jan Kara |
ef57d1 |
diff --git a/include/trace/events/fs_dax.h b/include/trace/events/fs_dax.h
|
|
Jan Kara |
ef57d1 |
index 88a9d19b8ff8..7725459fafef 100644
|
|
Jan Kara |
ef57d1 |
--- a/include/trace/events/fs_dax.h
|
|
Jan Kara |
ef57d1 |
+++ b/include/trace/events/fs_dax.h
|
|
Jan Kara |
ef57d1 |
@@ -190,6 +190,8 @@ DEFINE_EVENT(dax_pte_fault_class, name, \
|
|
Jan Kara |
ef57d1 |
DEFINE_PTE_FAULT_EVENT(dax_pte_fault);
|
|
Jan Kara |
ef57d1 |
DEFINE_PTE_FAULT_EVENT(dax_pte_fault_done);
|
|
Jan Kara |
ef57d1 |
DEFINE_PTE_FAULT_EVENT(dax_load_hole);
|
|
Jan Kara |
ef57d1 |
+DEFINE_PTE_FAULT_EVENT(dax_insert_pfn_mkwrite_no_entry);
|
|
Jan Kara |
ef57d1 |
+DEFINE_PTE_FAULT_EVENT(dax_insert_pfn_mkwrite);
|
|
Jan Kara |
ef57d1 |
|
|
Jan Kara |
ef57d1 |
TRACE_EVENT(dax_insert_mapping,
|
|
Jan Kara |
ef57d1 |
TP_PROTO(struct inode *inode, struct vm_fault *vmf, void *radix_entry),
|
|
Jan Kara |
ef57d1 |
--
|
|
Jan Kara |
ef57d1 |
2.12.3
|
|
Jan Kara |
ef57d1 |
|