mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 18:51:56 -04:00
Merge branch 'akpm' (patches from Andrew)
Merge second patch-bomb from Andrew Morton: - most of the rest of MM - procfs - lib/ updates - printk updates - bitops infrastructure tweaks - checkpatch updates - nilfs2 update - signals - various other misc bits: coredump, seqfile, kexec, pidns, zlib, ipc, dma-debug, dma-mapping, ... * emailed patches from Andrew Morton <[email protected]>: (102 commits) ipc,msg: drop dst nil validation in copy_msg include/linux/zutil.h: fix usage example of zlib_adler32() panic: release stale console lock to always get the logbuf printed out dma-debug: check nents in dma_sync_sg* dma-mapping: tidy up dma_parms default handling pidns: fix set/getpriority and ioprio_set/get in PRIO_USER mode kexec: use file name as the output message prefix fs, seqfile: always allow oom killer seq_file: reuse string_escape_str() fs/seq_file: use seq_* helpers in seq_hex_dump() coredump: change zap_threads() and zap_process() to use for_each_thread() coredump: ensure all coredumping tasks have SIGNAL_GROUP_COREDUMP signal: remove jffs2_garbage_collect_thread()->allow_signal(SIGCONT) signal: introduce kernel_signal_stop() to fix jffs2_garbage_collect_thread() signal: turn dequeue_signal_lock() into kernel_dequeue_signal() signals: kill block_all_signals() and unblock_all_signals() nilfs2: fix gcc uninitialized-variable warnings in powerpc build nilfs2: fix gcc unused-but-set-variable warnings MAINTAINERS: nilfs2: add header file for tracing nilfs2: add tracepoints for analyzing reading and writing metadata files ...
This commit is contained in:
commit
ad804a0b2a
211 changed files with 2298 additions and 1632 deletions
12
mm/Kconfig
12
mm/Kconfig
|
|
@ -200,18 +200,6 @@ config MEMORY_HOTREMOVE
|
|||
depends on MEMORY_HOTPLUG && ARCH_ENABLE_MEMORY_HOTREMOVE
|
||||
depends on MIGRATION
|
||||
|
||||
#
|
||||
# If we have space for more page flags then we can enable additional
|
||||
# optimizations and functionality.
|
||||
#
|
||||
# Regular Sparsemem takes page flag bits for the sectionid if it does not
|
||||
# use a virtual memmap. Disable extended page flags for 32 bit platforms
|
||||
# that require the use of a sectionid in the page flags.
|
||||
#
|
||||
config PAGEFLAGS_EXTENDED
|
||||
def_bool y
|
||||
depends on 64BIT || SPARSEMEM_VMEMMAP || !SPARSEMEM
|
||||
|
||||
# Heavily threaded applications may benefit from splitting the mm-wide
|
||||
# page_table_lock, so that faults on different parts of the user address
|
||||
# space can be handled with less contention: split it at this NR_CPUS.
|
||||
|
|
|
|||
|
|
@ -637,7 +637,7 @@ struct bdi_writeback *wb_get_create(struct backing_dev_info *bdi,
|
|||
{
|
||||
struct bdi_writeback *wb;
|
||||
|
||||
might_sleep_if(gfp & __GFP_WAIT);
|
||||
might_sleep_if(gfpflags_allow_blocking(gfp));
|
||||
|
||||
if (!memcg_css->parent)
|
||||
return &bdi->wb;
|
||||
|
|
|
|||
|
|
@ -25,12 +25,7 @@ static const struct trace_print_flags pageflag_names[] = {
|
|||
{1UL << PG_private, "private" },
|
||||
{1UL << PG_private_2, "private_2" },
|
||||
{1UL << PG_writeback, "writeback" },
|
||||
#ifdef CONFIG_PAGEFLAGS_EXTENDED
|
||||
{1UL << PG_head, "head" },
|
||||
{1UL << PG_tail, "tail" },
|
||||
#else
|
||||
{1UL << PG_compound, "compound" },
|
||||
#endif
|
||||
{1UL << PG_swapcache, "swapcache" },
|
||||
{1UL << PG_mappedtodisk, "mappedtodisk" },
|
||||
{1UL << PG_reclaim, "reclaim" },
|
||||
|
|
|
|||
|
|
@ -326,7 +326,7 @@ void *dma_pool_alloc(struct dma_pool *pool, gfp_t mem_flags,
|
|||
size_t offset;
|
||||
void *retval;
|
||||
|
||||
might_sleep_if(mem_flags & __GFP_WAIT);
|
||||
might_sleep_if(gfpflags_allow_blocking(mem_flags));
|
||||
|
||||
spin_lock_irqsave(&pool->lock, flags);
|
||||
list_for_each_entry(page, &pool->page_list, page_list) {
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
static struct {
|
||||
struct fault_attr attr;
|
||||
bool ignore_gfp_wait;
|
||||
bool ignore_gfp_reclaim;
|
||||
bool cache_filter;
|
||||
} failslab = {
|
||||
.attr = FAULT_ATTR_INITIALIZER,
|
||||
.ignore_gfp_wait = true,
|
||||
.ignore_gfp_reclaim = true,
|
||||
.cache_filter = false,
|
||||
};
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ bool should_failslab(size_t size, gfp_t gfpflags, unsigned long cache_flags)
|
|||
if (gfpflags & __GFP_NOFAIL)
|
||||
return false;
|
||||
|
||||
if (failslab.ignore_gfp_wait && (gfpflags & __GFP_WAIT))
|
||||
if (failslab.ignore_gfp_reclaim && (gfpflags & __GFP_RECLAIM))
|
||||
return false;
|
||||
|
||||
if (failslab.cache_filter && !(cache_flags & SLAB_FAILSLAB))
|
||||
|
|
@ -42,7 +42,7 @@ static int __init failslab_debugfs_init(void)
|
|||
return PTR_ERR(dir);
|
||||
|
||||
if (!debugfs_create_bool("ignore-gfp-wait", mode, dir,
|
||||
&failslab.ignore_gfp_wait))
|
||||
&failslab.ignore_gfp_reclaim))
|
||||
goto fail;
|
||||
if (!debugfs_create_bool("cache-filter", mode, dir,
|
||||
&failslab.cache_filter))
|
||||
|
|
|
|||
|
|
@ -1722,7 +1722,7 @@ no_cached_page:
|
|||
goto out;
|
||||
}
|
||||
error = add_to_page_cache_lru(page, mapping, index,
|
||||
GFP_KERNEL & mapping_gfp_mask(mapping));
|
||||
mapping_gfp_constraint(mapping, GFP_KERNEL));
|
||||
if (error) {
|
||||
page_cache_release(page);
|
||||
if (error == -EEXIST) {
|
||||
|
|
@ -1824,7 +1824,7 @@ static int page_cache_read(struct file *file, pgoff_t offset)
|
|||
return -ENOMEM;
|
||||
|
||||
ret = add_to_page_cache_lru(page, mapping, offset,
|
||||
GFP_KERNEL & mapping_gfp_mask(mapping));
|
||||
mapping_gfp_constraint(mapping, GFP_KERNEL));
|
||||
if (ret == 0)
|
||||
ret = mapping->a_ops->readpage(file, page);
|
||||
else if (ret == -EEXIST)
|
||||
|
|
@ -2713,7 +2713,7 @@ EXPORT_SYMBOL(generic_file_write_iter);
|
|||
* page is known to the local caching routines.
|
||||
*
|
||||
* The @gfp_mask argument specifies whether I/O may be performed to release
|
||||
* this page (__GFP_IO), and whether the call may block (__GFP_WAIT & __GFP_FS).
|
||||
* this page (__GFP_IO), and whether the call may block (__GFP_RECLAIM & __GFP_FS).
|
||||
*
|
||||
*/
|
||||
int try_to_release_page(struct page *page, gfp_t gfp_mask)
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ static void set_recommended_min_free_kbytes(void)
|
|||
for_each_populated_zone(zone)
|
||||
nr_zones++;
|
||||
|
||||
/* Make sure at least 2 hugepages are free for MIGRATE_RESERVE */
|
||||
/* Ensure 2 pageblocks are free to assist fragmentation avoidance */
|
||||
recommended_min = pageblock_nr_pages * nr_zones * 2;
|
||||
|
||||
/*
|
||||
|
|
@ -786,7 +786,7 @@ static int __do_huge_pmd_anonymous_page(struct mm_struct *mm,
|
|||
|
||||
static inline gfp_t alloc_hugepage_gfpmask(int defrag, gfp_t extra_gfp)
|
||||
{
|
||||
return (GFP_TRANSHUGE & ~(defrag ? 0 : __GFP_WAIT)) | extra_gfp;
|
||||
return (GFP_TRANSHUGE & ~(defrag ? 0 : __GFP_RECLAIM)) | extra_gfp;
|
||||
}
|
||||
|
||||
/* Caller must hold page table lock. */
|
||||
|
|
@ -1755,8 +1755,7 @@ static void __split_huge_page_refcount(struct page *page,
|
|||
(1L << PG_unevictable)));
|
||||
page_tail->flags |= (1L << PG_dirty);
|
||||
|
||||
/* clear PageTail before overwriting first_page */
|
||||
smp_wmb();
|
||||
clear_compound_head(page_tail);
|
||||
|
||||
if (page_is_young(page))
|
||||
set_page_young(page_tail);
|
||||
|
|
@ -2413,8 +2412,7 @@ static bool khugepaged_prealloc_page(struct page **hpage, bool *wait)
|
|||
|
||||
static struct page *
|
||||
khugepaged_alloc_page(struct page **hpage, gfp_t gfp, struct mm_struct *mm,
|
||||
struct vm_area_struct *vma, unsigned long address,
|
||||
int node)
|
||||
unsigned long address, int node)
|
||||
{
|
||||
VM_BUG_ON_PAGE(*hpage, *hpage);
|
||||
|
||||
|
|
@ -2481,8 +2479,7 @@ static bool khugepaged_prealloc_page(struct page **hpage, bool *wait)
|
|||
|
||||
static struct page *
|
||||
khugepaged_alloc_page(struct page **hpage, gfp_t gfp, struct mm_struct *mm,
|
||||
struct vm_area_struct *vma, unsigned long address,
|
||||
int node)
|
||||
unsigned long address, int node)
|
||||
{
|
||||
up_read(&mm->mmap_sem);
|
||||
VM_BUG_ON(!*hpage);
|
||||
|
|
@ -2530,7 +2527,7 @@ static void collapse_huge_page(struct mm_struct *mm,
|
|||
__GFP_THISNODE;
|
||||
|
||||
/* release the mmap_sem read lock. */
|
||||
new_page = khugepaged_alloc_page(hpage, gfp, mm, vma, address, node);
|
||||
new_page = khugepaged_alloc_page(hpage, gfp, mm, address, node);
|
||||
if (!new_page)
|
||||
return;
|
||||
|
||||
|
|
|
|||
35
mm/hugetlb.c
35
mm/hugetlb.c
|
|
@ -994,23 +994,22 @@ static int hstate_next_node_to_free(struct hstate *h, nodemask_t *nodes_allowed)
|
|||
|
||||
#if defined(CONFIG_CMA) && defined(CONFIG_X86_64)
|
||||
static void destroy_compound_gigantic_page(struct page *page,
|
||||
unsigned long order)
|
||||
unsigned int order)
|
||||
{
|
||||
int i;
|
||||
int nr_pages = 1 << order;
|
||||
struct page *p = page + 1;
|
||||
|
||||
for (i = 1; i < nr_pages; i++, p = mem_map_next(p, page, i)) {
|
||||
__ClearPageTail(p);
|
||||
clear_compound_head(p);
|
||||
set_page_refcounted(p);
|
||||
p->first_page = NULL;
|
||||
}
|
||||
|
||||
set_compound_order(page, 0);
|
||||
__ClearPageHead(page);
|
||||
}
|
||||
|
||||
static void free_gigantic_page(struct page *page, unsigned order)
|
||||
static void free_gigantic_page(struct page *page, unsigned int order)
|
||||
{
|
||||
free_contig_range(page_to_pfn(page), 1 << order);
|
||||
}
|
||||
|
|
@ -1054,7 +1053,7 @@ static bool zone_spans_last_pfn(const struct zone *zone,
|
|||
return zone_spans_pfn(zone, last_pfn);
|
||||
}
|
||||
|
||||
static struct page *alloc_gigantic_page(int nid, unsigned order)
|
||||
static struct page *alloc_gigantic_page(int nid, unsigned int order)
|
||||
{
|
||||
unsigned long nr_pages = 1 << order;
|
||||
unsigned long ret, pfn, flags;
|
||||
|
|
@ -1090,7 +1089,7 @@ static struct page *alloc_gigantic_page(int nid, unsigned order)
|
|||
}
|
||||
|
||||
static void prep_new_huge_page(struct hstate *h, struct page *page, int nid);
|
||||
static void prep_compound_gigantic_page(struct page *page, unsigned long order);
|
||||
static void prep_compound_gigantic_page(struct page *page, unsigned int order);
|
||||
|
||||
static struct page *alloc_fresh_gigantic_page_node(struct hstate *h, int nid)
|
||||
{
|
||||
|
|
@ -1123,9 +1122,9 @@ static int alloc_fresh_gigantic_page(struct hstate *h,
|
|||
static inline bool gigantic_page_supported(void) { return true; }
|
||||
#else
|
||||
static inline bool gigantic_page_supported(void) { return false; }
|
||||
static inline void free_gigantic_page(struct page *page, unsigned order) { }
|
||||
static inline void free_gigantic_page(struct page *page, unsigned int order) { }
|
||||
static inline void destroy_compound_gigantic_page(struct page *page,
|
||||
unsigned long order) { }
|
||||
unsigned int order) { }
|
||||
static inline int alloc_fresh_gigantic_page(struct hstate *h,
|
||||
nodemask_t *nodes_allowed) { return 0; }
|
||||
#endif
|
||||
|
|
@ -1146,7 +1145,7 @@ static void update_and_free_page(struct hstate *h, struct page *page)
|
|||
1 << PG_writeback);
|
||||
}
|
||||
VM_BUG_ON_PAGE(hugetlb_cgroup_from_page(page), page);
|
||||
set_compound_page_dtor(page, NULL);
|
||||
set_compound_page_dtor(page, NULL_COMPOUND_DTOR);
|
||||
set_page_refcounted(page);
|
||||
if (hstate_is_gigantic(h)) {
|
||||
destroy_compound_gigantic_page(page, huge_page_order(h));
|
||||
|
|
@ -1242,7 +1241,7 @@ void free_huge_page(struct page *page)
|
|||
static void prep_new_huge_page(struct hstate *h, struct page *page, int nid)
|
||||
{
|
||||
INIT_LIST_HEAD(&page->lru);
|
||||
set_compound_page_dtor(page, free_huge_page);
|
||||
set_compound_page_dtor(page, HUGETLB_PAGE_DTOR);
|
||||
spin_lock(&hugetlb_lock);
|
||||
set_hugetlb_cgroup(page, NULL);
|
||||
h->nr_huge_pages++;
|
||||
|
|
@ -1251,7 +1250,7 @@ static void prep_new_huge_page(struct hstate *h, struct page *page, int nid)
|
|||
put_page(page); /* free it into the hugepage allocator */
|
||||
}
|
||||
|
||||
static void prep_compound_gigantic_page(struct page *page, unsigned long order)
|
||||
static void prep_compound_gigantic_page(struct page *page, unsigned int order)
|
||||
{
|
||||
int i;
|
||||
int nr_pages = 1 << order;
|
||||
|
|
@ -1276,10 +1275,7 @@ static void prep_compound_gigantic_page(struct page *page, unsigned long order)
|
|||
*/
|
||||
__ClearPageReserved(p);
|
||||
set_page_count(p, 0);
|
||||
p->first_page = page;
|
||||
/* Make sure p->first_page is always valid for PageTail() */
|
||||
smp_wmb();
|
||||
__SetPageTail(p);
|
||||
set_compound_head(p, page);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1294,7 +1290,7 @@ int PageHuge(struct page *page)
|
|||
return 0;
|
||||
|
||||
page = compound_head(page);
|
||||
return get_compound_page_dtor(page) == free_huge_page;
|
||||
return page[1].compound_dtor == HUGETLB_PAGE_DTOR;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(PageHuge);
|
||||
|
||||
|
|
@ -1568,7 +1564,7 @@ static struct page *__alloc_buddy_huge_page(struct hstate *h,
|
|||
if (page) {
|
||||
INIT_LIST_HEAD(&page->lru);
|
||||
r_nid = page_to_nid(page);
|
||||
set_compound_page_dtor(page, free_huge_page);
|
||||
set_compound_page_dtor(page, HUGETLB_PAGE_DTOR);
|
||||
set_hugetlb_cgroup(page, NULL);
|
||||
/*
|
||||
* We incremented the global counters already
|
||||
|
|
@ -1972,7 +1968,8 @@ found:
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void __init prep_compound_huge_page(struct page *page, int order)
|
||||
static void __init prep_compound_huge_page(struct page *page,
|
||||
unsigned int order)
|
||||
{
|
||||
if (unlikely(order > (MAX_ORDER - 1)))
|
||||
prep_compound_gigantic_page(page, order);
|
||||
|
|
@ -2683,7 +2680,7 @@ static int __init hugetlb_init(void)
|
|||
module_init(hugetlb_init);
|
||||
|
||||
/* Should be called on processing a hugepagesz=... option */
|
||||
void __init hugetlb_add_hstate(unsigned order)
|
||||
void __init hugetlb_add_hstate(unsigned int order)
|
||||
{
|
||||
struct hstate *h;
|
||||
unsigned long i;
|
||||
|
|
|
|||
|
|
@ -385,7 +385,7 @@ void __init hugetlb_cgroup_file_init(void)
|
|||
/*
|
||||
* Add cgroup control files only if the huge page consists
|
||||
* of more than two normal pages. This is because we use
|
||||
* page[2].lru.next for storing cgroup details.
|
||||
* page[2].private for storing cgroup details.
|
||||
*/
|
||||
if (huge_page_order(h) >= HUGETLB_CGROUP_MIN_ORDER)
|
||||
__hugetlb_cgroup_file_init(hstate_index(h));
|
||||
|
|
|
|||
|
|
@ -14,6 +14,25 @@
|
|||
#include <linux/fs.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
/*
|
||||
* The set of flags that only affect watermark checking and reclaim
|
||||
* behaviour. This is used by the MM to obey the caller constraints
|
||||
* about IO, FS and watermark checking while ignoring placement
|
||||
* hints such as HIGHMEM usage.
|
||||
*/
|
||||
#define GFP_RECLAIM_MASK (__GFP_RECLAIM|__GFP_HIGH|__GFP_IO|__GFP_FS|\
|
||||
__GFP_NOWARN|__GFP_REPEAT|__GFP_NOFAIL|\
|
||||
__GFP_NORETRY|__GFP_MEMALLOC|__GFP_NOMEMALLOC)
|
||||
|
||||
/* The GFP flags allowed during early boot */
|
||||
#define GFP_BOOT_MASK (__GFP_BITS_MASK & ~(__GFP_RECLAIM|__GFP_IO|__GFP_FS))
|
||||
|
||||
/* Control allocation cpuset and node placement constraints */
|
||||
#define GFP_CONSTRAINT_MASK (__GFP_HARDWALL|__GFP_THISNODE)
|
||||
|
||||
/* Do not use these with a slab allocator */
|
||||
#define GFP_SLAB_BUG_MASK (__GFP_DMA32|__GFP_HIGHMEM|~__GFP_BITS_MASK)
|
||||
|
||||
void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *start_vma,
|
||||
unsigned long floor, unsigned long ceiling);
|
||||
|
||||
|
|
@ -61,9 +80,9 @@ static inline void __get_page_tail_foll(struct page *page,
|
|||
* speculative page access (like in
|
||||
* page_cache_get_speculative()) on tail pages.
|
||||
*/
|
||||
VM_BUG_ON_PAGE(atomic_read(&page->first_page->_count) <= 0, page);
|
||||
VM_BUG_ON_PAGE(atomic_read(&compound_head(page)->_count) <= 0, page);
|
||||
if (get_page_head)
|
||||
atomic_inc(&page->first_page->_count);
|
||||
atomic_inc(&compound_head(page)->_count);
|
||||
get_huge_page_tail(page);
|
||||
}
|
||||
|
||||
|
|
@ -129,6 +148,7 @@ struct alloc_context {
|
|||
int classzone_idx;
|
||||
int migratetype;
|
||||
enum zone_type high_zoneidx;
|
||||
bool spread_dirty_pages;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -157,7 +177,7 @@ __find_buddy_index(unsigned long page_idx, unsigned int order)
|
|||
extern int __isolate_free_page(struct page *page, unsigned int order);
|
||||
extern void __free_pages_bootmem(struct page *page, unsigned long pfn,
|
||||
unsigned int order);
|
||||
extern void prep_compound_page(struct page *page, unsigned long order);
|
||||
extern void prep_compound_page(struct page *page, unsigned int order);
|
||||
#ifdef CONFIG_MEMORY_FAILURE
|
||||
extern bool is_free_buddy_page(struct page *page);
|
||||
#endif
|
||||
|
|
@ -215,7 +235,7 @@ int find_suitable_fallback(struct free_area *area, unsigned int order,
|
|||
* page cannot be allocated or merged in parallel. Alternatively, it must
|
||||
* handle invalid values gracefully, and use page_order_unsafe() below.
|
||||
*/
|
||||
static inline unsigned long page_order(struct page *page)
|
||||
static inline unsigned int page_order(struct page *page)
|
||||
{
|
||||
/* PageBuddy() must be checked by the caller */
|
||||
return page_private(page);
|
||||
|
|
|
|||
|
|
@ -2046,7 +2046,7 @@ retry:
|
|||
if (unlikely(task_in_memcg_oom(current)))
|
||||
goto nomem;
|
||||
|
||||
if (!(gfp_mask & __GFP_WAIT))
|
||||
if (!gfpflags_allow_blocking(gfp_mask))
|
||||
goto nomem;
|
||||
|
||||
mem_cgroup_events(mem_over_limit, MEMCG_MAX, 1);
|
||||
|
|
@ -2120,7 +2120,7 @@ done_restock:
|
|||
/*
|
||||
* If the hierarchy is above the normal consumption range, schedule
|
||||
* reclaim on returning to userland. We can perform reclaim here
|
||||
* if __GFP_WAIT but let's always punt for simplicity and so that
|
||||
* if __GFP_RECLAIM but let's always punt for simplicity and so that
|
||||
* GFP_KERNEL can consistently be used during reclaim. @memcg is
|
||||
* not recorded as it most likely matches current's and won't
|
||||
* change in the meantime. As high limit is checked again before
|
||||
|
|
@ -2801,7 +2801,7 @@ static unsigned long tree_stat(struct mem_cgroup *memcg,
|
|||
return val;
|
||||
}
|
||||
|
||||
static inline unsigned long mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)
|
||||
static unsigned long mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)
|
||||
{
|
||||
unsigned long val;
|
||||
|
||||
|
|
@ -4364,8 +4364,8 @@ static int mem_cgroup_do_precharge(unsigned long count)
|
|||
{
|
||||
int ret;
|
||||
|
||||
/* Try a single bulk charge without reclaim first */
|
||||
ret = try_charge(mc.to, GFP_KERNEL & ~__GFP_WAIT, count);
|
||||
/* Try a single bulk charge without reclaim first, kswapd may wake */
|
||||
ret = try_charge(mc.to, GFP_KERNEL & ~__GFP_DIRECT_RECLAIM, count);
|
||||
if (!ret) {
|
||||
mc.precharge += count;
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -776,8 +776,6 @@ static int me_huge_page(struct page *p, unsigned long pfn)
|
|||
#define lru (1UL << PG_lru)
|
||||
#define swapbacked (1UL << PG_swapbacked)
|
||||
#define head (1UL << PG_head)
|
||||
#define tail (1UL << PG_tail)
|
||||
#define compound (1UL << PG_compound)
|
||||
#define slab (1UL << PG_slab)
|
||||
#define reserved (1UL << PG_reserved)
|
||||
|
||||
|
|
@ -800,12 +798,7 @@ static struct page_state {
|
|||
*/
|
||||
{ slab, slab, MF_MSG_SLAB, me_kernel },
|
||||
|
||||
#ifdef CONFIG_PAGEFLAGS_EXTENDED
|
||||
{ head, head, MF_MSG_HUGE, me_huge_page },
|
||||
{ tail, tail, MF_MSG_HUGE, me_huge_page },
|
||||
#else
|
||||
{ compound, compound, MF_MSG_HUGE, me_huge_page },
|
||||
#endif
|
||||
|
||||
{ sc|dirty, sc|dirty, MF_MSG_DIRTY_SWAPCACHE, me_swapcache_dirty },
|
||||
{ sc|dirty, sc, MF_MSG_CLEAN_SWAPCACHE, me_swapcache_clean },
|
||||
|
|
|
|||
10
mm/mempool.c
10
mm/mempool.c
|
|
@ -320,13 +320,13 @@ void * mempool_alloc(mempool_t *pool, gfp_t gfp_mask)
|
|||
gfp_t gfp_temp;
|
||||
|
||||
VM_WARN_ON_ONCE(gfp_mask & __GFP_ZERO);
|
||||
might_sleep_if(gfp_mask & __GFP_WAIT);
|
||||
might_sleep_if(gfp_mask & __GFP_DIRECT_RECLAIM);
|
||||
|
||||
gfp_mask |= __GFP_NOMEMALLOC; /* don't allocate emergency reserves */
|
||||
gfp_mask |= __GFP_NORETRY; /* don't loop in __alloc_pages */
|
||||
gfp_mask |= __GFP_NOWARN; /* failures are OK */
|
||||
|
||||
gfp_temp = gfp_mask & ~(__GFP_WAIT|__GFP_IO);
|
||||
gfp_temp = gfp_mask & ~(__GFP_DIRECT_RECLAIM|__GFP_IO);
|
||||
|
||||
repeat_alloc:
|
||||
|
||||
|
|
@ -349,7 +349,7 @@ repeat_alloc:
|
|||
}
|
||||
|
||||
/*
|
||||
* We use gfp mask w/o __GFP_WAIT or IO for the first round. If
|
||||
* We use gfp mask w/o direct reclaim or IO for the first round. If
|
||||
* alloc failed with that and @pool was empty, retry immediately.
|
||||
*/
|
||||
if (gfp_temp != gfp_mask) {
|
||||
|
|
@ -358,8 +358,8 @@ repeat_alloc:
|
|||
goto repeat_alloc;
|
||||
}
|
||||
|
||||
/* We must not sleep if !__GFP_WAIT */
|
||||
if (!(gfp_mask & __GFP_WAIT)) {
|
||||
/* We must not sleep if !__GFP_DIRECT_RECLAIM */
|
||||
if (!(gfp_mask & __GFP_DIRECT_RECLAIM)) {
|
||||
spin_unlock_irqrestore(&pool->lock, flags);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1578,7 +1578,7 @@ static struct page *alloc_misplaced_dst_page(struct page *page,
|
|||
(GFP_HIGHUSER_MOVABLE |
|
||||
__GFP_THISNODE | __GFP_NOMEMALLOC |
|
||||
__GFP_NORETRY | __GFP_NOWARN) &
|
||||
~GFP_IOFS, 0);
|
||||
~(__GFP_IO | __GFP_FS), 0);
|
||||
|
||||
return newpage;
|
||||
}
|
||||
|
|
@ -1752,7 +1752,7 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
|
|||
goto out_dropref;
|
||||
|
||||
new_page = alloc_pages_node(node,
|
||||
(GFP_TRANSHUGE | __GFP_THISNODE) & ~__GFP_WAIT,
|
||||
(GFP_TRANSHUGE | __GFP_THISNODE) & ~__GFP_RECLAIM,
|
||||
HPAGE_PMD_ORDER);
|
||||
if (!new_page)
|
||||
goto out_fail;
|
||||
|
|
|
|||
|
|
@ -118,6 +118,15 @@ found:
|
|||
return t;
|
||||
}
|
||||
|
||||
/*
|
||||
* order == -1 means the oom kill is required by sysrq, otherwise only
|
||||
* for display purposes.
|
||||
*/
|
||||
static inline bool is_sysrq_oom(struct oom_control *oc)
|
||||
{
|
||||
return oc->order == -1;
|
||||
}
|
||||
|
||||
/* return true if the task is not adequate as candidate victim task. */
|
||||
static bool oom_unkillable_task(struct task_struct *p,
|
||||
struct mem_cgroup *memcg, const nodemask_t *nodemask)
|
||||
|
|
@ -265,7 +274,7 @@ enum oom_scan_t oom_scan_process_thread(struct oom_control *oc,
|
|||
* Don't allow any other task to have access to the reserves.
|
||||
*/
|
||||
if (test_tsk_thread_flag(task, TIF_MEMDIE)) {
|
||||
if (oc->order != -1)
|
||||
if (!is_sysrq_oom(oc))
|
||||
return OOM_SCAN_ABORT;
|
||||
}
|
||||
if (!task->mm)
|
||||
|
|
@ -278,7 +287,7 @@ enum oom_scan_t oom_scan_process_thread(struct oom_control *oc,
|
|||
if (oom_task_origin(task))
|
||||
return OOM_SCAN_SELECT;
|
||||
|
||||
if (task_will_free_mem(task) && oc->order != -1)
|
||||
if (task_will_free_mem(task) && !is_sysrq_oom(oc))
|
||||
return OOM_SCAN_ABORT;
|
||||
|
||||
return OOM_SCAN_OK;
|
||||
|
|
@ -629,7 +638,7 @@ void check_panic_on_oom(struct oom_control *oc, enum oom_constraint constraint,
|
|||
return;
|
||||
}
|
||||
/* Do not panic for oom kills triggered by sysrq */
|
||||
if (oc->order == -1)
|
||||
if (is_sysrq_oom(oc))
|
||||
return;
|
||||
dump_header(oc, NULL, memcg);
|
||||
panic("Out of memory: %s panic_on_oom is enabled\n",
|
||||
|
|
@ -709,7 +718,7 @@ bool out_of_memory(struct oom_control *oc)
|
|||
|
||||
p = select_bad_process(oc, &points, totalpages);
|
||||
/* Found nothing?!?! Either we hang forever, or we panic. */
|
||||
if (!p && oc->order != -1) {
|
||||
if (!p && !is_sysrq_oom(oc)) {
|
||||
dump_header(oc, NULL, NULL);
|
||||
panic("Out of memory and no killable processes...\n");
|
||||
}
|
||||
|
|
|
|||
703
mm/page_alloc.c
703
mm/page_alloc.c
File diff suppressed because it is too large
Load diff
|
|
@ -90,7 +90,7 @@ int read_cache_pages(struct address_space *mapping, struct list_head *pages,
|
|||
page = list_to_page(pages);
|
||||
list_del(&page->lru);
|
||||
if (add_to_page_cache_lru(page, mapping, page->index,
|
||||
GFP_KERNEL & mapping_gfp_mask(mapping))) {
|
||||
mapping_gfp_constraint(mapping, GFP_KERNEL))) {
|
||||
read_cache_pages_invalidate_page(mapping, page);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -128,7 +128,7 @@ static int read_pages(struct address_space *mapping, struct file *filp,
|
|||
struct page *page = list_to_page(pages);
|
||||
list_del(&page->lru);
|
||||
if (!add_to_page_cache_lru(page, mapping, page->index,
|
||||
GFP_KERNEL & mapping_gfp_mask(mapping))) {
|
||||
mapping_gfp_constraint(mapping, GFP_KERNEL))) {
|
||||
mapping->a_ops->readpage(filp, page);
|
||||
}
|
||||
page_cache_release(page);
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@ static struct vfsmount *shm_mnt;
|
|||
#include <asm/uaccess.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#define BLOCKS_PER_PAGE (PAGE_CACHE_SIZE/512)
|
||||
#define VM_ACCT(size) (PAGE_CACHE_ALIGN(size) >> PAGE_SHIFT)
|
||||
|
||||
|
|
|
|||
35
mm/slab.c
35
mm/slab.c
|
|
@ -1031,12 +1031,12 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
|
|||
}
|
||||
|
||||
/*
|
||||
* Construct gfp mask to allocate from a specific node but do not invoke reclaim
|
||||
* or warn about failures.
|
||||
* Construct gfp mask to allocate from a specific node but do not direct reclaim
|
||||
* or warn about failures. kswapd may still wake to reclaim in the background.
|
||||
*/
|
||||
static inline gfp_t gfp_exact_node(gfp_t flags)
|
||||
{
|
||||
return (flags | __GFP_THISNODE | __GFP_NOWARN) & ~__GFP_WAIT;
|
||||
return (flags | __GFP_THISNODE | __GFP_NOWARN) & ~__GFP_DIRECT_RECLAIM;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -1889,21 +1889,10 @@ static void slab_destroy(struct kmem_cache *cachep, struct page *page)
|
|||
|
||||
freelist = page->freelist;
|
||||
slab_destroy_debugcheck(cachep, page);
|
||||
if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU)) {
|
||||
struct rcu_head *head;
|
||||
|
||||
/*
|
||||
* RCU free overloads the RCU head over the LRU.
|
||||
* slab_page has been overloeaded over the LRU,
|
||||
* however it is not used from now on so that
|
||||
* we can use it safely.
|
||||
*/
|
||||
head = (void *)&page->rcu_head;
|
||||
call_rcu(head, kmem_rcu_free);
|
||||
|
||||
} else {
|
||||
if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))
|
||||
call_rcu(&page->rcu_head, kmem_rcu_free);
|
||||
else
|
||||
kmem_freepages(cachep, page);
|
||||
}
|
||||
|
||||
/*
|
||||
* From now on, we don't use freelist
|
||||
|
|
@ -2633,7 +2622,7 @@ static int cache_grow(struct kmem_cache *cachep,
|
|||
|
||||
offset *= cachep->colour_off;
|
||||
|
||||
if (local_flags & __GFP_WAIT)
|
||||
if (gfpflags_allow_blocking(local_flags))
|
||||
local_irq_enable();
|
||||
|
||||
/*
|
||||
|
|
@ -2663,7 +2652,7 @@ static int cache_grow(struct kmem_cache *cachep,
|
|||
|
||||
cache_init_objs(cachep, page);
|
||||
|
||||
if (local_flags & __GFP_WAIT)
|
||||
if (gfpflags_allow_blocking(local_flags))
|
||||
local_irq_disable();
|
||||
check_irq_off();
|
||||
spin_lock(&n->list_lock);
|
||||
|
|
@ -2677,7 +2666,7 @@ static int cache_grow(struct kmem_cache *cachep,
|
|||
opps1:
|
||||
kmem_freepages(cachep, page);
|
||||
failed:
|
||||
if (local_flags & __GFP_WAIT)
|
||||
if (gfpflags_allow_blocking(local_flags))
|
||||
local_irq_disable();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2869,7 +2858,7 @@ force_grow:
|
|||
static inline void cache_alloc_debugcheck_before(struct kmem_cache *cachep,
|
||||
gfp_t flags)
|
||||
{
|
||||
might_sleep_if(flags & __GFP_WAIT);
|
||||
might_sleep_if(gfpflags_allow_blocking(flags));
|
||||
#if DEBUG
|
||||
kmem_flagcheck(cachep, flags);
|
||||
#endif
|
||||
|
|
@ -3057,11 +3046,11 @@ retry:
|
|||
*/
|
||||
struct page *page;
|
||||
|
||||
if (local_flags & __GFP_WAIT)
|
||||
if (gfpflags_allow_blocking(local_flags))
|
||||
local_irq_enable();
|
||||
kmem_flagcheck(cache, flags);
|
||||
page = kmem_getpages(cache, local_flags, numa_mem_id());
|
||||
if (local_flags & __GFP_WAIT)
|
||||
if (gfpflags_allow_blocking(local_flags))
|
||||
local_irq_disable();
|
||||
if (page) {
|
||||
/*
|
||||
|
|
|
|||
15
mm/slub.c
15
mm/slub.c
|
|
@ -1265,7 +1265,7 @@ static inline struct kmem_cache *slab_pre_alloc_hook(struct kmem_cache *s,
|
|||
{
|
||||
flags &= gfp_allowed_mask;
|
||||
lockdep_trace_alloc(flags);
|
||||
might_sleep_if(flags & __GFP_WAIT);
|
||||
might_sleep_if(gfpflags_allow_blocking(flags));
|
||||
|
||||
if (should_failslab(s->object_size, flags, s->flags))
|
||||
return NULL;
|
||||
|
|
@ -1353,7 +1353,7 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
|
|||
|
||||
flags &= gfp_allowed_mask;
|
||||
|
||||
if (flags & __GFP_WAIT)
|
||||
if (gfpflags_allow_blocking(flags))
|
||||
local_irq_enable();
|
||||
|
||||
flags |= s->allocflags;
|
||||
|
|
@ -1363,8 +1363,8 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
|
|||
* so we fall-back to the minimum order allocation.
|
||||
*/
|
||||
alloc_gfp = (flags | __GFP_NOWARN | __GFP_NORETRY) & ~__GFP_NOFAIL;
|
||||
if ((alloc_gfp & __GFP_WAIT) && oo_order(oo) > oo_order(s->min))
|
||||
alloc_gfp = (alloc_gfp | __GFP_NOMEMALLOC) & ~__GFP_WAIT;
|
||||
if ((alloc_gfp & __GFP_DIRECT_RECLAIM) && oo_order(oo) > oo_order(s->min))
|
||||
alloc_gfp = (alloc_gfp | __GFP_NOMEMALLOC) & ~__GFP_DIRECT_RECLAIM;
|
||||
|
||||
page = alloc_slab_page(s, alloc_gfp, node, oo);
|
||||
if (unlikely(!page)) {
|
||||
|
|
@ -1424,7 +1424,7 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
|
|||
page->frozen = 1;
|
||||
|
||||
out:
|
||||
if (flags & __GFP_WAIT)
|
||||
if (gfpflags_allow_blocking(flags))
|
||||
local_irq_disable();
|
||||
if (!page)
|
||||
return NULL;
|
||||
|
|
@ -1507,10 +1507,7 @@ static void free_slab(struct kmem_cache *s, struct page *page)
|
|||
VM_BUG_ON(s->reserved != sizeof(*head));
|
||||
head = page_address(page) + offset;
|
||||
} else {
|
||||
/*
|
||||
* RCU free overloads the RCU head over the LRU
|
||||
*/
|
||||
head = (void *)&page->lru;
|
||||
head = &page->rcu_head;
|
||||
}
|
||||
|
||||
call_rcu(head, rcu_free_slab);
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ out_put_single:
|
|||
__put_single_page(page);
|
||||
return;
|
||||
}
|
||||
VM_BUG_ON_PAGE(page_head != page->first_page, page);
|
||||
VM_BUG_ON_PAGE(page_head != compound_head(page), page);
|
||||
/*
|
||||
* We can release the refcount taken by
|
||||
* get_page_unless_zero() now that
|
||||
|
|
@ -262,7 +262,7 @@ static void put_compound_page(struct page *page)
|
|||
* Case 3 is possible, as we may race with
|
||||
* __split_huge_page_refcount tearing down a THP page.
|
||||
*/
|
||||
page_head = compound_head_by_tail(page);
|
||||
page_head = compound_head(page);
|
||||
if (!__compound_tail_refcounted(page_head))
|
||||
put_unrefcounted_compound_page(page_head, page);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@
|
|||
#include <asm/tlbflush.h>
|
||||
#include <asm/shmparam.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
struct vfree_deferred {
|
||||
struct llist_head list;
|
||||
struct work_struct wq;
|
||||
|
|
@ -1617,7 +1619,7 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
|
|||
goto fail;
|
||||
}
|
||||
area->pages[i] = page;
|
||||
if (gfp_mask & __GFP_WAIT)
|
||||
if (gfpflags_allow_blocking(gfp_mask))
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1476,7 +1476,7 @@ static int too_many_isolated(struct zone *zone, int file,
|
|||
* won't get blocked by normal direct-reclaimers, forming a circular
|
||||
* deadlock.
|
||||
*/
|
||||
if ((sc->gfp_mask & GFP_IOFS) == GFP_IOFS)
|
||||
if ((sc->gfp_mask & (__GFP_IO | __GFP_FS)) == (__GFP_IO | __GFP_FS))
|
||||
inactive >>= 3;
|
||||
|
||||
return isolated > inactive;
|
||||
|
|
@ -2477,7 +2477,7 @@ static inline bool compaction_ready(struct zone *zone, int order)
|
|||
balance_gap = min(low_wmark_pages(zone), DIV_ROUND_UP(
|
||||
zone->managed_pages, KSWAPD_ZONE_BALANCE_GAP_RATIO));
|
||||
watermark = high_wmark_pages(zone) + balance_gap + (2UL << order);
|
||||
watermark_ok = zone_watermark_ok_safe(zone, 0, watermark, 0, 0);
|
||||
watermark_ok = zone_watermark_ok_safe(zone, 0, watermark, 0);
|
||||
|
||||
/*
|
||||
* If compaction is deferred, reclaim up to a point where
|
||||
|
|
@ -2960,7 +2960,7 @@ static bool zone_balanced(struct zone *zone, int order,
|
|||
unsigned long balance_gap, int classzone_idx)
|
||||
{
|
||||
if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone) +
|
||||
balance_gap, classzone_idx, 0))
|
||||
balance_gap, classzone_idx))
|
||||
return false;
|
||||
|
||||
if (IS_ENABLED(CONFIG_COMPACTION) && order && compaction_suitable(zone,
|
||||
|
|
@ -3791,7 +3791,7 @@ int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
|
|||
/*
|
||||
* Do not scan if the allocation should not be delayed.
|
||||
*/
|
||||
if (!(gfp_mask & __GFP_WAIT) || (current->flags & PF_MEMALLOC))
|
||||
if (!gfpflags_allow_blocking(gfp_mask) || (current->flags & PF_MEMALLOC))
|
||||
return ZONE_RECLAIM_NOSCAN;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -923,7 +923,7 @@ static char * const migratetype_names[MIGRATE_TYPES] = {
|
|||
"Unmovable",
|
||||
"Reclaimable",
|
||||
"Movable",
|
||||
"Reserve",
|
||||
"HighAtomic",
|
||||
#ifdef CONFIG_CMA
|
||||
"CMA",
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ static const struct zbud_ops zbud_zpool_ops = {
|
|||
.evict = zbud_zpool_evict
|
||||
};
|
||||
|
||||
static void *zbud_zpool_create(char *name, gfp_t gfp,
|
||||
static void *zbud_zpool_create(const char *name, gfp_t gfp,
|
||||
const struct zpool_ops *zpool_ops,
|
||||
struct zpool *zpool)
|
||||
{
|
||||
|
|
|
|||
18
mm/zpool.c
18
mm/zpool.c
|
|
@ -18,8 +18,6 @@
|
|||
#include <linux/zpool.h>
|
||||
|
||||
struct zpool {
|
||||
char *type;
|
||||
|
||||
struct zpool_driver *driver;
|
||||
void *pool;
|
||||
const struct zpool_ops *ops;
|
||||
|
|
@ -73,7 +71,8 @@ int zpool_unregister_driver(struct zpool_driver *driver)
|
|||
}
|
||||
EXPORT_SYMBOL(zpool_unregister_driver);
|
||||
|
||||
static struct zpool_driver *zpool_get_driver(char *type)
|
||||
/* this assumes @type is null-terminated. */
|
||||
static struct zpool_driver *zpool_get_driver(const char *type)
|
||||
{
|
||||
struct zpool_driver *driver;
|
||||
|
||||
|
|
@ -113,6 +112,8 @@ static void zpool_put_driver(struct zpool_driver *driver)
|
|||
* not be loaded, and calling @zpool_create_pool() with the pool type will
|
||||
* fail.
|
||||
*
|
||||
* The @type string must be null-terminated.
|
||||
*
|
||||
* Returns: true if @type pool is available, false if not
|
||||
*/
|
||||
bool zpool_has_pool(char *type)
|
||||
|
|
@ -145,9 +146,11 @@ EXPORT_SYMBOL(zpool_has_pool);
|
|||
*
|
||||
* Implementations must guarantee this to be thread-safe.
|
||||
*
|
||||
* The @type and @name strings must be null-terminated.
|
||||
*
|
||||
* Returns: New zpool on success, NULL on failure.
|
||||
*/
|
||||
struct zpool *zpool_create_pool(char *type, char *name, gfp_t gfp,
|
||||
struct zpool *zpool_create_pool(const char *type, const char *name, gfp_t gfp,
|
||||
const struct zpool_ops *ops)
|
||||
{
|
||||
struct zpool_driver *driver;
|
||||
|
|
@ -174,7 +177,6 @@ struct zpool *zpool_create_pool(char *type, char *name, gfp_t gfp,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
zpool->type = driver->type;
|
||||
zpool->driver = driver;
|
||||
zpool->pool = driver->create(name, gfp, ops, zpool);
|
||||
zpool->ops = ops;
|
||||
|
|
@ -208,7 +210,7 @@ struct zpool *zpool_create_pool(char *type, char *name, gfp_t gfp,
|
|||
*/
|
||||
void zpool_destroy_pool(struct zpool *zpool)
|
||||
{
|
||||
pr_debug("destroying pool type %s\n", zpool->type);
|
||||
pr_debug("destroying pool type %s\n", zpool->driver->type);
|
||||
|
||||
spin_lock(&pools_lock);
|
||||
list_del(&zpool->list);
|
||||
|
|
@ -228,9 +230,9 @@ void zpool_destroy_pool(struct zpool *zpool)
|
|||
*
|
||||
* Returns: The type of zpool.
|
||||
*/
|
||||
char *zpool_get_type(struct zpool *zpool)
|
||||
const char *zpool_get_type(struct zpool *zpool)
|
||||
{
|
||||
return zpool->type;
|
||||
return zpool->driver->type;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
* struct page(s) to form a zspage.
|
||||
*
|
||||
* Usage of struct page fields:
|
||||
* page->first_page: points to the first component (0-order) page
|
||||
* page->private: points to the first component (0-order) page
|
||||
* page->index (union with page->freelist): offset of the first object
|
||||
* starting in this page. For the first page, this is
|
||||
* always 0, so we use this field (aka freelist) to point
|
||||
|
|
@ -26,8 +26,7 @@
|
|||
*
|
||||
* For _first_ page only:
|
||||
*
|
||||
* page->private (union with page->first_page): refers to the
|
||||
* component page after the first page
|
||||
* page->private: refers to the component page after the first page
|
||||
* If the page is first_page for huge object, it stores handle.
|
||||
* Look at size_class->huge.
|
||||
* page->freelist: points to the first free object in zspage.
|
||||
|
|
@ -38,6 +37,7 @@
|
|||
* page->lru: links together first pages of various zspages.
|
||||
* Basically forming list of zspages in a fullness group.
|
||||
* page->mapping: class index and fullness group of the zspage
|
||||
* page->inuse: the number of objects that are used in this zspage
|
||||
*
|
||||
* Usage of struct page flags:
|
||||
* PG_private: identifies the first component page
|
||||
|
|
@ -58,7 +58,7 @@
|
|||
#include <linux/cpumask.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/preempt.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
|
@ -166,9 +166,14 @@ enum zs_stat_type {
|
|||
OBJ_USED,
|
||||
CLASS_ALMOST_FULL,
|
||||
CLASS_ALMOST_EMPTY,
|
||||
NR_ZS_STAT_TYPE,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ZSMALLOC_STAT
|
||||
#define NR_ZS_STAT_TYPE (CLASS_ALMOST_EMPTY + 1)
|
||||
#else
|
||||
#define NR_ZS_STAT_TYPE (OBJ_USED + 1)
|
||||
#endif
|
||||
|
||||
struct zs_size_stat {
|
||||
unsigned long objs[NR_ZS_STAT_TYPE];
|
||||
};
|
||||
|
|
@ -237,7 +242,7 @@ struct link_free {
|
|||
};
|
||||
|
||||
struct zs_pool {
|
||||
char *name;
|
||||
const char *name;
|
||||
|
||||
struct size_class **size_class;
|
||||
struct kmem_cache *handle_cachep;
|
||||
|
|
@ -311,7 +316,7 @@ static void record_obj(unsigned long handle, unsigned long obj)
|
|||
|
||||
#ifdef CONFIG_ZPOOL
|
||||
|
||||
static void *zs_zpool_create(char *name, gfp_t gfp,
|
||||
static void *zs_zpool_create(const char *name, gfp_t gfp,
|
||||
const struct zpool_ops *zpool_ops,
|
||||
struct zpool *zpool)
|
||||
{
|
||||
|
|
@ -447,19 +452,23 @@ static int get_size_class_index(int size)
|
|||
static inline void zs_stat_inc(struct size_class *class,
|
||||
enum zs_stat_type type, unsigned long cnt)
|
||||
{
|
||||
class->stats.objs[type] += cnt;
|
||||
if (type < NR_ZS_STAT_TYPE)
|
||||
class->stats.objs[type] += cnt;
|
||||
}
|
||||
|
||||
static inline void zs_stat_dec(struct size_class *class,
|
||||
enum zs_stat_type type, unsigned long cnt)
|
||||
{
|
||||
class->stats.objs[type] -= cnt;
|
||||
if (type < NR_ZS_STAT_TYPE)
|
||||
class->stats.objs[type] -= cnt;
|
||||
}
|
||||
|
||||
static inline unsigned long zs_stat_get(struct size_class *class,
|
||||
enum zs_stat_type type)
|
||||
{
|
||||
return class->stats.objs[type];
|
||||
if (type < NR_ZS_STAT_TYPE)
|
||||
return class->stats.objs[type];
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ZSMALLOC_STAT
|
||||
|
|
@ -548,7 +557,7 @@ static const struct file_operations zs_stat_size_ops = {
|
|||
.release = single_release,
|
||||
};
|
||||
|
||||
static int zs_pool_stat_create(char *name, struct zs_pool *pool)
|
||||
static int zs_pool_stat_create(const char *name, struct zs_pool *pool)
|
||||
{
|
||||
struct dentry *entry;
|
||||
|
||||
|
|
@ -588,7 +597,7 @@ static void __exit zs_stat_exit(void)
|
|||
{
|
||||
}
|
||||
|
||||
static inline int zs_pool_stat_create(char *name, struct zs_pool *pool)
|
||||
static inline int zs_pool_stat_create(const char *name, struct zs_pool *pool)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -764,7 +773,7 @@ static struct page *get_first_page(struct page *page)
|
|||
if (is_first_page(page))
|
||||
return page;
|
||||
else
|
||||
return page->first_page;
|
||||
return (struct page *)page_private(page);
|
||||
}
|
||||
|
||||
static struct page *get_next_page(struct page *page)
|
||||
|
|
@ -824,7 +833,7 @@ static unsigned long obj_to_head(struct size_class *class, struct page *page,
|
|||
{
|
||||
if (class->huge) {
|
||||
VM_BUG_ON(!is_first_page(page));
|
||||
return *(unsigned long *)page_private(page);
|
||||
return page_private(page);
|
||||
} else
|
||||
return *(unsigned long *)obj;
|
||||
}
|
||||
|
|
@ -949,7 +958,7 @@ static struct page *alloc_zspage(struct size_class *class, gfp_t flags)
|
|||
* Allocate individual pages and link them together as:
|
||||
* 1. first page->private = first sub-page
|
||||
* 2. all sub-pages are linked together using page->lru
|
||||
* 3. each sub-page is linked to the first page using page->first_page
|
||||
* 3. each sub-page is linked to the first page using page->private
|
||||
*
|
||||
* For each size class, First/Head pages are linked together using
|
||||
* page->lru. Also, we set PG_private to identify the first page
|
||||
|
|
@ -974,7 +983,7 @@ static struct page *alloc_zspage(struct size_class *class, gfp_t flags)
|
|||
if (i == 1)
|
||||
set_page_private(first_page, (unsigned long)page);
|
||||
if (i >= 1)
|
||||
page->first_page = first_page;
|
||||
set_page_private(page, (unsigned long)first_page);
|
||||
if (i >= 2)
|
||||
list_add(&page->lru, &prev_page->lru);
|
||||
if (i == class->pages_per_zspage - 1) /* last page */
|
||||
|
|
@ -1428,8 +1437,6 @@ static void obj_free(struct zs_pool *pool, struct size_class *class,
|
|||
struct page *first_page, *f_page;
|
||||
unsigned long f_objidx, f_offset;
|
||||
void *vaddr;
|
||||
int class_idx;
|
||||
enum fullness_group fullness;
|
||||
|
||||
BUG_ON(!obj);
|
||||
|
||||
|
|
@ -1437,7 +1444,6 @@ static void obj_free(struct zs_pool *pool, struct size_class *class,
|
|||
obj_to_location(obj, &f_page, &f_objidx);
|
||||
first_page = get_first_page(f_page);
|
||||
|
||||
get_zspage_mapping(first_page, &class_idx, &fullness);
|
||||
f_offset = obj_idx_to_offset(f_page, f_objidx, class->size);
|
||||
|
||||
vaddr = kmap_atomic(f_page);
|
||||
|
|
@ -1822,9 +1828,6 @@ static unsigned long zs_shrinker_count(struct shrinker *shrinker,
|
|||
struct zs_pool *pool = container_of(shrinker, struct zs_pool,
|
||||
shrinker);
|
||||
|
||||
if (!pool->shrinker_enabled)
|
||||
return 0;
|
||||
|
||||
for (i = zs_size_classes - 1; i >= 0; i--) {
|
||||
class = pool->size_class[i];
|
||||
if (!class)
|
||||
|
|
@ -1866,7 +1869,7 @@ static int zs_register_shrinker(struct zs_pool *pool)
|
|||
* On success, a pointer to the newly created pool is returned,
|
||||
* otherwise NULL.
|
||||
*/
|
||||
struct zs_pool *zs_create_pool(char *name, gfp_t flags)
|
||||
struct zs_pool *zs_create_pool(const char *name, gfp_t flags)
|
||||
{
|
||||
int i;
|
||||
struct zs_pool *pool;
|
||||
|
|
|
|||
89
mm/zswap.c
89
mm/zswap.c
|
|
@ -82,33 +82,27 @@ module_param_named(enabled, zswap_enabled, bool, 0644);
|
|||
|
||||
/* Crypto compressor to use */
|
||||
#define ZSWAP_COMPRESSOR_DEFAULT "lzo"
|
||||
static char zswap_compressor[CRYPTO_MAX_ALG_NAME] = ZSWAP_COMPRESSOR_DEFAULT;
|
||||
static struct kparam_string zswap_compressor_kparam = {
|
||||
.string = zswap_compressor,
|
||||
.maxlen = sizeof(zswap_compressor),
|
||||
};
|
||||
static char *zswap_compressor = ZSWAP_COMPRESSOR_DEFAULT;
|
||||
static int zswap_compressor_param_set(const char *,
|
||||
const struct kernel_param *);
|
||||
static struct kernel_param_ops zswap_compressor_param_ops = {
|
||||
.set = zswap_compressor_param_set,
|
||||
.get = param_get_string,
|
||||
.get = param_get_charp,
|
||||
.free = param_free_charp,
|
||||
};
|
||||
module_param_cb(compressor, &zswap_compressor_param_ops,
|
||||
&zswap_compressor_kparam, 0644);
|
||||
&zswap_compressor, 0644);
|
||||
|
||||
/* Compressed storage zpool to use */
|
||||
#define ZSWAP_ZPOOL_DEFAULT "zbud"
|
||||
static char zswap_zpool_type[32 /* arbitrary */] = ZSWAP_ZPOOL_DEFAULT;
|
||||
static struct kparam_string zswap_zpool_kparam = {
|
||||
.string = zswap_zpool_type,
|
||||
.maxlen = sizeof(zswap_zpool_type),
|
||||
};
|
||||
static char *zswap_zpool_type = ZSWAP_ZPOOL_DEFAULT;
|
||||
static int zswap_zpool_param_set(const char *, const struct kernel_param *);
|
||||
static struct kernel_param_ops zswap_zpool_param_ops = {
|
||||
.set = zswap_zpool_param_set,
|
||||
.get = param_get_string,
|
||||
.set = zswap_zpool_param_set,
|
||||
.get = param_get_charp,
|
||||
.free = param_free_charp,
|
||||
};
|
||||
module_param_cb(zpool, &zswap_zpool_param_ops, &zswap_zpool_kparam, 0644);
|
||||
module_param_cb(zpool, &zswap_zpool_param_ops, &zswap_zpool_type, 0644);
|
||||
|
||||
/* The maximum percentage of memory that the compressed pool can occupy */
|
||||
static unsigned int zswap_max_pool_percent = 20;
|
||||
|
|
@ -342,7 +336,7 @@ static void zswap_entry_put(struct zswap_tree *tree,
|
|||
static struct zswap_entry *zswap_entry_find_get(struct rb_root *root,
|
||||
pgoff_t offset)
|
||||
{
|
||||
struct zswap_entry *entry = NULL;
|
||||
struct zswap_entry *entry;
|
||||
|
||||
entry = zswap_rb_search(root, offset);
|
||||
if (entry)
|
||||
|
|
@ -571,7 +565,7 @@ static struct zswap_pool *zswap_pool_find_get(char *type, char *compressor)
|
|||
static struct zswap_pool *zswap_pool_create(char *type, char *compressor)
|
||||
{
|
||||
struct zswap_pool *pool;
|
||||
gfp_t gfp = __GFP_NORETRY | __GFP_NOWARN;
|
||||
gfp_t gfp = __GFP_NORETRY | __GFP_NOWARN | __GFP_KSWAPD_RECLAIM;
|
||||
|
||||
pool = kzalloc(sizeof(*pool), GFP_KERNEL);
|
||||
if (!pool) {
|
||||
|
|
@ -615,19 +609,29 @@ error:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct zswap_pool *__zswap_pool_create_fallback(void)
|
||||
static __init struct zswap_pool *__zswap_pool_create_fallback(void)
|
||||
{
|
||||
if (!crypto_has_comp(zswap_compressor, 0, 0)) {
|
||||
if (!strcmp(zswap_compressor, ZSWAP_COMPRESSOR_DEFAULT)) {
|
||||
pr_err("default compressor %s not available\n",
|
||||
zswap_compressor);
|
||||
return NULL;
|
||||
}
|
||||
pr_err("compressor %s not available, using default %s\n",
|
||||
zswap_compressor, ZSWAP_COMPRESSOR_DEFAULT);
|
||||
strncpy(zswap_compressor, ZSWAP_COMPRESSOR_DEFAULT,
|
||||
sizeof(zswap_compressor));
|
||||
param_free_charp(&zswap_compressor);
|
||||
zswap_compressor = ZSWAP_COMPRESSOR_DEFAULT;
|
||||
}
|
||||
if (!zpool_has_pool(zswap_zpool_type)) {
|
||||
if (!strcmp(zswap_zpool_type, ZSWAP_ZPOOL_DEFAULT)) {
|
||||
pr_err("default zpool %s not available\n",
|
||||
zswap_zpool_type);
|
||||
return NULL;
|
||||
}
|
||||
pr_err("zpool %s not available, using default %s\n",
|
||||
zswap_zpool_type, ZSWAP_ZPOOL_DEFAULT);
|
||||
strncpy(zswap_zpool_type, ZSWAP_ZPOOL_DEFAULT,
|
||||
sizeof(zswap_zpool_type));
|
||||
param_free_charp(&zswap_zpool_type);
|
||||
zswap_zpool_type = ZSWAP_ZPOOL_DEFAULT;
|
||||
}
|
||||
|
||||
return zswap_pool_create(zswap_zpool_type, zswap_compressor);
|
||||
|
|
@ -684,43 +688,39 @@ static void zswap_pool_put(struct zswap_pool *pool)
|
|||
* param callbacks
|
||||
**********************************/
|
||||
|
||||
/* val must be a null-terminated string */
|
||||
static int __zswap_param_set(const char *val, const struct kernel_param *kp,
|
||||
char *type, char *compressor)
|
||||
{
|
||||
struct zswap_pool *pool, *put_pool = NULL;
|
||||
char str[kp->str->maxlen], *s;
|
||||
char *s = strstrip((char *)val);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* kp is either zswap_zpool_kparam or zswap_compressor_kparam, defined
|
||||
* at the top of this file, so maxlen is CRYPTO_MAX_ALG_NAME (64) or
|
||||
* 32 (arbitrary).
|
||||
*/
|
||||
strlcpy(str, val, kp->str->maxlen);
|
||||
s = strim(str);
|
||||
/* no change required */
|
||||
if (!strcmp(s, *(char **)kp->arg))
|
||||
return 0;
|
||||
|
||||
/* if this is load-time (pre-init) param setting,
|
||||
* don't create a pool; that's done during init.
|
||||
*/
|
||||
if (!zswap_init_started)
|
||||
return param_set_copystring(s, kp);
|
||||
|
||||
/* no change required */
|
||||
if (!strncmp(kp->str->string, s, kp->str->maxlen))
|
||||
return 0;
|
||||
return param_set_charp(s, kp);
|
||||
|
||||
if (!type) {
|
||||
if (!zpool_has_pool(s)) {
|
||||
pr_err("zpool %s not available\n", s);
|
||||
return -ENOENT;
|
||||
}
|
||||
type = s;
|
||||
if (!zpool_has_pool(type)) {
|
||||
pr_err("zpool %s not available\n", type);
|
||||
return -ENOENT;
|
||||
}
|
||||
} else if (!compressor) {
|
||||
compressor = s;
|
||||
if (!crypto_has_comp(compressor, 0, 0)) {
|
||||
pr_err("compressor %s not available\n", compressor);
|
||||
if (!crypto_has_comp(s, 0, 0)) {
|
||||
pr_err("compressor %s not available\n", s);
|
||||
return -ENOENT;
|
||||
}
|
||||
compressor = s;
|
||||
} else {
|
||||
WARN_ON(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock(&zswap_pools_lock);
|
||||
|
|
@ -736,7 +736,7 @@ static int __zswap_param_set(const char *val, const struct kernel_param *kp,
|
|||
}
|
||||
|
||||
if (pool)
|
||||
ret = param_set_copystring(s, kp);
|
||||
ret = param_set_charp(s, kp);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
||||
|
|
@ -1011,7 +1011,8 @@ static int zswap_frontswap_store(unsigned type, pgoff_t offset,
|
|||
/* store */
|
||||
len = dlen + sizeof(struct zswap_header);
|
||||
ret = zpool_malloc(entry->pool->zpool, len,
|
||||
__GFP_NORETRY | __GFP_NOWARN, &handle);
|
||||
__GFP_NORETRY | __GFP_NOWARN | __GFP_KSWAPD_RECLAIM,
|
||||
&handle);
|
||||
if (ret == -ENOSPC) {
|
||||
zswap_reject_compress_poor++;
|
||||
goto put_dstmem;
|
||||
|
|
|
|||
Loading…
Reference in a new issue