Skip to content

Commit 6c71013

Browse files
ming1axboe
authored andcommitted
block: partition: convert percpu ref
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>
1 parent b54e5ed commit 6c71013

File tree

3 files changed

+27
-15
lines changed

3 files changed

+27
-15
lines changed

block/genhd.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1284,7 +1284,11 @@ struct gendisk *alloc_disk_node(int minors, int node_id)
12841284
* converted to make use of bd_mutex and sequence counters.
12851285
*/
12861286
seqcount_init(&disk->part0.nr_sects_seq);
1287-
hd_ref_init(&disk->part0);
1287+
if (hd_ref_init(&disk->part0)) {
1288+
hd_free_part(&disk->part0);
1289+
kfree(disk);
1290+
return NULL;
1291+
}
12881292

12891293
disk->minors = minors;
12901294
rand_initialize_disk(disk);

block/partition-generic.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,9 @@ static void delete_partition_rcu_cb(struct rcu_head *head)
232232
put_device(part_to_dev(part));
233233
}
234234

235-
void __delete_partition(struct hd_struct *part)
235+
void __delete_partition(struct percpu_ref *ref)
236236
{
237+
struct hd_struct *part = container_of(ref, struct hd_struct, ref);
237238
call_rcu(&part->rcu_head, delete_partition_rcu_cb);
238239
}
239240

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

257-
hd_struct_put(part);
258+
hd_struct_kill(part);
258259
}
259260

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

358-
hd_ref_init(p);
359-
return p;
359+
if (!hd_ref_init(p))
360+
return p;
360361

361362
out_free_info:
362363
free_part_info(p);

include/linux/genhd.h

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/kdev_t.h>
1414
#include <linux/rcupdate.h>
1515
#include <linux/slab.h>
16+
#include <linux/percpu-refcount.h>
1617

1718
#ifdef CONFIG_BLOCK
1819

@@ -124,7 +125,7 @@ struct hd_struct {
124125
#else
125126
struct disk_stats dkstats;
126127
#endif
127-
atomic_t ref;
128+
struct percpu_ref ref;
128129
struct rcu_head rcu_head;
129130
};
130131

@@ -611,7 +612,7 @@ extern struct hd_struct * __must_check add_partition(struct gendisk *disk,
611612
sector_t len, int flags,
612613
struct partition_meta_info
613614
*info);
614-
extern void __delete_partition(struct hd_struct *);
615+
extern void __delete_partition(struct percpu_ref *);
615616
extern void delete_partition(struct gendisk *, int);
616617
extern void printk_all_partitions(void);
617618

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

643-
static inline void hd_ref_init(struct hd_struct *part)
644+
static inline int hd_ref_init(struct hd_struct *part)
644645
{
645-
atomic_set(&part->ref, 1);
646-
smp_mb();
646+
if (percpu_ref_init(&part->ref, __delete_partition, 0,
647+
GFP_KERNEL))
648+
return -ENOMEM;
649+
return 0;
647650
}
648651

649652
static inline void hd_struct_get(struct hd_struct *part)
650653
{
651-
atomic_inc(&part->ref);
652-
smp_mb__after_atomic();
654+
percpu_ref_get(&part->ref);
653655
}
654656

655657
static inline int hd_struct_try_get(struct hd_struct *part)
656658
{
657-
return atomic_inc_not_zero(&part->ref);
659+
return percpu_ref_tryget_live(&part->ref);
658660
}
659661

660662
static inline void hd_struct_put(struct hd_struct *part)
661663
{
662-
if (atomic_dec_and_test(&part->ref))
663-
__delete_partition(part);
664+
percpu_ref_put(&part->ref);
665+
}
666+
667+
static inline void hd_struct_kill(struct hd_struct *part)
668+
{
669+
percpu_ref_kill(&part->ref);
664670
}
665671

666672
static inline void hd_free_part(struct hd_struct *part)
667673
{
668674
free_part_stats(part);
669675
free_part_info(part);
676+
percpu_ref_exit(&part->ref);
670677
}
671678

672679
/*

0 commit comments

Comments
 (0)