Merge branch 'akpm' (patches from Andrew)
Merge more updates from Andrew Morton: - a few misc things - kexec updates - DMA-mapping updates to better support networking DMA operations - IPC updates - various MM changes to improve DAX fault handling - lots of radix-tree changes, mainly to the test suite. All leading up to reimplementing the IDA/IDR code to be a wrapper layer over the radix-tree. However the final trigger-pulling patch is held off for 4.11. * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (114 commits) radix tree test suite: delete unused rcupdate.c radix tree test suite: add new tag check radix-tree: ensure counts are initialised radix tree test suite: cache recently freed objects radix tree test suite: add some more functionality idr: reduce the number of bits per level from 8 to 6 rxrpc: abstract away knowledge of IDR internals tpm: use idr_find(), not idr_find_slowpath() idr: add ida_is_empty radix tree test suite: check multiorder iteration radix-tree: fix replacement for multiorder entries radix-tree: add radix_tree_split_preload() radix-tree: add radix_tree_split radix-tree: add radix_tree_join radix-tree: delete radix_tree_range_tag_if_tagged() radix-tree: delete radix_tree_locate_item() radix-tree: improve multiorder iterators btrfs: fix race in btrfs_free_dummy_fs_info() radix-tree: improve dump output radix-tree: make radix_tree_find_next_bit more useful ...
This commit is contained in:
@@ -46,7 +46,6 @@ void dax_wake_mapping_entry_waiter(struct address_space *mapping,
|
||||
|
||||
#ifdef CONFIG_FS_DAX
|
||||
struct page *read_dax_sector(struct block_device *bdev, sector_t n);
|
||||
void dax_unlock_mapping_entry(struct address_space *mapping, pgoff_t index);
|
||||
int __dax_zero_page_range(struct block_device *bdev, sector_t sector,
|
||||
unsigned int offset, unsigned int length);
|
||||
#else
|
||||
@@ -55,12 +54,6 @@ static inline struct page *read_dax_sector(struct block_device *bdev,
|
||||
{
|
||||
return ERR_PTR(-ENXIO);
|
||||
}
|
||||
/* Shouldn't ever be called when dax is disabled. */
|
||||
static inline void dax_unlock_mapping_entry(struct address_space *mapping,
|
||||
pgoff_t index)
|
||||
{
|
||||
BUG();
|
||||
}
|
||||
static inline int __dax_zero_page_range(struct block_device *bdev,
|
||||
sector_t sector, unsigned int offset, unsigned int length)
|
||||
{
|
||||
|
@@ -243,29 +243,33 @@ static inline void dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg
|
||||
ops->unmap_sg(dev, sg, nents, dir, attrs);
|
||||
}
|
||||
|
||||
static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
|
||||
size_t offset, size_t size,
|
||||
enum dma_data_direction dir)
|
||||
static inline dma_addr_t dma_map_page_attrs(struct device *dev,
|
||||
struct page *page,
|
||||
size_t offset, size_t size,
|
||||
enum dma_data_direction dir,
|
||||
unsigned long attrs)
|
||||
{
|
||||
struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
dma_addr_t addr;
|
||||
|
||||
kmemcheck_mark_initialized(page_address(page) + offset, size);
|
||||
BUG_ON(!valid_dma_direction(dir));
|
||||
addr = ops->map_page(dev, page, offset, size, dir, 0);
|
||||
addr = ops->map_page(dev, page, offset, size, dir, attrs);
|
||||
debug_dma_map_page(dev, page, offset, size, dir, addr, false);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
|
||||
size_t size, enum dma_data_direction dir)
|
||||
static inline void dma_unmap_page_attrs(struct device *dev,
|
||||
dma_addr_t addr, size_t size,
|
||||
enum dma_data_direction dir,
|
||||
unsigned long attrs)
|
||||
{
|
||||
struct dma_map_ops *ops = get_dma_ops(dev);
|
||||
|
||||
BUG_ON(!valid_dma_direction(dir));
|
||||
if (ops->unmap_page)
|
||||
ops->unmap_page(dev, addr, size, dir, 0);
|
||||
ops->unmap_page(dev, addr, size, dir, attrs);
|
||||
debug_dma_unmap_page(dev, addr, size, dir, false);
|
||||
}
|
||||
|
||||
@@ -385,6 +389,8 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
|
||||
#define dma_unmap_single(d, a, s, r) dma_unmap_single_attrs(d, a, s, r, 0)
|
||||
#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0)
|
||||
#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
|
||||
#define dma_map_page(d, p, o, s, r) dma_map_page_attrs(d, p, o, s, r, 0)
|
||||
#define dma_unmap_page(d, a, s, r) dma_unmap_page_attrs(d, a, s, r, 0)
|
||||
|
||||
extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
|
||||
void *cpu_addr, dma_addr_t dma_addr, size_t size);
|
||||
|
@@ -506,6 +506,8 @@ extern void free_hot_cold_page(struct page *page, bool cold);
|
||||
extern void free_hot_cold_page_list(struct list_head *list, bool cold);
|
||||
|
||||
struct page_frag_cache;
|
||||
extern void __page_frag_drain(struct page *page, unsigned int order,
|
||||
unsigned int count);
|
||||
extern void *__alloc_page_frag(struct page_frag_cache *nc,
|
||||
unsigned int fragsz, gfp_t gfp_mask);
|
||||
extern void __free_page_frag(void *addr);
|
||||
|
@@ -1,12 +1,12 @@
|
||||
#ifndef _LINUX_HUGE_MM_H
|
||||
#define _LINUX_HUGE_MM_H
|
||||
|
||||
extern int do_huge_pmd_anonymous_page(struct fault_env *fe);
|
||||
extern int do_huge_pmd_anonymous_page(struct vm_fault *vmf);
|
||||
extern int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
|
||||
pmd_t *dst_pmd, pmd_t *src_pmd, unsigned long addr,
|
||||
struct vm_area_struct *vma);
|
||||
extern void huge_pmd_set_accessed(struct fault_env *fe, pmd_t orig_pmd);
|
||||
extern int do_huge_pmd_wp_page(struct fault_env *fe, pmd_t orig_pmd);
|
||||
extern void huge_pmd_set_accessed(struct vm_fault *vmf, pmd_t orig_pmd);
|
||||
extern int do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd);
|
||||
extern struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
|
||||
unsigned long addr,
|
||||
pmd_t *pmd,
|
||||
@@ -142,7 +142,7 @@ static inline int hpage_nr_pages(struct page *page)
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern int do_huge_pmd_numa_page(struct fault_env *fe, pmd_t orig_pmd);
|
||||
extern int do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t orig_pmd);
|
||||
|
||||
extern struct page *huge_zero_page;
|
||||
|
||||
@@ -212,7 +212,7 @@ static inline spinlock_t *pmd_trans_huge_lock(pmd_t *pmd,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int do_huge_pmd_numa_page(struct fault_env *fe, pmd_t orig_pmd)
|
||||
static inline int do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t orig_pmd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@@ -18,12 +18,11 @@
|
||||
#include <linux/rcupdate.h>
|
||||
|
||||
/*
|
||||
* We want shallower trees and thus more bits covered at each layer. 8
|
||||
* bits gives us large enough first layer for most use cases and maximum
|
||||
* tree depth of 4. Each idr_layer is slightly larger than 2k on 64bit and
|
||||
* 1k on 32bit.
|
||||
* Using 6 bits at each layer allows us to allocate 7 layers out of each page.
|
||||
* 8 bits only gave us 3 layers out of every pair of pages, which is less
|
||||
* efficient except for trees with a largest element between 192-255 inclusive.
|
||||
*/
|
||||
#define IDR_BITS 8
|
||||
#define IDR_BITS 6
|
||||
#define IDR_SIZE (1 << IDR_BITS)
|
||||
#define IDR_MASK ((1 << IDR_BITS)-1)
|
||||
|
||||
@@ -55,6 +54,32 @@ struct idr {
|
||||
}
|
||||
#define DEFINE_IDR(name) struct idr name = IDR_INIT(name)
|
||||
|
||||
/**
|
||||
* idr_get_cursor - Return the current position of the cyclic allocator
|
||||
* @idr: idr handle
|
||||
*
|
||||
* The value returned is the value that will be next returned from
|
||||
* idr_alloc_cyclic() if it is free (otherwise the search will start from
|
||||
* this position).
|
||||
*/
|
||||
static inline unsigned int idr_get_cursor(struct idr *idr)
|
||||
{
|
||||
return READ_ONCE(idr->cur);
|
||||
}
|
||||
|
||||
/**
|
||||
* idr_set_cursor - Set the current position of the cyclic allocator
|
||||
* @idr: idr handle
|
||||
* @val: new position
|
||||
*
|
||||
* The next call to idr_alloc_cyclic() will return @val if it is free
|
||||
* (otherwise the search will start from this position).
|
||||
*/
|
||||
static inline void idr_set_cursor(struct idr *idr, unsigned int val)
|
||||
{
|
||||
WRITE_ONCE(idr->cur, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* DOC: idr sync
|
||||
* idr synchronization (stolen from radix-tree.h)
|
||||
@@ -195,6 +220,11 @@ static inline int ida_get_new(struct ida *ida, int *p_id)
|
||||
return ida_get_new_above(ida, 0, p_id);
|
||||
}
|
||||
|
||||
static inline bool ida_is_empty(struct ida *ida)
|
||||
{
|
||||
return idr_is_empty(&ida->idr);
|
||||
}
|
||||
|
||||
void __init idr_init_cache(void);
|
||||
|
||||
#endif /* __IDR_H__ */
|
||||
|
@@ -77,7 +77,6 @@ extern int kdb_poll_idx;
|
||||
* number whenever the kernel debugger is entered.
|
||||
*/
|
||||
extern int kdb_initial_cpu;
|
||||
extern atomic_t kdb_event;
|
||||
|
||||
/* Types and messages used for dynamically added kdb shell commands */
|
||||
|
||||
@@ -162,6 +161,7 @@ enum kdb_msgsrc {
|
||||
};
|
||||
|
||||
extern int kdb_trap_printk;
|
||||
extern int kdb_printf_cpu;
|
||||
extern __printf(2, 0) int vkdb_printf(enum kdb_msgsrc src, const char *fmt,
|
||||
va_list args);
|
||||
extern __printf(1, 2) int kdb_printf(const char *, ...);
|
||||
|
@@ -259,12 +259,6 @@ phys_addr_t paddr_vmcoreinfo_note(void);
|
||||
vmcoreinfo_append_str("NUMBER(%s)=%ld\n", #name, (long)name)
|
||||
#define VMCOREINFO_CONFIG(name) \
|
||||
vmcoreinfo_append_str("CONFIG_%s=y\n", #name)
|
||||
#define VMCOREINFO_PAGE_OFFSET(value) \
|
||||
vmcoreinfo_append_str("PAGE_OFFSET=%lx\n", (unsigned long)value)
|
||||
#define VMCOREINFO_VMALLOC_START(value) \
|
||||
vmcoreinfo_append_str("VMALLOC_START=%lx\n", (unsigned long)value)
|
||||
#define VMCOREINFO_VMEMMAP_START(value) \
|
||||
vmcoreinfo_append_str("VMEMMAP_START=%lx\n", (unsigned long)value)
|
||||
|
||||
extern struct kimage *kexec_image;
|
||||
extern struct kimage *kexec_crash_image;
|
||||
|
@@ -292,36 +292,23 @@ extern pgprot_t protection_map[16];
|
||||
* pgoff should be used in favour of virtual_address, if possible.
|
||||
*/
|
||||
struct vm_fault {
|
||||
struct vm_area_struct *vma; /* Target VMA */
|
||||
unsigned int flags; /* FAULT_FLAG_xxx flags */
|
||||
gfp_t gfp_mask; /* gfp mask to be used for allocations */
|
||||
pgoff_t pgoff; /* Logical page offset based on vma */
|
||||
void __user *virtual_address; /* Faulting virtual address */
|
||||
unsigned long address; /* Faulting virtual address */
|
||||
pmd_t *pmd; /* Pointer to pmd entry matching
|
||||
* the 'address' */
|
||||
pte_t orig_pte; /* Value of PTE at the time of fault */
|
||||
|
||||
struct page *cow_page; /* Handler may choose to COW */
|
||||
struct page *cow_page; /* Page handler may use for COW fault */
|
||||
struct mem_cgroup *memcg; /* Cgroup cow_page belongs to */
|
||||
struct page *page; /* ->fault handlers should return a
|
||||
* page here, unless VM_FAULT_NOPAGE
|
||||
* is set (which is also implied by
|
||||
* VM_FAULT_ERROR).
|
||||
*/
|
||||
void *entry; /* ->fault handler can alternatively
|
||||
* return locked DAX entry. In that
|
||||
* case handler should return
|
||||
* VM_FAULT_DAX_LOCKED and fill in
|
||||
* entry here.
|
||||
*/
|
||||
};
|
||||
|
||||
/*
|
||||
* Page fault context: passes though page fault handler instead of endless list
|
||||
* of function arguments.
|
||||
*/
|
||||
struct fault_env {
|
||||
struct vm_area_struct *vma; /* Target VMA */
|
||||
unsigned long address; /* Faulting virtual address */
|
||||
unsigned int flags; /* FAULT_FLAG_xxx flags */
|
||||
pmd_t *pmd; /* Pointer to pmd entry matching
|
||||
* the 'address'
|
||||
*/
|
||||
/* These three entries are valid only while holding ptl lock */
|
||||
pte_t *pte; /* Pointer to pte entry matching
|
||||
* the 'address'. NULL if the page
|
||||
* table hasn't been allocated.
|
||||
@@ -351,7 +338,7 @@ struct vm_operations_struct {
|
||||
int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf);
|
||||
int (*pmd_fault)(struct vm_area_struct *, unsigned long address,
|
||||
pmd_t *, unsigned int flags);
|
||||
void (*map_pages)(struct fault_env *fe,
|
||||
void (*map_pages)(struct vm_fault *vmf,
|
||||
pgoff_t start_pgoff, pgoff_t end_pgoff);
|
||||
|
||||
/* notification that a previously read-only page is about to become
|
||||
@@ -625,8 +612,10 @@ static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
|
||||
return pte;
|
||||
}
|
||||
|
||||
int alloc_set_pte(struct fault_env *fe, struct mem_cgroup *memcg,
|
||||
int alloc_set_pte(struct vm_fault *vmf, struct mem_cgroup *memcg,
|
||||
struct page *page);
|
||||
int finish_fault(struct vm_fault *vmf);
|
||||
int finish_mkwrite_fault(struct vm_fault *vmf);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -1110,7 +1099,7 @@ static inline void clear_page_pfmemalloc(struct page *page)
|
||||
#define VM_FAULT_LOCKED 0x0200 /* ->fault locked the returned page */
|
||||
#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_DAX_LOCKED 0x1000 /* ->fault has locked DAX entry */
|
||||
#define VM_FAULT_DONE_COW 0x1000 /* ->fault has fully handled COW */
|
||||
|
||||
#define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */
|
||||
|
||||
@@ -1221,6 +1210,8 @@ int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
|
||||
struct vm_area_struct *vma);
|
||||
void unmap_mapping_range(struct address_space *mapping,
|
||||
loff_t const holebegin, loff_t const holelen, int even_cows);
|
||||
int follow_pte(struct mm_struct *mm, unsigned long address, pte_t **ptepp,
|
||||
spinlock_t **ptlp);
|
||||
int follow_pfn(struct vm_area_struct *vma, unsigned long address,
|
||||
unsigned long *pfn);
|
||||
int follow_phys(struct vm_area_struct *vma, unsigned long address,
|
||||
@@ -1276,15 +1267,12 @@ extern int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
|
||||
long get_user_pages_remote(struct task_struct *tsk, struct mm_struct *mm,
|
||||
unsigned long start, unsigned long nr_pages,
|
||||
unsigned int gup_flags, struct page **pages,
|
||||
struct vm_area_struct **vmas);
|
||||
struct vm_area_struct **vmas, int *locked);
|
||||
long get_user_pages(unsigned long start, unsigned long nr_pages,
|
||||
unsigned int gup_flags, struct page **pages,
|
||||
struct vm_area_struct **vmas);
|
||||
long get_user_pages_locked(unsigned long start, unsigned long nr_pages,
|
||||
unsigned int gup_flags, struct page **pages, int *locked);
|
||||
long __get_user_pages_unlocked(struct task_struct *tsk, struct mm_struct *mm,
|
||||
unsigned long start, unsigned long nr_pages,
|
||||
struct page **pages, unsigned int gup_flags);
|
||||
long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
|
||||
struct page **pages, unsigned int gup_flags);
|
||||
int get_user_pages_fast(unsigned long start, int nr_pages, int write,
|
||||
@@ -2099,7 +2087,7 @@ extern void truncate_inode_pages_final(struct address_space *);
|
||||
|
||||
/* generic vm_area_ops exported for stackable file systems */
|
||||
extern int filemap_fault(struct vm_area_struct *, struct vm_fault *);
|
||||
extern void filemap_map_pages(struct fault_env *fe,
|
||||
extern void filemap_map_pages(struct vm_fault *vmf,
|
||||
pgoff_t start_pgoff, pgoff_t end_pgoff);
|
||||
extern int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);
|
||||
|
||||
|
@@ -7,6 +7,23 @@
|
||||
#include <linux/sched.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
/*
|
||||
* The run state of the lockup detectors is controlled by the content of the
|
||||
* 'watchdog_enabled' variable. Each lockup detector has its dedicated bit -
|
||||
* bit 0 for the hard lockup detector and bit 1 for the soft lockup detector.
|
||||
*
|
||||
* 'watchdog_user_enabled', 'nmi_watchdog_enabled' and 'soft_watchdog_enabled'
|
||||
* are variables that are only used as an 'interface' between the parameters
|
||||
* in /proc/sys/kernel and the internal state bits in 'watchdog_enabled'. The
|
||||
* 'watchdog_thresh' variable is handled differently because its value is not
|
||||
* boolean, and the lockup detectors are 'suspended' while 'watchdog_thresh'
|
||||
* is equal zero.
|
||||
*/
|
||||
#define NMI_WATCHDOG_ENABLED_BIT 0
|
||||
#define SOFT_WATCHDOG_ENABLED_BIT 1
|
||||
#define NMI_WATCHDOG_ENABLED (1 << NMI_WATCHDOG_ENABLED_BIT)
|
||||
#define SOFT_WATCHDOG_ENABLED (1 << SOFT_WATCHDOG_ENABLED_BIT)
|
||||
|
||||
/**
|
||||
* touch_nmi_watchdog - restart NMI watchdog timeout.
|
||||
*
|
||||
@@ -91,9 +108,16 @@ extern int nmi_watchdog_enabled;
|
||||
extern int soft_watchdog_enabled;
|
||||
extern int watchdog_user_enabled;
|
||||
extern int watchdog_thresh;
|
||||
extern unsigned long watchdog_enabled;
|
||||
extern unsigned long *watchdog_cpumask_bits;
|
||||
#ifdef CONFIG_SMP
|
||||
extern int sysctl_softlockup_all_cpu_backtrace;
|
||||
extern int sysctl_hardlockup_all_cpu_backtrace;
|
||||
#else
|
||||
#define sysctl_softlockup_all_cpu_backtrace 0
|
||||
#define sysctl_hardlockup_all_cpu_backtrace 0
|
||||
#endif
|
||||
extern bool is_hardlockup(void);
|
||||
struct ctl_table;
|
||||
extern int proc_watchdog(struct ctl_table *, int ,
|
||||
void __user *, size_t *, loff_t *);
|
||||
|
@@ -80,23 +80,25 @@ static inline bool radix_tree_is_internal_node(void *ptr)
|
||||
#define RADIX_TREE_MAX_PATH (DIV_ROUND_UP(RADIX_TREE_INDEX_BITS, \
|
||||
RADIX_TREE_MAP_SHIFT))
|
||||
|
||||
/*
|
||||
* @count is the count of every non-NULL element in the ->slots array
|
||||
* whether that is an exceptional entry, a retry entry, a user pointer,
|
||||
* a sibling entry or a pointer to the next level of the tree.
|
||||
* @exceptional is the count of every element in ->slots which is
|
||||
* either radix_tree_exceptional_entry() or is a sibling entry for an
|
||||
* exceptional entry.
|
||||
*/
|
||||
struct radix_tree_node {
|
||||
unsigned char shift; /* Bits remaining in each slot */
|
||||
unsigned char offset; /* Slot offset in parent */
|
||||
unsigned char count; /* Total entry count */
|
||||
unsigned char exceptional; /* Exceptional entry count */
|
||||
struct radix_tree_node *parent; /* Used when ascending tree */
|
||||
void *private_data; /* For tree user */
|
||||
union {
|
||||
struct {
|
||||
/* Used when ascending tree */
|
||||
struct radix_tree_node *parent;
|
||||
/* For tree user */
|
||||
void *private_data;
|
||||
};
|
||||
/* Used when freeing node */
|
||||
struct rcu_head rcu_head;
|
||||
struct list_head private_list; /* For tree user */
|
||||
struct rcu_head rcu_head; /* Used when freeing node */
|
||||
};
|
||||
/* For tree user */
|
||||
struct list_head private_list;
|
||||
void __rcu *slots[RADIX_TREE_MAP_SIZE];
|
||||
unsigned long tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS];
|
||||
};
|
||||
@@ -126,6 +128,41 @@ static inline bool radix_tree_empty(struct radix_tree_root *root)
|
||||
return root->rnode == NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* struct radix_tree_iter - radix tree iterator state
|
||||
*
|
||||
* @index: index of current slot
|
||||
* @next_index: one beyond the last index for this chunk
|
||||
* @tags: bit-mask for tag-iterating
|
||||
* @node: node that contains current slot
|
||||
* @shift: shift for the node that holds our slots
|
||||
*
|
||||
* This radix tree iterator works in terms of "chunks" of slots. A chunk is a
|
||||
* subinterval of slots contained within one radix tree leaf node. It is
|
||||
* described by a pointer to its first slot and a struct radix_tree_iter
|
||||
* which holds the chunk's position in the tree and its size. For tagged
|
||||
* iteration radix_tree_iter also holds the slots' bit-mask for one chosen
|
||||
* radix tree tag.
|
||||
*/
|
||||
struct radix_tree_iter {
|
||||
unsigned long index;
|
||||
unsigned long next_index;
|
||||
unsigned long tags;
|
||||
struct radix_tree_node *node;
|
||||
#ifdef CONFIG_RADIX_TREE_MULTIORDER
|
||||
unsigned int shift;
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline unsigned int iter_shift(const struct radix_tree_iter *iter)
|
||||
{
|
||||
#ifdef CONFIG_RADIX_TREE_MULTIORDER
|
||||
return iter->shift;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Radix-tree synchronization
|
||||
*
|
||||
@@ -264,6 +301,8 @@ void __radix_tree_replace(struct radix_tree_root *root,
|
||||
struct radix_tree_node *node,
|
||||
void **slot, void *item,
|
||||
radix_tree_update_node_t update_node, void *private);
|
||||
void radix_tree_iter_replace(struct radix_tree_root *,
|
||||
const struct radix_tree_iter *, void **slot, void *item);
|
||||
void radix_tree_replace_slot(struct radix_tree_root *root,
|
||||
void **slot, void *item);
|
||||
void __radix_tree_delete_node(struct radix_tree_root *root,
|
||||
@@ -289,6 +328,8 @@ void *radix_tree_tag_clear(struct radix_tree_root *root,
|
||||
unsigned long index, unsigned int tag);
|
||||
int radix_tree_tag_get(struct radix_tree_root *root,
|
||||
unsigned long index, unsigned int tag);
|
||||
void radix_tree_iter_tag_set(struct radix_tree_root *root,
|
||||
const struct radix_tree_iter *iter, unsigned int tag);
|
||||
unsigned int
|
||||
radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results,
|
||||
unsigned long first_index, unsigned int max_items,
|
||||
@@ -297,50 +338,18 @@ unsigned int
|
||||
radix_tree_gang_lookup_tag_slot(struct radix_tree_root *root, void ***results,
|
||||
unsigned long first_index, unsigned int max_items,
|
||||
unsigned int tag);
|
||||
unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root,
|
||||
unsigned long *first_indexp, unsigned long last_index,
|
||||
unsigned long nr_to_tag,
|
||||
unsigned int fromtag, unsigned int totag);
|
||||
int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag);
|
||||
unsigned long radix_tree_locate_item(struct radix_tree_root *root, void *item);
|
||||
|
||||
static inline void radix_tree_preload_end(void)
|
||||
{
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* struct radix_tree_iter - radix tree iterator state
|
||||
*
|
||||
* @index: index of current slot
|
||||
* @next_index: one beyond the last index for this chunk
|
||||
* @tags: bit-mask for tag-iterating
|
||||
* @shift: shift for the node that holds our slots
|
||||
*
|
||||
* This radix tree iterator works in terms of "chunks" of slots. A chunk is a
|
||||
* subinterval of slots contained within one radix tree leaf node. It is
|
||||
* described by a pointer to its first slot and a struct radix_tree_iter
|
||||
* which holds the chunk's position in the tree and its size. For tagged
|
||||
* iteration radix_tree_iter also holds the slots' bit-mask for one chosen
|
||||
* radix tree tag.
|
||||
*/
|
||||
struct radix_tree_iter {
|
||||
unsigned long index;
|
||||
unsigned long next_index;
|
||||
unsigned long tags;
|
||||
#ifdef CONFIG_RADIX_TREE_MULTIORDER
|
||||
unsigned int shift;
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline unsigned int iter_shift(struct radix_tree_iter *iter)
|
||||
{
|
||||
#ifdef CONFIG_RADIX_TREE_MULTIORDER
|
||||
return iter->shift;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
int radix_tree_split_preload(unsigned old_order, unsigned new_order, gfp_t);
|
||||
int radix_tree_split(struct radix_tree_root *, unsigned long index,
|
||||
unsigned new_order);
|
||||
int radix_tree_join(struct radix_tree_root *, unsigned long index,
|
||||
unsigned new_order, void *);
|
||||
|
||||
#define RADIX_TREE_ITER_TAG_MASK 0x00FF /* tag index in lower byte */
|
||||
#define RADIX_TREE_ITER_TAGGED 0x0100 /* lookup tagged slots */
|
||||
@@ -409,20 +418,17 @@ __radix_tree_iter_add(struct radix_tree_iter *iter, unsigned long slots)
|
||||
}
|
||||
|
||||
/**
|
||||
* radix_tree_iter_next - resume iterating when the chunk may be invalid
|
||||
* @iter: iterator state
|
||||
* radix_tree_iter_resume - resume iterating when the chunk may be invalid
|
||||
* @slot: pointer to current slot
|
||||
* @iter: iterator state
|
||||
* Returns: New slot pointer
|
||||
*
|
||||
* If the iterator needs to release then reacquire a lock, the chunk may
|
||||
* have been invalidated by an insertion or deletion. Call this function
|
||||
* to continue the iteration from the next index.
|
||||
* before releasing the lock to continue the iteration from the next index.
|
||||
*/
|
||||
static inline __must_check
|
||||
void **radix_tree_iter_next(struct radix_tree_iter *iter)
|
||||
{
|
||||
iter->next_index = __radix_tree_iter_add(iter, 1);
|
||||
iter->tags = 0;
|
||||
return NULL;
|
||||
}
|
||||
void **__must_check radix_tree_iter_resume(void **slot,
|
||||
struct radix_tree_iter *iter);
|
||||
|
||||
/**
|
||||
* radix_tree_chunk_size - get current chunk size
|
||||
@@ -436,10 +442,17 @@ radix_tree_chunk_size(struct radix_tree_iter *iter)
|
||||
return (iter->next_index - iter->index) >> iter_shift(iter);
|
||||
}
|
||||
|
||||
static inline struct radix_tree_node *entry_to_node(void *ptr)
|
||||
#ifdef CONFIG_RADIX_TREE_MULTIORDER
|
||||
void ** __radix_tree_next_slot(void **slot, struct radix_tree_iter *iter,
|
||||
unsigned flags);
|
||||
#else
|
||||
/* Can't happen without sibling entries, but the compiler can't tell that */
|
||||
static inline void ** __radix_tree_next_slot(void **slot,
|
||||
struct radix_tree_iter *iter, unsigned flags)
|
||||
{
|
||||
return (void *)((unsigned long)ptr & ~RADIX_TREE_INTERNAL_NODE);
|
||||
return slot;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* radix_tree_next_slot - find next slot in chunk
|
||||
@@ -453,7 +466,7 @@ static inline struct radix_tree_node *entry_to_node(void *ptr)
|
||||
* For tagged lookup it also eats @iter->tags.
|
||||
*
|
||||
* There are several cases where 'slot' can be passed in as NULL to this
|
||||
* function. These cases result from the use of radix_tree_iter_next() or
|
||||
* function. These cases result from the use of radix_tree_iter_resume() or
|
||||
* radix_tree_iter_retry(). In these cases we don't end up dereferencing
|
||||
* 'slot' because either:
|
||||
* a) we are doing tagged iteration and iter->tags has been set to 0, or
|
||||
@@ -464,51 +477,31 @@ static __always_inline void **
|
||||
radix_tree_next_slot(void **slot, struct radix_tree_iter *iter, unsigned flags)
|
||||
{
|
||||
if (flags & RADIX_TREE_ITER_TAGGED) {
|
||||
void *canon = slot;
|
||||
|
||||
iter->tags >>= 1;
|
||||
if (unlikely(!iter->tags))
|
||||
return NULL;
|
||||
while (IS_ENABLED(CONFIG_RADIX_TREE_MULTIORDER) &&
|
||||
radix_tree_is_internal_node(slot[1])) {
|
||||
if (entry_to_node(slot[1]) == canon) {
|
||||
iter->tags >>= 1;
|
||||
iter->index = __radix_tree_iter_add(iter, 1);
|
||||
slot++;
|
||||
continue;
|
||||
}
|
||||
iter->next_index = __radix_tree_iter_add(iter, 1);
|
||||
return NULL;
|
||||
}
|
||||
if (likely(iter->tags & 1ul)) {
|
||||
iter->index = __radix_tree_iter_add(iter, 1);
|
||||
return slot + 1;
|
||||
slot++;
|
||||
goto found;
|
||||
}
|
||||
if (!(flags & RADIX_TREE_ITER_CONTIG)) {
|
||||
unsigned offset = __ffs(iter->tags);
|
||||
|
||||
iter->tags >>= offset;
|
||||
iter->index = __radix_tree_iter_add(iter, offset + 1);
|
||||
return slot + offset + 1;
|
||||
iter->tags >>= offset++;
|
||||
iter->index = __radix_tree_iter_add(iter, offset);
|
||||
slot += offset;
|
||||
goto found;
|
||||
}
|
||||
} else {
|
||||
long count = radix_tree_chunk_size(iter);
|
||||
void *canon = slot;
|
||||
|
||||
while (--count > 0) {
|
||||
slot++;
|
||||
iter->index = __radix_tree_iter_add(iter, 1);
|
||||
|
||||
if (IS_ENABLED(CONFIG_RADIX_TREE_MULTIORDER) &&
|
||||
radix_tree_is_internal_node(*slot)) {
|
||||
if (entry_to_node(*slot) == canon)
|
||||
continue;
|
||||
iter->next_index = iter->index;
|
||||
break;
|
||||
}
|
||||
|
||||
if (likely(*slot))
|
||||
return slot;
|
||||
goto found;
|
||||
if (flags & RADIX_TREE_ITER_CONTIG) {
|
||||
/* forbid switching to the next chunk */
|
||||
iter->next_index = 0;
|
||||
@@ -517,6 +510,11 @@ radix_tree_next_slot(void **slot, struct radix_tree_iter *iter, unsigned flags)
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
found:
|
||||
if (unlikely(radix_tree_is_internal_node(*slot)))
|
||||
return __radix_tree_next_slot(slot, iter, flags);
|
||||
return slot;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -567,6 +565,6 @@ radix_tree_next_slot(void **slot, struct radix_tree_iter *iter, unsigned flags)
|
||||
slot || (slot = radix_tree_next_chunk(root, iter, \
|
||||
RADIX_TREE_ITER_TAGGED | tag)) ; \
|
||||
slot = radix_tree_next_slot(slot, iter, \
|
||||
RADIX_TREE_ITER_TAGGED))
|
||||
RADIX_TREE_ITER_TAGGED | tag))
|
||||
|
||||
#endif /* _LINUX_RADIX_TREE_H */
|
||||
|
@@ -97,6 +97,23 @@ static inline int sigisemptyset(sigset_t *set)
|
||||
}
|
||||
}
|
||||
|
||||
static inline int sigequalsets(const sigset_t *set1, const sigset_t *set2)
|
||||
{
|
||||
switch (_NSIG_WORDS) {
|
||||
case 4:
|
||||
return (set1->sig[3] == set2->sig[3]) &&
|
||||
(set1->sig[2] == set2->sig[2]) &&
|
||||
(set1->sig[1] == set2->sig[1]) &&
|
||||
(set1->sig[0] == set2->sig[0]);
|
||||
case 2:
|
||||
return (set1->sig[1] == set2->sig[1]) &&
|
||||
(set1->sig[0] == set2->sig[0]);
|
||||
case 1:
|
||||
return set1->sig[0] == set2->sig[0];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define sigmask(sig) (1UL << ((sig) - 1))
|
||||
|
||||
#ifndef __HAVE_ARCH_SIG_SETOPS
|
||||
|
@@ -27,7 +27,7 @@
|
||||
#define UFFD_SHARED_FCNTL_FLAGS (O_CLOEXEC | O_NONBLOCK)
|
||||
#define UFFD_FLAGS_SET (EFD_SHARED_FCNTL_FLAGS)
|
||||
|
||||
extern int handle_userfault(struct fault_env *fe, unsigned long reason);
|
||||
extern int handle_userfault(struct vm_fault *vmf, unsigned long reason);
|
||||
|
||||
extern ssize_t mcopy_atomic(struct mm_struct *dst_mm, unsigned long dst_start,
|
||||
unsigned long src_start, unsigned long len);
|
||||
@@ -55,7 +55,7 @@ static inline bool userfaultfd_armed(struct vm_area_struct *vma)
|
||||
#else /* CONFIG_USERFAULTFD */
|
||||
|
||||
/* mm helpers */
|
||||
static inline int handle_userfault(struct fault_env *fe, unsigned long reason)
|
||||
static inline int handle_userfault(struct vm_fault *vmf, unsigned long reason)
|
||||
{
|
||||
return VM_FAULT_SIGBUS;
|
||||
}
|
||||
|
Reference in New Issue
Block a user