Commit 570203ec authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'akpm' (patches from Andrew)

Merge vm fixes from Andrew Morton:
 "5 fixes"

* emailed patches from Andrew Morton <akpm@linux-foundation.org>:
  mm/sparse: fix kernel crash with pfn_section_valid check
  mm: fork: fix kernel_stack memcg stats for various stack implementations
  hugetlb_cgroup: fix illegal access to memory
  drivers/base/memory.c: indicate all memory blocks as removable
  mm/swapfile.c: move inode_lock out of claim_swapfile
parents ab93e984 b943f045
Loading
Loading
Loading
Loading
+3 −20
Original line number Diff line number Diff line
@@ -97,30 +97,13 @@ static ssize_t phys_index_show(struct device *dev,
}

/*
 * Show whether the memory block is likely to be offlineable (or is already
 * offline). Once offline, the memory block could be removed. The return
 * value does, however, not indicate that there is a way to remove the
 * memory block.
 * Legacy interface that we cannot remove. Always indicate "removable"
 * with CONFIG_MEMORY_HOTREMOVE - bad heuristic.
 */
static ssize_t removable_show(struct device *dev, struct device_attribute *attr,
			      char *buf)
{
	struct memory_block *mem = to_memory_block(dev);
	unsigned long pfn;
	int ret = 1, i;

	if (mem->state != MEM_ONLINE)
		goto out;

	for (i = 0; i < sections_per_block; i++) {
		if (!present_section_nr(mem->start_section_nr + i))
			continue;
		pfn = section_nr_to_pfn(mem->start_section_nr + i);
		ret &= is_mem_section_removable(pfn, PAGES_PER_SECTION);
	}

out:
	return sprintf(buf, "%d\n", ret);
	return sprintf(buf, "%d\n", (int)IS_ENABLED(CONFIG_MEMORY_HOTREMOVE));
}

/*
+12 −0
Original line number Diff line number Diff line
@@ -695,6 +695,7 @@ static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec,
void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx,
			int val);
void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, int val);
void mod_memcg_obj_state(void *p, int idx, int val);

static inline void mod_lruvec_state(struct lruvec *lruvec,
				    enum node_stat_item idx, int val)
@@ -1123,6 +1124,10 @@ static inline void __mod_lruvec_slab_state(void *p, enum node_stat_item idx,
	__mod_node_page_state(page_pgdat(page), idx, val);
}

static inline void mod_memcg_obj_state(void *p, int idx, int val)
{
}

static inline
unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order,
					    gfp_t gfp_mask,
@@ -1427,6 +1432,8 @@ static inline int memcg_cache_id(struct mem_cgroup *memcg)
	return memcg ? memcg->kmemcg_id : -1;
}

struct mem_cgroup *mem_cgroup_from_obj(void *p);

#else

static inline int memcg_kmem_charge(struct page *page, gfp_t gfp, int order)
@@ -1468,6 +1475,11 @@ static inline void memcg_put_cache_ids(void)
{
}

static inline struct mem_cgroup *mem_cgroup_from_obj(void *p)
{
       return NULL;
}

#endif /* CONFIG_MEMCG_KMEM */

#endif /* _LINUX_MEMCONTROL_H */
+2 −2
Original line number Diff line number Diff line
@@ -397,7 +397,7 @@ static void account_kernel_stack(struct task_struct *tsk, int account)
		mod_zone_page_state(page_zone(first_page), NR_KERNEL_STACK_KB,
				    THREAD_SIZE / 1024 * account);

		mod_memcg_page_state(first_page, MEMCG_KERNEL_STACK_KB,
		mod_memcg_obj_state(stack, MEMCG_KERNEL_STACK_KB,
				    account * (THREAD_SIZE / 1024));
	}
}
+1 −2
Original line number Diff line number Diff line
@@ -240,8 +240,7 @@ again:
	if (!page_counter_try_charge(&h_cg->hugepage[idx], nr_pages,
				     &counter)) {
		ret = -ENOMEM;
		hugetlb_event(hugetlb_cgroup_from_counter(counter, idx), idx,
			      HUGETLB_MAX);
		hugetlb_event(h_cg, idx, HUGETLB_MAX);
	}
	css_put(&h_cg->css);
done:
+38 −0
Original line number Diff line number Diff line
@@ -777,6 +777,17 @@ void __mod_lruvec_slab_state(void *p, enum node_stat_item idx, int val)
	rcu_read_unlock();
}

void mod_memcg_obj_state(void *p, int idx, int val)
{
	struct mem_cgroup *memcg;

	rcu_read_lock();
	memcg = mem_cgroup_from_obj(p);
	if (memcg)
		mod_memcg_state(memcg, idx, val);
	rcu_read_unlock();
}

/**
 * __count_memcg_events - account VM events in a cgroup
 * @memcg: the memory cgroup
@@ -2661,6 +2672,33 @@ static void commit_charge(struct page *page, struct mem_cgroup *memcg,
}

#ifdef CONFIG_MEMCG_KMEM
/*
 * Returns a pointer to the memory cgroup to which the kernel object is charged.
 *
 * The caller must ensure the memcg lifetime, e.g. by taking rcu_read_lock(),
 * cgroup_mutex, etc.
 */
struct mem_cgroup *mem_cgroup_from_obj(void *p)
{
	struct page *page;

	if (mem_cgroup_disabled())
		return NULL;

	page = virt_to_head_page(p);

	/*
	 * Slab pages don't have page->mem_cgroup set because corresponding
	 * kmem caches can be reparented during the lifetime. That's why
	 * memcg_from_slab_page() should be used instead.
	 */
	if (PageSlab(page))
		return memcg_from_slab_page(page);

	/* All other pages use page->mem_cgroup */
	return page->mem_cgroup;
}

static int memcg_alloc_cache_id(void)
{
	int id, size;
Loading