Skip to content

Commit

Permalink
block: partition: convert percpu ref
Browse files Browse the repository at this point in the history
Percpu refcount is the perfect match for partition's case,
and the conversion is quite straight.

With the convertion, one pair of atomic inc/dec can be saved
for accounting block I/O, which is run in hot path of block I/O.

Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jens Axboe <axboe@fb.com>
  • Loading branch information
ming1 authored and axboe committed Jul 17, 2015
1 parent b54e5ed commit 6c71013
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 15 deletions.
6 changes: 5 additions & 1 deletion block/genhd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1284,7 +1284,11 @@ struct gendisk *alloc_disk_node(int minors, int node_id)
* converted to make use of bd_mutex and sequence counters.
*/
seqcount_init(&disk->part0.nr_sects_seq);
hd_ref_init(&disk->part0);
if (hd_ref_init(&disk->part0)) {
hd_free_part(&disk->part0);
kfree(disk);
return NULL;
}

disk->minors = minors;
rand_initialize_disk(disk);
Expand Down
9 changes: 5 additions & 4 deletions block/partition-generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,9 @@ static void delete_partition_rcu_cb(struct rcu_head *head)
put_device(part_to_dev(part));
}

void __delete_partition(struct hd_struct *part)
void __delete_partition(struct percpu_ref *ref)
{
struct hd_struct *part = container_of(ref, struct hd_struct, ref);
call_rcu(&part->rcu_head, delete_partition_rcu_cb);
}

Expand All @@ -254,7 +255,7 @@ void delete_partition(struct gendisk *disk, int partno)
kobject_put(part->holder_dir);
device_del(part_to_dev(part));

hd_struct_put(part);
hd_struct_kill(part);
}

static ssize_t whole_disk_show(struct device *dev,
Expand Down Expand Up @@ -355,8 +356,8 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno,
if (!dev_get_uevent_suppress(ddev))
kobject_uevent(&pdev->kobj, KOBJ_ADD);

hd_ref_init(p);
return p;
if (!hd_ref_init(p))
return p;

out_free_info:
free_part_info(p);
Expand Down
27 changes: 17 additions & 10 deletions include/linux/genhd.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/kdev_t.h>
#include <linux/rcupdate.h>
#include <linux/slab.h>
#include <linux/percpu-refcount.h>

#ifdef CONFIG_BLOCK

Expand Down Expand Up @@ -124,7 +125,7 @@ struct hd_struct {
#else
struct disk_stats dkstats;
#endif
atomic_t ref;
struct percpu_ref ref;
struct rcu_head rcu_head;
};

Expand Down Expand Up @@ -611,7 +612,7 @@ extern struct hd_struct * __must_check add_partition(struct gendisk *disk,
sector_t len, int flags,
struct partition_meta_info
*info);
extern void __delete_partition(struct hd_struct *);
extern void __delete_partition(struct percpu_ref *);
extern void delete_partition(struct gendisk *, int);
extern void printk_all_partitions(void);

Expand Down Expand Up @@ -640,33 +641,39 @@ extern ssize_t part_fail_store(struct device *dev,
const char *buf, size_t count);
#endif /* CONFIG_FAIL_MAKE_REQUEST */

static inline void hd_ref_init(struct hd_struct *part)
static inline int hd_ref_init(struct hd_struct *part)
{
atomic_set(&part->ref, 1);
smp_mb();
if (percpu_ref_init(&part->ref, __delete_partition, 0,
GFP_KERNEL))
return -ENOMEM;
return 0;
}

static inline void hd_struct_get(struct hd_struct *part)
{
atomic_inc(&part->ref);
smp_mb__after_atomic();
percpu_ref_get(&part->ref);
}

static inline int hd_struct_try_get(struct hd_struct *part)
{
return atomic_inc_not_zero(&part->ref);
return percpu_ref_tryget_live(&part->ref);
}

static inline void hd_struct_put(struct hd_struct *part)
{
if (atomic_dec_and_test(&part->ref))
__delete_partition(part);
percpu_ref_put(&part->ref);
}

static inline void hd_struct_kill(struct hd_struct *part)
{
percpu_ref_kill(&part->ref);
}

static inline void hd_free_part(struct hd_struct *part)
{
free_part_stats(part);
free_part_info(part);
percpu_ref_exit(&part->ref);
}

/*
Expand Down

0 comments on commit 6c71013

Please sign in to comment.