Loading block/blk-core.c +3 −3 Original line number Diff line number Diff line Loading @@ -70,7 +70,7 @@ static void drive_stat_acct(struct request *rq, int new_io) part_stat_inc(cpu, part, merges[rw]); } else { part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq)); if (!kref_test_and_get(&part->ref)) { if (!hd_struct_try_get(part)) { /* * The partition is already being removed, * the request will be accounted on the disk only Loading @@ -80,7 +80,7 @@ static void drive_stat_acct(struct request *rq, int new_io) * it as any other partition. */ part = &rq->rq_disk->part0; kref_get(&part->ref); hd_struct_get(part); } part_round_stats(cpu, part); part_inc_in_flight(part, rw); Loading Loading @@ -1818,7 +1818,7 @@ static void blk_account_io_done(struct request *req) part_round_stats(cpu, part); part_dec_in_flight(part, rw); kref_put(&part->ref, __delete_partition); hd_struct_put(part); part_stat_unlock(); } } Loading block/blk-merge.c +1 −1 Original line number Diff line number Diff line Loading @@ -356,7 +356,7 @@ static void blk_account_io_merge(struct request *req) part_round_stats(cpu, part); part_dec_in_flight(part, rq_data_dir(req)); kref_put(&part->ref, __delete_partition); hd_struct_put(part); part_stat_unlock(); } } Loading block/genhd.c +2 −1 Original line number Diff line number Diff line Loading @@ -1192,7 +1192,8 @@ struct gendisk *alloc_disk_node(int minors, int node_id) return NULL; } disk->part_tbl->part[0] = &disk->part0; kref_init(&disk->part0.ref); hd_ref_init(&disk->part0); disk->minors = minors; rand_initialize_disk(disk); Loading fs/partitions/check.c +3 −5 Original line number Diff line number Diff line Loading @@ -381,10 +381,8 @@ static void delete_partition_rcu_cb(struct rcu_head *head) put_device(part_to_dev(part)); } void __delete_partition(struct kref *ref) void __delete_partition(struct hd_struct *part) { struct hd_struct *part = container_of(ref, struct hd_struct, ref); call_rcu(&part->rcu_head, delete_partition_rcu_cb); } Loading @@ -406,7 +404,7 @@ void delete_partition(struct gendisk *disk, int partno) kobject_put(part->holder_dir); device_del(part_to_dev(part)); kref_put(&part->ref, __delete_partition); hd_struct_put(part); } static ssize_t whole_disk_show(struct device *dev, Loading Loading @@ -505,7 +503,7 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, if (!dev_get_uevent_suppress(ddev)) kobject_uevent(&pdev->kobj, KOBJ_ADD); kref_init(&p->ref); hd_ref_init(p); return p; out_free_info: Loading include/linux/genhd.h +25 −2 Original line number Diff line number Diff line Loading @@ -115,8 +115,8 @@ struct hd_struct { #else struct disk_stats dkstats; #endif atomic_t ref; struct rcu_head rcu_head; struct kref ref; }; #define GENHD_FL_REMOVABLE 1 Loading Loading @@ -584,7 +584,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 kref *ref); extern void __delete_partition(struct hd_struct *); extern void delete_partition(struct gendisk *, int); extern void printk_all_partitions(void); Loading Loading @@ -613,6 +613,29 @@ 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) { atomic_set(&part->ref, 1); smp_mb(); } static inline void hd_struct_get(struct hd_struct *part) { atomic_inc(&part->ref); smp_mb__after_atomic_inc(); } static inline int hd_struct_try_get(struct hd_struct *part) { return atomic_inc_not_zero(&part->ref); } static inline void hd_struct_put(struct hd_struct *part) { if (atomic_dec_and_test(&part->ref)) __delete_partition(part); } #else /* CONFIG_BLOCK */ static inline void printk_all_partitions(void) { } Loading Loading
block/blk-core.c +3 −3 Original line number Diff line number Diff line Loading @@ -70,7 +70,7 @@ static void drive_stat_acct(struct request *rq, int new_io) part_stat_inc(cpu, part, merges[rw]); } else { part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq)); if (!kref_test_and_get(&part->ref)) { if (!hd_struct_try_get(part)) { /* * The partition is already being removed, * the request will be accounted on the disk only Loading @@ -80,7 +80,7 @@ static void drive_stat_acct(struct request *rq, int new_io) * it as any other partition. */ part = &rq->rq_disk->part0; kref_get(&part->ref); hd_struct_get(part); } part_round_stats(cpu, part); part_inc_in_flight(part, rw); Loading Loading @@ -1818,7 +1818,7 @@ static void blk_account_io_done(struct request *req) part_round_stats(cpu, part); part_dec_in_flight(part, rw); kref_put(&part->ref, __delete_partition); hd_struct_put(part); part_stat_unlock(); } } Loading
block/blk-merge.c +1 −1 Original line number Diff line number Diff line Loading @@ -356,7 +356,7 @@ static void blk_account_io_merge(struct request *req) part_round_stats(cpu, part); part_dec_in_flight(part, rq_data_dir(req)); kref_put(&part->ref, __delete_partition); hd_struct_put(part); part_stat_unlock(); } } Loading
block/genhd.c +2 −1 Original line number Diff line number Diff line Loading @@ -1192,7 +1192,8 @@ struct gendisk *alloc_disk_node(int minors, int node_id) return NULL; } disk->part_tbl->part[0] = &disk->part0; kref_init(&disk->part0.ref); hd_ref_init(&disk->part0); disk->minors = minors; rand_initialize_disk(disk); Loading
fs/partitions/check.c +3 −5 Original line number Diff line number Diff line Loading @@ -381,10 +381,8 @@ static void delete_partition_rcu_cb(struct rcu_head *head) put_device(part_to_dev(part)); } void __delete_partition(struct kref *ref) void __delete_partition(struct hd_struct *part) { struct hd_struct *part = container_of(ref, struct hd_struct, ref); call_rcu(&part->rcu_head, delete_partition_rcu_cb); } Loading @@ -406,7 +404,7 @@ void delete_partition(struct gendisk *disk, int partno) kobject_put(part->holder_dir); device_del(part_to_dev(part)); kref_put(&part->ref, __delete_partition); hd_struct_put(part); } static ssize_t whole_disk_show(struct device *dev, Loading Loading @@ -505,7 +503,7 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, if (!dev_get_uevent_suppress(ddev)) kobject_uevent(&pdev->kobj, KOBJ_ADD); kref_init(&p->ref); hd_ref_init(p); return p; out_free_info: Loading
include/linux/genhd.h +25 −2 Original line number Diff line number Diff line Loading @@ -115,8 +115,8 @@ struct hd_struct { #else struct disk_stats dkstats; #endif atomic_t ref; struct rcu_head rcu_head; struct kref ref; }; #define GENHD_FL_REMOVABLE 1 Loading Loading @@ -584,7 +584,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 kref *ref); extern void __delete_partition(struct hd_struct *); extern void delete_partition(struct gendisk *, int); extern void printk_all_partitions(void); Loading Loading @@ -613,6 +613,29 @@ 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) { atomic_set(&part->ref, 1); smp_mb(); } static inline void hd_struct_get(struct hd_struct *part) { atomic_inc(&part->ref); smp_mb__after_atomic_inc(); } static inline int hd_struct_try_get(struct hd_struct *part) { return atomic_inc_not_zero(&part->ref); } static inline void hd_struct_put(struct hd_struct *part) { if (atomic_dec_and_test(&part->ref)) __delete_partition(part); } #else /* CONFIG_BLOCK */ static inline void printk_all_partitions(void) { } Loading