Merge branch 'akpm' (patches from Andrew)

Merge more updates from Andrew Morton:

 - almost all of the rest of -mm

 - various other subsystems

Subsystems affected by this patch series:
  memcg, misc, core-kernel, lib, checkpatch, reiserfs, fat, fork,
  cpumask, kexec, uaccess, kconfig, kgdb, bug, ipc, lzo, kasan, madvise,
  cleanups, pagemap

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (77 commits)
  arch/sparc/include/asm/pgtable_64.h: fix build
  mm: treewide: clarify pgtable_page_{ctor,dtor}() naming
  ntfs: remove (un)?likely() from IS_ERR() conditions
  IB/hfi1: remove unlikely() from IS_ERR*() condition
  xfs: remove unlikely() from WARN_ON() condition
  wimax/i2400m: remove unlikely() from WARN*() condition
  fs: remove unlikely() from WARN_ON() condition
  xen/events: remove unlikely() from WARN() condition
  checkpatch: check for nested (un)?likely() calls
  hexagon: drop empty and unused free_initrd_mem
  mm: factor out common parts between MADV_COLD and MADV_PAGEOUT
  mm: introduce MADV_PAGEOUT
  mm: change PAGEREF_RECLAIM_CLEAN with PAGE_REFRECLAIM
  mm: introduce MADV_COLD
  mm: untag user pointers in mmap/munmap/mremap/brk
  vfio/type1: untag user pointers in vaddr_get_pfn
  tee/shm: untag user pointers in tee_shm_register
  media/v4l2-core: untag user pointers in videobuf_dma_contig_user_get
  drm/radeon: untag user pointers in radeon_gem_userptr_ioctl
  drm/amdgpu: untag user pointers
  ...
This commit is contained in:
Linus Torvalds
2019-09-26 10:29:42 -07:00
114 changed files with 1006 additions and 565 deletions

View File

@@ -42,6 +42,9 @@ String Manipulation
.. kernel-doc:: lib/string.c .. kernel-doc:: lib/string.c
:export: :export:
.. kernel-doc:: include/linux/string.h
:internal:
.. kernel-doc:: mm/util.c .. kernel-doc:: mm/util.c
:functions: kstrdup kstrdup_const kstrndup kmemdup kmemdup_nul memdup_user :functions: kstrdup kstrdup_const kstrndup kmemdup kmemdup_nul memdup_user
vmemdup_user strndup_user memdup_user_nul vmemdup_user strndup_user memdup_user_nul

View File

@@ -54,9 +54,9 @@ Hugetlb-specific helpers:
Support of split page table lock by an architecture Support of split page table lock by an architecture
=================================================== ===================================================
There's no need in special enabling of PTE split page table lock: There's no need in special enabling of PTE split page table lock: everything
everything required is done by pgtable_page_ctor() and pgtable_page_dtor(), required is done by pgtable_pte_page_ctor() and pgtable_pte_page_dtor(), which
which must be called on PTE table allocation / freeing. must be called on PTE table allocation / freeing.
Make sure the architecture doesn't use slab allocator for page table Make sure the architecture doesn't use slab allocator for page table
allocation: slab uses page->slab_cache for its pages. allocation: slab uses page->slab_cache for its pages.
@@ -74,7 +74,7 @@ paths: i.e X86_PAE preallocate few PMDs on pgd_alloc().
With everything in place you can set CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK. With everything in place you can set CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK.
NOTE: pgtable_page_ctor() and pgtable_pmd_page_ctor() can fail -- it must NOTE: pgtable_pte_page_ctor() and pgtable_pmd_page_ctor() can fail -- it must
be handled properly. be handled properly.
page->ptl page->ptl
@@ -94,7 +94,7 @@ trick:
split lock with enabled DEBUG_SPINLOCK or DEBUG_LOCK_ALLOC, but costs split lock with enabled DEBUG_SPINLOCK or DEBUG_LOCK_ALLOC, but costs
one more cache line for indirect access; one more cache line for indirect access;
The spinlock_t allocated in pgtable_page_ctor() for PTE table and in The spinlock_t allocated in pgtable_pte_page_ctor() for PTE table and in
pgtable_pmd_page_ctor() for PMD table. pgtable_pmd_page_ctor() for PMD table.
Please, never access page->ptl directly -- use appropriate helper. Please, never access page->ptl directly -- use appropriate helper.

View File

@@ -68,6 +68,9 @@
#define MADV_WIPEONFORK 18 /* Zero memory on fork, child only */ #define MADV_WIPEONFORK 18 /* Zero memory on fork, child only */
#define MADV_KEEPONFORK 19 /* Undo MADV_WIPEONFORK */ #define MADV_KEEPONFORK 19 /* Undo MADV_WIPEONFORK */
#define MADV_COLD 20 /* deactivate these pages */
#define MADV_PAGEOUT 21 /* reclaim these pages */
/* compatibility flags */ /* compatibility flags */
#define MAP_FILE 0 #define MAP_FILE 0

View File

@@ -108,7 +108,7 @@ pte_alloc_one(struct mm_struct *mm)
return 0; return 0;
memzero((void *)pte_pg, PTRS_PER_PTE * sizeof(pte_t)); memzero((void *)pte_pg, PTRS_PER_PTE * sizeof(pte_t));
page = virt_to_page(pte_pg); page = virt_to_page(pte_pg);
if (!pgtable_page_ctor(page)) { if (!pgtable_pte_page_ctor(page)) {
__free_page(page); __free_page(page);
return 0; return 0;
} }
@@ -123,7 +123,7 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
static inline void pte_free(struct mm_struct *mm, pgtable_t ptep) static inline void pte_free(struct mm_struct *mm, pgtable_t ptep)
{ {
pgtable_page_dtor(virt_to_page(ptep)); pgtable_pte_page_dtor(virt_to_page(ptep));
free_pages((unsigned long)ptep, __get_order_pte()); free_pages((unsigned long)ptep, __get_order_pte());
} }

View File

@@ -44,7 +44,7 @@ static inline void __tlb_remove_table(void *_table)
static inline void static inline void
__pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, unsigned long addr) __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, unsigned long addr)
{ {
pgtable_page_dtor(pte); pgtable_pte_page_dtor(pte);
#ifndef CONFIG_ARM_LPAE #ifndef CONFIG_ARM_LPAE
/* /*

View File

@@ -731,7 +731,7 @@ static void *__init late_alloc(unsigned long sz)
{ {
void *ptr = (void *)__get_free_pages(GFP_PGTABLE_KERNEL, get_order(sz)); void *ptr = (void *)__get_free_pages(GFP_PGTABLE_KERNEL, get_order(sz));
if (!ptr || !pgtable_page_ctor(virt_to_page(ptr))) if (!ptr || !pgtable_pte_page_ctor(virt_to_page(ptr)))
BUG(); BUG();
return ptr; return ptr;
} }

View File

@@ -44,7 +44,7 @@ static inline void tlb_flush(struct mmu_gather *tlb)
static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
unsigned long addr) unsigned long addr)
{ {
pgtable_page_dtor(pte); pgtable_pte_page_dtor(pte);
tlb_remove_table(tlb, pte); tlb_remove_table(tlb, pte);
} }

View File

@@ -384,7 +384,7 @@ static phys_addr_t pgd_pgtable_alloc(int shift)
* folded, and if so pgtable_pmd_page_ctor() becomes nop. * folded, and if so pgtable_pmd_page_ctor() becomes nop.
*/ */
if (shift == PAGE_SHIFT) if (shift == PAGE_SHIFT)
BUG_ON(!pgtable_page_ctor(phys_to_page(pa))); BUG_ON(!pgtable_pte_page_ctor(phys_to_page(pa)));
else if (shift == PMD_SHIFT) else if (shift == PMD_SHIFT)
BUG_ON(!pgtable_pmd_page_ctor(phys_to_page(pa))); BUG_ON(!pgtable_pmd_page_ctor(phys_to_page(pa)));

View File

@@ -71,7 +71,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
#define __pte_free_tlb(tlb, pte, address) \ #define __pte_free_tlb(tlb, pte, address) \
do { \ do { \
pgtable_page_dtor(pte); \ pgtable_pte_page_dtor(pte); \
tlb_remove_page(tlb, pte); \ tlb_remove_page(tlb, pte); \
} while (0) } while (0)

View File

@@ -94,7 +94,7 @@ static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
#define __pte_free_tlb(tlb, pte, addr) \ #define __pte_free_tlb(tlb, pte, addr) \
do { \ do { \
pgtable_page_dtor((pte)); \ pgtable_pte_page_dtor((pte)); \
tlb_remove_page((tlb), (pte)); \ tlb_remove_page((tlb), (pte)); \
} while (0) } while (0)

View File

@@ -71,19 +71,6 @@ void __init mem_init(void)
init_mm.context.ptbase = __pa(init_mm.pgd); init_mm.context.ptbase = __pa(init_mm.pgd);
} }
/*
* free_initrd_mem - frees... initrd memory.
* @start - start of init memory
* @end - end of init memory
*
* Apparently has to be passed the address of the initrd memory.
*
* Wrapped by #ifdef CONFIG_BLKDEV_INITRD
*/
void free_initrd_mem(unsigned long start, unsigned long end)
{
}
void sync_icache_dcache(pte_t pte) void sync_icache_dcache(pte_t pte)
{ {
unsigned long addr; unsigned long addr;

View File

@@ -41,7 +41,7 @@ extern inline pmd_t *pmd_alloc_kernel(pgd_t *pgd, unsigned long address)
static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page, static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page,
unsigned long address) unsigned long address)
{ {
pgtable_page_dtor(page); pgtable_pte_page_dtor(page);
__free_page(page); __free_page(page);
} }
@@ -54,7 +54,7 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm)
if (!page) if (!page)
return NULL; return NULL;
if (!pgtable_page_ctor(page)) { if (!pgtable_pte_page_ctor(page)) {
__free_page(page); __free_page(page);
return NULL; return NULL;
} }
@@ -73,7 +73,7 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm)
static inline void pte_free(struct mm_struct *mm, struct page *page) static inline void pte_free(struct mm_struct *mm, struct page *page)
{ {
pgtable_page_dtor(page); pgtable_pte_page_dtor(page);
__free_page(page); __free_page(page);
} }

View File

@@ -36,7 +36,7 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm)
page = alloc_pages(GFP_KERNEL|__GFP_ZERO, 0); page = alloc_pages(GFP_KERNEL|__GFP_ZERO, 0);
if(!page) if(!page)
return NULL; return NULL;
if (!pgtable_page_ctor(page)) { if (!pgtable_pte_page_ctor(page)) {
__free_page(page); __free_page(page);
return NULL; return NULL;
} }
@@ -51,7 +51,7 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm)
static inline void pte_free(struct mm_struct *mm, pgtable_t page) static inline void pte_free(struct mm_struct *mm, pgtable_t page)
{ {
pgtable_page_dtor(page); pgtable_pte_page_dtor(page);
cache_page(kmap(page)); cache_page(kmap(page));
kunmap(page); kunmap(page);
__free_page(page); __free_page(page);
@@ -60,7 +60,7 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t page)
static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page, static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page,
unsigned long address) unsigned long address)
{ {
pgtable_page_dtor(page); pgtable_pte_page_dtor(page);
cache_page(kmap(page)); cache_page(kmap(page));
kunmap(page); kunmap(page);
__free_page(page); __free_page(page);

View File

@@ -21,7 +21,7 @@ extern const char bad_pmd_string[];
#define __pte_free_tlb(tlb,pte,addr) \ #define __pte_free_tlb(tlb,pte,addr) \
do { \ do { \
pgtable_page_dtor(pte); \ pgtable_pte_page_dtor(pte); \
tlb_remove_page((tlb), pte); \ tlb_remove_page((tlb), pte); \
} while (0) } while (0)

View File

@@ -54,7 +54,7 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
#define __pte_free_tlb(tlb,pte,address) \ #define __pte_free_tlb(tlb,pte,address) \
do { \ do { \
pgtable_page_dtor(pte); \ pgtable_pte_page_dtor(pte); \
tlb_remove_page((tlb), pte); \ tlb_remove_page((tlb), pte); \
} while (0) } while (0)

View File

@@ -95,6 +95,9 @@
#define MADV_WIPEONFORK 18 /* Zero memory on fork, child only */ #define MADV_WIPEONFORK 18 /* Zero memory on fork, child only */
#define MADV_KEEPONFORK 19 /* Undo MADV_WIPEONFORK */ #define MADV_KEEPONFORK 19 /* Undo MADV_WIPEONFORK */
#define MADV_COLD 20 /* deactivate these pages */
#define MADV_PAGEOUT 21 /* reclaim these pages */
/* compatibility flags */ /* compatibility flags */
#define MAP_FILE 0 #define MAP_FILE 0

View File

@@ -41,7 +41,7 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
#define __pte_free_tlb(tlb, pte, addr) \ #define __pte_free_tlb(tlb, pte, addr) \
do { \ do { \
pgtable_page_dtor(pte); \ pgtable_pte_page_dtor(pte); \
tlb_remove_page((tlb), (pte)); \ tlb_remove_page((tlb), (pte)); \
} while (0) } while (0)

View File

@@ -75,7 +75,7 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm)
if (!pte) if (!pte)
return NULL; return NULL;
clear_page(page_address(pte)); clear_page(page_address(pte));
if (!pgtable_page_ctor(pte)) { if (!pgtable_pte_page_ctor(pte)) {
__free_page(pte); __free_page(pte);
return NULL; return NULL;
} }
@@ -89,13 +89,13 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
static inline void pte_free(struct mm_struct *mm, struct page *pte) static inline void pte_free(struct mm_struct *mm, struct page *pte)
{ {
pgtable_page_dtor(pte); pgtable_pte_page_dtor(pte);
__free_page(pte); __free_page(pte);
} }
#define __pte_free_tlb(tlb, pte, addr) \ #define __pte_free_tlb(tlb, pte, addr) \
do { \ do { \
pgtable_page_dtor(pte); \ pgtable_pte_page_dtor(pte); \
tlb_remove_page((tlb), (pte)); \ tlb_remove_page((tlb), (pte)); \
} while (0) } while (0)

View File

@@ -48,6 +48,9 @@
#define MADV_DONTFORK 10 /* don't inherit across fork */ #define MADV_DONTFORK 10 /* don't inherit across fork */
#define MADV_DOFORK 11 /* do inherit across fork */ #define MADV_DOFORK 11 /* do inherit across fork */
#define MADV_COLD 20 /* deactivate these pages */
#define MADV_PAGEOUT 21 /* reclaim these pages */
#define MADV_MERGEABLE 65 /* KSM may merge identical pages */ #define MADV_MERGEABLE 65 /* KSM may merge identical pages */
#define MADV_UNMERGEABLE 66 /* KSM may not merge identical pages */ #define MADV_UNMERGEABLE 66 /* KSM may not merge identical pages */

View File

@@ -25,7 +25,7 @@ void pte_frag_destroy(void *pte_frag)
count = ((unsigned long)pte_frag & ~PAGE_MASK) >> PTE_FRAG_SIZE_SHIFT; count = ((unsigned long)pte_frag & ~PAGE_MASK) >> PTE_FRAG_SIZE_SHIFT;
/* We allow PTE_FRAG_NR fragments from a PTE page */ /* We allow PTE_FRAG_NR fragments from a PTE page */
if (atomic_sub_and_test(PTE_FRAG_NR - count, &page->pt_frag_refcount)) { if (atomic_sub_and_test(PTE_FRAG_NR - count, &page->pt_frag_refcount)) {
pgtable_page_dtor(page); pgtable_pte_page_dtor(page);
__free_page(page); __free_page(page);
} }
} }
@@ -61,7 +61,7 @@ static pte_t *__alloc_for_ptecache(struct mm_struct *mm, int kernel)
page = alloc_page(PGALLOC_GFP | __GFP_ACCOUNT); page = alloc_page(PGALLOC_GFP | __GFP_ACCOUNT);
if (!page) if (!page)
return NULL; return NULL;
if (!pgtable_page_ctor(page)) { if (!pgtable_pte_page_ctor(page)) {
__free_page(page); __free_page(page);
return NULL; return NULL;
} }
@@ -113,7 +113,7 @@ void pte_fragment_free(unsigned long *table, int kernel)
BUG_ON(atomic_read(&page->pt_frag_refcount) <= 0); BUG_ON(atomic_read(&page->pt_frag_refcount) <= 0);
if (atomic_dec_and_test(&page->pt_frag_refcount)) { if (atomic_dec_and_test(&page->pt_frag_refcount)) {
if (!kernel) if (!kernel)
pgtable_page_dtor(page); pgtable_pte_page_dtor(page);
__free_page(page); __free_page(page);
} }
} }

View File

@@ -78,7 +78,7 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
#define __pte_free_tlb(tlb, pte, buf) \ #define __pte_free_tlb(tlb, pte, buf) \
do { \ do { \
pgtable_page_dtor(pte); \ pgtable_pte_page_dtor(pte); \
tlb_remove_page((tlb), pte); \ tlb_remove_page((tlb), pte); \
} while (0) } while (0)

View File

@@ -210,7 +210,7 @@ unsigned long *page_table_alloc(struct mm_struct *mm)
page = alloc_page(GFP_KERNEL); page = alloc_page(GFP_KERNEL);
if (!page) if (!page)
return NULL; return NULL;
if (!pgtable_page_ctor(page)) { if (!pgtable_pte_page_ctor(page)) {
__free_page(page); __free_page(page);
return NULL; return NULL;
} }
@@ -256,7 +256,7 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
atomic_xor_bits(&page->_refcount, 3U << 24); atomic_xor_bits(&page->_refcount, 3U << 24);
} }
pgtable_page_dtor(page); pgtable_pte_page_dtor(page);
__free_page(page); __free_page(page);
} }
@@ -308,7 +308,7 @@ void __tlb_remove_table(void *_table)
case 3: /* 4K page table with pgstes */ case 3: /* 4K page table with pgstes */
if (mask & 3) if (mask & 3)
atomic_xor_bits(&page->_refcount, 3 << 24); atomic_xor_bits(&page->_refcount, 3 << 24);
pgtable_page_dtor(page); pgtable_pte_page_dtor(page);
__free_page(page); __free_page(page);
break; break;
} }

View File

@@ -29,7 +29,7 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
#define __pte_free_tlb(tlb,pte,addr) \ #define __pte_free_tlb(tlb,pte,addr) \
do { \ do { \
pgtable_page_dtor(pte); \ pgtable_pte_page_dtor(pte); \
tlb_remove_page((tlb), (pte)); \ tlb_remove_page((tlb), (pte)); \
} while (0) } while (0)

View File

@@ -1078,7 +1078,7 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma,
} }
#define io_remap_pfn_range io_remap_pfn_range #define io_remap_pfn_range io_remap_pfn_range
static inline unsigned long untagged_addr(unsigned long start) static inline unsigned long __untagged_addr(unsigned long start)
{ {
if (adi_capable()) { if (adi_capable()) {
long addr = start; long addr = start;
@@ -1098,7 +1098,8 @@ static inline unsigned long untagged_addr(unsigned long start)
return start; return start;
} }
#define untagged_addr untagged_addr #define untagged_addr(addr) \
((__typeof__(addr))(__untagged_addr((unsigned long)(addr))))
static inline bool pte_access_permitted(pte_t pte, bool write) static inline bool pte_access_permitted(pte_t pte, bool write)
{ {

View File

@@ -2903,7 +2903,7 @@ pgtable_t pte_alloc_one(struct mm_struct *mm)
struct page *page = alloc_page(GFP_KERNEL | __GFP_ZERO); struct page *page = alloc_page(GFP_KERNEL | __GFP_ZERO);
if (!page) if (!page)
return NULL; return NULL;
if (!pgtable_page_ctor(page)) { if (!pgtable_pte_page_ctor(page)) {
free_unref_page(page); free_unref_page(page);
return NULL; return NULL;
} }
@@ -2919,7 +2919,7 @@ static void __pte_free(pgtable_t pte)
{ {
struct page *page = virt_to_page(pte); struct page *page = virt_to_page(pte);
pgtable_page_dtor(page); pgtable_pte_page_dtor(page);
__free_page(page); __free_page(page);
} }

View File

@@ -378,7 +378,7 @@ pgtable_t pte_alloc_one(struct mm_struct *mm)
if ((pte = (unsigned long)pte_alloc_one_kernel(mm)) == 0) if ((pte = (unsigned long)pte_alloc_one_kernel(mm)) == 0)
return NULL; return NULL;
page = pfn_to_page(__nocache_pa(pte) >> PAGE_SHIFT); page = pfn_to_page(__nocache_pa(pte) >> PAGE_SHIFT);
if (!pgtable_page_ctor(page)) { if (!pgtable_pte_page_ctor(page)) {
__free_page(page); __free_page(page);
return NULL; return NULL;
} }
@@ -389,7 +389,7 @@ void pte_free(struct mm_struct *mm, pgtable_t pte)
{ {
unsigned long p; unsigned long p;
pgtable_page_dtor(pte); pgtable_pte_page_dtor(pte);
p = (unsigned long)page_address(pte); /* Cached address (for test) */ p = (unsigned long)page_address(pte); /* Cached address (for test) */
if (p == 0) if (p == 0)
BUG(); BUG();

View File

@@ -29,7 +29,7 @@ extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
#define __pte_free_tlb(tlb,pte, address) \ #define __pte_free_tlb(tlb,pte, address) \
do { \ do { \
pgtable_page_dtor(pte); \ pgtable_pte_page_dtor(pte); \
tlb_remove_page((tlb),(pte)); \ tlb_remove_page((tlb),(pte)); \
} while (0) } while (0)

View File

@@ -15,7 +15,7 @@
#define __pte_free_tlb(tlb, pte, addr) \ #define __pte_free_tlb(tlb, pte, addr) \
do { \ do { \
pgtable_page_dtor(pte); \ pgtable_pte_page_dtor(pte); \
tlb_remove_page((tlb), (pte)); \ tlb_remove_page((tlb), (pte)); \
} while (0) } while (0)

View File

@@ -54,23 +54,10 @@ static u64 get_subtree_max_end(struct rb_node *node)
return ret; return ret;
} }
static u64 compute_subtree_max_end(struct memtype *data) #define NODE_END(node) ((node)->end)
{
u64 max_end = data->end, child_max_end;
child_max_end = get_subtree_max_end(data->rb.rb_right); RB_DECLARE_CALLBACKS_MAX(static, memtype_rb_augment_cb,
if (child_max_end > max_end) struct memtype, rb, u64, subtree_max_end, NODE_END)
max_end = child_max_end;
child_max_end = get_subtree_max_end(data->rb.rb_left);
if (child_max_end > max_end)
max_end = child_max_end;
return max_end;
}
RB_DECLARE_CALLBACKS(static, memtype_rb_augment_cb, struct memtype, rb,
u64, subtree_max_end, compute_subtree_max_end)
/* Find the first (lowest start addr) overlapping range from rb tree */ /* Find the first (lowest start addr) overlapping range from rb tree */
static struct memtype *memtype_rb_lowest_match(struct rb_root *root, static struct memtype *memtype_rb_lowest_match(struct rb_root *root,

View File

@@ -45,7 +45,7 @@ early_param("userpte", setup_userpte);
void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte) void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
{ {
pgtable_page_dtor(pte); pgtable_pte_page_dtor(pte);
paravirt_release_pte(page_to_pfn(pte)); paravirt_release_pte(page_to_pfn(pte));
paravirt_tlb_remove_table(tlb, pte); paravirt_tlb_remove_table(tlb, pte);
} }

View File

@@ -55,7 +55,7 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm)
if (!pte) if (!pte)
return NULL; return NULL;
page = virt_to_page(pte); page = virt_to_page(pte);
if (!pgtable_page_ctor(page)) { if (!pgtable_pte_page_ctor(page)) {
__free_page(page); __free_page(page);
return NULL; return NULL;
} }
@@ -69,7 +69,7 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
static inline void pte_free(struct mm_struct *mm, pgtable_t pte) static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
{ {
pgtable_page_dtor(pte); pgtable_pte_page_dtor(pte);
__free_page(pte); __free_page(pte);
} }
#define pmd_pgtable(pmd) pmd_page(pmd) #define pmd_pgtable(pmd) pmd_page(pmd)

View File

@@ -103,6 +103,9 @@
#define MADV_WIPEONFORK 18 /* Zero memory on fork, child only */ #define MADV_WIPEONFORK 18 /* Zero memory on fork, child only */
#define MADV_KEEPONFORK 19 /* Undo MADV_WIPEONFORK */ #define MADV_KEEPONFORK 19 /* Undo MADV_WIPEONFORK */
#define MADV_COLD 20 /* deactivate these pages */
#define MADV_PAGEOUT 21 /* reclaim these pages */
/* compatibility flags */ /* compatibility flags */
#define MAP_FILE 0 #define MAP_FILE 0

View File

@@ -13,33 +13,10 @@ sector_t interval_end(struct rb_node *node)
return this->end; return this->end;
} }
/** #define NODE_END(node) ((node)->sector + ((node)->size >> 9))
* compute_subtree_last - compute end of @node
*
* The end of an interval is the highest (start + (size >> 9)) value of this
* node and of its children. Called for @node and its parents whenever the end
* may have changed.
*/
static inline sector_t
compute_subtree_last(struct drbd_interval *node)
{
sector_t max = node->sector + (node->size >> 9);
if (node->rb.rb_left) { RB_DECLARE_CALLBACKS_MAX(static, augment_callbacks,
sector_t left = interval_end(node->rb.rb_left); struct drbd_interval, rb, sector_t, end, NODE_END);
if (left > max)
max = left;
}
if (node->rb.rb_right) {
sector_t right = interval_end(node->rb.rb_right);
if (right > max)
max = right;
}
return max;
}
RB_DECLARE_CALLBACKS(static, augment_callbacks, struct drbd_interval, rb,
sector_t, end, compute_subtree_last);
/** /**
* drbd_insert_interval - insert a new interval into a tree * drbd_insert_interval - insert a new interval into a tree

View File

@@ -1103,7 +1103,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
alloc_flags = 0; alloc_flags = 0;
if (!offset || !*offset) if (!offset || !*offset)
return -EINVAL; return -EINVAL;
user_addr = *offset; user_addr = untagged_addr(*offset);
} else if (flags & (ALLOC_MEM_FLAGS_DOORBELL | } else if (flags & (ALLOC_MEM_FLAGS_DOORBELL |
ALLOC_MEM_FLAGS_MMIO_REMAP)) { ALLOC_MEM_FLAGS_MMIO_REMAP)) {
domain = AMDGPU_GEM_DOMAIN_GTT; domain = AMDGPU_GEM_DOMAIN_GTT;

View File

@@ -291,6 +291,8 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data,
uint32_t handle; uint32_t handle;
int r; int r;
args->addr = untagged_addr(args->addr);
if (offset_in_page(args->addr | args->size)) if (offset_in_page(args->addr | args->size))
return -EINVAL; return -EINVAL;

View File

@@ -296,6 +296,8 @@ int radeon_gem_userptr_ioctl(struct drm_device *dev, void *data,
uint32_t handle; uint32_t handle;
int r; int r;
args->addr = untagged_addr(args->addr);
if (offset_in_page(args->addr | args->size)) if (offset_in_page(args->addr | args->size))
return -EINVAL; return -EINVAL;

View File

@@ -1041,7 +1041,7 @@ int hfi1_verbs_send_pio(struct rvt_qp *qp, struct hfi1_pkt_state *ps,
if (cb) if (cb)
iowait_pio_inc(&priv->s_iowait); iowait_pio_inc(&priv->s_iowait);
pbuf = sc_buffer_alloc(sc, plen, cb, qp); pbuf = sc_buffer_alloc(sc, plen, cb, qp);
if (unlikely(IS_ERR_OR_NULL(pbuf))) { if (IS_ERR_OR_NULL(pbuf)) {
if (cb) if (cb)
verbs_pio_complete(qp, 0); verbs_pio_complete(qp, 0);
if (IS_ERR(pbuf)) { if (IS_ERR(pbuf)) {

View File

@@ -157,6 +157,7 @@ static void videobuf_dma_contig_user_put(struct videobuf_dma_contig_memory *mem)
static int videobuf_dma_contig_user_get(struct videobuf_dma_contig_memory *mem, static int videobuf_dma_contig_user_get(struct videobuf_dma_contig_memory *mem,
struct videobuf_buffer *vb) struct videobuf_buffer *vb)
{ {
unsigned long untagged_baddr = untagged_addr(vb->baddr);
struct mm_struct *mm = current->mm; struct mm_struct *mm = current->mm;
struct vm_area_struct *vma; struct vm_area_struct *vma;
unsigned long prev_pfn, this_pfn; unsigned long prev_pfn, this_pfn;
@@ -164,22 +165,22 @@ static int videobuf_dma_contig_user_get(struct videobuf_dma_contig_memory *mem,
unsigned int offset; unsigned int offset;
int ret; int ret;
offset = vb->baddr & ~PAGE_MASK; offset = untagged_baddr & ~PAGE_MASK;
mem->size = PAGE_ALIGN(vb->size + offset); mem->size = PAGE_ALIGN(vb->size + offset);
ret = -EINVAL; ret = -EINVAL;
down_read(&mm->mmap_sem); down_read(&mm->mmap_sem);
vma = find_vma(mm, vb->baddr); vma = find_vma(mm, untagged_baddr);
if (!vma) if (!vma)
goto out_up; goto out_up;
if ((vb->baddr + mem->size) > vma->vm_end) if ((untagged_baddr + mem->size) > vma->vm_end)
goto out_up; goto out_up;
pages_done = 0; pages_done = 0;
prev_pfn = 0; /* kill warning */ prev_pfn = 0; /* kill warning */
user_address = vb->baddr; user_address = untagged_baddr;
while (pages_done < (mem->size >> PAGE_SHIFT)) { while (pages_done < (mem->size >> PAGE_SHIFT)) {
ret = follow_pfn(vma, user_address, &this_pfn); ret = follow_pfn(vma, user_address, &this_pfn);

View File

@@ -654,8 +654,7 @@ void i2400m_tx_close(struct i2400m *i2400m)
padding = aligned_size - tx_msg_moved->size; padding = aligned_size - tx_msg_moved->size;
if (padding > 0) { if (padding > 0) {
pad_buf = i2400m_tx_fifo_push(i2400m, padding, 0, 0); pad_buf = i2400m_tx_fifo_push(i2400m, padding, 0, 0);
if (unlikely(WARN_ON(pad_buf == NULL if (WARN_ON(pad_buf == NULL || pad_buf == TAIL_FULL)) {
|| pad_buf == TAIL_FULL))) {
/* This should not happen -- append should verify /* This should not happen -- append should verify
* there is always space left at least to append * there is always space left at least to append
* tx_block_size */ * tx_block_size */

View File

@@ -254,6 +254,7 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
shm->teedev = teedev; shm->teedev = teedev;
shm->ctx = ctx; shm->ctx = ctx;
shm->id = -1; shm->id = -1;
addr = untagged_addr(addr);
start = rounddown(addr, PAGE_SIZE); start = rounddown(addr, PAGE_SIZE);
shm->offset = addr - start; shm->offset = addr - start;
shm->size = length; shm->size = length;

View File

@@ -375,6 +375,8 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr,
down_read(&mm->mmap_sem); down_read(&mm->mmap_sem);
vaddr = untagged_addr(vaddr);
vma = find_vma_intersection(mm, vaddr, vaddr + 1); vma = find_vma_intersection(mm, vaddr, vaddr + 1);
if (vma && vma->vm_flags & VM_PFNMAP) { if (vma && vma->vm_flags & VM_PFNMAP) {

View File

@@ -247,7 +247,7 @@ static void xen_irq_info_cleanup(struct irq_info *info)
*/ */
unsigned int evtchn_from_irq(unsigned irq) unsigned int evtchn_from_irq(unsigned irq)
{ {
if (unlikely(WARN(irq >= nr_irqs, "Invalid irq %d!\n", irq))) if (WARN(irq >= nr_irqs, "Invalid irq %d!\n", irq))
return 0; return 0;
return info_for_irq(irq)->evtchn; return info_for_irq(irq)->evtchn;

View File

@@ -88,9 +88,7 @@ static int fat__get_entry(struct inode *dir, loff_t *pos,
int err, offset; int err, offset;
next: next:
if (*bh) brelse(*bh);
brelse(*bh);
*bh = NULL; *bh = NULL;
iblock = *pos >> sb->s_blocksize_bits; iblock = *pos >> sb->s_blocksize_bits;
err = fat_bmap(dir, iblock, &phys, &mapped_blocks, 0, false); err = fat_bmap(dir, iblock, &phys, &mapped_blocks, 0, false);

View File

@@ -3026,7 +3026,7 @@ void *copy_mount_options(const void __user * data)
* the remainder of the page. * the remainder of the page.
*/ */
/* copy_from_user cannot cross TASK_SIZE ! */ /* copy_from_user cannot cross TASK_SIZE ! */
size = TASK_SIZE - (unsigned long)data; size = TASK_SIZE - (unsigned long)untagged_addr(data);
if (size > PAGE_SIZE) if (size > PAGE_SIZE)
size = PAGE_SIZE; size = PAGE_SIZE;

View File

@@ -71,7 +71,7 @@ static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni)
} }
/* Read, map, and pin the page. */ /* Read, map, and pin the page. */
page = ntfs_map_page(mft_vi->i_mapping, index); page = ntfs_map_page(mft_vi->i_mapping, index);
if (likely(!IS_ERR(page))) { if (!IS_ERR(page)) {
/* Catch multi sector transfer fixup errors. */ /* Catch multi sector transfer fixup errors. */
if (likely(ntfs_is_mft_recordp((le32*)(page_address(page) + if (likely(ntfs_is_mft_recordp((le32*)(page_address(page) +
ofs)))) { ofs)))) {
@@ -154,7 +154,7 @@ MFT_RECORD *map_mft_record(ntfs_inode *ni)
mutex_lock(&ni->mrec_lock); mutex_lock(&ni->mrec_lock);
m = map_mft_record_page(ni); m = map_mft_record_page(ni);
if (likely(!IS_ERR(m))) if (!IS_ERR(m))
return m; return m;
mutex_unlock(&ni->mrec_lock); mutex_unlock(&ni->mrec_lock);
@@ -271,7 +271,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
m = map_mft_record(ni); m = map_mft_record(ni);
/* map_mft_record() has incremented this on success. */ /* map_mft_record() has incremented this on success. */
atomic_dec(&ni->count); atomic_dec(&ni->count);
if (likely(!IS_ERR(m))) { if (!IS_ERR(m)) {
/* Verify the sequence number. */ /* Verify the sequence number. */
if (likely(le16_to_cpu(m->sequence_number) == seq_no)) { if (likely(le16_to_cpu(m->sequence_number) == seq_no)) {
ntfs_debug("Done 1."); ntfs_debug("Done 1.");
@@ -1303,7 +1303,7 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol)
read_unlock_irqrestore(&mftbmp_ni->size_lock, flags); read_unlock_irqrestore(&mftbmp_ni->size_lock, flags);
rl = ntfs_attr_find_vcn_nolock(mftbmp_ni, rl = ntfs_attr_find_vcn_nolock(mftbmp_ni,
(ll - 1) >> vol->cluster_size_bits, NULL); (ll - 1) >> vol->cluster_size_bits, NULL);
if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) { if (IS_ERR(rl) || unlikely(!rl->length || rl->lcn < 0)) {
up_write(&mftbmp_ni->runlist.lock); up_write(&mftbmp_ni->runlist.lock);
ntfs_error(vol->sb, "Failed to determine last allocated " ntfs_error(vol->sb, "Failed to determine last allocated "
"cluster of mft bitmap attribute."); "cluster of mft bitmap attribute.");
@@ -1734,7 +1734,7 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol)
read_unlock_irqrestore(&mft_ni->size_lock, flags); read_unlock_irqrestore(&mft_ni->size_lock, flags);
rl = ntfs_attr_find_vcn_nolock(mft_ni, rl = ntfs_attr_find_vcn_nolock(mft_ni,
(ll - 1) >> vol->cluster_size_bits, NULL); (ll - 1) >> vol->cluster_size_bits, NULL);
if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) { if (IS_ERR(rl) || unlikely(!rl->length || rl->lcn < 0)) {
up_write(&mft_ni->runlist.lock); up_write(&mft_ni->runlist.lock);
ntfs_error(vol->sb, "Failed to determine last allocated " ntfs_error(vol->sb, "Failed to determine last allocated "
"cluster of mft data attribute."); "cluster of mft data attribute.");
@@ -1776,7 +1776,7 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol)
do { do {
rl2 = ntfs_cluster_alloc(vol, old_last_vcn, nr, lcn, MFT_ZONE, rl2 = ntfs_cluster_alloc(vol, old_last_vcn, nr, lcn, MFT_ZONE,
true); true);
if (likely(!IS_ERR(rl2))) if (!IS_ERR(rl2))
break; break;
if (PTR_ERR(rl2) != -ENOSPC || nr == min_nr) { if (PTR_ERR(rl2) != -ENOSPC || nr == min_nr) {
ntfs_error(vol->sb, "Failed to allocate the minimal " ntfs_error(vol->sb, "Failed to allocate the minimal "

View File

@@ -115,7 +115,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent,
dent_ino = MREF(mref); dent_ino = MREF(mref);
ntfs_debug("Found inode 0x%lx. Calling ntfs_iget.", dent_ino); ntfs_debug("Found inode 0x%lx. Calling ntfs_iget.", dent_ino);
dent_inode = ntfs_iget(vol->sb, dent_ino); dent_inode = ntfs_iget(vol->sb, dent_ino);
if (likely(!IS_ERR(dent_inode))) { if (!IS_ERR(dent_inode)) {
/* Consistency check. */ /* Consistency check. */
if (is_bad_inode(dent_inode) || MSEQNO(mref) == if (is_bad_inode(dent_inode) || MSEQNO(mref) ==
NTFS_I(dent_inode)->seq_no || NTFS_I(dent_inode)->seq_no ||

View File

@@ -951,7 +951,7 @@ mpa_err:
} }
/* Now combine the new and old runlists checking for overlaps. */ /* Now combine the new and old runlists checking for overlaps. */
old_rl = ntfs_runlists_merge(old_rl, rl); old_rl = ntfs_runlists_merge(old_rl, rl);
if (likely(!IS_ERR(old_rl))) if (!IS_ERR(old_rl))
return old_rl; return old_rl;
ntfs_free(rl); ntfs_free(rl);
ntfs_error(vol->sb, "Failed to merge runlists."); ntfs_error(vol->sb, "Failed to merge runlists.");

View File

@@ -1475,7 +1475,7 @@ not_enabled:
kfree(name); kfree(name);
/* Get the inode. */ /* Get the inode. */
tmp_ino = ntfs_iget(vol->sb, MREF(mref)); tmp_ino = ntfs_iget(vol->sb, MREF(mref));
if (unlikely(IS_ERR(tmp_ino) || is_bad_inode(tmp_ino))) { if (IS_ERR(tmp_ino) || unlikely(is_bad_inode(tmp_ino))) {
if (!IS_ERR(tmp_ino)) if (!IS_ERR(tmp_ino))
iput(tmp_ino); iput(tmp_ino);
ntfs_error(vol->sb, "Failed to load $UsnJrnl."); ntfs_error(vol->sb, "Failed to load $UsnJrnl.");

View File

@@ -776,7 +776,7 @@ static int do_dentry_open(struct file *f,
f->f_mode |= FMODE_ATOMIC_POS; f->f_mode |= FMODE_ATOMIC_POS;
f->f_op = fops_get(inode->i_fop); f->f_op = fops_get(inode->i_fop);
if (unlikely(WARN_ON(!f->f_op))) { if (WARN_ON(!f->f_op)) {
error = -ENODEV; error = -ENODEV;
goto cleanup_all; goto cleanup_all;
} }

View File

@@ -239,10 +239,8 @@ static int balance_leaf_when_delete_left(struct tree_balance *tb)
static int balance_leaf_when_delete(struct tree_balance *tb, int flag) static int balance_leaf_when_delete(struct tree_balance *tb, int flag)
{ {
struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
int item_pos = PATH_LAST_POSITION(tb->tb_path);
struct buffer_info bi; struct buffer_info bi;
int n; int n;
struct item_head *ih;
RFALSE(tb->FR[0] && B_LEVEL(tb->FR[0]) != DISK_LEAF_NODE_LEVEL + 1, RFALSE(tb->FR[0] && B_LEVEL(tb->FR[0]) != DISK_LEAF_NODE_LEVEL + 1,
"vs- 12000: level: wrong FR %z", tb->FR[0]); "vs- 12000: level: wrong FR %z", tb->FR[0]);
@@ -251,7 +249,6 @@ static int balance_leaf_when_delete(struct tree_balance *tb, int flag)
RFALSE(!tb->blknum[0] && !PATH_H_PPARENT(tb->tb_path, 0), RFALSE(!tb->blknum[0] && !PATH_H_PPARENT(tb->tb_path, 0),
"PAP-12010: tree can not be empty"); "PAP-12010: tree can not be empty");
ih = item_head(tbS0, item_pos);
buffer_info_init_tbS0(tb, &bi); buffer_info_init_tbS0(tb, &bi);
/* Delete or truncate the item */ /* Delete or truncate the item */
@@ -298,7 +295,6 @@ static unsigned int balance_leaf_insert_left(struct tree_balance *tb,
if (tb->item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) { if (tb->item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) {
/* part of new item falls into L[0] */ /* part of new item falls into L[0] */
int new_item_len, shift; int new_item_len, shift;
int version;
ret = leaf_shift_left(tb, tb->lnum[0] - 1, -1); ret = leaf_shift_left(tb, tb->lnum[0] - 1, -1);
@@ -317,8 +313,6 @@ static unsigned int balance_leaf_insert_left(struct tree_balance *tb,
leaf_insert_into_buf(&bi, n + tb->item_pos - ret, ih, body, leaf_insert_into_buf(&bi, n + tb->item_pos - ret, ih, body,
min_t(int, tb->zeroes_num, ih_item_len(ih))); min_t(int, tb->zeroes_num, ih_item_len(ih)));
version = ih_version(ih);
/* /*
* Calculate key component, item length and body to * Calculate key component, item length and body to
* insert into S[0] * insert into S[0]
@@ -632,7 +626,6 @@ static void balance_leaf_insert_right(struct tree_balance *tb,
struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
int n = B_NR_ITEMS(tbS0); int n = B_NR_ITEMS(tbS0);
struct buffer_info bi; struct buffer_info bi;
int ret;
/* new item or part of it doesn't fall into R[0] */ /* new item or part of it doesn't fall into R[0] */
if (n - tb->rnum[0] >= tb->item_pos) { if (n - tb->rnum[0] >= tb->item_pos) {
@@ -646,13 +639,11 @@ static void balance_leaf_insert_right(struct tree_balance *tb,
if (tb->item_pos == n - tb->rnum[0] + 1 && tb->rbytes != -1) { if (tb->item_pos == n - tb->rnum[0] + 1 && tb->rbytes != -1) {
loff_t old_key_comp, old_len, r_zeroes_number; loff_t old_key_comp, old_len, r_zeroes_number;
const char *r_body; const char *r_body;
int version, shift; int shift;
loff_t offset; loff_t offset;
leaf_shift_right(tb, tb->rnum[0] - 1, -1); leaf_shift_right(tb, tb->rnum[0] - 1, -1);
version = ih_version(ih);
/* Remember key component and item length */ /* Remember key component and item length */
old_key_comp = le_ih_k_offset(ih); old_key_comp = le_ih_k_offset(ih);
old_len = ih_item_len(ih); old_len = ih_item_len(ih);
@@ -698,7 +689,7 @@ static void balance_leaf_insert_right(struct tree_balance *tb,
/* whole new item falls into R[0] */ /* whole new item falls into R[0] */
/* Shift rnum[0]-1 items to R[0] */ /* Shift rnum[0]-1 items to R[0] */
ret = leaf_shift_right(tb, tb->rnum[0] - 1, tb->rbytes); leaf_shift_right(tb, tb->rnum[0] - 1, tb->rbytes);
/* Insert new item into R[0] */ /* Insert new item into R[0] */
buffer_info_init_right(tb, &bi); buffer_info_init_right(tb, &bi);
@@ -950,14 +941,12 @@ static void balance_leaf_new_nodes_insert(struct tree_balance *tb,
if (tb->item_pos == n - tb->snum[i] + 1 && tb->sbytes[i] != -1) { if (tb->item_pos == n - tb->snum[i] + 1 && tb->sbytes[i] != -1) {
int old_key_comp, old_len, r_zeroes_number; int old_key_comp, old_len, r_zeroes_number;
const char *r_body; const char *r_body;
int version;
/* Move snum[i]-1 items from S[0] to S_new[i] */ /* Move snum[i]-1 items from S[0] to S_new[i] */
leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i] - 1, -1, leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i] - 1, -1,
tb->S_new[i]); tb->S_new[i]);
/* Remember key component and item length */ /* Remember key component and item length */
version = ih_version(ih);
old_key_comp = le_ih_k_offset(ih); old_key_comp = le_ih_k_offset(ih);
old_len = ih_item_len(ih); old_len = ih_item_len(ih);

View File

@@ -376,7 +376,6 @@ static int get_num_ver(int mode, struct tree_balance *tb, int h,
int to, int to_bytes, short *snum012, int flow) int to, int to_bytes, short *snum012, int flow)
{ {
int i; int i;
int cur_free;
int units; int units;
struct virtual_node *vn = tb->tb_vn; struct virtual_node *vn = tb->tb_vn;
int total_node_size, max_node_size, current_item_size; int total_node_size, max_node_size, current_item_size;
@@ -438,7 +437,6 @@ static int get_num_ver(int mode, struct tree_balance *tb, int h,
/* leaf level */ /* leaf level */
needed_nodes = 1; needed_nodes = 1;
total_node_size = 0; total_node_size = 0;
cur_free = max_node_size;
/* start from 'from'-th item */ /* start from 'from'-th item */
start_item = from; start_item = from;
@@ -1734,14 +1732,12 @@ static int dc_check_balance_internal(struct tree_balance *tb, int h)
* and Fh is its father. * and Fh is its father.
*/ */
struct buffer_head *Sh, *Fh; struct buffer_head *Sh, *Fh;
int maxsize, ret; int ret;
int lfree, rfree /* free space in L and R */ ; int lfree, rfree /* free space in L and R */ ;
Sh = PATH_H_PBUFFER(tb->tb_path, h); Sh = PATH_H_PBUFFER(tb->tb_path, h);
Fh = PATH_H_PPARENT(tb->tb_path, h); Fh = PATH_H_PPARENT(tb->tb_path, h);
maxsize = MAX_CHILD_SIZE(Sh);
/* /*
* using tb->insert_size[h], which is negative in this case, * using tb->insert_size[h], which is negative in this case,
* create_virtual_node calculates: * create_virtual_node calculates:

View File

@@ -891,7 +891,6 @@ static int flush_older_commits(struct super_block *s,
struct list_head *entry; struct list_head *entry;
unsigned int trans_id = jl->j_trans_id; unsigned int trans_id = jl->j_trans_id;
unsigned int other_trans_id; unsigned int other_trans_id;
unsigned int first_trans_id;
find_first: find_first:
/* /*
@@ -914,8 +913,6 @@ find_first:
return 0; return 0;
} }
first_trans_id = first_jl->j_trans_id;
entry = &first_jl->j_list; entry = &first_jl->j_list;
while (1) { while (1) {
other_jl = JOURNAL_LIST_ENTRY(entry); other_jl = JOURNAL_LIST_ENTRY(entry);
@@ -1351,7 +1348,7 @@ static int flush_journal_list(struct super_block *s,
struct reiserfs_journal_list *jl, int flushall) struct reiserfs_journal_list *jl, int flushall)
{ {
struct reiserfs_journal_list *pjl; struct reiserfs_journal_list *pjl;
struct reiserfs_journal_cnode *cn, *last; struct reiserfs_journal_cnode *cn;
int count; int count;
int was_jwait = 0; int was_jwait = 0;
int was_dirty = 0; int was_dirty = 0;
@@ -1509,7 +1506,6 @@ static int flush_journal_list(struct super_block *s,
b_blocknr, __func__); b_blocknr, __func__);
} }
free_cnode: free_cnode:
last = cn;
cn = cn->next; cn = cn->next;
if (saved_bh) { if (saved_bh) {
/* /*
@@ -1792,7 +1788,6 @@ static int flush_used_journal_lists(struct super_block *s,
{ {
unsigned long len = 0; unsigned long len = 0;
unsigned long cur_len; unsigned long cur_len;
int ret;
int i; int i;
int limit = 256; int limit = 256;
struct reiserfs_journal_list *tjl; struct reiserfs_journal_list *tjl;
@@ -1829,9 +1824,9 @@ static int flush_used_journal_lists(struct super_block *s,
* transactions, but only bother if we've actually spanned * transactions, but only bother if we've actually spanned
* across multiple lists * across multiple lists
*/ */
if (flush_jl != jl) { if (flush_jl != jl)
ret = kupdate_transactions(s, jl, &tjl, &trans_id, len, i); kupdate_transactions(s, jl, &tjl, &trans_id, len, i);
}
flush_journal_list(s, flush_jl, 1); flush_journal_list(s, flush_jl, 1);
put_journal_list(s, flush_jl); put_journal_list(s, flush_jl);
put_journal_list(s, jl); put_journal_list(s, jl);
@@ -1911,7 +1906,6 @@ static int do_journal_release(struct reiserfs_transaction_handle *th,
struct super_block *sb, int error) struct super_block *sb, int error)
{ {
struct reiserfs_transaction_handle myth; struct reiserfs_transaction_handle myth;
int flushed = 0;
struct reiserfs_journal *journal = SB_JOURNAL(sb); struct reiserfs_journal *journal = SB_JOURNAL(sb);
/* /*
@@ -1933,7 +1927,6 @@ static int do_journal_release(struct reiserfs_transaction_handle *th,
1); 1);
journal_mark_dirty(&myth, SB_BUFFER_WITH_SB(sb)); journal_mark_dirty(&myth, SB_BUFFER_WITH_SB(sb));
do_journal_end(&myth, FLUSH_ALL); do_journal_end(&myth, FLUSH_ALL);
flushed = 1;
} }
} }
@@ -3444,9 +3437,8 @@ static int remove_from_transaction(struct super_block *sb,
if (cn == journal->j_last) { if (cn == journal->j_last) {
journal->j_last = cn->prev; journal->j_last = cn->prev;
} }
if (bh) remove_journal_hash(sb, journal->j_hash_table, NULL,
remove_journal_hash(sb, journal->j_hash_table, NULL, bh->b_blocknr, 0);
bh->b_blocknr, 0);
clear_buffer_journaled(bh); /* don't log this one */ clear_buffer_journaled(bh); /* don't log this one */
if (!already_cleaned) { if (!already_cleaned) {
@@ -3988,7 +3980,6 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, int flags)
struct buffer_head *c_bh; /* commit bh */ struct buffer_head *c_bh; /* commit bh */
struct buffer_head *d_bh; /* desc bh */ struct buffer_head *d_bh; /* desc bh */
int cur_write_start = 0; /* start index of current log write */ int cur_write_start = 0; /* start index of current log write */
int old_start;
int i; int i;
int flush; int flush;
int wait_on_commit; int wait_on_commit;
@@ -4245,7 +4236,6 @@ static int do_journal_end(struct reiserfs_transaction_handle *th, int flags)
journal->j_num_work_lists++; journal->j_num_work_lists++;
/* reset journal values for the next transaction */ /* reset journal values for the next transaction */
old_start = journal->j_start;
journal->j_start = journal->j_start =
(journal->j_start + journal->j_len + (journal->j_start + journal->j_len +
2) % SB_ONDISK_JOURNAL_SIZE(sb); 2) % SB_ONDISK_JOURNAL_SIZE(sb);

View File

@@ -1322,7 +1322,7 @@ void leaf_paste_entries(struct buffer_info *bi,
char *item; char *item;
struct reiserfs_de_head *deh; struct reiserfs_de_head *deh;
char *insert_point; char *insert_point;
int i, old_entry_num; int i;
struct buffer_head *bh = bi->bi_bh; struct buffer_head *bh = bi->bi_bh;
if (new_entry_count == 0) if (new_entry_count == 0)
@@ -1362,7 +1362,6 @@ void leaf_paste_entries(struct buffer_info *bi,
put_deh_location(&deh[i], put_deh_location(&deh[i],
deh_location(&deh[i]) + paste_size); deh_location(&deh[i]) + paste_size);
old_entry_num = ih_entry_count(ih);
put_ih_entry_count(ih, ih_entry_count(ih) + new_entry_count); put_ih_entry_count(ih, ih_entry_count(ih) + new_entry_count);
/* prepare space for pasted records */ /* prepare space for pasted records */

View File

@@ -183,13 +183,12 @@ int reiserfs_convert_objectid_map_v1(struct super_block *s)
int new_size = (s->s_blocksize - SB_SIZE) / sizeof(__u32) / 2 * 2; int new_size = (s->s_blocksize - SB_SIZE) / sizeof(__u32) / 2 * 2;
int old_max = sb_oid_maxsize(disk_sb); int old_max = sb_oid_maxsize(disk_sb);
struct reiserfs_super_block_v1 *disk_sb_v1; struct reiserfs_super_block_v1 *disk_sb_v1;
__le32 *objectid_map, *new_objectid_map; __le32 *objectid_map;
int i; int i;
disk_sb_v1 = disk_sb_v1 =
(struct reiserfs_super_block_v1 *)(SB_BUFFER_WITH_SB(s)->b_data); (struct reiserfs_super_block_v1 *)(SB_BUFFER_WITH_SB(s)->b_data);
objectid_map = (__le32 *) (disk_sb_v1 + 1); objectid_map = (__le32 *) (disk_sb_v1 + 1);
new_objectid_map = (__le32 *) (disk_sb + 1);
if (cur_size > new_size) { if (cur_size > new_size) {
/* /*

View File

@@ -746,9 +746,6 @@ static void check_leaf_block_head(struct buffer_head *bh)
static void check_internal_block_head(struct buffer_head *bh) static void check_internal_block_head(struct buffer_head *bh)
{ {
struct block_head *blkh;
blkh = B_BLK_HEAD(bh);
if (!(B_LEVEL(bh) > DISK_LEAF_NODE_LEVEL && B_LEVEL(bh) <= MAX_HEIGHT)) if (!(B_LEVEL(bh) > DISK_LEAF_NODE_LEVEL && B_LEVEL(bh) <= MAX_HEIGHT))
reiserfs_panic(NULL, "vs-6025", "invalid level %z", bh); reiserfs_panic(NULL, "vs-6025", "invalid level %z", bh);

View File

@@ -593,7 +593,6 @@ int search_by_key(struct super_block *sb, const struct cpu_key *key,
struct buffer_head *bh; struct buffer_head *bh;
struct path_element *last_element; struct path_element *last_element;
int node_level, retval; int node_level, retval;
int right_neighbor_of_leaf_node;
int fs_gen; int fs_gen;
struct buffer_head *reada_bh[SEARCH_BY_KEY_READA]; struct buffer_head *reada_bh[SEARCH_BY_KEY_READA];
b_blocknr_t reada_blocks[SEARCH_BY_KEY_READA]; b_blocknr_t reada_blocks[SEARCH_BY_KEY_READA];
@@ -614,8 +613,6 @@ int search_by_key(struct super_block *sb, const struct cpu_key *key,
pathrelse(search_path); pathrelse(search_path);
right_neighbor_of_leaf_node = 0;
/* /*
* With each iteration of this loop we search through the items in the * With each iteration of this loop we search through the items in the
* current node, and calculate the next current node(next path element) * current node, and calculate the next current node(next path element)
@@ -701,7 +698,6 @@ io_error:
*/ */
block_number = SB_ROOT_BLOCK(sb); block_number = SB_ROOT_BLOCK(sb);
expected_level = -1; expected_level = -1;
right_neighbor_of_leaf_node = 0;
/* repeat search from the root */ /* repeat search from the root */
continue; continue;

View File

@@ -1272,21 +1272,23 @@ static __always_inline void wake_userfault(struct userfaultfd_ctx *ctx,
} }
static __always_inline int validate_range(struct mm_struct *mm, static __always_inline int validate_range(struct mm_struct *mm,
__u64 start, __u64 len) __u64 *start, __u64 len)
{ {
__u64 task_size = mm->task_size; __u64 task_size = mm->task_size;
if (start & ~PAGE_MASK) *start = untagged_addr(*start);
if (*start & ~PAGE_MASK)
return -EINVAL; return -EINVAL;
if (len & ~PAGE_MASK) if (len & ~PAGE_MASK)
return -EINVAL; return -EINVAL;
if (!len) if (!len)
return -EINVAL; return -EINVAL;
if (start < mmap_min_addr) if (*start < mmap_min_addr)
return -EINVAL; return -EINVAL;
if (start >= task_size) if (*start >= task_size)
return -EINVAL; return -EINVAL;
if (len > task_size - start) if (len > task_size - *start)
return -EINVAL; return -EINVAL;
return 0; return 0;
} }
@@ -1336,7 +1338,7 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
goto out; goto out;
} }
ret = validate_range(mm, uffdio_register.range.start, ret = validate_range(mm, &uffdio_register.range.start,
uffdio_register.range.len); uffdio_register.range.len);
if (ret) if (ret)
goto out; goto out;
@@ -1525,7 +1527,7 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx,
if (copy_from_user(&uffdio_unregister, buf, sizeof(uffdio_unregister))) if (copy_from_user(&uffdio_unregister, buf, sizeof(uffdio_unregister)))
goto out; goto out;
ret = validate_range(mm, uffdio_unregister.start, ret = validate_range(mm, &uffdio_unregister.start,
uffdio_unregister.len); uffdio_unregister.len);
if (ret) if (ret)
goto out; goto out;
@@ -1676,7 +1678,7 @@ static int userfaultfd_wake(struct userfaultfd_ctx *ctx,
if (copy_from_user(&uffdio_wake, buf, sizeof(uffdio_wake))) if (copy_from_user(&uffdio_wake, buf, sizeof(uffdio_wake)))
goto out; goto out;
ret = validate_range(ctx->mm, uffdio_wake.start, uffdio_wake.len); ret = validate_range(ctx->mm, &uffdio_wake.start, uffdio_wake.len);
if (ret) if (ret)
goto out; goto out;
@@ -1716,7 +1718,7 @@ static int userfaultfd_copy(struct userfaultfd_ctx *ctx,
sizeof(uffdio_copy)-sizeof(__s64))) sizeof(uffdio_copy)-sizeof(__s64)))
goto out; goto out;
ret = validate_range(ctx->mm, uffdio_copy.dst, uffdio_copy.len); ret = validate_range(ctx->mm, &uffdio_copy.dst, uffdio_copy.len);
if (ret) if (ret)
goto out; goto out;
/* /*
@@ -1772,7 +1774,7 @@ static int userfaultfd_zeropage(struct userfaultfd_ctx *ctx,
sizeof(uffdio_zeropage)-sizeof(__s64))) sizeof(uffdio_zeropage)-sizeof(__s64)))
goto out; goto out;
ret = validate_range(ctx->mm, uffdio_zeropage.range.start, ret = validate_range(ctx->mm, &uffdio_zeropage.range.start,
uffdio_zeropage.range.len); uffdio_zeropage.range.len);
if (ret) if (ret)
goto out; goto out;

View File

@@ -2097,7 +2097,7 @@ xfs_verify_magic(
int idx; int idx;
idx = xfs_sb_version_hascrc(&mp->m_sb); idx = xfs_sb_version_hascrc(&mp->m_sb);
if (unlikely(WARN_ON(!bp->b_ops || !bp->b_ops->magic[idx]))) if (WARN_ON(!bp->b_ops || !bp->b_ops->magic[idx]))
return false; return false;
return dmagic == bp->b_ops->magic[idx]; return dmagic == bp->b_ops->magic[idx];
} }
@@ -2115,7 +2115,7 @@ xfs_verify_magic16(
int idx; int idx;
idx = xfs_sb_version_hascrc(&mp->m_sb); idx = xfs_sb_version_hascrc(&mp->m_sb);
if (unlikely(WARN_ON(!bp->b_ops || !bp->b_ops->magic16[idx]))) if (WARN_ON(!bp->b_ops || !bp->b_ops->magic16[idx]))
return false; return false;
return dmagic == bp->b_ops->magic16[idx]; return dmagic == bp->b_ops->magic16[idx];
} }

View File

@@ -10,6 +10,7 @@
#define BUGFLAG_WARNING (1 << 0) #define BUGFLAG_WARNING (1 << 0)
#define BUGFLAG_ONCE (1 << 1) #define BUGFLAG_ONCE (1 << 1)
#define BUGFLAG_DONE (1 << 2) #define BUGFLAG_DONE (1 << 2)
#define BUGFLAG_NO_CUT_HERE (1 << 3) /* CUT_HERE already sent */
#define BUGFLAG_TAINT(taint) ((taint) << 8) #define BUGFLAG_TAINT(taint) ((taint) << 8)
#define BUG_GET_TAINT(bug) ((bug)->flags >> 8) #define BUG_GET_TAINT(bug) ((bug)->flags >> 8)
#endif #endif
@@ -61,18 +62,6 @@ struct bug_entry {
#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0) #define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0)
#endif #endif
#ifdef __WARN_FLAGS
#define __WARN_TAINT(taint) __WARN_FLAGS(BUGFLAG_TAINT(taint))
#define __WARN_ONCE_TAINT(taint) __WARN_FLAGS(BUGFLAG_ONCE|BUGFLAG_TAINT(taint))
#define WARN_ON_ONCE(condition) ({ \
int __ret_warn_on = !!(condition); \
if (unlikely(__ret_warn_on)) \
__WARN_ONCE_TAINT(TAINT_WARN); \
unlikely(__ret_warn_on); \
})
#endif
/* /*
* WARN(), WARN_ON(), WARN_ON_ONCE, and so on can be used to report * WARN(), WARN_ON(), WARN_ON_ONCE, and so on can be used to report
* significant kernel issues that need prompt attention if they should ever * significant kernel issues that need prompt attention if they should ever
@@ -89,27 +78,27 @@ struct bug_entry {
* *
* Use the versions with printk format strings to provide better diagnostics. * Use the versions with printk format strings to provide better diagnostics.
*/ */
#ifndef __WARN_TAINT #ifndef __WARN_FLAGS
extern __printf(3, 4)
void warn_slowpath_fmt(const char *file, const int line,
const char *fmt, ...);
extern __printf(4, 5) extern __printf(4, 5)
void warn_slowpath_fmt_taint(const char *file, const int line, unsigned taint, void warn_slowpath_fmt(const char *file, const int line, unsigned taint,
const char *fmt, ...); const char *fmt, ...);
extern void warn_slowpath_null(const char *file, const int line); #define __WARN() __WARN_printf(TAINT_WARN, NULL)
#define WANT_WARN_ON_SLOWPATH #define __WARN_printf(taint, arg...) \
#define __WARN() warn_slowpath_null(__FILE__, __LINE__) warn_slowpath_fmt(__FILE__, __LINE__, taint, arg)
#define __WARN_printf(arg...) warn_slowpath_fmt(__FILE__, __LINE__, arg)
#define __WARN_printf_taint(taint, arg...) \
warn_slowpath_fmt_taint(__FILE__, __LINE__, taint, arg)
#else #else
extern __printf(1, 2) void __warn_printk(const char *fmt, ...); extern __printf(1, 2) void __warn_printk(const char *fmt, ...);
#define __WARN() do { \ #define __WARN() __WARN_FLAGS(BUGFLAG_TAINT(TAINT_WARN))
printk(KERN_WARNING CUT_HERE); __WARN_TAINT(TAINT_WARN); \ #define __WARN_printf(taint, arg...) do { \
} while (0) __warn_printk(arg); \
#define __WARN_printf(arg...) __WARN_printf_taint(TAINT_WARN, arg) __WARN_FLAGS(BUGFLAG_NO_CUT_HERE | BUGFLAG_TAINT(taint));\
#define __WARN_printf_taint(taint, arg...) \ } while (0)
do { __warn_printk(arg); __WARN_TAINT(taint); } while (0) #define WARN_ON_ONCE(condition) ({ \
int __ret_warn_on = !!(condition); \
if (unlikely(__ret_warn_on)) \
__WARN_FLAGS(BUGFLAG_ONCE | \
BUGFLAG_TAINT(TAINT_WARN)); \
unlikely(__ret_warn_on); \
})
#endif #endif
/* used internally by panic.c */ /* used internally by panic.c */
@@ -132,7 +121,7 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
#define WARN(condition, format...) ({ \ #define WARN(condition, format...) ({ \
int __ret_warn_on = !!(condition); \ int __ret_warn_on = !!(condition); \
if (unlikely(__ret_warn_on)) \ if (unlikely(__ret_warn_on)) \
__WARN_printf(format); \ __WARN_printf(TAINT_WARN, format); \
unlikely(__ret_warn_on); \ unlikely(__ret_warn_on); \
}) })
#endif #endif
@@ -140,7 +129,7 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
#define WARN_TAINT(condition, taint, format...) ({ \ #define WARN_TAINT(condition, taint, format...) ({ \
int __ret_warn_on = !!(condition); \ int __ret_warn_on = !!(condition); \
if (unlikely(__ret_warn_on)) \ if (unlikely(__ret_warn_on)) \
__WARN_printf_taint(taint, format); \ __WARN_printf(taint, format); \
unlikely(__ret_warn_on); \ unlikely(__ret_warn_on); \
}) })

View File

@@ -49,7 +49,7 @@ static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
* @mm: the mm_struct of the current context * @mm: the mm_struct of the current context
* @gfp: GFP flags to use for the allocation * @gfp: GFP flags to use for the allocation
* *
* Allocates a page and runs the pgtable_page_ctor(). * Allocates a page and runs the pgtable_pte_page_ctor().
* *
* This function is intended for architectures that need * This function is intended for architectures that need
* anything beyond simple page allocation or must have custom GFP flags. * anything beyond simple page allocation or must have custom GFP flags.
@@ -63,7 +63,7 @@ static inline pgtable_t __pte_alloc_one(struct mm_struct *mm, gfp_t gfp)
pte = alloc_page(gfp); pte = alloc_page(gfp);
if (!pte) if (!pte)
return NULL; return NULL;
if (!pgtable_page_ctor(pte)) { if (!pgtable_pte_page_ctor(pte)) {
__free_page(pte); __free_page(pte);
return NULL; return NULL;
} }
@@ -76,7 +76,7 @@ static inline pgtable_t __pte_alloc_one(struct mm_struct *mm, gfp_t gfp)
* pte_alloc_one - allocate a page for PTE-level user page table * pte_alloc_one - allocate a page for PTE-level user page table
* @mm: the mm_struct of the current context * @mm: the mm_struct of the current context
* *
* Allocates a page and runs the pgtable_page_ctor(). * Allocates a page and runs the pgtable_pte_page_ctor().
* *
* Return: `struct page` initialized as page table or %NULL on error * Return: `struct page` initialized as page table or %NULL on error
*/ */
@@ -98,7 +98,7 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm)
*/ */
static inline void pte_free(struct mm_struct *mm, struct page *pte_page) static inline void pte_free(struct mm_struct *mm, struct page *pte_page)
{ {
pgtable_page_dtor(pte_page); pgtable_pte_page_dtor(pte_page);
__free_page(pte_page); __free_page(pte_page);
} }

View File

@@ -200,8 +200,8 @@ static inline unsigned int cpumask_local_spread(unsigned int i, int node)
for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask) for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask)
#define for_each_cpu_wrap(cpu, mask, start) \ #define for_each_cpu_wrap(cpu, mask, start) \
for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask, (void)(start)) for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask, (void)(start))
#define for_each_cpu_and(cpu, mask, and) \ #define for_each_cpu_and(cpu, mask1, mask2) \
for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask, (void)and) for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask1, (void)mask2)
#else #else
/** /**
* cpumask_first - get the first cpu in a cpumask * cpumask_first - get the first cpu in a cpumask
@@ -290,20 +290,20 @@ extern int cpumask_next_wrap(int n, const struct cpumask *mask, int start, bool
/** /**
* for_each_cpu_and - iterate over every cpu in both masks * for_each_cpu_and - iterate over every cpu in both masks
* @cpu: the (optionally unsigned) integer iterator * @cpu: the (optionally unsigned) integer iterator
* @mask: the first cpumask pointer * @mask1: the first cpumask pointer
* @and: the second cpumask pointer * @mask2: the second cpumask pointer
* *
* This saves a temporary CPU mask in many places. It is equivalent to: * This saves a temporary CPU mask in many places. It is equivalent to:
* struct cpumask tmp; * struct cpumask tmp;
* cpumask_and(&tmp, &mask, &and); * cpumask_and(&tmp, &mask1, &mask2);
* for_each_cpu(cpu, &tmp) * for_each_cpu(cpu, &tmp)
* ... * ...
* *
* After the loop, cpu is >= nr_cpu_ids. * After the loop, cpu is >= nr_cpu_ids.
*/ */
#define for_each_cpu_and(cpu, mask, and) \ #define for_each_cpu_and(cpu, mask1, mask2) \
for ((cpu) = -1; \ for ((cpu) = -1; \
(cpu) = cpumask_next_and((cpu), (mask), (and)), \ (cpu) = cpumask_next_and((cpu), (mask1), (mask2)), \
(cpu) < nr_cpu_ids;) (cpu) < nr_cpu_ids;)
#endif /* SMP */ #endif /* SMP */

View File

@@ -30,26 +30,8 @@
\ \
/* Callbacks for augmented rbtree insert and remove */ \ /* Callbacks for augmented rbtree insert and remove */ \
\ \
static inline ITTYPE ITPREFIX ## _compute_subtree_last(ITSTRUCT *node) \ RB_DECLARE_CALLBACKS_MAX(static, ITPREFIX ## _augment, \
{ \ ITSTRUCT, ITRB, ITTYPE, ITSUBTREE, ITLAST) \
ITTYPE max = ITLAST(node), subtree_last; \
if (node->ITRB.rb_left) { \
subtree_last = rb_entry(node->ITRB.rb_left, \
ITSTRUCT, ITRB)->ITSUBTREE; \
if (max < subtree_last) \
max = subtree_last; \
} \
if (node->ITRB.rb_right) { \
subtree_last = rb_entry(node->ITRB.rb_right, \
ITSTRUCT, ITRB)->ITSUBTREE; \
if (max < subtree_last) \
max = subtree_last; \
} \
return max; \
} \
\
RB_DECLARE_CALLBACKS(static, ITPREFIX ## _augment, ITSTRUCT, ITRB, \
ITTYPE, ITSUBTREE, ITPREFIX ## _compute_subtree_last) \
\ \
/* Insert / remove interval nodes from the tree */ \ /* Insert / remove interval nodes from the tree */ \
\ \

View File

@@ -183,6 +183,8 @@ int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name,
bool get_value); bool get_value);
void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *name); void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *name);
int __weak arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
unsigned long buf_len);
void * __weak arch_kexec_kernel_image_load(struct kimage *image); void * __weak arch_kexec_kernel_image_load(struct kimage *image);
int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi, int __weak arch_kexec_apply_relocations_add(struct purgatory_info *pi,
Elf_Shdr *section, Elf_Shdr *section,

View File

@@ -326,8 +326,10 @@ extern atomic_t kgdb_active;
(raw_smp_processor_id() == atomic_read(&kgdb_active)) (raw_smp_processor_id() == atomic_read(&kgdb_active))
extern bool dbg_is_early; extern bool dbg_is_early;
extern void __init dbg_late_init(void); extern void __init dbg_late_init(void);
extern void kgdb_panic(const char *msg);
#else /* ! CONFIG_KGDB */ #else /* ! CONFIG_KGDB */
#define in_dbg_master() (0) #define in_dbg_master() (0)
#define dbg_late_init() #define dbg_late_init()
static inline void kgdb_panic(const char *msg) {}
#endif /* ! CONFIG_KGDB */ #endif /* ! CONFIG_KGDB */
#endif /* _KGDB_H_ */ #endif /* _KGDB_H_ */

View File

@@ -1949,7 +1949,7 @@ static inline void pgtable_init(void)
pgtable_cache_init(); pgtable_cache_init();
} }
static inline bool pgtable_page_ctor(struct page *page) static inline bool pgtable_pte_page_ctor(struct page *page)
{ {
if (!ptlock_init(page)) if (!ptlock_init(page))
return false; return false;
@@ -1958,7 +1958,7 @@ static inline bool pgtable_page_ctor(struct page *page)
return true; return true;
} }
static inline void pgtable_page_dtor(struct page *page) static inline void pgtable_pte_page_dtor(struct page *page)
{ {
ptlock_free(page); ptlock_free(page);
__ClearPageTable(page); __ClearPageTable(page);

View File

@@ -36,6 +36,10 @@ struct vmacache {
struct vm_area_struct *vmas[VMACACHE_SIZE]; struct vm_area_struct *vmas[VMACACHE_SIZE];
}; };
/*
* When updating this, please also update struct resident_page_types[] in
* kernel/fork.c
*/
enum { enum {
MM_FILEPAGES, /* Resident file mapping pages */ MM_FILEPAGES, /* Resident file mapping pages */
MM_ANONPAGES, /* Resident anonymous pages */ MM_ANONPAGES, /* Resident anonymous pages */

View File

@@ -488,13 +488,6 @@ extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
extern void print_hex_dump(const char *level, const char *prefix_str, extern void print_hex_dump(const char *level, const char *prefix_str,
int prefix_type, int rowsize, int groupsize, int prefix_type, int rowsize, int groupsize,
const void *buf, size_t len, bool ascii); const void *buf, size_t len, bool ascii);
#if defined(CONFIG_DYNAMIC_DEBUG)
#define print_hex_dump_bytes(prefix_str, prefix_type, buf, len) \
dynamic_hex_dump(prefix_str, prefix_type, 16, 1, buf, len, true)
#else
extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
const void *buf, size_t len);
#endif /* defined(CONFIG_DYNAMIC_DEBUG) */
#else #else
static inline void print_hex_dump(const char *level, const char *prefix_str, static inline void print_hex_dump(const char *level, const char *prefix_str,
int prefix_type, int rowsize, int groupsize, int prefix_type, int rowsize, int groupsize,
@@ -526,4 +519,19 @@ static inline void print_hex_dump_debug(const char *prefix_str, int prefix_type,
} }
#endif #endif
/**
* print_hex_dump_bytes - shorthand form of print_hex_dump() with default params
* @prefix_str: string to prefix each line with;
* caller supplies trailing spaces for alignment if desired
* @prefix_type: controls whether prefix of an offset, address, or none
* is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
* @buf: data blob to dump
* @len: number of bytes in the @buf
*
* Calls print_hex_dump(), with log level of KERN_DEBUG,
* rowsize of 16, groupsize of 1, and ASCII output included.
*/
#define print_hex_dump_bytes(prefix_str, prefix_type, buf, len) \
print_hex_dump_debug(prefix_str, prefix_type, 16, 1, buf, len, true)
#endif #endif

View File

@@ -60,41 +60,87 @@ rb_insert_augmented_cached(struct rb_node *node,
rb_insert_augmented(node, &root->rb_root, augment); rb_insert_augmented(node, &root->rb_root, augment);
} }
#define RB_DECLARE_CALLBACKS(rbstatic, rbname, rbstruct, rbfield, \ /*
rbtype, rbaugmented, rbcompute) \ * Template for declaring augmented rbtree callbacks (generic case)
*
* RBSTATIC: 'static' or empty
* RBNAME: name of the rb_augment_callbacks structure
* RBSTRUCT: struct type of the tree nodes
* RBFIELD: name of struct rb_node field within RBSTRUCT
* RBAUGMENTED: name of field within RBSTRUCT holding data for subtree
* RBCOMPUTE: name of function that recomputes the RBAUGMENTED data
*/
#define RB_DECLARE_CALLBACKS(RBSTATIC, RBNAME, \
RBSTRUCT, RBFIELD, RBAUGMENTED, RBCOMPUTE) \
static inline void \ static inline void \
rbname ## _propagate(struct rb_node *rb, struct rb_node *stop) \ RBNAME ## _propagate(struct rb_node *rb, struct rb_node *stop) \
{ \ { \
while (rb != stop) { \ while (rb != stop) { \
rbstruct *node = rb_entry(rb, rbstruct, rbfield); \ RBSTRUCT *node = rb_entry(rb, RBSTRUCT, RBFIELD); \
rbtype augmented = rbcompute(node); \ if (RBCOMPUTE(node, true)) \
if (node->rbaugmented == augmented) \
break; \ break; \
node->rbaugmented = augmented; \ rb = rb_parent(&node->RBFIELD); \
rb = rb_parent(&node->rbfield); \
} \ } \
} \ } \
static inline void \ static inline void \
rbname ## _copy(struct rb_node *rb_old, struct rb_node *rb_new) \ RBNAME ## _copy(struct rb_node *rb_old, struct rb_node *rb_new) \
{ \ { \
rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \ RBSTRUCT *old = rb_entry(rb_old, RBSTRUCT, RBFIELD); \
rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \ RBSTRUCT *new = rb_entry(rb_new, RBSTRUCT, RBFIELD); \
new->rbaugmented = old->rbaugmented; \ new->RBAUGMENTED = old->RBAUGMENTED; \
} \ } \
static void \ static void \
rbname ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new) \ RBNAME ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new) \
{ \ { \
rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \ RBSTRUCT *old = rb_entry(rb_old, RBSTRUCT, RBFIELD); \
rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \ RBSTRUCT *new = rb_entry(rb_new, RBSTRUCT, RBFIELD); \
new->rbaugmented = old->rbaugmented; \ new->RBAUGMENTED = old->RBAUGMENTED; \
old->rbaugmented = rbcompute(old); \ RBCOMPUTE(old, false); \
} \ } \
rbstatic const struct rb_augment_callbacks rbname = { \ RBSTATIC const struct rb_augment_callbacks RBNAME = { \
.propagate = rbname ## _propagate, \ .propagate = RBNAME ## _propagate, \
.copy = rbname ## _copy, \ .copy = RBNAME ## _copy, \
.rotate = rbname ## _rotate \ .rotate = RBNAME ## _rotate \
}; };
/*
* Template for declaring augmented rbtree callbacks,
* computing RBAUGMENTED scalar as max(RBCOMPUTE(node)) for all subtree nodes.
*
* RBSTATIC: 'static' or empty
* RBNAME: name of the rb_augment_callbacks structure
* RBSTRUCT: struct type of the tree nodes
* RBFIELD: name of struct rb_node field within RBSTRUCT
* RBTYPE: type of the RBAUGMENTED field
* RBAUGMENTED: name of RBTYPE field within RBSTRUCT holding data for subtree
* RBCOMPUTE: name of function that returns the per-node RBTYPE scalar
*/
#define RB_DECLARE_CALLBACKS_MAX(RBSTATIC, RBNAME, RBSTRUCT, RBFIELD, \
RBTYPE, RBAUGMENTED, RBCOMPUTE) \
static inline bool RBNAME ## _compute_max(RBSTRUCT *node, bool exit) \
{ \
RBSTRUCT *child; \
RBTYPE max = RBCOMPUTE(node); \
if (node->RBFIELD.rb_left) { \
child = rb_entry(node->RBFIELD.rb_left, RBSTRUCT, RBFIELD); \
if (child->RBAUGMENTED > max) \
max = child->RBAUGMENTED; \
} \
if (node->RBFIELD.rb_right) { \
child = rb_entry(node->RBFIELD.rb_right, RBSTRUCT, RBFIELD); \
if (child->RBAUGMENTED > max) \
max = child->RBAUGMENTED; \
} \
if (exit && node->RBAUGMENTED == max) \
return true; \
node->RBAUGMENTED = max; \
return false; \
} \
RB_DECLARE_CALLBACKS(RBSTATIC, RBNAME, \
RBSTRUCT, RBFIELD, RBAUGMENTED, RBNAME ## _compute_max)
#define RB_RED 0 #define RB_RED 0
#define RB_BLACK 1 #define RB_BLACK 1

View File

@@ -474,8 +474,9 @@ static inline void memcpy_and_pad(void *dest, size_t dest_len,
* But this can lead to bugs due to typos, or if prefix is a pointer * But this can lead to bugs due to typos, or if prefix is a pointer
* and not a constant. Instead use str_has_prefix(). * and not a constant. Instead use str_has_prefix().
* *
* Returns: 0 if @str does not start with @prefix * Returns:
strlen(@prefix) if @str does start with @prefix * * strlen(@prefix) if @str starts with @prefix
* * 0 if @str does not start with @prefix
*/ */
static __always_inline size_t str_has_prefix(const char *str, const char *prefix) static __always_inline size_t str_has_prefix(const char *str, const char *prefix)
{ {

View File

@@ -340,6 +340,7 @@ extern void lru_add_drain_cpu(int cpu);
extern void lru_add_drain_all(void); extern void lru_add_drain_all(void);
extern void rotate_reclaimable_page(struct page *page); extern void rotate_reclaimable_page(struct page *page);
extern void deactivate_file_page(struct page *page); extern void deactivate_file_page(struct page *page);
extern void deactivate_page(struct page *page);
extern void mark_page_lazyfree(struct page *page); extern void mark_page_lazyfree(struct page *page);
extern void swap_setup(void); extern void swap_setup(void);
@@ -364,6 +365,7 @@ extern int vm_swappiness;
extern int remove_mapping(struct address_space *mapping, struct page *page); extern int remove_mapping(struct address_space *mapping, struct page *page);
extern unsigned long vm_total_pages; extern unsigned long vm_total_pages;
extern unsigned long reclaim_pages(struct list_head *page_list);
#ifdef CONFIG_NUMA #ifdef CONFIG_NUMA
extern int node_reclaim_mode; extern int node_reclaim_mode;
extern int sysctl_min_unmapped_ratio; extern int sysctl_min_unmapped_ratio;

View File

@@ -134,7 +134,7 @@ static inline void copy_overflow(int size, unsigned long count)
WARN(1, "Buffer overflow detected (%d < %lu)!\n", size, count); WARN(1, "Buffer overflow detected (%d < %lu)!\n", size, count);
} }
static __always_inline bool static __always_inline __must_check bool
check_copy_size(const void *addr, size_t bytes, bool is_source) check_copy_size(const void *addr, size_t bytes, bool is_source)
{ {
int sz = __compiletime_object_size(addr); int sz = __compiletime_object_size(addr);

View File

@@ -55,7 +55,7 @@
* as usual) and both source and destination can trigger faults. * as usual) and both source and destination can trigger faults.
*/ */
static __always_inline unsigned long static __always_inline __must_check unsigned long
__copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
{ {
kasan_check_write(to, n); kasan_check_write(to, n);
@@ -63,7 +63,7 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
return raw_copy_from_user(to, from, n); return raw_copy_from_user(to, from, n);
} }
static __always_inline unsigned long static __always_inline __must_check unsigned long
__copy_from_user(void *to, const void __user *from, unsigned long n) __copy_from_user(void *to, const void __user *from, unsigned long n)
{ {
might_fault(); might_fault();
@@ -85,7 +85,7 @@ __copy_from_user(void *to, const void __user *from, unsigned long n)
* The caller should also make sure he pins the user space address * The caller should also make sure he pins the user space address
* so that we don't result in page fault and sleep. * so that we don't result in page fault and sleep.
*/ */
static __always_inline unsigned long static __always_inline __must_check unsigned long
__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
{ {
kasan_check_read(from, n); kasan_check_read(from, n);
@@ -93,7 +93,7 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
return raw_copy_to_user(to, from, n); return raw_copy_to_user(to, from, n);
} }
static __always_inline unsigned long static __always_inline __must_check unsigned long
__copy_to_user(void __user *to, const void *from, unsigned long n) __copy_to_user(void __user *to, const void *from, unsigned long n)
{ {
might_fault(); might_fault();
@@ -103,7 +103,7 @@ __copy_to_user(void __user *to, const void *from, unsigned long n)
} }
#ifdef INLINE_COPY_FROM_USER #ifdef INLINE_COPY_FROM_USER
static inline unsigned long static inline __must_check unsigned long
_copy_from_user(void *to, const void __user *from, unsigned long n) _copy_from_user(void *to, const void __user *from, unsigned long n)
{ {
unsigned long res = n; unsigned long res = n;
@@ -117,12 +117,12 @@ _copy_from_user(void *to, const void __user *from, unsigned long n)
return res; return res;
} }
#else #else
extern unsigned long extern __must_check unsigned long
_copy_from_user(void *, const void __user *, unsigned long); _copy_from_user(void *, const void __user *, unsigned long);
#endif #endif
#ifdef INLINE_COPY_TO_USER #ifdef INLINE_COPY_TO_USER
static inline unsigned long static inline __must_check unsigned long
_copy_to_user(void __user *to, const void *from, unsigned long n) _copy_to_user(void __user *to, const void *from, unsigned long n)
{ {
might_fault(); might_fault();
@@ -133,7 +133,7 @@ _copy_to_user(void __user *to, const void *from, unsigned long n)
return n; return n;
} }
#else #else
extern unsigned long extern __must_check unsigned long
_copy_to_user(void __user *, const void *, unsigned long); _copy_to_user(void __user *, const void *, unsigned long);
#endif #endif
@@ -222,8 +222,9 @@ static inline bool pagefault_disabled(void)
#ifndef ARCH_HAS_NOCACHE_UACCESS #ifndef ARCH_HAS_NOCACHE_UACCESS
static inline unsigned long __copy_from_user_inatomic_nocache(void *to, static inline __must_check unsigned long
const void __user *from, unsigned long n) __copy_from_user_inatomic_nocache(void *to, const void __user *from,
unsigned long n)
{ {
return __copy_from_user_inatomic(to, from, n); return __copy_from_user_inatomic(to, from, n);
} }

View File

@@ -66,8 +66,9 @@ DECLARE_EVENT_CLASS(writeback_page_template,
), ),
TP_fast_assign( TP_fast_assign(
strncpy(__entry->name, strscpy_pad(__entry->name,
mapping ? dev_name(inode_to_bdi(mapping->host)->dev) : "(unknown)", 32); mapping ? dev_name(inode_to_bdi(mapping->host)->dev) : "(unknown)",
32);
__entry->ino = mapping ? mapping->host->i_ino : 0; __entry->ino = mapping ? mapping->host->i_ino : 0;
__entry->index = page->index; __entry->index = page->index;
), ),
@@ -110,8 +111,8 @@ DECLARE_EVENT_CLASS(writeback_dirty_inode_template,
struct backing_dev_info *bdi = inode_to_bdi(inode); struct backing_dev_info *bdi = inode_to_bdi(inode);
/* may be called for files on pseudo FSes w/ unregistered bdi */ /* may be called for files on pseudo FSes w/ unregistered bdi */
strncpy(__entry->name, strscpy_pad(__entry->name,
bdi->dev ? dev_name(bdi->dev) : "(unknown)", 32); bdi->dev ? dev_name(bdi->dev) : "(unknown)", 32);
__entry->ino = inode->i_ino; __entry->ino = inode->i_ino;
__entry->state = inode->i_state; __entry->state = inode->i_state;
__entry->flags = flags; __entry->flags = flags;
@@ -316,8 +317,8 @@ DECLARE_EVENT_CLASS(writeback_write_inode_template,
), ),
TP_fast_assign( TP_fast_assign(
strncpy(__entry->name, strscpy_pad(__entry->name,
dev_name(inode_to_bdi(inode)->dev), 32); dev_name(inode_to_bdi(inode)->dev), 32);
__entry->ino = inode->i_ino; __entry->ino = inode->i_ino;
__entry->sync_mode = wbc->sync_mode; __entry->sync_mode = wbc->sync_mode;
__entry->cgroup_ino = __trace_wbc_assign_cgroup(wbc); __entry->cgroup_ino = __trace_wbc_assign_cgroup(wbc);
@@ -360,8 +361,9 @@ DECLARE_EVENT_CLASS(writeback_work_class,
__field(unsigned int, cgroup_ino) __field(unsigned int, cgroup_ino)
), ),
TP_fast_assign( TP_fast_assign(
strncpy(__entry->name, strscpy_pad(__entry->name,
wb->bdi->dev ? dev_name(wb->bdi->dev) : "(unknown)", 32); wb->bdi->dev ? dev_name(wb->bdi->dev) :
"(unknown)", 32);
__entry->nr_pages = work->nr_pages; __entry->nr_pages = work->nr_pages;
__entry->sb_dev = work->sb ? work->sb->s_dev : 0; __entry->sb_dev = work->sb ? work->sb->s_dev : 0;
__entry->sync_mode = work->sync_mode; __entry->sync_mode = work->sync_mode;
@@ -414,7 +416,7 @@ DECLARE_EVENT_CLASS(writeback_class,
__field(unsigned int, cgroup_ino) __field(unsigned int, cgroup_ino)
), ),
TP_fast_assign( TP_fast_assign(
strncpy(__entry->name, dev_name(wb->bdi->dev), 32); strscpy_pad(__entry->name, dev_name(wb->bdi->dev), 32);
__entry->cgroup_ino = __trace_wb_assign_cgroup(wb); __entry->cgroup_ino = __trace_wb_assign_cgroup(wb);
), ),
TP_printk("bdi %s: cgroup_ino=%u", TP_printk("bdi %s: cgroup_ino=%u",
@@ -436,7 +438,7 @@ TRACE_EVENT(writeback_bdi_register,
__array(char, name, 32) __array(char, name, 32)
), ),
TP_fast_assign( TP_fast_assign(
strncpy(__entry->name, dev_name(bdi->dev), 32); strscpy_pad(__entry->name, dev_name(bdi->dev), 32);
), ),
TP_printk("bdi %s", TP_printk("bdi %s",
__entry->name __entry->name
@@ -461,7 +463,7 @@ DECLARE_EVENT_CLASS(wbc_class,
), ),
TP_fast_assign( TP_fast_assign(
strncpy(__entry->name, dev_name(bdi->dev), 32); strscpy_pad(__entry->name, dev_name(bdi->dev), 32);
__entry->nr_to_write = wbc->nr_to_write; __entry->nr_to_write = wbc->nr_to_write;
__entry->pages_skipped = wbc->pages_skipped; __entry->pages_skipped = wbc->pages_skipped;
__entry->sync_mode = wbc->sync_mode; __entry->sync_mode = wbc->sync_mode;
@@ -512,7 +514,7 @@ TRACE_EVENT(writeback_queue_io,
), ),
TP_fast_assign( TP_fast_assign(
unsigned long *older_than_this = work->older_than_this; unsigned long *older_than_this = work->older_than_this;
strncpy(__entry->name, dev_name(wb->bdi->dev), 32); strscpy_pad(__entry->name, dev_name(wb->bdi->dev), 32);
__entry->older = older_than_this ? *older_than_this : 0; __entry->older = older_than_this ? *older_than_this : 0;
__entry->age = older_than_this ? __entry->age = older_than_this ?
(jiffies - *older_than_this) * 1000 / HZ : -1; (jiffies - *older_than_this) * 1000 / HZ : -1;
@@ -598,7 +600,7 @@ TRACE_EVENT(bdi_dirty_ratelimit,
), ),
TP_fast_assign( TP_fast_assign(
strlcpy(__entry->bdi, dev_name(wb->bdi->dev), 32); strscpy_pad(__entry->bdi, dev_name(wb->bdi->dev), 32);
__entry->write_bw = KBps(wb->write_bandwidth); __entry->write_bw = KBps(wb->write_bandwidth);
__entry->avg_write_bw = KBps(wb->avg_write_bandwidth); __entry->avg_write_bw = KBps(wb->avg_write_bandwidth);
__entry->dirty_rate = KBps(dirty_rate); __entry->dirty_rate = KBps(dirty_rate);
@@ -663,7 +665,7 @@ TRACE_EVENT(balance_dirty_pages,
TP_fast_assign( TP_fast_assign(
unsigned long freerun = (thresh + bg_thresh) / 2; unsigned long freerun = (thresh + bg_thresh) / 2;
strlcpy(__entry->bdi, dev_name(wb->bdi->dev), 32); strscpy_pad(__entry->bdi, dev_name(wb->bdi->dev), 32);
__entry->limit = global_wb_domain.dirty_limit; __entry->limit = global_wb_domain.dirty_limit;
__entry->setpoint = (global_wb_domain.dirty_limit + __entry->setpoint = (global_wb_domain.dirty_limit +
@@ -723,8 +725,8 @@ TRACE_EVENT(writeback_sb_inodes_requeue,
), ),
TP_fast_assign( TP_fast_assign(
strncpy(__entry->name, strscpy_pad(__entry->name,
dev_name(inode_to_bdi(inode)->dev), 32); dev_name(inode_to_bdi(inode)->dev), 32);
__entry->ino = inode->i_ino; __entry->ino = inode->i_ino;
__entry->state = inode->i_state; __entry->state = inode->i_state;
__entry->dirtied_when = inode->dirtied_when; __entry->dirtied_when = inode->dirtied_when;
@@ -797,8 +799,8 @@ DECLARE_EVENT_CLASS(writeback_single_inode_template,
), ),
TP_fast_assign( TP_fast_assign(
strncpy(__entry->name, strscpy_pad(__entry->name,
dev_name(inode_to_bdi(inode)->dev), 32); dev_name(inode_to_bdi(inode)->dev), 32);
__entry->ino = inode->i_ino; __entry->ino = inode->i_ino;
__entry->state = inode->i_state; __entry->state = inode->i_state;
__entry->dirtied_when = inode->dirtied_when; __entry->dirtied_when = inode->dirtied_when;

View File

@@ -67,6 +67,9 @@
#define MADV_WIPEONFORK 18 /* Zero memory on fork, child only */ #define MADV_WIPEONFORK 18 /* Zero memory on fork, child only */
#define MADV_KEEPONFORK 19 /* Undo MADV_WIPEONFORK */ #define MADV_KEEPONFORK 19 /* Undo MADV_WIPEONFORK */
#define MADV_COLD 20 /* deactivate these pages */
#define MADV_PAGEOUT 21 /* reclaim these pages */
/* compatibility flags */ /* compatibility flags */
#define MAP_FILE 0 #define MAP_FILE 0

View File

@@ -11,6 +11,9 @@
more information about COFF, then O'Reilly has a very excellent book. more information about COFF, then O'Reilly has a very excellent book.
*/ */
#ifndef _UAPI_LINUX_COFF_H
#define _UAPI_LINUX_COFF_H
#define E_SYMNMLEN 8 /* Number of characters in a symbol name */ #define E_SYMNMLEN 8 /* Number of characters in a symbol name */
#define E_FILNMLEN 14 /* Number of characters in a file name */ #define E_FILNMLEN 14 /* Number of characters in a file name */
#define E_DIMNUM 4 /* Number of array dimensions in auxiliary entry */ #define E_DIMNUM 4 /* Number of array dimensions in auxiliary entry */
@@ -350,3 +353,5 @@ struct COFF_reloc {
/* For new sections we haven't heard of before */ /* For new sections we haven't heard of before */
#define COFF_DEF_SECTION_ALIGNMENT 4 #define COFF_DEF_SECTION_ALIGNMENT 4
#endif /* _UAPI_LINUX_COFF_H */

View File

@@ -1240,15 +1240,14 @@ static int do_mq_notify(mqd_t mqdes, const struct sigevent *notification)
/* create the notify skb */ /* create the notify skb */
nc = alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL); nc = alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL);
if (!nc) { if (!nc)
ret = -ENOMEM; return -ENOMEM;
goto out;
}
if (copy_from_user(nc->data, if (copy_from_user(nc->data,
notification->sigev_value.sival_ptr, notification->sigev_value.sival_ptr,
NOTIFY_COOKIE_LEN)) { NOTIFY_COOKIE_LEN)) {
ret = -EFAULT; ret = -EFAULT;
goto out; goto free_skb;
} }
/* TODO: add a header? */ /* TODO: add a header? */
@@ -1264,8 +1263,7 @@ retry:
fdput(f); fdput(f);
if (IS_ERR(sock)) { if (IS_ERR(sock)) {
ret = PTR_ERR(sock); ret = PTR_ERR(sock);
sock = NULL; goto free_skb;
goto out;
} }
timeo = MAX_SCHEDULE_TIMEOUT; timeo = MAX_SCHEDULE_TIMEOUT;
@@ -1274,11 +1272,8 @@ retry:
sock = NULL; sock = NULL;
goto retry; goto retry;
} }
if (ret) { if (ret)
sock = NULL; return ret;
nc = NULL;
goto out;
}
} }
} }
@@ -1333,7 +1328,8 @@ out_fput:
out: out:
if (sock) if (sock)
netlink_detachskb(sock, nc); netlink_detachskb(sock, nc);
else if (nc) else
free_skb:
dev_kfree_skb(nc); dev_kfree_skb(nc);
return ret; return ret;

View File

@@ -1852,7 +1852,8 @@ static struct sem_undo *__lookup_undo(struct sem_undo_list *ulp, int semid)
{ {
struct sem_undo *un; struct sem_undo *un;
list_for_each_entry_rcu(un, &ulp->list_proc, list_proc) { list_for_each_entry_rcu(un, &ulp->list_proc, list_proc,
spin_is_locked(&ulp->lock)) {
if (un->semid == semid) if (un->semid == semid)
return un; return un;
} }

View File

@@ -893,29 +893,24 @@ static struct sysrq_key_op sysrq_dbg_op = {
}; };
#endif #endif
static int kgdb_panic_event(struct notifier_block *self, void kgdb_panic(const char *msg)
unsigned long val,
void *data)
{ {
if (!kgdb_io_module_registered)
return;
/* /*
* Avoid entering the debugger if we were triggered due to a panic * We don't want to get stuck waiting for input from user if
* We don't want to get stuck waiting for input from user in such case. * "panic_timeout" indicates the system should automatically
* panic_timeout indicates the system should automatically
* reboot on panic. * reboot on panic.
*/ */
if (panic_timeout) if (panic_timeout)
return NOTIFY_DONE; return;
if (dbg_kdb_mode) if (dbg_kdb_mode)
kdb_printf("PANIC: %s\n", (char *)data); kdb_printf("PANIC: %s\n", msg);
kgdb_breakpoint();
return NOTIFY_DONE;
}
static struct notifier_block kgdb_panic_event_nb = { kgdb_breakpoint();
.notifier_call = kgdb_panic_event, }
.priority = INT_MAX,
};
void __weak kgdb_arch_late(void) void __weak kgdb_arch_late(void)
{ {
@@ -965,8 +960,6 @@ static void kgdb_register_callbacks(void)
kgdb_arch_late(); kgdb_arch_late();
register_module_notifier(&dbg_module_load_nb); register_module_notifier(&dbg_module_load_nb);
register_reboot_notifier(&dbg_reboot_notifier); register_reboot_notifier(&dbg_reboot_notifier);
atomic_notifier_chain_register(&panic_notifier_list,
&kgdb_panic_event_nb);
#ifdef CONFIG_MAGIC_SYSRQ #ifdef CONFIG_MAGIC_SYSRQ
register_sysrq_key('g', &sysrq_dbg_op); register_sysrq_key('g', &sysrq_dbg_op);
#endif #endif
@@ -980,16 +973,14 @@ static void kgdb_register_callbacks(void)
static void kgdb_unregister_callbacks(void) static void kgdb_unregister_callbacks(void)
{ {
/* /*
* When this routine is called KGDB should unregister from the * When this routine is called KGDB should unregister from
* panic handler and clean up, making sure it is not handling any * handlers and clean up, making sure it is not handling any
* break exceptions at the time. * break exceptions at the time.
*/ */
if (kgdb_io_module_registered) { if (kgdb_io_module_registered) {
kgdb_io_module_registered = 0; kgdb_io_module_registered = 0;
unregister_reboot_notifier(&dbg_reboot_notifier); unregister_reboot_notifier(&dbg_reboot_notifier);
unregister_module_notifier(&dbg_module_load_nb); unregister_module_notifier(&dbg_module_load_nb);
atomic_notifier_chain_unregister(&panic_notifier_list,
&kgdb_panic_event_nb);
kgdb_arch_exit(); kgdb_arch_exit();
#ifdef CONFIG_MAGIC_SYSRQ #ifdef CONFIG_MAGIC_SYSRQ
unregister_sysrq_key('g', &sysrq_dbg_op); unregister_sysrq_key('g', &sysrq_dbg_op);

View File

@@ -3,6 +3,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/binfmts.h> #include <linux/binfmts.h>
#include <linux/elfcore.h>
Elf_Half __weak elf_core_extra_phdrs(void) Elf_Half __weak elf_core_extra_phdrs(void)
{ {

View File

@@ -125,6 +125,15 @@ int nr_threads; /* The idle threads do not count.. */
static int max_threads; /* tunable limit on nr_threads */ static int max_threads; /* tunable limit on nr_threads */
#define NAMED_ARRAY_INDEX(x) [x] = __stringify(x)
static const char * const resident_page_types[] = {
NAMED_ARRAY_INDEX(MM_FILEPAGES),
NAMED_ARRAY_INDEX(MM_ANONPAGES),
NAMED_ARRAY_INDEX(MM_SWAPENTS),
NAMED_ARRAY_INDEX(MM_SHMEMPAGES),
};
DEFINE_PER_CPU(unsigned long, process_counts) = 0; DEFINE_PER_CPU(unsigned long, process_counts) = 0;
__cacheline_aligned DEFINE_RWLOCK(tasklist_lock); /* outer */ __cacheline_aligned DEFINE_RWLOCK(tasklist_lock); /* outer */
@@ -645,12 +654,15 @@ static void check_mm(struct mm_struct *mm)
{ {
int i; int i;
BUILD_BUG_ON_MSG(ARRAY_SIZE(resident_page_types) != NR_MM_COUNTERS,
"Please make sure 'struct resident_page_types[]' is updated as well");
for (i = 0; i < NR_MM_COUNTERS; i++) { for (i = 0; i < NR_MM_COUNTERS; i++) {
long x = atomic_long_read(&mm->rss_stat.count[i]); long x = atomic_long_read(&mm->rss_stat.count[i]);
if (unlikely(x)) if (unlikely(x))
printk(KERN_ALERT "BUG: Bad rss-counter state " pr_alert("BUG: Bad rss-counter state mm:%p type:%s val:%ld\n",
"mm:%p idx:%d val:%ld\n", mm, i, x); mm, resident_page_types[i], x);
} }
if (mm_pgtables_bytes(mm)) if (mm_pgtables_bytes(mm))

View File

@@ -300,6 +300,8 @@ static struct page *kimage_alloc_pages(gfp_t gfp_mask, unsigned int order)
{ {
struct page *pages; struct page *pages;
if (fatal_signal_pending(current))
return NULL;
pages = alloc_pages(gfp_mask & ~__GFP_ZERO, order); pages = alloc_pages(gfp_mask & ~__GFP_ZERO, order);
if (pages) { if (pages) {
unsigned int count, i; unsigned int count, i;

View File

@@ -12,6 +12,7 @@
#include <linux/debug_locks.h> #include <linux/debug_locks.h>
#include <linux/sched/debug.h> #include <linux/sched/debug.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/kgdb.h>
#include <linux/kmsg_dump.h> #include <linux/kmsg_dump.h>
#include <linux/kallsyms.h> #include <linux/kallsyms.h>
#include <linux/notifier.h> #include <linux/notifier.h>
@@ -219,6 +220,13 @@ void panic(const char *fmt, ...)
dump_stack(); dump_stack();
#endif #endif
/*
* If kgdb is enabled, give it a chance to run before we stop all
* the other CPUs or else we won't be able to debug processes left
* running on them.
*/
kgdb_panic(buf);
/* /*
* If we have crashed and we have a crash kernel loaded let it handle * If we have crashed and we have a crash kernel loaded let it handle
* everything else. * everything else.
@@ -551,9 +559,6 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
{ {
disable_trace_on_warning(); disable_trace_on_warning();
if (args)
pr_warn(CUT_HERE);
if (file) if (file)
pr_warn("WARNING: CPU: %d PID: %d at %s:%d %pS\n", pr_warn("WARNING: CPU: %d PID: %d at %s:%d %pS\n",
raw_smp_processor_id(), current->pid, file, line, raw_smp_processor_id(), current->pid, file, line,
@@ -591,37 +596,26 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
add_taint(taint, LOCKDEP_STILL_OK); add_taint(taint, LOCKDEP_STILL_OK);
} }
#ifdef WANT_WARN_ON_SLOWPATH #ifndef __WARN_FLAGS
void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...) void warn_slowpath_fmt(const char *file, int line, unsigned taint,
const char *fmt, ...)
{ {
struct warn_args args; struct warn_args args;
args.fmt = fmt; pr_warn(CUT_HERE);
va_start(args.args, fmt);
__warn(file, line, __builtin_return_address(0), TAINT_WARN, NULL,
&args);
va_end(args.args);
}
EXPORT_SYMBOL(warn_slowpath_fmt);
void warn_slowpath_fmt_taint(const char *file, int line, if (!fmt) {
unsigned taint, const char *fmt, ...) __warn(file, line, __builtin_return_address(0), taint,
{ NULL, NULL);
struct warn_args args; return;
}
args.fmt = fmt; args.fmt = fmt;
va_start(args.args, fmt); va_start(args.args, fmt);
__warn(file, line, __builtin_return_address(0), taint, NULL, &args); __warn(file, line, __builtin_return_address(0), taint, NULL, &args);
va_end(args.args); va_end(args.args);
} }
EXPORT_SYMBOL(warn_slowpath_fmt_taint); EXPORT_SYMBOL(warn_slowpath_fmt);
void warn_slowpath_null(const char *file, int line)
{
pr_warn(CUT_HERE);
__warn(file, line, __builtin_return_address(0), TAINT_WARN, NULL, NULL);
}
EXPORT_SYMBOL(warn_slowpath_null);
#else #else
void __warn_printk(const char *fmt, ...) void __warn_printk(const char *fmt, ...)
{ {

View File

@@ -311,7 +311,7 @@ config HEADERS_CHECK
relevant for userspace, say 'Y'. relevant for userspace, say 'Y'.
config OPTIMIZE_INLINING config OPTIMIZE_INLINING
bool "Allow compiler to uninline functions marked 'inline'" def_bool y
help help
This option determines if the kernel forces gcc to inline the functions This option determines if the kernel forces gcc to inline the functions
developers have marked 'inline'. Doing so takes away freedom from gcc to developers have marked 'inline'. Doing so takes away freedom from gcc to
@@ -322,8 +322,6 @@ config OPTIMIZE_INLINING
decision will become the default in the future. Until then this option decision will become the default in the future. Until then this option
is there to test gcc for this. is there to test gcc for this.
If unsure, say N.
config DEBUG_SECTION_MISMATCH config DEBUG_SECTION_MISMATCH
bool "Enable full Section mismatch analysis" bool "Enable full Section mismatch analysis"
help help

View File

@@ -181,6 +181,15 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
} }
} }
/*
* BUG() and WARN_ON() families don't print a custom debug message
* before triggering the exception handler, so we must add the
* "cut here" line now. WARN() issues its own "cut here" before the
* extra debugging message it writes before triggering the handler.
*/
if ((bug->flags & BUGFLAG_NO_CUT_HERE) == 0)
printk(KERN_DEFAULT CUT_HERE);
if (warning) { if (warning) {
/* this is a WARN_ON rather than BUG/BUG_ON */ /* this is a WARN_ON rather than BUG/BUG_ON */
__warn(file, line, (void *)bugaddr, BUG_GET_TAINT(bug), regs, __warn(file, line, (void *)bugaddr, BUG_GET_TAINT(bug), regs,
@@ -188,8 +197,6 @@ enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
return BUG_TRAP_TYPE_WARN; return BUG_TRAP_TYPE_WARN;
} }
printk(KERN_DEFAULT CUT_HERE);
if (file) if (file)
pr_crit("kernel BUG at %s:%u!\n", file, line); pr_crit("kernel BUG at %s:%u!\n", file, line);
else else

View File

@@ -10,6 +10,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/sort.h> #include <linux/sort.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/extable.h>
#ifndef ARCH_HAS_RELATIVE_EXTABLE #ifndef ARCH_HAS_RELATIVE_EXTABLE
#define ex_to_insn(x) ((x)->insn) #define ex_to_insn(x) ((x)->insn)

View File

@@ -36,12 +36,12 @@ static inline size_t genradix_depth_size(unsigned depth)
#define GENRADIX_DEPTH_MASK \ #define GENRADIX_DEPTH_MASK \
((unsigned long) (roundup_pow_of_two(GENRADIX_MAX_DEPTH + 1) - 1)) ((unsigned long) (roundup_pow_of_two(GENRADIX_MAX_DEPTH + 1) - 1))
unsigned genradix_root_to_depth(struct genradix_root *r) static inline unsigned genradix_root_to_depth(struct genradix_root *r)
{ {
return (unsigned long) r & GENRADIX_DEPTH_MASK; return (unsigned long) r & GENRADIX_DEPTH_MASK;
} }
struct genradix_node *genradix_root_to_node(struct genradix_root *r) static inline struct genradix_node *genradix_root_to_node(struct genradix_root *r)
{ {
return (void *) ((unsigned long) r & ~GENRADIX_DEPTH_MASK); return (void *) ((unsigned long) r & ~GENRADIX_DEPTH_MASK);
} }

View File

@@ -270,25 +270,4 @@ void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
} }
EXPORT_SYMBOL(print_hex_dump); EXPORT_SYMBOL(print_hex_dump);
#if !defined(CONFIG_DYNAMIC_DEBUG)
/**
* print_hex_dump_bytes - shorthand form of print_hex_dump() with default params
* @prefix_str: string to prefix each line with;
* caller supplies trailing spaces for alignment if desired
* @prefix_type: controls whether prefix of an offset, address, or none
* is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
* @buf: data blob to dump
* @len: number of bytes in the @buf
*
* Calls print_hex_dump(), with log level of KERN_DEBUG,
* rowsize of 16, groupsize of 1, and ASCII output included.
*/
void print_hex_dump_bytes(const char *prefix_str, int prefix_type,
const void *buf, size_t len)
{
print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, 16, 1,
buf, len, true);
}
EXPORT_SYMBOL(print_hex_dump_bytes);
#endif /* !defined(CONFIG_DYNAMIC_DEBUG) */
#endif /* defined(CONFIG_PRINTK) */ #endif /* defined(CONFIG_PRINTK) */

View File

@@ -83,17 +83,19 @@ next:
ALIGN((uintptr_t)ir, 4)) && ALIGN((uintptr_t)ir, 4)) &&
(ir < limit) && (*ir == 0)) (ir < limit) && (*ir == 0))
ir++; ir++;
for (; (ir + 4) <= limit; ir += 4) { if (IS_ALIGNED((uintptr_t)ir, 4)) {
dv = *((u32 *)ir); for (; (ir + 4) <= limit; ir += 4) {
if (dv) { dv = *((u32 *)ir);
if (dv) {
# if defined(__LITTLE_ENDIAN) # if defined(__LITTLE_ENDIAN)
ir += __builtin_ctz(dv) >> 3; ir += __builtin_ctz(dv) >> 3;
# elif defined(__BIG_ENDIAN) # elif defined(__BIG_ENDIAN)
ir += __builtin_clz(dv) >> 3; ir += __builtin_clz(dv) >> 3;
# else # else
# error "missing endian definition" # error "missing endian definition"
# endif # endif
break; break;
}
} }
} }
#endif #endif

View File

@@ -77,26 +77,10 @@ static inline void erase_cached(struct test_node *node, struct rb_root_cached *r
} }
static inline u32 augment_recompute(struct test_node *node) #define NODE_VAL(node) ((node)->val)
{
u32 max = node->val, child_augmented;
if (node->rb.rb_left) {
child_augmented = rb_entry(node->rb.rb_left, struct test_node,
rb)->augmented;
if (max < child_augmented)
max = child_augmented;
}
if (node->rb.rb_right) {
child_augmented = rb_entry(node->rb.rb_right, struct test_node,
rb)->augmented;
if (max < child_augmented)
max = child_augmented;
}
return max;
}
RB_DECLARE_CALLBACKS(static, augment_callbacks, struct test_node, rb, RB_DECLARE_CALLBACKS_MAX(static, augment_callbacks,
u32, augmented, augment_recompute) struct test_node, rb, u32, augmented, NODE_VAL)
static void insert_augmented(struct test_node *node, static void insert_augmented(struct test_node *node,
struct rb_root_cached *root) struct rb_root_cached *root)
@@ -238,7 +222,20 @@ static void check_augmented(int nr_nodes)
check(nr_nodes); check(nr_nodes);
for (rb = rb_first(&root.rb_root); rb; rb = rb_next(rb)) { for (rb = rb_first(&root.rb_root); rb; rb = rb_next(rb)) {
struct test_node *node = rb_entry(rb, struct test_node, rb); struct test_node *node = rb_entry(rb, struct test_node, rb);
WARN_ON_ONCE(node->augmented != augment_recompute(node)); u32 subtree, max = node->val;
if (node->rb.rb_left) {
subtree = rb_entry(node->rb.rb_left, struct test_node,
rb)->augmented;
if (max < subtree)
max = subtree;
}
if (node->rb.rb_right) {
subtree = rb_entry(node->rb.rb_right, struct test_node,
rb)->augmented;
if (max < subtree)
max = subtree;
}
WARN_ON_ONCE(node->augmented != max);
} }
} }

View File

@@ -173,8 +173,9 @@ EXPORT_SYMBOL(strlcpy);
* doesn't unnecessarily force the tail of the destination buffer to be * doesn't unnecessarily force the tail of the destination buffer to be
* zeroed. If zeroing is desired please use strscpy_pad(). * zeroed. If zeroing is desired please use strscpy_pad().
* *
* Return: The number of characters copied (not including the trailing * Returns:
* %NUL) or -E2BIG if the destination buffer wasn't big enough. * * The number of characters copied (not including the trailing %NUL)
* * -E2BIG if count is 0 or @src was truncated.
*/ */
ssize_t strscpy(char *dest, const char *src, size_t count) ssize_t strscpy(char *dest, const char *src, size_t count)
{ {
@@ -182,7 +183,7 @@ ssize_t strscpy(char *dest, const char *src, size_t count)
size_t max = count; size_t max = count;
long res = 0; long res = 0;
if (count == 0) if (count == 0 || WARN_ON_ONCE(count > INT_MAX))
return -E2BIG; return -E2BIG;
#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
@@ -253,8 +254,9 @@ EXPORT_SYMBOL(strscpy);
* For full explanation of why you may want to consider using the * For full explanation of why you may want to consider using the
* 'strscpy' functions please see the function docstring for strscpy(). * 'strscpy' functions please see the function docstring for strscpy().
* *
* Return: The number of characters copied (not including the trailing * Returns:
* %NUL) or -E2BIG if the destination buffer wasn't big enough. * * The number of characters copied (not including the trailing %NUL)
* * -E2BIG if count is 0 or @src was truncated.
*/ */
ssize_t strscpy_pad(char *dest, const char *src, size_t count) ssize_t strscpy_pad(char *dest, const char *src, size_t count)
{ {

View File

@@ -6,6 +6,7 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/mm.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/word-at-a-time.h> #include <asm/word-at-a-time.h>
@@ -108,7 +109,7 @@ long strncpy_from_user(char *dst, const char __user *src, long count)
return 0; return 0;
max_addr = user_addr_max(); max_addr = user_addr_max();
src_addr = (unsigned long)src; src_addr = (unsigned long)untagged_addr(src);
if (likely(src_addr < max_addr)) { if (likely(src_addr < max_addr)) {
unsigned long max = max_addr - src_addr; unsigned long max = max_addr - src_addr;
long retval; long retval;

View File

@@ -2,6 +2,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/mm.h>
#include <asm/word-at-a-time.h> #include <asm/word-at-a-time.h>
@@ -109,7 +110,7 @@ long strnlen_user(const char __user *str, long count)
return 0; return 0;
max_addr = user_addr_max(); max_addr = user_addr_max();
src_addr = (unsigned long)str; src_addr = (unsigned long)untagged_addr(str);
if (likely(src_addr < max_addr)) { if (likely(src_addr < max_addr)) {
unsigned long max = max_addr - src_addr; unsigned long max = max_addr - src_addr;
long retval; long retval;

View File

@@ -46,6 +46,8 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
if (WARN_ON_ONCE(nr_frames > vec->nr_allocated)) if (WARN_ON_ONCE(nr_frames > vec->nr_allocated))
nr_frames = vec->nr_allocated; nr_frames = vec->nr_allocated;
start = untagged_addr(start);
down_read(&mm->mmap_sem); down_read(&mm->mmap_sem);
locked = 1; locked = 1;
vma = find_vma_intersection(mm, start, start + 1); vma = find_vma_intersection(mm, start, start + 1);

View File

@@ -788,6 +788,8 @@ static long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
if (!nr_pages) if (!nr_pages)
return 0; return 0;
start = untagged_addr(start);
VM_BUG_ON(!!pages != !!(gup_flags & FOLL_GET)); VM_BUG_ON(!!pages != !!(gup_flags & FOLL_GET));
/* /*
@@ -950,6 +952,8 @@ int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
struct vm_area_struct *vma; struct vm_area_struct *vma;
vm_fault_t ret, major = 0; vm_fault_t ret, major = 0;
address = untagged_addr(address);
if (unlocked) if (unlocked)
fault_flags |= FAULT_FLAG_ALLOW_RETRY; fault_flags |= FAULT_FLAG_ALLOW_RETRY;

View File

@@ -39,7 +39,7 @@ vm_fault_t do_swap_page(struct vm_fault *vmf);
void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *start_vma, void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *start_vma,
unsigned long floor, unsigned long ceiling); unsigned long floor, unsigned long ceiling);
static inline bool can_madv_dontneed_vma(struct vm_area_struct *vma) static inline bool can_madv_lru_vma(struct vm_area_struct *vma)
{ {
return !(vma->vm_flags & (VM_LOCKED|VM_HUGETLB|VM_PFNMAP)); return !(vma->vm_flags & (VM_LOCKED|VM_HUGETLB|VM_PFNMAP));
} }

View File

@@ -11,6 +11,7 @@
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <linux/mempolicy.h> #include <linux/mempolicy.h>
#include <linux/page-isolation.h> #include <linux/page-isolation.h>
#include <linux/page_idle.h>
#include <linux/userfaultfd_k.h> #include <linux/userfaultfd_k.h>
#include <linux/hugetlb.h> #include <linux/hugetlb.h>
#include <linux/falloc.h> #include <linux/falloc.h>
@@ -31,6 +32,11 @@
#include "internal.h" #include "internal.h"
struct madvise_walk_private {
struct mmu_gather *tlb;
bool pageout;
};
/* /*
* Any behaviour which results in changes to the vma->vm_flags needs to * Any behaviour which results in changes to the vma->vm_flags needs to
* take mmap_sem for writing. Others, which simply traverse vmas, need * take mmap_sem for writing. Others, which simply traverse vmas, need
@@ -42,6 +48,8 @@ static int madvise_need_mmap_write(int behavior)
case MADV_REMOVE: case MADV_REMOVE:
case MADV_WILLNEED: case MADV_WILLNEED:
case MADV_DONTNEED: case MADV_DONTNEED:
case MADV_COLD:
case MADV_PAGEOUT:
case MADV_FREE: case MADV_FREE:
return 0; return 0;
default: default:
@@ -289,6 +297,254 @@ static long madvise_willneed(struct vm_area_struct *vma,
return 0; return 0;
} }
static int madvise_cold_or_pageout_pte_range(pmd_t *pmd,
unsigned long addr, unsigned long end,
struct mm_walk *walk)
{
struct madvise_walk_private *private = walk->private;
struct mmu_gather *tlb = private->tlb;
bool pageout = private->pageout;
struct mm_struct *mm = tlb->mm;
struct vm_area_struct *vma = walk->vma;
pte_t *orig_pte, *pte, ptent;
spinlock_t *ptl;
struct page *page = NULL;
LIST_HEAD(page_list);
if (fatal_signal_pending(current))
return -EINTR;
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
if (pmd_trans_huge(*pmd)) {
pmd_t orig_pmd;
unsigned long next = pmd_addr_end(addr, end);
tlb_change_page_size(tlb, HPAGE_PMD_SIZE);
ptl = pmd_trans_huge_lock(pmd, vma);
if (!ptl)
return 0;
orig_pmd = *pmd;
if (is_huge_zero_pmd(orig_pmd))
goto huge_unlock;
if (unlikely(!pmd_present(orig_pmd))) {
VM_BUG_ON(thp_migration_supported() &&
!is_pmd_migration_entry(orig_pmd));
goto huge_unlock;
}
page = pmd_page(orig_pmd);
if (next - addr != HPAGE_PMD_SIZE) {
int err;
if (page_mapcount(page) != 1)
goto huge_unlock;
get_page(page);
spin_unlock(ptl);
lock_page(page);
err = split_huge_page(page);
unlock_page(page);
put_page(page);
if (!err)
goto regular_page;
return 0;
}
if (pmd_young(orig_pmd)) {
pmdp_invalidate(vma, addr, pmd);
orig_pmd = pmd_mkold(orig_pmd);
set_pmd_at(mm, addr, pmd, orig_pmd);
tlb_remove_pmd_tlb_entry(tlb, pmd, addr);
}
ClearPageReferenced(page);
test_and_clear_page_young(page);
if (pageout) {
if (!isolate_lru_page(page))
list_add(&page->lru, &page_list);
} else
deactivate_page(page);
huge_unlock:
spin_unlock(ptl);
if (pageout)
reclaim_pages(&page_list);
return 0;
}
if (pmd_trans_unstable(pmd))
return 0;
regular_page:
#endif
tlb_change_page_size(tlb, PAGE_SIZE);
orig_pte = pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
flush_tlb_batched_pending(mm);
arch_enter_lazy_mmu_mode();
for (; addr < end; pte++, addr += PAGE_SIZE) {
ptent = *pte;
if (pte_none(ptent))
continue;
if (!pte_present(ptent))
continue;
page = vm_normal_page(vma, addr, ptent);
if (!page)
continue;
/*
* Creating a THP page is expensive so split it only if we
* are sure it's worth. Split it if we are only owner.
*/
if (PageTransCompound(page)) {
if (page_mapcount(page) != 1)
break;
get_page(page);
if (!trylock_page(page)) {
put_page(page);
break;
}
pte_unmap_unlock(orig_pte, ptl);
if (split_huge_page(page)) {
unlock_page(page);
put_page(page);
pte_offset_map_lock(mm, pmd, addr, &ptl);
break;
}
unlock_page(page);
put_page(page);
pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
pte--;
addr -= PAGE_SIZE;
continue;
}
VM_BUG_ON_PAGE(PageTransCompound(page), page);
if (pte_young(ptent)) {
ptent = ptep_get_and_clear_full(mm, addr, pte,
tlb->fullmm);
ptent = pte_mkold(ptent);
set_pte_at(mm, addr, pte, ptent);
tlb_remove_tlb_entry(tlb, pte, addr);
}
/*
* We are deactivating a page for accelerating reclaiming.
* VM couldn't reclaim the page unless we clear PG_young.
* As a side effect, it makes confuse idle-page tracking
* because they will miss recent referenced history.
*/
ClearPageReferenced(page);
test_and_clear_page_young(page);
if (pageout) {
if (!isolate_lru_page(page))
list_add(&page->lru, &page_list);
} else
deactivate_page(page);
}
arch_leave_lazy_mmu_mode();
pte_unmap_unlock(orig_pte, ptl);
if (pageout)
reclaim_pages(&page_list);
cond_resched();
return 0;
}
static const struct mm_walk_ops cold_walk_ops = {
.pmd_entry = madvise_cold_or_pageout_pte_range,
};
static void madvise_cold_page_range(struct mmu_gather *tlb,
struct vm_area_struct *vma,
unsigned long addr, unsigned long end)
{
struct madvise_walk_private walk_private = {
.pageout = false,
.tlb = tlb,
};
tlb_start_vma(tlb, vma);
walk_page_range(vma->vm_mm, addr, end, &cold_walk_ops, &walk_private);
tlb_end_vma(tlb, vma);
}
static long madvise_cold(struct vm_area_struct *vma,
struct vm_area_struct **prev,
unsigned long start_addr, unsigned long end_addr)
{
struct mm_struct *mm = vma->vm_mm;
struct mmu_gather tlb;
*prev = vma;
if (!can_madv_lru_vma(vma))
return -EINVAL;
lru_add_drain();
tlb_gather_mmu(&tlb, mm, start_addr, end_addr);
madvise_cold_page_range(&tlb, vma, start_addr, end_addr);
tlb_finish_mmu(&tlb, start_addr, end_addr);
return 0;
}
static void madvise_pageout_page_range(struct mmu_gather *tlb,
struct vm_area_struct *vma,
unsigned long addr, unsigned long end)
{
struct madvise_walk_private walk_private = {
.pageout = true,
.tlb = tlb,
};
tlb_start_vma(tlb, vma);
walk_page_range(vma->vm_mm, addr, end, &cold_walk_ops, &walk_private);
tlb_end_vma(tlb, vma);
}
static inline bool can_do_pageout(struct vm_area_struct *vma)
{
if (vma_is_anonymous(vma))
return true;
if (!vma->vm_file)
return false;
/*
* paging out pagecache only for non-anonymous mappings that correspond
* to the files the calling process could (if tried) open for writing;
* otherwise we'd be including shared non-exclusive mappings, which
* opens a side channel.
*/
return inode_owner_or_capable(file_inode(vma->vm_file)) ||
inode_permission(file_inode(vma->vm_file), MAY_WRITE) == 0;
}
static long madvise_pageout(struct vm_area_struct *vma,
struct vm_area_struct **prev,
unsigned long start_addr, unsigned long end_addr)
{
struct mm_struct *mm = vma->vm_mm;
struct mmu_gather tlb;
*prev = vma;
if (!can_madv_lru_vma(vma))
return -EINVAL;
if (!can_do_pageout(vma))
return 0;
lru_add_drain();
tlb_gather_mmu(&tlb, mm, start_addr, end_addr);
madvise_pageout_page_range(&tlb, vma, start_addr, end_addr);
tlb_finish_mmu(&tlb, start_addr, end_addr);
return 0;
}
static int madvise_free_pte_range(pmd_t *pmd, unsigned long addr, static int madvise_free_pte_range(pmd_t *pmd, unsigned long addr,
unsigned long end, struct mm_walk *walk) unsigned long end, struct mm_walk *walk)
@@ -493,7 +749,7 @@ static long madvise_dontneed_free(struct vm_area_struct *vma,
int behavior) int behavior)
{ {
*prev = vma; *prev = vma;
if (!can_madv_dontneed_vma(vma)) if (!can_madv_lru_vma(vma))
return -EINVAL; return -EINVAL;
if (!userfaultfd_remove(vma, start, end)) { if (!userfaultfd_remove(vma, start, end)) {
@@ -515,7 +771,7 @@ static long madvise_dontneed_free(struct vm_area_struct *vma,
*/ */
return -ENOMEM; return -ENOMEM;
} }
if (!can_madv_dontneed_vma(vma)) if (!can_madv_lru_vma(vma))
return -EINVAL; return -EINVAL;
if (end > vma->vm_end) { if (end > vma->vm_end) {
/* /*
@@ -669,6 +925,10 @@ madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev,
return madvise_remove(vma, prev, start, end); return madvise_remove(vma, prev, start, end);
case MADV_WILLNEED: case MADV_WILLNEED:
return madvise_willneed(vma, prev, start, end); return madvise_willneed(vma, prev, start, end);
case MADV_COLD:
return madvise_cold(vma, prev, start, end);
case MADV_PAGEOUT:
return madvise_pageout(vma, prev, start, end);
case MADV_FREE: case MADV_FREE:
case MADV_DONTNEED: case MADV_DONTNEED:
return madvise_dontneed_free(vma, prev, start, end, behavior); return madvise_dontneed_free(vma, prev, start, end, behavior);
@@ -690,6 +950,8 @@ madvise_behavior_valid(int behavior)
case MADV_WILLNEED: case MADV_WILLNEED:
case MADV_DONTNEED: case MADV_DONTNEED:
case MADV_FREE: case MADV_FREE:
case MADV_COLD:
case MADV_PAGEOUT:
#ifdef CONFIG_KSM #ifdef CONFIG_KSM
case MADV_MERGEABLE: case MADV_MERGEABLE:
case MADV_UNMERGEABLE: case MADV_UNMERGEABLE:
@@ -784,6 +1046,8 @@ SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior)
size_t len; size_t len;
struct blk_plug plug; struct blk_plug plug;
start = untagged_addr(start);
if (!madvise_behavior_valid(behavior)) if (!madvise_behavior_valid(behavior))
return error; return error;

View File

@@ -2943,6 +2943,16 @@ int __memcg_kmem_charge_memcg(struct page *page, gfp_t gfp, int order,
if (!cgroup_subsys_on_dfl(memory_cgrp_subsys) && if (!cgroup_subsys_on_dfl(memory_cgrp_subsys) &&
!page_counter_try_charge(&memcg->kmem, nr_pages, &counter)) { !page_counter_try_charge(&memcg->kmem, nr_pages, &counter)) {
/*
* Enforce __GFP_NOFAIL allocation because callers are not
* prepared to see failures and likely do not have any failure
* handling code.
*/
if (gfp & __GFP_NOFAIL) {
page_counter_charge(&memcg->kmem, nr_pages);
return 0;
}
cancel_charge(memcg, nr_pages); cancel_charge(memcg, nr_pages);
return -ENOMEM; return -ENOMEM;
} }

View File

@@ -1405,6 +1405,7 @@ static long kernel_mbind(unsigned long start, unsigned long len,
int err; int err;
unsigned short mode_flags; unsigned short mode_flags;
start = untagged_addr(start);
mode_flags = mode & MPOL_MODE_FLAGS; mode_flags = mode & MPOL_MODE_FLAGS;
mode &= ~MPOL_MODE_FLAGS; mode &= ~MPOL_MODE_FLAGS;
if (mode >= MPOL_MAX) if (mode >= MPOL_MAX)
@@ -1558,6 +1559,8 @@ static int kernel_get_mempolicy(int __user *policy,
int uninitialized_var(pval); int uninitialized_var(pval);
nodemask_t nodes; nodemask_t nodes;
addr = untagged_addr(addr);
if (nmask != NULL && maxnode < nr_node_ids) if (nmask != NULL && maxnode < nr_node_ids)
return -EINVAL; return -EINVAL;

View File

@@ -1612,7 +1612,7 @@ static int do_pages_move(struct mm_struct *mm, nodemask_t task_nodes,
goto out_flush; goto out_flush;
if (get_user(node, nodes + i)) if (get_user(node, nodes + i))
goto out_flush; goto out_flush;
addr = (unsigned long)p; addr = (unsigned long)untagged_addr(p);
err = -ENODEV; err = -ENODEV;
if (node < 0 || node >= MAX_NUMNODES) if (node < 0 || node >= MAX_NUMNODES)

View File

@@ -256,6 +256,8 @@ SYSCALL_DEFINE3(mincore, unsigned long, start, size_t, len,
unsigned long pages; unsigned long pages;
unsigned char *tmp; unsigned char *tmp;
start = untagged_addr(start);
/* Check the start address: needs to be page-aligned.. */ /* Check the start address: needs to be page-aligned.. */
if (start & ~PAGE_MASK) if (start & ~PAGE_MASK)
return -EINVAL; return -EINVAL;

Some files were not shown because too many files have changed in this diff Show More