Merge branch 'akpm' (patches from Andrew)
Merge updates from Andrew Morton: "142 patches: - DAX updates - various misc bits - OCFS2 updates - most of MM" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (142 commits) mm/z3fold.c: limit first_num to the actual range of possible buddy indexes mm: fix <linux/pagemap.h> stray kernel-doc notation zram: remove obsolete sysfs attrs mm/memblock.c: remove unnecessary log and clean up oom-reaper: use madvise_dontneed() logic to decide if unmap the VMA mm: drop unused argument of zap_page_range() mm: drop zap_details::check_swap_entries mm: drop zap_details::ignore_dirty mm, page_alloc: warn_alloc nodemask is NULL when cpusets are disabled mm: help __GFP_NOFAIL allocations which do not trigger OOM killer mm, oom: do not enforce OOM killer for __GFP_NOFAIL automatically mm: consolidate GFP_NOFAIL checks in the allocator slowpath lib/show_mem.c: teach show_mem to work with the given nodemask arch, mm: remove arch specific show_mem mm, page_alloc: warn_alloc print nodemask mm, page_alloc: do not report all nodes in show_mem Revert "mm: bail out in shrink_inactive_list()" mm, vmscan: consider eligible zones in get_scan_count mm, vmscan: cleanup lru size claculations mm, vmscan: do not count freed pages as PGDEACTIVATE ...
This commit is contained in:
104
fs/dax.c
104
fs/dax.c
@@ -35,6 +35,9 @@
|
||||
#include <linux/iomap.h>
|
||||
#include "internal.h"
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/fs_dax.h>
|
||||
|
||||
/* We choose 4096 entries - same as per-zone page wait tables */
|
||||
#define DAX_WAIT_TABLE_BITS 12
|
||||
#define DAX_WAIT_TABLE_ENTRIES (1 << DAX_WAIT_TABLE_BITS)
|
||||
@@ -1253,21 +1256,21 @@ EXPORT_SYMBOL_GPL(dax_iomap_fault);
|
||||
*/
|
||||
#define PG_PMD_COLOUR ((PMD_SIZE >> PAGE_SHIFT) - 1)
|
||||
|
||||
static int dax_pmd_insert_mapping(struct vm_area_struct *vma, pmd_t *pmd,
|
||||
struct vm_fault *vmf, unsigned long address,
|
||||
struct iomap *iomap, loff_t pos, bool write, void **entryp)
|
||||
static int dax_pmd_insert_mapping(struct vm_fault *vmf, struct iomap *iomap,
|
||||
loff_t pos, void **entryp)
|
||||
{
|
||||
struct address_space *mapping = vma->vm_file->f_mapping;
|
||||
struct address_space *mapping = vmf->vma->vm_file->f_mapping;
|
||||
struct block_device *bdev = iomap->bdev;
|
||||
struct inode *inode = mapping->host;
|
||||
struct blk_dax_ctl dax = {
|
||||
.sector = dax_iomap_sector(iomap, pos),
|
||||
.size = PMD_SIZE,
|
||||
};
|
||||
long length = dax_map_atomic(bdev, &dax);
|
||||
void *ret;
|
||||
void *ret = NULL;
|
||||
|
||||
if (length < 0) /* dax_map_atomic() failed */
|
||||
return VM_FAULT_FALLBACK;
|
||||
goto fallback;
|
||||
if (length < PMD_SIZE)
|
||||
goto unmap_fallback;
|
||||
if (pfn_t_to_pfn(dax.pfn) & PG_PMD_COLOUR)
|
||||
@@ -1280,67 +1283,86 @@ static int dax_pmd_insert_mapping(struct vm_area_struct *vma, pmd_t *pmd,
|
||||
ret = dax_insert_mapping_entry(mapping, vmf, *entryp, dax.sector,
|
||||
RADIX_DAX_PMD);
|
||||
if (IS_ERR(ret))
|
||||
return VM_FAULT_FALLBACK;
|
||||
goto fallback;
|
||||
*entryp = ret;
|
||||
|
||||
return vmf_insert_pfn_pmd(vma, address, pmd, dax.pfn, write);
|
||||
trace_dax_pmd_insert_mapping(inode, vmf, length, dax.pfn, ret);
|
||||
return vmf_insert_pfn_pmd(vmf->vma, vmf->address, vmf->pmd,
|
||||
dax.pfn, vmf->flags & FAULT_FLAG_WRITE);
|
||||
|
||||
unmap_fallback:
|
||||
dax_unmap_atomic(bdev, &dax);
|
||||
fallback:
|
||||
trace_dax_pmd_insert_mapping_fallback(inode, vmf, length,
|
||||
dax.pfn, ret);
|
||||
return VM_FAULT_FALLBACK;
|
||||
}
|
||||
|
||||
static int dax_pmd_load_hole(struct vm_area_struct *vma, pmd_t *pmd,
|
||||
struct vm_fault *vmf, unsigned long address,
|
||||
struct iomap *iomap, void **entryp)
|
||||
static int dax_pmd_load_hole(struct vm_fault *vmf, struct iomap *iomap,
|
||||
void **entryp)
|
||||
{
|
||||
struct address_space *mapping = vma->vm_file->f_mapping;
|
||||
unsigned long pmd_addr = address & PMD_MASK;
|
||||
struct address_space *mapping = vmf->vma->vm_file->f_mapping;
|
||||
unsigned long pmd_addr = vmf->address & PMD_MASK;
|
||||
struct inode *inode = mapping->host;
|
||||
struct page *zero_page;
|
||||
void *ret = NULL;
|
||||
spinlock_t *ptl;
|
||||
pmd_t pmd_entry;
|
||||
void *ret;
|
||||
|
||||
zero_page = mm_get_huge_zero_page(vma->vm_mm);
|
||||
zero_page = mm_get_huge_zero_page(vmf->vma->vm_mm);
|
||||
|
||||
if (unlikely(!zero_page))
|
||||
return VM_FAULT_FALLBACK;
|
||||
goto fallback;
|
||||
|
||||
ret = dax_insert_mapping_entry(mapping, vmf, *entryp, 0,
|
||||
RADIX_DAX_PMD | RADIX_DAX_HZP);
|
||||
if (IS_ERR(ret))
|
||||
return VM_FAULT_FALLBACK;
|
||||
goto fallback;
|
||||
*entryp = ret;
|
||||
|
||||
ptl = pmd_lock(vma->vm_mm, pmd);
|
||||
if (!pmd_none(*pmd)) {
|
||||
ptl = pmd_lock(vmf->vma->vm_mm, vmf->pmd);
|
||||
if (!pmd_none(*(vmf->pmd))) {
|
||||
spin_unlock(ptl);
|
||||
return VM_FAULT_FALLBACK;
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
pmd_entry = mk_pmd(zero_page, vma->vm_page_prot);
|
||||
pmd_entry = mk_pmd(zero_page, vmf->vma->vm_page_prot);
|
||||
pmd_entry = pmd_mkhuge(pmd_entry);
|
||||
set_pmd_at(vma->vm_mm, pmd_addr, pmd, pmd_entry);
|
||||
set_pmd_at(vmf->vma->vm_mm, pmd_addr, vmf->pmd, pmd_entry);
|
||||
spin_unlock(ptl);
|
||||
trace_dax_pmd_load_hole(inode, vmf, zero_page, ret);
|
||||
return VM_FAULT_NOPAGE;
|
||||
|
||||
fallback:
|
||||
trace_dax_pmd_load_hole_fallback(inode, vmf, zero_page, ret);
|
||||
return VM_FAULT_FALLBACK;
|
||||
}
|
||||
|
||||
int dax_iomap_pmd_fault(struct vm_area_struct *vma, unsigned long address,
|
||||
pmd_t *pmd, unsigned int flags, const struct iomap_ops *ops)
|
||||
int dax_iomap_pmd_fault(struct vm_fault *vmf, const struct iomap_ops *ops)
|
||||
{
|
||||
struct vm_area_struct *vma = vmf->vma;
|
||||
struct address_space *mapping = vma->vm_file->f_mapping;
|
||||
unsigned long pmd_addr = address & PMD_MASK;
|
||||
bool write = flags & FAULT_FLAG_WRITE;
|
||||
unsigned long pmd_addr = vmf->address & PMD_MASK;
|
||||
bool write = vmf->flags & FAULT_FLAG_WRITE;
|
||||
unsigned int iomap_flags = (write ? IOMAP_WRITE : 0) | IOMAP_FAULT;
|
||||
struct inode *inode = mapping->host;
|
||||
int result = VM_FAULT_FALLBACK;
|
||||
struct iomap iomap = { 0 };
|
||||
pgoff_t max_pgoff, pgoff;
|
||||
struct vm_fault vmf;
|
||||
void *entry;
|
||||
loff_t pos;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Check whether offset isn't beyond end of file now. Caller is
|
||||
* supposed to hold locks serializing us with truncate / punch hole so
|
||||
* this is a reliable test.
|
||||
*/
|
||||
pgoff = linear_page_index(vma, pmd_addr);
|
||||
max_pgoff = (i_size_read(inode) - 1) >> PAGE_SHIFT;
|
||||
|
||||
trace_dax_pmd_fault(inode, vmf, max_pgoff, 0);
|
||||
|
||||
/* Fall back to PTEs if we're going to COW */
|
||||
if (write && !(vma->vm_flags & VM_SHARED))
|
||||
goto fallback;
|
||||
@@ -1351,16 +1373,10 @@ int dax_iomap_pmd_fault(struct vm_area_struct *vma, unsigned long address,
|
||||
if ((pmd_addr + PMD_SIZE) > vma->vm_end)
|
||||
goto fallback;
|
||||
|
||||
/*
|
||||
* Check whether offset isn't beyond end of file now. Caller is
|
||||
* supposed to hold locks serializing us with truncate / punch hole so
|
||||
* this is a reliable test.
|
||||
*/
|
||||
pgoff = linear_page_index(vma, pmd_addr);
|
||||
max_pgoff = (i_size_read(inode) - 1) >> PAGE_SHIFT;
|
||||
|
||||
if (pgoff > max_pgoff)
|
||||
return VM_FAULT_SIGBUS;
|
||||
if (pgoff > max_pgoff) {
|
||||
result = VM_FAULT_SIGBUS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* If the PMD would extend beyond the file size */
|
||||
if ((pgoff | PG_PMD_COLOUR) > max_pgoff)
|
||||
@@ -1389,21 +1405,15 @@ int dax_iomap_pmd_fault(struct vm_area_struct *vma, unsigned long address,
|
||||
if (IS_ERR(entry))
|
||||
goto finish_iomap;
|
||||
|
||||
vmf.pgoff = pgoff;
|
||||
vmf.flags = flags;
|
||||
vmf.gfp_mask = mapping_gfp_mask(mapping) | __GFP_IO;
|
||||
|
||||
switch (iomap.type) {
|
||||
case IOMAP_MAPPED:
|
||||
result = dax_pmd_insert_mapping(vma, pmd, &vmf, address,
|
||||
&iomap, pos, write, &entry);
|
||||
result = dax_pmd_insert_mapping(vmf, &iomap, pos, &entry);
|
||||
break;
|
||||
case IOMAP_UNWRITTEN:
|
||||
case IOMAP_HOLE:
|
||||
if (WARN_ON_ONCE(write))
|
||||
goto unlock_entry;
|
||||
result = dax_pmd_load_hole(vma, pmd, &vmf, address, &iomap,
|
||||
&entry);
|
||||
result = dax_pmd_load_hole(vmf, &iomap, &entry);
|
||||
break;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
@@ -1429,9 +1439,11 @@ int dax_iomap_pmd_fault(struct vm_area_struct *vma, unsigned long address,
|
||||
}
|
||||
fallback:
|
||||
if (result == VM_FAULT_FALLBACK) {
|
||||
split_huge_pmd(vma, pmd, address);
|
||||
split_huge_pmd(vma, vmf->pmd, vmf->address);
|
||||
count_vm_event(THP_FAULT_FALLBACK);
|
||||
}
|
||||
out:
|
||||
trace_dax_pmd_fault_done(inode, vmf, max_pgoff, result);
|
||||
return result;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dax_iomap_pmd_fault);
|
||||
|
Reference in New Issue
Block a user