Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

block: add internal hd part table references

We can't use krefs since it's apparently restricted to very basic
reference counting.

This reverts commit e4a683c8.

Signed-off-by: Jens Axboe <jaxboe@fusionio.com>

+34 -25
+3 -3
block/blk-core.c
··· 70 70 part_stat_inc(cpu, part, merges[rw]); 71 71 } else { 72 72 part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq)); 73 - if (!kref_test_and_get(&part->ref)) { 73 + if (!hd_struct_try_get(part)) { 74 74 /* 75 75 * The partition is already being removed, 76 76 * the request will be accounted on the disk only ··· 80 80 * it as any other partition. 81 81 */ 82 82 part = &rq->rq_disk->part0; 83 - kref_get(&part->ref); 83 + hd_struct_get(part); 84 84 } 85 85 part_round_stats(cpu, part); 86 86 part_inc_in_flight(part, rw); ··· 1818 1818 part_round_stats(cpu, part); 1819 1819 part_dec_in_flight(part, rw); 1820 1820 1821 - kref_put(&part->ref, __delete_partition); 1821 + hd_struct_put(part); 1822 1822 part_stat_unlock(); 1823 1823 } 1824 1824 }
+1 -1
block/blk-merge.c
··· 356 356 part_round_stats(cpu, part); 357 357 part_dec_in_flight(part, rq_data_dir(req)); 358 358 359 - kref_put(&part->ref, __delete_partition); 359 + hd_struct_put(part); 360 360 part_stat_unlock(); 361 361 } 362 362 }
+2 -1
block/genhd.c
··· 1192 1192 return NULL; 1193 1193 } 1194 1194 disk->part_tbl->part[0] = &disk->part0; 1195 - kref_init(&disk->part0.ref); 1195 + 1196 + hd_ref_init(&disk->part0); 1196 1197 1197 1198 disk->minors = minors; 1198 1199 rand_initialize_disk(disk);
+3 -5
fs/partitions/check.c
··· 381 381 put_device(part_to_dev(part)); 382 382 } 383 383 384 - void __delete_partition(struct kref *ref) 384 + void __delete_partition(struct hd_struct *part) 385 385 { 386 - struct hd_struct *part = container_of(ref, struct hd_struct, ref); 387 - 388 386 call_rcu(&part->rcu_head, delete_partition_rcu_cb); 389 387 } 390 388 ··· 404 406 kobject_put(part->holder_dir); 405 407 device_del(part_to_dev(part)); 406 408 407 - kref_put(&part->ref, __delete_partition); 409 + hd_struct_put(part); 408 410 } 409 411 410 412 static ssize_t whole_disk_show(struct device *dev, ··· 503 505 if (!dev_get_uevent_suppress(ddev)) 504 506 kobject_uevent(&pdev->kobj, KOBJ_ADD); 505 507 506 - kref_init(&p->ref); 508 + hd_ref_init(p); 507 509 return p; 508 510 509 511 out_free_info:
+25 -2
include/linux/genhd.h
··· 115 115 #else 116 116 struct disk_stats dkstats; 117 117 #endif 118 + atomic_t ref; 118 119 struct rcu_head rcu_head; 119 - struct kref ref; 120 120 }; 121 121 122 122 #define GENHD_FL_REMOVABLE 1 ··· 584 584 sector_t len, int flags, 585 585 struct partition_meta_info 586 586 *info); 587 - extern void __delete_partition(struct kref *ref); 587 + extern void __delete_partition(struct hd_struct *); 588 588 extern void delete_partition(struct gendisk *, int); 589 589 extern void printk_all_partitions(void); 590 590 ··· 612 612 struct device_attribute *attr, 613 613 const char *buf, size_t count); 614 614 #endif /* CONFIG_FAIL_MAKE_REQUEST */ 615 + 616 + static inline void hd_ref_init(struct hd_struct *part) 617 + { 618 + atomic_set(&part->ref, 1); 619 + smp_mb(); 620 + } 621 + 622 + static inline void hd_struct_get(struct hd_struct *part) 623 + { 624 + atomic_inc(&part->ref); 625 + smp_mb__after_atomic_inc(); 626 + } 627 + 628 + static inline int hd_struct_try_get(struct hd_struct *part) 629 + { 630 + return atomic_inc_not_zero(&part->ref); 631 + } 632 + 633 + static inline void hd_struct_put(struct hd_struct *part) 634 + { 635 + if (atomic_dec_and_test(&part->ref)) 636 + __delete_partition(part); 637 + } 615 638 616 639 #else /* CONFIG_BLOCK */ 617 640
-1
include/linux/kref.h
··· 23 23 24 24 void kref_init(struct kref *kref); 25 25 void kref_get(struct kref *kref); 26 - int kref_test_and_get(struct kref *kref); 27 26 int kref_put(struct kref *kref, void (*release) (struct kref *kref)); 28 27 29 28 #endif /* _KREF_H_ */
-12
lib/kref.c
··· 37 37 } 38 38 39 39 /** 40 - * kref_test_and_get - increment refcount for object only if refcount is not 41 - * zero. 42 - * @kref: object. 43 - * 44 - * Return non-zero if the refcount was incremented, 0 otherwise 45 - */ 46 - int kref_test_and_get(struct kref *kref) 47 - { 48 - return atomic_inc_not_zero(&kref->refcount); 49 - } 50 - 51 - /** 52 40 * kref_put - decrement refcount for object. 53 41 * @kref: object. 54 42 * @release: pointer to the function that will clean up the object when the