Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932080AbbGPDTx (ORCPT ); Wed, 15 Jul 2015 23:19:53 -0400 Received: from mail-pd0-f169.google.com ([209.85.192.169]:33572 "EHLO mail-pd0-f169.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753660AbbGPDTu (ORCPT ); Wed, 15 Jul 2015 23:19:50 -0400 From: Ming Lei To: Jens Axboe , linux-kernel@vger.kernel.org Cc: Mike Snitzer , Tejun Heo , Ming Lei Subject: [PATCH 2/4] block: partition: convert percpu ref Date: Thu, 16 Jul 2015 11:16:45 +0800 Message-Id: <1437016607-375-3-git-send-email-tom.leiming@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1437016607-375-1-git-send-email-tom.leiming@gmail.com> References: <1437016607-375-1-git-send-email-tom.leiming@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4258 Lines: 151 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 --- block/genhd.c | 6 +++++- block/partition-generic.c | 9 +++++---- include/linux/genhd.h | 27 +++++++++++++++++---------- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index ed3f5b9..3213b66 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -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); diff --git a/block/partition-generic.c b/block/partition-generic.c index eca0d02..e771113 100644 --- a/block/partition-generic.c +++ b/block/partition-generic.c @@ -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); } @@ -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, @@ -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); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index a221220..2adbfa6 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -13,6 +13,7 @@ #include #include #include +#include #ifdef CONFIG_BLOCK @@ -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; }; @@ -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); @@ -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); } /* -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/