diff options
author | Jens Axboe <jaxboe@fusionio.com> | 2011-01-07 02:43:37 -0500 |
---|---|---|
committer | Jens Axboe <jaxboe@fusionio.com> | 2011-01-07 02:43:37 -0500 |
commit | 6c23a9681c0fe7fb7dd331b39dda11926f43746e (patch) | |
tree | bf113a475a17faa866e7e59806378107dcb3aa40 | |
parent | 09e099d4bafea3b15be003d548bdf94b4b6e0e17 (diff) |
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>
-rw-r--r-- | block/blk-core.c | 6 | ||||
-rw-r--r-- | block/blk-merge.c | 2 | ||||
-rw-r--r-- | block/genhd.c | 3 | ||||
-rw-r--r-- | fs/partitions/check.c | 8 | ||||
-rw-r--r-- | include/linux/genhd.h | 27 | ||||
-rw-r--r-- | include/linux/kref.h | 1 | ||||
-rw-r--r-- | lib/kref.c | 12 |
7 files changed, 34 insertions, 25 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index 500c080a6a6b..2f4002f79a24 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -70,7 +70,7 @@ static void drive_stat_acct(struct request *rq, int new_io) | |||
70 | part_stat_inc(cpu, part, merges[rw]); | 70 | part_stat_inc(cpu, part, merges[rw]); |
71 | } else { | 71 | } else { |
72 | part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq)); | 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 | * The partition is already being removed, | 75 | * The partition is already being removed, |
76 | * the request will be accounted on the disk only | 76 | * the request will be accounted on the disk only |
@@ -80,7 +80,7 @@ static void drive_stat_acct(struct request *rq, int new_io) | |||
80 | * it as any other partition. | 80 | * it as any other partition. |
81 | */ | 81 | */ |
82 | part = &rq->rq_disk->part0; | 82 | part = &rq->rq_disk->part0; |
83 | kref_get(&part->ref); | 83 | hd_struct_get(part); |
84 | } | 84 | } |
85 | part_round_stats(cpu, part); | 85 | part_round_stats(cpu, part); |
86 | part_inc_in_flight(part, rw); | 86 | part_inc_in_flight(part, rw); |
@@ -1818,7 +1818,7 @@ static void blk_account_io_done(struct request *req) | |||
1818 | part_round_stats(cpu, part); | 1818 | part_round_stats(cpu, part); |
1819 | part_dec_in_flight(part, rw); | 1819 | part_dec_in_flight(part, rw); |
1820 | 1820 | ||
1821 | kref_put(&part->ref, __delete_partition); | 1821 | hd_struct_put(part); |
1822 | part_stat_unlock(); | 1822 | part_stat_unlock(); |
1823 | } | 1823 | } |
1824 | } | 1824 | } |
diff --git a/block/blk-merge.c b/block/blk-merge.c index b06b83b89d89..00b7d31b38a2 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c | |||
@@ -356,7 +356,7 @@ static void blk_account_io_merge(struct request *req) | |||
356 | part_round_stats(cpu, part); | 356 | part_round_stats(cpu, part); |
357 | part_dec_in_flight(part, rq_data_dir(req)); | 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 | part_stat_unlock(); | 360 | part_stat_unlock(); |
361 | } | 361 | } |
362 | } | 362 | } |
diff --git a/block/genhd.c b/block/genhd.c index 85c150598830..399d37ec7412 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
@@ -1192,7 +1192,8 @@ struct gendisk *alloc_disk_node(int minors, int node_id) | |||
1192 | return NULL; | 1192 | return NULL; |
1193 | } | 1193 | } |
1194 | disk->part_tbl->part[0] = &disk->part0; | 1194 | disk->part_tbl->part[0] = &disk->part0; |
1195 | kref_init(&disk->part0.ref); | 1195 | |
1196 | hd_ref_init(&disk->part0); | ||
1196 | 1197 | ||
1197 | disk->minors = minors; | 1198 | disk->minors = minors; |
1198 | rand_initialize_disk(disk); | 1199 | rand_initialize_disk(disk); |
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 48209f58522b..011520df71ae 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
@@ -381,10 +381,8 @@ static void delete_partition_rcu_cb(struct rcu_head *head) | |||
381 | put_device(part_to_dev(part)); | 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 | call_rcu(&part->rcu_head, delete_partition_rcu_cb); | 386 | call_rcu(&part->rcu_head, delete_partition_rcu_cb); |
389 | } | 387 | } |
390 | 388 | ||
@@ -406,7 +404,7 @@ void delete_partition(struct gendisk *disk, int partno) | |||
406 | kobject_put(part->holder_dir); | 404 | kobject_put(part->holder_dir); |
407 | device_del(part_to_dev(part)); | 405 | device_del(part_to_dev(part)); |
408 | 406 | ||
409 | kref_put(&part->ref, __delete_partition); | 407 | hd_struct_put(part); |
410 | } | 408 | } |
411 | 409 | ||
412 | static ssize_t whole_disk_show(struct device *dev, | 410 | static ssize_t whole_disk_show(struct device *dev, |
@@ -505,7 +503,7 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, | |||
505 | if (!dev_get_uevent_suppress(ddev)) | 503 | if (!dev_get_uevent_suppress(ddev)) |
506 | kobject_uevent(&pdev->kobj, KOBJ_ADD); | 504 | kobject_uevent(&pdev->kobj, KOBJ_ADD); |
507 | 505 | ||
508 | kref_init(&p->ref); | 506 | hd_ref_init(p); |
509 | return p; | 507 | return p; |
510 | 508 | ||
511 | out_free_info: | 509 | out_free_info: |
diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 2ba2792a3dd4..2d0468145967 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h | |||
@@ -115,8 +115,8 @@ struct hd_struct { | |||
115 | #else | 115 | #else |
116 | struct disk_stats dkstats; | 116 | struct disk_stats dkstats; |
117 | #endif | 117 | #endif |
118 | atomic_t ref; | ||
118 | struct rcu_head rcu_head; | 119 | struct rcu_head rcu_head; |
119 | struct kref ref; | ||
120 | }; | 120 | }; |
121 | 121 | ||
122 | #define GENHD_FL_REMOVABLE 1 | 122 | #define GENHD_FL_REMOVABLE 1 |
@@ -584,7 +584,7 @@ extern struct hd_struct * __must_check add_partition(struct gendisk *disk, | |||
584 | sector_t len, int flags, | 584 | sector_t len, int flags, |
585 | struct partition_meta_info | 585 | struct partition_meta_info |
586 | *info); | 586 | *info); |
587 | extern void __delete_partition(struct kref *ref); | 587 | extern void __delete_partition(struct hd_struct *); |
588 | extern void delete_partition(struct gendisk *, int); | 588 | extern void delete_partition(struct gendisk *, int); |
589 | extern void printk_all_partitions(void); | 589 | extern void printk_all_partitions(void); |
590 | 590 | ||
@@ -613,6 +613,29 @@ extern ssize_t part_fail_store(struct device *dev, | |||
613 | const char *buf, size_t count); | 613 | const char *buf, size_t count); |
614 | #endif /* CONFIG_FAIL_MAKE_REQUEST */ | 614 | #endif /* CONFIG_FAIL_MAKE_REQUEST */ |
615 | 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 | } | ||
638 | |||
616 | #else /* CONFIG_BLOCK */ | 639 | #else /* CONFIG_BLOCK */ |
617 | 640 | ||
618 | static inline void printk_all_partitions(void) { } | 641 | static inline void printk_all_partitions(void) { } |
diff --git a/include/linux/kref.h b/include/linux/kref.h index 90b9e44abf54..6cc38fc07ab7 100644 --- a/include/linux/kref.h +++ b/include/linux/kref.h | |||
@@ -23,7 +23,6 @@ struct kref { | |||
23 | 23 | ||
24 | void kref_init(struct kref *kref); | 24 | void kref_init(struct kref *kref); |
25 | void kref_get(struct kref *kref); | 25 | void kref_get(struct kref *kref); |
26 | int kref_test_and_get(struct kref *kref); | ||
27 | int kref_put(struct kref *kref, void (*release) (struct kref *kref)); | 26 | int kref_put(struct kref *kref, void (*release) (struct kref *kref)); |
28 | 27 | ||
29 | #endif /* _KREF_H_ */ | 28 | #endif /* _KREF_H_ */ |
diff --git a/lib/kref.c b/lib/kref.c index e7a6e1067122..d3d227a08a4b 100644 --- a/lib/kref.c +++ b/lib/kref.c | |||
@@ -37,18 +37,6 @@ void kref_get(struct kref *kref) | |||
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 | * kref_put - decrement refcount for object. | 40 | * kref_put - decrement refcount for object. |
53 | * @kref: object. | 41 | * @kref: object. |
54 | * @release: pointer to the function that will clean up the object when the | 42 | * @release: pointer to the function that will clean up the object when the |