You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08:00
Merge branch 'akpm' (patches from Andrew)
Merge updates from Andrew Morton: "Incoming: - a small number of updates to scripts/, ocfs2 and fs/buffer.c - most of MM I still have quite a lot of material (mostly not MM) staged after linux-next due to -next dependencies. I'll send those across next week as the preprequisites get merged up" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (135 commits) mm/page_io.c: annotate refault stalls from swap_readpage mm/Kconfig: fix trivial help text punctuation mm/Kconfig: fix indentation mm/memory_hotplug.c: remove __online_page_set_limits() mm: fix typos in comments when calling __SetPageUptodate() mm: fix struct member name in function comments mm/shmem.c: cast the type of unmap_start to u64 mm: shmem: use proper gfp flags for shmem_writepage() mm/shmem.c: make array 'values' static const, makes object smaller userfaultfd: require CAP_SYS_PTRACE for UFFD_FEATURE_EVENT_FORK fs/userfaultfd.c: wp: clear VM_UFFD_MISSING or VM_UFFD_WP during userfaultfd_register() userfaultfd: wrap the common dst_vma check into an inlined function userfaultfd: remove unnecessary WARN_ON() in __mcopy_atomic_hugetlb() userfaultfd: use vma_pagesize for all huge page size calculation mm/madvise.c: use PAGE_ALIGN[ED] for range checking mm/madvise.c: replace with page_size() in madvise_inject_error() mm/mmap.c: make vma_merge() comment more easy to understand mm/hwpoison-inject: use DEFINE_DEBUGFS_ATTRIBUTE to define debugfs fops autonuma: reduce cache footprint when scanning page tables autonuma: fix watermark checking in migrate_balanced_pgdat() ...
This commit is contained in:
@@ -1288,7 +1288,12 @@ PAGE_SIZE multiple when read back.
|
||||
inactive_anon, active_anon, inactive_file, active_file, unevictable
|
||||
Amount of memory, swap-backed and filesystem-backed,
|
||||
on the internal memory management lists used by the
|
||||
page reclaim algorithm
|
||||
page reclaim algorithm.
|
||||
|
||||
As these represent internal list state (eg. shmem pages are on anon
|
||||
memory management lists), inactive_foo + active_foo may not be equal to
|
||||
the value for the foo counter, since the foo counter is type-based, not
|
||||
list-based.
|
||||
|
||||
slab_reclaimable
|
||||
Part of "slab" that might be reclaimed, such as
|
||||
|
||||
@@ -218,3 +218,66 @@ brk handler is used to print bug reports.
|
||||
A potential expansion of this mode is a hardware tag-based mode, which would
|
||||
use hardware memory tagging support instead of compiler instrumentation and
|
||||
manual shadow memory manipulation.
|
||||
|
||||
What memory accesses are sanitised by KASAN?
|
||||
--------------------------------------------
|
||||
|
||||
The kernel maps memory in a number of different parts of the address
|
||||
space. This poses something of a problem for KASAN, which requires
|
||||
that all addresses accessed by instrumented code have a valid shadow
|
||||
region.
|
||||
|
||||
The range of kernel virtual addresses is large: there is not enough
|
||||
real memory to support a real shadow region for every address that
|
||||
could be accessed by the kernel.
|
||||
|
||||
By default
|
||||
~~~~~~~~~~
|
||||
|
||||
By default, architectures only map real memory over the shadow region
|
||||
for the linear mapping (and potentially other small areas). For all
|
||||
other areas - such as vmalloc and vmemmap space - a single read-only
|
||||
page is mapped over the shadow area. This read-only shadow page
|
||||
declares all memory accesses as permitted.
|
||||
|
||||
This presents a problem for modules: they do not live in the linear
|
||||
mapping, but in a dedicated module space. By hooking in to the module
|
||||
allocator, KASAN can temporarily map real shadow memory to cover
|
||||
them. This allows detection of invalid accesses to module globals, for
|
||||
example.
|
||||
|
||||
This also creates an incompatibility with ``VMAP_STACK``: if the stack
|
||||
lives in vmalloc space, it will be shadowed by the read-only page, and
|
||||
the kernel will fault when trying to set up the shadow data for stack
|
||||
variables.
|
||||
|
||||
CONFIG_KASAN_VMALLOC
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
With ``CONFIG_KASAN_VMALLOC``, KASAN can cover vmalloc space at the
|
||||
cost of greater memory usage. Currently this is only supported on x86.
|
||||
|
||||
This works by hooking into vmalloc and vmap, and dynamically
|
||||
allocating real shadow memory to back the mappings.
|
||||
|
||||
Most mappings in vmalloc space are small, requiring less than a full
|
||||
page of shadow space. Allocating a full shadow page per mapping would
|
||||
therefore be wasteful. Furthermore, to ensure that different mappings
|
||||
use different shadow pages, mappings would have to be aligned to
|
||||
``KASAN_SHADOW_SCALE_SIZE * PAGE_SIZE``.
|
||||
|
||||
Instead, we share backing space across multiple mappings. We allocate
|
||||
a backing page when a mapping in vmalloc space uses a particular page
|
||||
of the shadow region. This page can be shared by other vmalloc
|
||||
mappings later on.
|
||||
|
||||
We hook in to the vmap infrastructure to lazily clean up unused shadow
|
||||
memory.
|
||||
|
||||
To avoid the difficulties around swapping mappings around, we expect
|
||||
that the part of the shadow region that covers the vmalloc space will
|
||||
not be covered by the early shadow page, but will be left
|
||||
unmapped. This will require changes in arch-specific code.
|
||||
|
||||
This allows ``VMAP_STACK`` support on x86, and can simplify support of
|
||||
architectures that do not have a fixed module region.
|
||||
|
||||
@@ -836,16 +836,17 @@ config HAVE_ARCH_VMAP_STACK
|
||||
config VMAP_STACK
|
||||
default y
|
||||
bool "Use a virtually-mapped stack"
|
||||
depends on HAVE_ARCH_VMAP_STACK && !KASAN
|
||||
depends on HAVE_ARCH_VMAP_STACK
|
||||
depends on !KASAN || KASAN_VMALLOC
|
||||
---help---
|
||||
Enable this if you want the use virtually-mapped kernel stacks
|
||||
with guard pages. This causes kernel stack overflows to be
|
||||
caught immediately rather than causing difficult-to-diagnose
|
||||
corruption.
|
||||
|
||||
This is presently incompatible with KASAN because KASAN expects
|
||||
the stack to map directly to the KASAN shadow map using a formula
|
||||
that is incorrect if the stack is in vmalloc space.
|
||||
To use this with KASAN, the architecture must support backing
|
||||
virtual mappings with real shadow memory, and KASAN_VMALLOC must
|
||||
be enabled.
|
||||
|
||||
config ARCH_OPTIONAL_KERNEL_RWX
|
||||
def_bool n
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#define _ASM_ARC_PGTABLE_H
|
||||
|
||||
#include <linux/bits.h>
|
||||
#define __ARCH_USE_5LEVEL_HACK
|
||||
#include <asm-generic/pgtable-nopmd.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/mmu.h> /* to propagate CONFIG_ARC_MMU_VER <n> */
|
||||
|
||||
@@ -30,6 +30,7 @@ noinline static int handle_kernel_vaddr_fault(unsigned long address)
|
||||
* with the 'reference' page table.
|
||||
*/
|
||||
pgd_t *pgd, *pgd_k;
|
||||
p4d_t *p4d, *p4d_k;
|
||||
pud_t *pud, *pud_k;
|
||||
pmd_t *pmd, *pmd_k;
|
||||
|
||||
@@ -39,8 +40,13 @@ noinline static int handle_kernel_vaddr_fault(unsigned long address)
|
||||
if (!pgd_present(*pgd_k))
|
||||
goto bad_area;
|
||||
|
||||
pud = pud_offset(pgd, address);
|
||||
pud_k = pud_offset(pgd_k, address);
|
||||
p4d = p4d_offset(pgd, address);
|
||||
p4d_k = p4d_offset(pgd_k, address);
|
||||
if (!p4d_present(*p4d_k))
|
||||
goto bad_area;
|
||||
|
||||
pud = pud_offset(p4d, address);
|
||||
pud_k = pud_offset(p4d_k, address);
|
||||
if (!pud_present(*pud_k))
|
||||
goto bad_area;
|
||||
|
||||
|
||||
@@ -111,12 +111,14 @@ EXPORT_SYMBOL(__kunmap_atomic);
|
||||
static noinline pte_t * __init alloc_kmap_pgtable(unsigned long kvaddr)
|
||||
{
|
||||
pgd_t *pgd_k;
|
||||
p4d_t *p4d_k;
|
||||
pud_t *pud_k;
|
||||
pmd_t *pmd_k;
|
||||
pte_t *pte_k;
|
||||
|
||||
pgd_k = pgd_offset_k(kvaddr);
|
||||
pud_k = pud_offset(pgd_k, kvaddr);
|
||||
p4d_k = p4d_offset(pgd_k, kvaddr);
|
||||
pud_k = pud_offset(p4d_k, kvaddr);
|
||||
pmd_k = pmd_offset(pud_k, kvaddr);
|
||||
|
||||
pte_k = (pte_t *)memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
|
||||
|
||||
@@ -70,9 +70,6 @@ static inline int get_hugepd_cache_index(int index)
|
||||
/* should not reach */
|
||||
}
|
||||
|
||||
#else /* !CONFIG_HUGETLB_PAGE */
|
||||
static inline int pmd_huge(pmd_t pmd) { return 0; }
|
||||
static inline int pud_huge(pud_t pud) { return 0; }
|
||||
#endif /* CONFIG_HUGETLB_PAGE */
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
@@ -59,9 +59,6 @@ static inline int get_hugepd_cache_index(int index)
|
||||
BUG();
|
||||
}
|
||||
|
||||
#else /* !CONFIG_HUGETLB_PAGE */
|
||||
static inline int pmd_huge(pmd_t pmd) { return 0; }
|
||||
static inline int pud_huge(pud_t pud) { return 0; }
|
||||
#endif /* CONFIG_HUGETLB_PAGE */
|
||||
|
||||
static inline int remap_4k_pfn(struct vm_area_struct *vma, unsigned long addr,
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/hugetlb.h>
|
||||
#include <linux/string_helpers.h>
|
||||
#include <linux/stop_machine.h>
|
||||
|
||||
|
||||
@@ -134,6 +134,7 @@ config X86
|
||||
select HAVE_ARCH_JUMP_LABEL
|
||||
select HAVE_ARCH_JUMP_LABEL_RELATIVE
|
||||
select HAVE_ARCH_KASAN if X86_64
|
||||
select HAVE_ARCH_KASAN_VMALLOC if X86_64
|
||||
select HAVE_ARCH_KGDB
|
||||
select HAVE_ARCH_MMAP_RND_BITS if MMU
|
||||
select HAVE_ARCH_MMAP_RND_COMPAT_BITS if MMU && COMPAT
|
||||
|
||||
@@ -245,6 +245,49 @@ static void __init kasan_map_early_shadow(pgd_t *pgd)
|
||||
} while (pgd++, addr = next, addr != end);
|
||||
}
|
||||
|
||||
static void __init kasan_shallow_populate_p4ds(pgd_t *pgd,
|
||||
unsigned long addr,
|
||||
unsigned long end)
|
||||
{
|
||||
p4d_t *p4d;
|
||||
unsigned long next;
|
||||
void *p;
|
||||
|
||||
p4d = p4d_offset(pgd, addr);
|
||||
do {
|
||||
next = p4d_addr_end(addr, end);
|
||||
|
||||
if (p4d_none(*p4d)) {
|
||||
p = early_alloc(PAGE_SIZE, NUMA_NO_NODE, true);
|
||||
p4d_populate(&init_mm, p4d, p);
|
||||
}
|
||||
} while (p4d++, addr = next, addr != end);
|
||||
}
|
||||
|
||||
static void __init kasan_shallow_populate_pgds(void *start, void *end)
|
||||
{
|
||||
unsigned long addr, next;
|
||||
pgd_t *pgd;
|
||||
void *p;
|
||||
|
||||
addr = (unsigned long)start;
|
||||
pgd = pgd_offset_k(addr);
|
||||
do {
|
||||
next = pgd_addr_end(addr, (unsigned long)end);
|
||||
|
||||
if (pgd_none(*pgd)) {
|
||||
p = early_alloc(PAGE_SIZE, NUMA_NO_NODE, true);
|
||||
pgd_populate(&init_mm, pgd, p);
|
||||
}
|
||||
|
||||
/*
|
||||
* we need to populate p4ds to be synced when running in
|
||||
* four level mode - see sync_global_pgds_l4()
|
||||
*/
|
||||
kasan_shallow_populate_p4ds(pgd, addr, next);
|
||||
} while (pgd++, addr = next, addr != (unsigned long)end);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KASAN_INLINE
|
||||
static int kasan_die_handler(struct notifier_block *self,
|
||||
unsigned long val,
|
||||
@@ -354,6 +397,24 @@ void __init kasan_init(void)
|
||||
|
||||
kasan_populate_early_shadow(
|
||||
kasan_mem_to_shadow((void *)PAGE_OFFSET + MAXMEM),
|
||||
kasan_mem_to_shadow((void *)VMALLOC_START));
|
||||
|
||||
/*
|
||||
* If we're in full vmalloc mode, don't back vmalloc space with early
|
||||
* shadow pages. Instead, prepopulate pgds/p4ds so they are synced to
|
||||
* the global table and we can populate the lower levels on demand.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_KASAN_VMALLOC))
|
||||
kasan_shallow_populate_pgds(
|
||||
kasan_mem_to_shadow((void *)VMALLOC_START),
|
||||
kasan_mem_to_shadow((void *)VMALLOC_END));
|
||||
else
|
||||
kasan_populate_early_shadow(
|
||||
kasan_mem_to_shadow((void *)VMALLOC_START),
|
||||
kasan_mem_to_shadow((void *)VMALLOC_END));
|
||||
|
||||
kasan_populate_early_shadow(
|
||||
kasan_mem_to_shadow((void *)VMALLOC_END + 1),
|
||||
shadow_cpu_entry_begin);
|
||||
|
||||
kasan_populate_shadow((unsigned long)shadow_cpu_entry_begin,
|
||||
|
||||
@@ -19,15 +19,12 @@
|
||||
#include <linux/memory.h>
|
||||
#include <linux/memory_hotplug.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
static DEFINE_MUTEX(mem_sysfs_mutex);
|
||||
|
||||
#define MEMORY_CLASS_NAME "memory"
|
||||
|
||||
#define to_memory_block(dev) container_of(dev, struct memory_block, dev)
|
||||
@@ -538,12 +535,7 @@ static ssize_t soft_offline_page_store(struct device *dev,
|
||||
if (kstrtoull(buf, 0, &pfn) < 0)
|
||||
return -EINVAL;
|
||||
pfn >>= PAGE_SHIFT;
|
||||
if (!pfn_valid(pfn))
|
||||
return -ENXIO;
|
||||
/* Only online pages can be soft-offlined (esp., not ZONE_DEVICE). */
|
||||
if (!pfn_to_online_page(pfn))
|
||||
return -EIO;
|
||||
ret = soft_offline_page(pfn_to_page(pfn), 0);
|
||||
ret = soft_offline_page(pfn, 0);
|
||||
return ret == 0 ? count : ret;
|
||||
}
|
||||
|
||||
@@ -705,6 +697,8 @@ static void unregister_memory(struct memory_block *memory)
|
||||
* Create memory block devices for the given memory area. Start and size
|
||||
* have to be aligned to memory block granularity. Memory block devices
|
||||
* will be initialized as offline.
|
||||
*
|
||||
* Called under device_hotplug_lock.
|
||||
*/
|
||||
int create_memory_block_devices(unsigned long start, unsigned long size)
|
||||
{
|
||||
@@ -718,7 +712,6 @@ int create_memory_block_devices(unsigned long start, unsigned long size)
|
||||
!IS_ALIGNED(size, memory_block_size_bytes())))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&mem_sysfs_mutex);
|
||||
for (block_id = start_block_id; block_id != end_block_id; block_id++) {
|
||||
ret = init_memory_block(&mem, block_id, MEM_OFFLINE);
|
||||
if (ret)
|
||||
@@ -730,11 +723,12 @@ int create_memory_block_devices(unsigned long start, unsigned long size)
|
||||
for (block_id = start_block_id; block_id != end_block_id;
|
||||
block_id++) {
|
||||
mem = find_memory_block_by_id(block_id);
|
||||
if (WARN_ON_ONCE(!mem))
|
||||
continue;
|
||||
mem->section_count = 0;
|
||||
unregister_memory(mem);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&mem_sysfs_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -742,6 +736,8 @@ int create_memory_block_devices(unsigned long start, unsigned long size)
|
||||
* Remove memory block devices for the given memory area. Start and size
|
||||
* have to be aligned to memory block granularity. Memory block devices
|
||||
* have to be offline.
|
||||
*
|
||||
* Called under device_hotplug_lock.
|
||||
*/
|
||||
void remove_memory_block_devices(unsigned long start, unsigned long size)
|
||||
{
|
||||
@@ -754,7 +750,6 @@ void remove_memory_block_devices(unsigned long start, unsigned long size)
|
||||
!IS_ALIGNED(size, memory_block_size_bytes())))
|
||||
return;
|
||||
|
||||
mutex_lock(&mem_sysfs_mutex);
|
||||
for (block_id = start_block_id; block_id != end_block_id; block_id++) {
|
||||
mem = find_memory_block_by_id(block_id);
|
||||
if (WARN_ON_ONCE(!mem))
|
||||
@@ -763,7 +758,6 @@ void remove_memory_block_devices(unsigned long start, unsigned long size)
|
||||
unregister_memory_block_under_nodes(mem);
|
||||
unregister_memory(mem);
|
||||
}
|
||||
mutex_unlock(&mem_sysfs_mutex);
|
||||
}
|
||||
|
||||
/* return true if the memory block is offlined, otherwise, return false */
|
||||
@@ -797,12 +791,13 @@ static const struct attribute_group *memory_root_attr_groups[] = {
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize the sysfs support for memory devices...
|
||||
* Initialize the sysfs support for memory devices. At the time this function
|
||||
* is called, we cannot have concurrent creation/deletion of memory block
|
||||
* devices, the device_hotplug_lock is not needed.
|
||||
*/
|
||||
void __init memory_dev_init(void)
|
||||
{
|
||||
int ret;
|
||||
int err;
|
||||
unsigned long block_sz, nr;
|
||||
|
||||
/* Validate the configured memory block size */
|
||||
@@ -813,24 +808,19 @@ void __init memory_dev_init(void)
|
||||
|
||||
ret = subsys_system_register(&memory_subsys, memory_root_attr_groups);
|
||||
if (ret)
|
||||
goto out;
|
||||
panic("%s() failed to register subsystem: %d\n", __func__, ret);
|
||||
|
||||
/*
|
||||
* Create entries for memory sections that were found
|
||||
* during boot and have been initialized
|
||||
*/
|
||||
mutex_lock(&mem_sysfs_mutex);
|
||||
for (nr = 0; nr <= __highest_present_section_nr;
|
||||
nr += sections_per_block) {
|
||||
err = add_memory_block(nr);
|
||||
if (!ret)
|
||||
ret = err;
|
||||
ret = add_memory_block(nr);
|
||||
if (ret)
|
||||
panic("%s() failed to add memory block: %d\n", __func__,
|
||||
ret);
|
||||
}
|
||||
mutex_unlock(&mem_sysfs_mutex);
|
||||
|
||||
out:
|
||||
if (ret)
|
||||
panic("%s() failed: %d\n", __func__, ret);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -682,9 +682,7 @@ static void hv_page_online_one(struct hv_hotadd_state *has, struct page *pg)
|
||||
__ClearPageOffline(pg);
|
||||
|
||||
/* This frame is currently backed; online the page. */
|
||||
__online_page_set_limits(pg);
|
||||
__online_page_increment_counters(pg);
|
||||
__online_page_free(pg);
|
||||
generic_online_page(pg, 0);
|
||||
|
||||
lockdep_assert_held(&dm_device.ha_lock);
|
||||
dm_device.num_pages_onlined++;
|
||||
|
||||
@@ -374,7 +374,6 @@ static void xen_online_page(struct page *page, unsigned int order)
|
||||
mutex_lock(&balloon_mutex);
|
||||
for (i = 0; i < size; i++) {
|
||||
p = pfn_to_page(start_pfn + i);
|
||||
__online_page_set_limits(p);
|
||||
balloon_append(p);
|
||||
}
|
||||
mutex_unlock(&balloon_mutex);
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
#include <trace/events/block.h>
|
||||
#include <linux/fscrypt.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
|
||||
static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh,
|
||||
enum rw_hint hint, struct writeback_control *wbc);
|
||||
@@ -1423,10 +1425,10 @@ static bool has_bh_in_lru(int cpu, void *dummy)
|
||||
|
||||
for (i = 0; i < BH_LRU_SIZE; i++) {
|
||||
if (b->bhs[i])
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
void invalidate_bh_lrus(void)
|
||||
|
||||
@@ -220,27 +220,6 @@ static inline struct page *dio_get_page(struct dio *dio,
|
||||
return dio->pages[sdio->head];
|
||||
}
|
||||
|
||||
/*
|
||||
* Warn about a page cache invalidation failure during a direct io write.
|
||||
*/
|
||||
void dio_warn_stale_pagecache(struct file *filp)
|
||||
{
|
||||
static DEFINE_RATELIMIT_STATE(_rs, 86400 * HZ, DEFAULT_RATELIMIT_BURST);
|
||||
char pathname[128];
|
||||
struct inode *inode = file_inode(filp);
|
||||
char *path;
|
||||
|
||||
errseq_set(&inode->i_mapping->wb_err, -EIO);
|
||||
if (__ratelimit(&_rs)) {
|
||||
path = file_path(filp, pathname, sizeof(pathname));
|
||||
if (IS_ERR(path))
|
||||
path = "(unknown)";
|
||||
pr_crit("Page cache invalidation failure on direct I/O. Possible data corruption due to collision with buffered I/O!\n");
|
||||
pr_crit("File: %s PID: %d Comm: %.20s\n", path, current->pid,
|
||||
current->comm);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* dio_complete() - called when all DIO BIO I/O has been completed
|
||||
*
|
||||
|
||||
@@ -440,7 +440,7 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
|
||||
u32 hash;
|
||||
|
||||
index = page->index;
|
||||
hash = hugetlb_fault_mutex_hash(h, mapping, index, 0);
|
||||
hash = hugetlb_fault_mutex_hash(mapping, index);
|
||||
mutex_lock(&hugetlb_fault_mutex_table[hash]);
|
||||
|
||||
/*
|
||||
@@ -644,7 +644,7 @@ static long hugetlbfs_fallocate(struct file *file, int mode, loff_t offset,
|
||||
addr = index * hpage_size;
|
||||
|
||||
/* mutex taken here, fault path and hole punch */
|
||||
hash = hugetlb_fault_mutex_hash(h, mapping, index, addr);
|
||||
hash = hugetlb_fault_mutex_hash(mapping, index);
|
||||
mutex_lock(&hugetlb_fault_mutex_table[hash]);
|
||||
|
||||
/* See if already present in mapping to avoid alloc/free */
|
||||
@@ -815,8 +815,11 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb,
|
||||
/*
|
||||
* File creation. Allocate an inode, and we're done..
|
||||
*/
|
||||
static int hugetlbfs_mknod(struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, dev_t dev)
|
||||
static int do_hugetlbfs_mknod(struct inode *dir,
|
||||
struct dentry *dentry,
|
||||
umode_t mode,
|
||||
dev_t dev,
|
||||
bool tmpfile)
|
||||
{
|
||||
struct inode *inode;
|
||||
int error = -ENOSPC;
|
||||
@@ -824,13 +827,23 @@ static int hugetlbfs_mknod(struct inode *dir,
|
||||
inode = hugetlbfs_get_inode(dir->i_sb, dir, mode, dev);
|
||||
if (inode) {
|
||||
dir->i_ctime = dir->i_mtime = current_time(dir);
|
||||
d_instantiate(dentry, inode);
|
||||
dget(dentry); /* Extra count - pin the dentry in core */
|
||||
if (tmpfile) {
|
||||
d_tmpfile(dentry, inode);
|
||||
} else {
|
||||
d_instantiate(dentry, inode);
|
||||
dget(dentry);/* Extra count - pin the dentry in core */
|
||||
}
|
||||
error = 0;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
static int hugetlbfs_mknod(struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode, dev_t dev)
|
||||
{
|
||||
return do_hugetlbfs_mknod(dir, dentry, mode, dev, false);
|
||||
}
|
||||
|
||||
static int hugetlbfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
int retval = hugetlbfs_mknod(dir, dentry, mode | S_IFDIR, 0);
|
||||
@@ -844,6 +857,12 @@ static int hugetlbfs_create(struct inode *dir, struct dentry *dentry, umode_t mo
|
||||
return hugetlbfs_mknod(dir, dentry, mode | S_IFREG, 0);
|
||||
}
|
||||
|
||||
static int hugetlbfs_tmpfile(struct inode *dir,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
return do_hugetlbfs_mknod(dir, dentry, mode | S_IFREG, 0, true);
|
||||
}
|
||||
|
||||
static int hugetlbfs_symlink(struct inode *dir,
|
||||
struct dentry *dentry, const char *symname)
|
||||
{
|
||||
@@ -1102,6 +1121,7 @@ static const struct inode_operations hugetlbfs_dir_inode_operations = {
|
||||
.mknod = hugetlbfs_mknod,
|
||||
.rename = simple_rename,
|
||||
.setattr = hugetlbfs_setattr,
|
||||
.tmpfile = hugetlbfs_tmpfile,
|
||||
};
|
||||
|
||||
static const struct inode_operations hugetlbfs_inode_operations = {
|
||||
@@ -1461,28 +1481,41 @@ static int __init init_hugetlbfs_fs(void)
|
||||
sizeof(struct hugetlbfs_inode_info),
|
||||
0, SLAB_ACCOUNT, init_once);
|
||||
if (hugetlbfs_inode_cachep == NULL)
|
||||
goto out2;
|
||||
goto out;
|
||||
|
||||
error = register_filesystem(&hugetlbfs_fs_type);
|
||||
if (error)
|
||||
goto out;
|
||||
goto out_free;
|
||||
|
||||
/* default hstate mount is required */
|
||||
mnt = mount_one_hugetlbfs(&hstates[default_hstate_idx]);
|
||||
if (IS_ERR(mnt)) {
|
||||
error = PTR_ERR(mnt);
|
||||
goto out_unreg;
|
||||
}
|
||||
hugetlbfs_vfsmount[default_hstate_idx] = mnt;
|
||||
|
||||
/* other hstates are optional */
|
||||
i = 0;
|
||||
for_each_hstate(h) {
|
||||
if (i == default_hstate_idx)
|
||||
continue;
|
||||
|
||||
mnt = mount_one_hugetlbfs(h);
|
||||
if (IS_ERR(mnt) && i == 0) {
|
||||
error = PTR_ERR(mnt);
|
||||
goto out;
|
||||
}
|
||||
hugetlbfs_vfsmount[i] = mnt;
|
||||
if (IS_ERR(mnt))
|
||||
hugetlbfs_vfsmount[i] = NULL;
|
||||
else
|
||||
hugetlbfs_vfsmount[i] = mnt;
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
out_unreg:
|
||||
(void)unregister_filesystem(&hugetlbfs_fs_type);
|
||||
out_free:
|
||||
kmem_cache_destroy(hugetlbfs_inode_cachep);
|
||||
out2:
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
fs_initcall(init_hugetlbfs_fs)
|
||||
|
||||
@@ -327,8 +327,8 @@ int ocfs2_acl_chmod(struct inode *inode, struct buffer_head *bh)
|
||||
down_read(&OCFS2_I(inode)->ip_xattr_sem);
|
||||
acl = ocfs2_get_acl_nolock(inode, ACL_TYPE_ACCESS, bh);
|
||||
up_read(&OCFS2_I(inode)->ip_xattr_sem);
|
||||
if (IS_ERR(acl) || !acl)
|
||||
return PTR_ERR(acl);
|
||||
if (IS_ERR_OR_NULL(acl))
|
||||
return PTR_ERR_OR_ZERO(acl);
|
||||
ret = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -1460,7 +1460,8 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
|
||||
start = vma->vm_start;
|
||||
vma_end = min(end, vma->vm_end);
|
||||
|
||||
new_flags = (vma->vm_flags & ~vm_flags) | vm_flags;
|
||||
new_flags = (vma->vm_flags &
|
||||
~(VM_UFFD_MISSING|VM_UFFD_WP)) | vm_flags;
|
||||
prev = vma_merge(mm, prev, start, vma_end, new_flags,
|
||||
vma->anon_vma, vma->vm_file, vma->vm_pgoff,
|
||||
vma_policy(vma),
|
||||
@@ -1834,13 +1835,12 @@ static int userfaultfd_api(struct userfaultfd_ctx *ctx,
|
||||
if (copy_from_user(&uffdio_api, buf, sizeof(uffdio_api)))
|
||||
goto out;
|
||||
features = uffdio_api.features;
|
||||
if (uffdio_api.api != UFFD_API || (features & ~UFFD_API_FEATURES)) {
|
||||
memset(&uffdio_api, 0, sizeof(uffdio_api));
|
||||
if (copy_to_user(buf, &uffdio_api, sizeof(uffdio_api)))
|
||||
goto out;
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
ret = -EINVAL;
|
||||
if (uffdio_api.api != UFFD_API || (features & ~UFFD_API_FEATURES))
|
||||
goto err_out;
|
||||
ret = -EPERM;
|
||||
if ((features & UFFD_FEATURE_EVENT_FORK) && !capable(CAP_SYS_PTRACE))
|
||||
goto err_out;
|
||||
/* report all available features and ioctls to userland */
|
||||
uffdio_api.features = UFFD_API_FEATURES;
|
||||
uffdio_api.ioctls = UFFD_API_IOCTLS;
|
||||
@@ -1853,6 +1853,11 @@ static int userfaultfd_api(struct userfaultfd_ctx *ctx,
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
err_out:
|
||||
memset(&uffdio_api, 0, sizeof(uffdio_api));
|
||||
if (copy_to_user(buf, &uffdio_api, sizeof(uffdio_api)))
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
static long userfaultfd_ioctl(struct file *file, unsigned cmd,
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#undef pud_free_tlb
|
||||
#define pud_free_tlb(tlb, x, addr) do { } while (0)
|
||||
#define pud_free(mm, x) do { } while (0)
|
||||
#define __pud_free_tlb(tlb, x, addr) do { } while (0)
|
||||
|
||||
#undef pud_addr_end
|
||||
#define pud_addr_end(addr, end) (end)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user