Skip to content

Commit

Permalink
Merge branch 'for-3.18' 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:
 "A lot of activities on percpu front.  Notable changes are...

   - percpu allocator now can take @gfp.  If @gfp doesn't contain
     GFP_KERNEL, it tries to allocate from what's already available to
     the allocator and a work item tries to keep the reserve around
     certain level so that these atomic allocations usually succeed.

     This will replace the ad-hoc percpu memory pool used by
     blk-throttle and also be used by the planned blkcg support for
     writeback IOs.

     Please note that I noticed a bug in how @gfp is interpreted while
     preparing this pull request and applied the fix 6ae833c
     ("percpu: fix how @gfp is interpreted by the percpu allocator")
     just now.

   - percpu_ref now uses longs for percpu and global counters instead of
     ints.  It leads to more sparse packing of the percpu counters on
     64bit machines but the overhead should be negligible and this
     allows using percpu_ref for refcnting pages and in-memory objects
     directly.

   - The switching between percpu and single counter modes of a
     percpu_ref is made independent of putting the base ref and a
     percpu_ref can now optionally be initialized in single or killed
     mode.  This allows avoiding percpu shutdown latency for cases where
     the refcounted objects may be synchronously created and destroyed
     in rapid succession with only a fraction of them reaching fully
     operational status (SCSI probing does this when combined with
     blk-mq support).  It's also planned to be used to implement forced
     single mode to detect underflow more timely for debugging.

  There's a separate branch percpu/for-3.18-consistent-ops which cleans
  up the duplicate percpu accessors.  That branch causes a number of
  conflicts with s390 and other trees.  I'll send a separate pull
  request w/ resolutions once other branches are merged"

* 'for-3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu: (33 commits)
  percpu: fix how @gfp is interpreted by the percpu allocator
  blk-mq, percpu_ref: start q->mq_usage_counter in atomic mode
  percpu_ref: make INIT_ATOMIC and switch_to_atomic() sticky
  percpu_ref: add PERCPU_REF_INIT_* flags
  percpu_ref: decouple switching to percpu mode and reinit
  percpu_ref: decouple switching to atomic mode and killing
  percpu_ref: add PCPU_REF_DEAD
  percpu_ref: rename things to prepare for decoupling percpu/atomic mode switch
  percpu_ref: replace pcpu_ prefix with percpu_
  percpu_ref: minor code and comment updates
  percpu_ref: relocate percpu_ref_reinit()
  Revert "blk-mq, percpu_ref: implement a kludge for SCSI blk-mq stall during probe"
  Revert "percpu: free percpu allocation info for uniprocessor system"
  percpu-refcount: make percpu_ref based on longs instead of ints
  percpu-refcount: improve WARN messages
  percpu: fix locking regression in the failure path of pcpu_alloc()
  percpu-refcount: add @gfp to percpu_ref_init()
  proportions: add @gfp to init functions
  percpu_counter: add @gfp to percpu_counter_init()
  percpu_counter: make percpu_counters_lock irq-safe
  ...
  • Loading branch information
torvalds committed Oct 10, 2014
2 parents b211e9d + 6ae833c commit c798360
Show file tree
Hide file tree
Showing 39 changed files with 879 additions and 444 deletions.
2 changes: 1 addition & 1 deletion arch/x86/kvm/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -4549,7 +4549,7 @@ int kvm_mmu_module_init(void)
if (!mmu_page_header_cache)
goto nomem;

if (percpu_counter_init(&kvm_total_used_mmu_pages, 0))
if (percpu_counter_init(&kvm_total_used_mmu_pages, 0, GFP_KERNEL))
goto nomem;

register_shrinker(&mmu_shrinker);
Expand Down
6 changes: 6 additions & 0 deletions block/blk-mq-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,12 @@ static void blk_mq_sysfs_init(struct request_queue *q)
}
}

/* see blk_register_queue() */
void blk_mq_finish_init(struct request_queue *q)
{
percpu_ref_switch_to_percpu(&q->mq_usage_counter);
}

int blk_mq_register_disk(struct gendisk *disk)
{
struct device *dev = disk_to_dev(disk);
Expand Down
18 changes: 7 additions & 11 deletions block/blk-mq.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,16 +119,7 @@ void blk_mq_freeze_queue(struct request_queue *q)
spin_unlock_irq(q->queue_lock);

if (freeze) {
/*
* XXX: Temporary kludge to work around SCSI blk-mq stall.
* SCSI synchronously creates and destroys many queues
* back-to-back during probe leading to lengthy stalls.
* This will be fixed by keeping ->mq_usage_counter in
* atomic mode until genhd registration, but, for now,
* let's work around using expedited synchronization.
*/
__percpu_ref_kill_expedited(&q->mq_usage_counter);

percpu_ref_kill(&q->mq_usage_counter);
blk_mq_run_queues(q, false);
}
wait_event(q->mq_freeze_wq, percpu_ref_is_zero(&q->mq_usage_counter));
Expand Down Expand Up @@ -1804,7 +1795,12 @@ struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *set)
if (!q)
goto err_hctxs;

if (percpu_ref_init(&q->mq_usage_counter, blk_mq_usage_counter_release))
/*
* Init percpu_ref in atomic mode so that it's faster to shutdown.
* See blk_register_queue() for details.
*/
if (percpu_ref_init(&q->mq_usage_counter, blk_mq_usage_counter_release,
PERCPU_REF_INIT_ATOMIC, GFP_KERNEL))
goto err_map;

setup_timer(&q->timeout, blk_mq_rq_timer, (unsigned long) q);
Expand Down
11 changes: 9 additions & 2 deletions block/blk-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -551,12 +551,19 @@ int blk_register_queue(struct gendisk *disk)
return -ENXIO;

/*
* Initialization must be complete by now. Finish the initial
* bypass from queue allocation.
* SCSI probing may synchronously create and destroy a lot of
* request_queues for non-existent devices. Shutting down a fully
* functional queue takes measureable wallclock time as RCU grace
* periods are involved. To avoid excessive latency in these
* cases, a request_queue starts out in a degraded mode which is
* faster to shut down and is made fully functional here as
* request_queues for non-existent devices never get registered.
*/
if (!blk_queue_init_done(q)) {
queue_flag_set_unlocked(QUEUE_FLAG_INIT_DONE, q);
blk_queue_bypass_end(q);
if (q->mq_ops)
blk_mq_finish_init(q);
}

ret = blk_trace_init_sysfs(dev);
Expand Down
3 changes: 2 additions & 1 deletion drivers/target/target_core_tpg.c
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,8 @@ int core_tpg_add_lun(
{
int ret;

ret = percpu_ref_init(&lun->lun_ref, core_tpg_lun_ref_release);
ret = percpu_ref_init(&lun->lun_ref, core_tpg_lun_ref_release, 0,
GFP_KERNEL);
if (ret < 0)
return ret;

Expand Down
4 changes: 2 additions & 2 deletions fs/aio.c
Original file line number Diff line number Diff line change
Expand Up @@ -661,10 +661,10 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)

INIT_LIST_HEAD(&ctx->active_reqs);

if (percpu_ref_init(&ctx->users, free_ioctx_users))
if (percpu_ref_init(&ctx->users, free_ioctx_users, 0, GFP_KERNEL))
goto err;

if (percpu_ref_init(&ctx->reqs, free_ioctx_reqs))
if (percpu_ref_init(&ctx->reqs, free_ioctx_reqs, 0, GFP_KERNEL))
goto err;

ctx->cpu = alloc_percpu(struct kioctx_cpu);
Expand Down
8 changes: 4 additions & 4 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -1183,7 +1183,7 @@ static struct btrfs_subvolume_writers *btrfs_alloc_subvolume_writers(void)
if (!writers)
return ERR_PTR(-ENOMEM);

ret = percpu_counter_init(&writers->counter, 0);
ret = percpu_counter_init(&writers->counter, 0, GFP_KERNEL);
if (ret < 0) {
kfree(writers);
return ERR_PTR(ret);
Expand Down Expand Up @@ -2188,21 +2188,21 @@ int open_ctree(struct super_block *sb,
goto fail_srcu;
}

ret = percpu_counter_init(&fs_info->dirty_metadata_bytes, 0);
ret = percpu_counter_init(&fs_info->dirty_metadata_bytes, 0, GFP_KERNEL);
if (ret) {
err = ret;
goto fail_bdi;
}
fs_info->dirty_metadata_batch = PAGE_CACHE_SIZE *
(1 + ilog2(nr_cpu_ids));

ret = percpu_counter_init(&fs_info->delalloc_bytes, 0);
ret = percpu_counter_init(&fs_info->delalloc_bytes, 0, GFP_KERNEL);
if (ret) {
err = ret;
goto fail_dirty_metadata_bytes;
}

ret = percpu_counter_init(&fs_info->bio_counter, 0);
ret = percpu_counter_init(&fs_info->bio_counter, 0, GFP_KERNEL);
if (ret) {
err = ret;
goto fail_delalloc_bytes;
Expand Down
2 changes: 1 addition & 1 deletion fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -3494,7 +3494,7 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
if (!found)
return -ENOMEM;

ret = percpu_counter_init(&found->total_bytes_pinned, 0);
ret = percpu_counter_init(&found->total_bytes_pinned, 0, GFP_KERNEL);
if (ret) {
kfree(found);
return ret;
Expand Down
6 changes: 3 additions & 3 deletions fs/ext2/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -1067,14 +1067,14 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
ext2_rsv_window_add(sb, &sbi->s_rsv_window_head);

err = percpu_counter_init(&sbi->s_freeblocks_counter,
ext2_count_free_blocks(sb));
ext2_count_free_blocks(sb), GFP_KERNEL);
if (!err) {
err = percpu_counter_init(&sbi->s_freeinodes_counter,
ext2_count_free_inodes(sb));
ext2_count_free_inodes(sb), GFP_KERNEL);
}
if (!err) {
err = percpu_counter_init(&sbi->s_dirs_counter,
ext2_count_dirs(sb));
ext2_count_dirs(sb), GFP_KERNEL);
}
if (err) {
ext2_msg(sb, KERN_ERR, "error: insufficient memory");
Expand Down
6 changes: 3 additions & 3 deletions fs/ext3/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -2039,14 +2039,14 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
goto failed_mount2;
}
err = percpu_counter_init(&sbi->s_freeblocks_counter,
ext3_count_free_blocks(sb));
ext3_count_free_blocks(sb), GFP_KERNEL);
if (!err) {
err = percpu_counter_init(&sbi->s_freeinodes_counter,
ext3_count_free_inodes(sb));
ext3_count_free_inodes(sb), GFP_KERNEL);
}
if (!err) {
err = percpu_counter_init(&sbi->s_dirs_counter,
ext3_count_dirs(sb));
ext3_count_dirs(sb), GFP_KERNEL);
}
if (err) {
ext3_msg(sb, KERN_ERR, "error: insufficient memory");
Expand Down
14 changes: 9 additions & 5 deletions fs/ext4/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -3892,7 +3892,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
/* Register extent status tree shrinker */
ext4_es_register_shrinker(sbi);

if ((err = percpu_counter_init(&sbi->s_extent_cache_cnt, 0)) != 0) {
err = percpu_counter_init(&sbi->s_extent_cache_cnt, 0, GFP_KERNEL);
if (err) {
ext4_msg(sb, KERN_ERR, "insufficient memory");
goto failed_mount3;
}
Expand Down Expand Up @@ -4106,17 +4107,20 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
block = ext4_count_free_clusters(sb);
ext4_free_blocks_count_set(sbi->s_es,
EXT4_C2B(sbi, block));
err = percpu_counter_init(&sbi->s_freeclusters_counter, block);
err = percpu_counter_init(&sbi->s_freeclusters_counter, block,
GFP_KERNEL);
if (!err) {
unsigned long freei = ext4_count_free_inodes(sb);
sbi->s_es->s_free_inodes_count = cpu_to_le32(freei);
err = percpu_counter_init(&sbi->s_freeinodes_counter, freei);
err = percpu_counter_init(&sbi->s_freeinodes_counter, freei,
GFP_KERNEL);
}
if (!err)
err = percpu_counter_init(&sbi->s_dirs_counter,
ext4_count_dirs(sb));
ext4_count_dirs(sb), GFP_KERNEL);
if (!err)
err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0);
err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0,
GFP_KERNEL);
if (err) {
ext4_msg(sb, KERN_ERR, "insufficient memory");
goto failed_mount6;
Expand Down
2 changes: 1 addition & 1 deletion fs/file_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,5 +331,5 @@ void __init files_init(unsigned long mempages)

n = (mempages * (PAGE_SIZE / 1024)) / 10;
files_stat.max_files = max_t(unsigned long, n, NR_FILE);
percpu_counter_init(&nr_files, 0);
percpu_counter_init(&nr_files, 0, GFP_KERNEL);
}
2 changes: 1 addition & 1 deletion fs/quota/dquot.c
Original file line number Diff line number Diff line change
Expand Up @@ -2725,7 +2725,7 @@ static int __init dquot_init(void)
panic("Cannot create dquot hash table");

for (i = 0; i < _DQST_DQSTAT_LAST; i++) {
ret = percpu_counter_init(&dqstats.counter[i], 0);
ret = percpu_counter_init(&dqstats.counter[i], 0, GFP_KERNEL);
if (ret)
panic("Cannot create dquot stat counters");
}
Expand Down
3 changes: 2 additions & 1 deletion fs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags)
goto fail;

for (i = 0; i < SB_FREEZE_LEVELS; i++) {
if (percpu_counter_init(&s->s_writers.counter[i], 0) < 0)
if (percpu_counter_init(&s->s_writers.counter[i], 0,
GFP_KERNEL) < 0)
goto fail;
lockdep_init_map(&s->s_writers.lock_map[i], sb_writers_name[i],
&type->s_writers_key[i], 0);
Expand Down
1 change: 1 addition & 0 deletions include/linux/blk-mq.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ enum {
};

struct request_queue *blk_mq_init_queue(struct blk_mq_tag_set *);
void blk_mq_finish_init(struct request_queue *q);
int blk_mq_register_disk(struct gendisk *);
void blk_mq_unregister_disk(struct gendisk *);

Expand Down
5 changes: 3 additions & 2 deletions include/linux/flex_proportions.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <linux/percpu_counter.h>
#include <linux/spinlock.h>
#include <linux/seqlock.h>
#include <linux/gfp.h>

/*
* When maximum proportion of some event type is specified, this is the
Expand All @@ -32,7 +33,7 @@ struct fprop_global {
seqcount_t sequence;
};

int fprop_global_init(struct fprop_global *p);
int fprop_global_init(struct fprop_global *p, gfp_t gfp);
void fprop_global_destroy(struct fprop_global *p);
bool fprop_new_period(struct fprop_global *p, int periods);

Expand Down Expand Up @@ -79,7 +80,7 @@ struct fprop_local_percpu {
raw_spinlock_t lock; /* Protect period and numerator */
};

int fprop_local_init_percpu(struct fprop_local_percpu *pl);
int fprop_local_init_percpu(struct fprop_local_percpu *pl, gfp_t gfp);
void fprop_local_destroy_percpu(struct fprop_local_percpu *pl);
void __fprop_inc_percpu(struct fprop_global *p, struct fprop_local_percpu *pl);
void __fprop_inc_percpu_max(struct fprop_global *p, struct fprop_local_percpu *pl,
Expand Down
Loading

0 comments on commit c798360

Please sign in to comment.