diff options
author | Jan Kara <jack@suse.cz> | 2017-11-01 11:36:43 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2017-11-03 09:26:25 -0400 |
commit | 71eab6dfd91eabf06fe782a590c07e8a0795f5ea (patch) | |
tree | fc0c38518d74b25f9038e1c880a262a6366e768e /fs/dax.c | |
parent | caa51d26f85c248f1c4f43a870ad3ef84bf9eb8f (diff) |
dax: Implement dax_finish_sync_fault()
Implement a function that filesystems can call to finish handling of
synchronous page faults. It takes care of syncing appropriare file range
and insertion of page table entry.
Reviewed-by: Ross Zwisler <ross.zwisler@linux.intel.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'fs/dax.c')
-rw-r--r-- | fs/dax.c | 83 |
1 files changed, 83 insertions, 0 deletions
@@ -1492,3 +1492,86 @@ int dax_iomap_fault(struct vm_fault *vmf, enum page_entry_size pe_size, | |||
1492 | } | 1492 | } |
1493 | } | 1493 | } |
1494 | EXPORT_SYMBOL_GPL(dax_iomap_fault); | 1494 | EXPORT_SYMBOL_GPL(dax_iomap_fault); |
1495 | |||
1496 | /** | ||
1497 | * dax_insert_pfn_mkwrite - insert PTE or PMD entry into page tables | ||
1498 | * @vmf: The description of the fault | ||
1499 | * @pe_size: Size of entry to be inserted | ||
1500 | * @pfn: PFN to insert | ||
1501 | * | ||
1502 | * This function inserts writeable PTE or PMD entry into page tables for mmaped | ||
1503 | * DAX file. It takes care of marking corresponding radix tree entry as dirty | ||
1504 | * as well. | ||
1505 | */ | ||
1506 | static int dax_insert_pfn_mkwrite(struct vm_fault *vmf, | ||
1507 | enum page_entry_size pe_size, | ||
1508 | pfn_t pfn) | ||
1509 | { | ||
1510 | struct address_space *mapping = vmf->vma->vm_file->f_mapping; | ||
1511 | void *entry, **slot; | ||
1512 | pgoff_t index = vmf->pgoff; | ||
1513 | int vmf_ret, error; | ||
1514 | |||
1515 | spin_lock_irq(&mapping->tree_lock); | ||
1516 | entry = get_unlocked_mapping_entry(mapping, index, &slot); | ||
1517 | /* Did we race with someone splitting entry or so? */ | ||
1518 | if (!entry || | ||
1519 | (pe_size == PE_SIZE_PTE && !dax_is_pte_entry(entry)) || | ||
1520 | (pe_size == PE_SIZE_PMD && !dax_is_pmd_entry(entry))) { | ||
1521 | put_unlocked_mapping_entry(mapping, index, entry); | ||
1522 | spin_unlock_irq(&mapping->tree_lock); | ||
1523 | trace_dax_insert_pfn_mkwrite_no_entry(mapping->host, vmf, | ||
1524 | VM_FAULT_NOPAGE); | ||
1525 | return VM_FAULT_NOPAGE; | ||
1526 | } | ||
1527 | radix_tree_tag_set(&mapping->page_tree, index, PAGECACHE_TAG_DIRTY); | ||
1528 | entry = lock_slot(mapping, slot); | ||
1529 | spin_unlock_irq(&mapping->tree_lock); | ||
1530 | switch (pe_size) { | ||
1531 | case PE_SIZE_PTE: | ||
1532 | error = vm_insert_mixed_mkwrite(vmf->vma, vmf->address, pfn); | ||
1533 | vmf_ret = dax_fault_return(error); | ||
1534 | break; | ||
1535 | #ifdef CONFIG_FS_DAX_PMD | ||
1536 | case PE_SIZE_PMD: | ||
1537 | vmf_ret = vmf_insert_pfn_pmd(vmf->vma, vmf->address, vmf->pmd, | ||
1538 | pfn, true); | ||
1539 | break; | ||
1540 | #endif | ||
1541 | default: | ||
1542 | vmf_ret = VM_FAULT_FALLBACK; | ||
1543 | } | ||
1544 | put_locked_mapping_entry(mapping, index); | ||
1545 | trace_dax_insert_pfn_mkwrite(mapping->host, vmf, vmf_ret); | ||
1546 | return vmf_ret; | ||
1547 | } | ||
1548 | |||
1549 | /** | ||
1550 | * dax_finish_sync_fault - finish synchronous page fault | ||
1551 | * @vmf: The description of the fault | ||
1552 | * @pe_size: Size of entry to be inserted | ||
1553 | * @pfn: PFN to insert | ||
1554 | * | ||
1555 | * This function ensures that the file range touched by the page fault is | ||
1556 | * stored persistently on the media and handles inserting of appropriate page | ||
1557 | * table entry. | ||
1558 | */ | ||
1559 | int dax_finish_sync_fault(struct vm_fault *vmf, enum page_entry_size pe_size, | ||
1560 | pfn_t pfn) | ||
1561 | { | ||
1562 | int err; | ||
1563 | loff_t start = ((loff_t)vmf->pgoff) << PAGE_SHIFT; | ||
1564 | size_t len = 0; | ||
1565 | |||
1566 | if (pe_size == PE_SIZE_PTE) | ||
1567 | len = PAGE_SIZE; | ||
1568 | else if (pe_size == PE_SIZE_PMD) | ||
1569 | len = PMD_SIZE; | ||
1570 | else | ||
1571 | WARN_ON_ONCE(1); | ||
1572 | err = vfs_fsync_range(vmf->vma->vm_file, start, start + len - 1, 1); | ||
1573 | if (err) | ||
1574 | return VM_FAULT_SIGBUS; | ||
1575 | return dax_insert_pfn_mkwrite(vmf, pe_size, pfn); | ||
1576 | } | ||
1577 | EXPORT_SYMBOL_GPL(dax_finish_sync_fault); | ||