Skip to content

Commit

Permalink
Merge branch 'for-4.13' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/tj/percpu

Pull percpu updates from Tejun Heo:
 "These are the percpu changes for the v4.13-rc1 merge window. There are
  a couple visibility related changes - tracepoints and allocator stats
  through debugfs, along with __ro_after_init markings and a cosmetic
  rename in percpu_counter.

  Please note that the simple O(#elements_in_the_chunk) area allocator
  used by percpu allocator is again showing scalability issues,
  primarily with bpf allocating and freeing large number of counters.
  Dennis is working on the replacement allocator and the percpu
  allocator will be seeing increased churns in the coming cycles"

* 'for-4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu:
  percpu: fix static checker warnings in pcpu_destroy_chunk
  percpu: fix early calls for spinlock in pcpu_stats
  percpu: resolve err may not be initialized in pcpu_alloc
  percpu_counter: Rename __percpu_counter_add to percpu_counter_add_batch
  percpu: add tracepoint support for percpu memory
  percpu: expose statistics about percpu memory via debugfs
  percpu: migrate percpu data structures to internal header
  percpu: add missing lockdep_assert_held to func pcpu_free_area
  mark most percpu globals as __ro_after_init
  • Loading branch information
torvalds committed Jul 6, 2017
2 parents 9b51f04 + e3efe3d commit a4c20b9
Show file tree
Hide file tree
Showing 19 changed files with 621 additions and 70 deletions.
12 changes: 6 additions & 6 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -1256,9 +1256,9 @@ void clean_tree_block(struct btrfs_fs_info *fs_info,
btrfs_assert_tree_locked(buf);

if (test_and_clear_bit(EXTENT_BUFFER_DIRTY, &buf->bflags)) {
__percpu_counter_add(&fs_info->dirty_metadata_bytes,
-buf->len,
fs_info->dirty_metadata_batch);
percpu_counter_add_batch(&fs_info->dirty_metadata_bytes,
-buf->len,
fs_info->dirty_metadata_batch);
/* ugh, clear_extent_buffer_dirty needs to lock the page */
btrfs_set_lock_blocking(buf);
clear_extent_buffer_dirty(buf);
Expand Down Expand Up @@ -4047,9 +4047,9 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
buf->start, transid, fs_info->generation);
was_dirty = set_extent_buffer_dirty(buf);
if (!was_dirty)
__percpu_counter_add(&fs_info->dirty_metadata_bytes,
buf->len,
fs_info->dirty_metadata_batch);
percpu_counter_add_batch(&fs_info->dirty_metadata_bytes,
buf->len,
fs_info->dirty_metadata_batch);
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
if (btrfs_header_level(buf) == 0 && check_leaf(root, buf)) {
btrfs_print_leaf(fs_info, buf);
Expand Down
6 changes: 3 additions & 3 deletions fs/btrfs/extent_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -3577,9 +3577,9 @@ lock_extent_buffer_for_io(struct extent_buffer *eb,
set_bit(EXTENT_BUFFER_WRITEBACK, &eb->bflags);
spin_unlock(&eb->refs_lock);
btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
__percpu_counter_add(&fs_info->dirty_metadata_bytes,
-eb->len,
fs_info->dirty_metadata_batch);
percpu_counter_add_batch(&fs_info->dirty_metadata_bytes,
-eb->len,
fs_info->dirty_metadata_batch);
ret = 1;
} else {
spin_unlock(&eb->refs_lock);
Expand Down
8 changes: 4 additions & 4 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1763,8 +1763,8 @@ static void btrfs_set_bit_hook(void *private_data,
if (btrfs_is_testing(fs_info))
return;

__percpu_counter_add(&fs_info->delalloc_bytes, len,
fs_info->delalloc_batch);
percpu_counter_add_batch(&fs_info->delalloc_bytes, len,
fs_info->delalloc_batch);
spin_lock(&BTRFS_I(inode)->lock);
BTRFS_I(inode)->delalloc_bytes += len;
if (*bits & EXTENT_DEFRAG)
Expand Down Expand Up @@ -1838,8 +1838,8 @@ static void btrfs_clear_bit_hook(void *private_data,
&inode->vfs_inode,
state->start, len);

__percpu_counter_add(&fs_info->delalloc_bytes, -len,
fs_info->delalloc_batch);
percpu_counter_add_batch(&fs_info->delalloc_bytes, -len,
fs_info->delalloc_batch);
spin_lock(&inode->lock);
inode->delalloc_bytes -= len;
if (do_list && inode->delalloc_bytes == 0 &&
Expand Down
4 changes: 2 additions & 2 deletions fs/xfs/xfs_mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -1211,7 +1211,7 @@ xfs_mod_icount(
struct xfs_mount *mp,
int64_t delta)
{
__percpu_counter_add(&mp->m_icount, delta, XFS_ICOUNT_BATCH);
percpu_counter_add_batch(&mp->m_icount, delta, XFS_ICOUNT_BATCH);
if (__percpu_counter_compare(&mp->m_icount, 0, XFS_ICOUNT_BATCH) < 0) {
ASSERT(0);
percpu_counter_add(&mp->m_icount, -delta);
Expand Down Expand Up @@ -1290,7 +1290,7 @@ xfs_mod_fdblocks(
else
batch = XFS_FDBLOCKS_BATCH;

__percpu_counter_add(&mp->m_fdblocks, delta, batch);
percpu_counter_add_batch(&mp->m_fdblocks, delta, batch);
if (__percpu_counter_compare(&mp->m_fdblocks, mp->m_alloc_set_aside,
XFS_FDBLOCKS_BATCH) >= 0) {
/* we had space! */
Expand Down
2 changes: 1 addition & 1 deletion include/linux/backing-dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ static inline bool bdi_has_dirty_io(struct backing_dev_info *bdi)
static inline void __add_wb_stat(struct bdi_writeback *wb,
enum wb_stat_item item, s64 amount)
{
__percpu_counter_add(&wb->stat[item], amount, WB_STAT_BATCH);
percpu_counter_add_batch(&wb->stat[item], amount, WB_STAT_BATCH);
}

static inline void __inc_wb_stat(struct bdi_writeback *wb,
Expand Down
6 changes: 3 additions & 3 deletions include/linux/blk-cgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ static inline void blkg_stat_exit(struct blkg_stat *stat)
*/
static inline void blkg_stat_add(struct blkg_stat *stat, uint64_t val)
{
__percpu_counter_add(&stat->cpu_cnt, val, BLKG_STAT_CPU_BATCH);
percpu_counter_add_batch(&stat->cpu_cnt, val, BLKG_STAT_CPU_BATCH);
}

/**
Expand Down Expand Up @@ -597,14 +597,14 @@ static inline void blkg_rwstat_add(struct blkg_rwstat *rwstat,
else
cnt = &rwstat->cpu_cnt[BLKG_RWSTAT_READ];

__percpu_counter_add(cnt, val, BLKG_STAT_CPU_BATCH);
percpu_counter_add_batch(cnt, val, BLKG_STAT_CPU_BATCH);

if (op_is_sync(op))
cnt = &rwstat->cpu_cnt[BLKG_RWSTAT_SYNC];
else
cnt = &rwstat->cpu_cnt[BLKG_RWSTAT_ASYNC];

__percpu_counter_add(cnt, val, BLKG_STAT_CPU_BATCH);
percpu_counter_add_batch(cnt, val, BLKG_STAT_CPU_BATCH);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion include/linux/mman.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ unsigned long vm_memory_committed(void);

static inline void vm_acct_memory(long pages)
{
__percpu_counter_add(&vm_committed_as, pages, vm_committed_as_batch);
percpu_counter_add_batch(&vm_committed_as, pages, vm_committed_as_batch);
}

static inline void vm_unacct_memory(long pages)
Expand Down
7 changes: 4 additions & 3 deletions include/linux/percpu_counter.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ int __percpu_counter_init(struct percpu_counter *fbc, s64 amount, gfp_t gfp,

void percpu_counter_destroy(struct percpu_counter *fbc);
void percpu_counter_set(struct percpu_counter *fbc, s64 amount);
void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch);
void percpu_counter_add_batch(struct percpu_counter *fbc, s64 amount,
s32 batch);
s64 __percpu_counter_sum(struct percpu_counter *fbc);
int __percpu_counter_compare(struct percpu_counter *fbc, s64 rhs, s32 batch);

Expand All @@ -50,7 +51,7 @@ static inline int percpu_counter_compare(struct percpu_counter *fbc, s64 rhs)

static inline void percpu_counter_add(struct percpu_counter *fbc, s64 amount)
{
__percpu_counter_add(fbc, amount, percpu_counter_batch);
percpu_counter_add_batch(fbc, amount, percpu_counter_batch);
}

static inline s64 percpu_counter_sum_positive(struct percpu_counter *fbc)
Expand Down Expand Up @@ -136,7 +137,7 @@ percpu_counter_add(struct percpu_counter *fbc, s64 amount)
}

static inline void
__percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch)
percpu_counter_add_batch(struct percpu_counter *fbc, s64 amount, s32 batch)
{
percpu_counter_add(fbc, amount);
}
Expand Down
4 changes: 2 additions & 2 deletions include/net/inet_frag.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,12 @@ static inline int frag_mem_limit(struct netns_frags *nf)

static inline void sub_frag_mem_limit(struct netns_frags *nf, int i)
{
__percpu_counter_add(&nf->mem, -i, frag_percpu_counter_batch);
percpu_counter_add_batch(&nf->mem, -i, frag_percpu_counter_batch);
}

static inline void add_frag_mem_limit(struct netns_frags *nf, int i)
{
__percpu_counter_add(&nf->mem, i, frag_percpu_counter_batch);
percpu_counter_add_batch(&nf->mem, i, frag_percpu_counter_batch);
}

static inline unsigned int sum_frag_mem_limit(struct netns_frags *nf)
Expand Down
125 changes: 125 additions & 0 deletions include/trace/events/percpu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#undef TRACE_SYSTEM
#define TRACE_SYSTEM percpu

#if !defined(_TRACE_PERCPU_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_PERCPU_H

#include <linux/tracepoint.h>

TRACE_EVENT(percpu_alloc_percpu,

TP_PROTO(bool reserved, bool is_atomic, size_t size,
size_t align, void *base_addr, int off, void __percpu *ptr),

TP_ARGS(reserved, is_atomic, size, align, base_addr, off, ptr),

TP_STRUCT__entry(
__field( bool, reserved )
__field( bool, is_atomic )
__field( size_t, size )
__field( size_t, align )
__field( void *, base_addr )
__field( int, off )
__field( void __percpu *, ptr )
),

TP_fast_assign(
__entry->reserved = reserved;
__entry->is_atomic = is_atomic;
__entry->size = size;
__entry->align = align;
__entry->base_addr = base_addr;
__entry->off = off;
__entry->ptr = ptr;
),

TP_printk("reserved=%d is_atomic=%d size=%zu align=%zu base_addr=%p off=%d ptr=%p",
__entry->reserved, __entry->is_atomic,
__entry->size, __entry->align,
__entry->base_addr, __entry->off, __entry->ptr)
);

TRACE_EVENT(percpu_free_percpu,

TP_PROTO(void *base_addr, int off, void __percpu *ptr),

TP_ARGS(base_addr, off, ptr),

TP_STRUCT__entry(
__field( void *, base_addr )
__field( int, off )
__field( void __percpu *, ptr )
),

TP_fast_assign(
__entry->base_addr = base_addr;
__entry->off = off;
__entry->ptr = ptr;
),

TP_printk("base_addr=%p off=%d ptr=%p",
__entry->base_addr, __entry->off, __entry->ptr)
);

TRACE_EVENT(percpu_alloc_percpu_fail,

TP_PROTO(bool reserved, bool is_atomic, size_t size, size_t align),

TP_ARGS(reserved, is_atomic, size, align),

TP_STRUCT__entry(
__field( bool, reserved )
__field( bool, is_atomic )
__field( size_t, size )
__field( size_t, align )
),

TP_fast_assign(
__entry->reserved = reserved;
__entry->is_atomic = is_atomic;
__entry->size = size;
__entry->align = align;
),

TP_printk("reserved=%d is_atomic=%d size=%zu align=%zu",
__entry->reserved, __entry->is_atomic,
__entry->size, __entry->align)
);

TRACE_EVENT(percpu_create_chunk,

TP_PROTO(void *base_addr),

TP_ARGS(base_addr),

TP_STRUCT__entry(
__field( void *, base_addr )
),

TP_fast_assign(
__entry->base_addr = base_addr;
),

TP_printk("base_addr=%p", __entry->base_addr)
);

TRACE_EVENT(percpu_destroy_chunk,

TP_PROTO(void *base_addr),

TP_ARGS(base_addr),

TP_STRUCT__entry(
__field( void *, base_addr )
),

TP_fast_assign(
__entry->base_addr = base_addr;
),

TP_printk("base_addr=%p", __entry->base_addr)
);

#endif /* _TRACE_PERCPU_H */

#include <trace/define_trace.h>
6 changes: 3 additions & 3 deletions lib/flex_proportions.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ static void fprop_reflect_period_percpu(struct fprop_global *p,
if (val < (nr_cpu_ids * PROP_BATCH))
val = percpu_counter_sum(&pl->events);

__percpu_counter_add(&pl->events,
percpu_counter_add_batch(&pl->events,
-val + (val >> (period-pl->period)), PROP_BATCH);
} else
percpu_counter_set(&pl->events, 0);
Expand All @@ -219,7 +219,7 @@ static void fprop_reflect_period_percpu(struct fprop_global *p,
void __fprop_inc_percpu(struct fprop_global *p, struct fprop_local_percpu *pl)
{
fprop_reflect_period_percpu(p, pl);
__percpu_counter_add(&pl->events, 1, PROP_BATCH);
percpu_counter_add_batch(&pl->events, 1, PROP_BATCH);
percpu_counter_add(&p->events, 1);
}

Expand Down Expand Up @@ -267,6 +267,6 @@ void __fprop_inc_percpu_max(struct fprop_global *p,
return;
} else
fprop_reflect_period_percpu(p, pl);
__percpu_counter_add(&pl->events, 1, PROP_BATCH);
percpu_counter_add_batch(&pl->events, 1, PROP_BATCH);
percpu_counter_add(&p->events, 1);
}
4 changes: 2 additions & 2 deletions lib/percpu_counter.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ void percpu_counter_set(struct percpu_counter *fbc, s64 amount)
}
EXPORT_SYMBOL(percpu_counter_set);

void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch)
void percpu_counter_add_batch(struct percpu_counter *fbc, s64 amount, s32 batch)
{
s64 count;

Expand All @@ -89,7 +89,7 @@ void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch)
}
preempt_enable();
}
EXPORT_SYMBOL(__percpu_counter_add);
EXPORT_SYMBOL(percpu_counter_add_batch);

/*
* Add up all the per-cpu counts, return the result. This is a more accurate
Expand Down
8 changes: 8 additions & 0 deletions mm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -706,3 +706,11 @@ config ARCH_USES_HIGH_VMA_FLAGS
bool
config ARCH_HAS_PKEYS
bool

config PERCPU_STATS
bool "Collect percpu memory statistics"
default n
help
This feature collects and exposes statistics via debugfs. The
information includes global and per chunk statistics, which can
be used to help understand percpu memory usage.
1 change: 1 addition & 0 deletions mm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,4 @@ obj-$(CONFIG_IDLE_PAGE_TRACKING) += page_idle.o
obj-$(CONFIG_FRAME_VECTOR) += frame_vector.o
obj-$(CONFIG_DEBUG_PAGE_REF) += debug_page_ref.o
obj-$(CONFIG_HARDENED_USERCOPY) += usercopy.o
obj-$(CONFIG_PERCPU_STATS) += percpu-stats.o
Loading

0 comments on commit a4c20b9

Please sign in to comment.