diff options
author | Jan Kara <jack@suse.cz> | 2017-02-02 09:56:51 -0500 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2017-02-02 10:20:50 -0500 |
commit | d03f6cdc1fc422accb734c7c07a661a0018d8631 (patch) | |
tree | fe3500795df51b8ad11a0f76dddfa27d60fecf13 /mm/backing-dev.c | |
parent | dc3b17cc8bf21307c7e076e7c778d5db756f7871 (diff) |
block: Dynamically allocate and refcount backing_dev_info
Instead of storing backing_dev_info inside struct request_queue,
allocate it dynamically, reference count it, and free it when the last
reference is dropped. Currently only request_queue holds the reference
but in the following patch we add other users referencing
backing_dev_info.
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'mm/backing-dev.c')
-rw-r--r-- | mm/backing-dev.c | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 3bfed5ab2475..28ce6cf7b2ff 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c | |||
@@ -237,6 +237,7 @@ static __init int bdi_class_init(void) | |||
237 | 237 | ||
238 | bdi_class->dev_groups = bdi_dev_groups; | 238 | bdi_class->dev_groups = bdi_dev_groups; |
239 | bdi_debug_init(); | 239 | bdi_debug_init(); |
240 | |||
240 | return 0; | 241 | return 0; |
241 | } | 242 | } |
242 | postcore_initcall(bdi_class_init); | 243 | postcore_initcall(bdi_class_init); |
@@ -776,6 +777,7 @@ int bdi_init(struct backing_dev_info *bdi) | |||
776 | 777 | ||
777 | bdi->dev = NULL; | 778 | bdi->dev = NULL; |
778 | 779 | ||
780 | kref_init(&bdi->refcnt); | ||
779 | bdi->min_ratio = 0; | 781 | bdi->min_ratio = 0; |
780 | bdi->max_ratio = 100; | 782 | bdi->max_ratio = 100; |
781 | bdi->max_prop_frac = FPROP_FRAC_BASE; | 783 | bdi->max_prop_frac = FPROP_FRAC_BASE; |
@@ -791,6 +793,22 @@ int bdi_init(struct backing_dev_info *bdi) | |||
791 | } | 793 | } |
792 | EXPORT_SYMBOL(bdi_init); | 794 | EXPORT_SYMBOL(bdi_init); |
793 | 795 | ||
796 | struct backing_dev_info *bdi_alloc_node(gfp_t gfp_mask, int node_id) | ||
797 | { | ||
798 | struct backing_dev_info *bdi; | ||
799 | |||
800 | bdi = kmalloc_node(sizeof(struct backing_dev_info), | ||
801 | gfp_mask | __GFP_ZERO, node_id); | ||
802 | if (!bdi) | ||
803 | return NULL; | ||
804 | |||
805 | if (bdi_init(bdi)) { | ||
806 | kfree(bdi); | ||
807 | return NULL; | ||
808 | } | ||
809 | return bdi; | ||
810 | } | ||
811 | |||
794 | int bdi_register(struct backing_dev_info *bdi, struct device *parent, | 812 | int bdi_register(struct backing_dev_info *bdi, struct device *parent, |
795 | const char *fmt, ...) | 813 | const char *fmt, ...) |
796 | { | 814 | { |
@@ -871,12 +889,26 @@ void bdi_unregister(struct backing_dev_info *bdi) | |||
871 | } | 889 | } |
872 | } | 890 | } |
873 | 891 | ||
874 | void bdi_exit(struct backing_dev_info *bdi) | 892 | static void bdi_exit(struct backing_dev_info *bdi) |
875 | { | 893 | { |
876 | WARN_ON_ONCE(bdi->dev); | 894 | WARN_ON_ONCE(bdi->dev); |
877 | wb_exit(&bdi->wb); | 895 | wb_exit(&bdi->wb); |
878 | } | 896 | } |
879 | 897 | ||
898 | static void release_bdi(struct kref *ref) | ||
899 | { | ||
900 | struct backing_dev_info *bdi = | ||
901 | container_of(ref, struct backing_dev_info, refcnt); | ||
902 | |||
903 | bdi_exit(bdi); | ||
904 | kfree(bdi); | ||
905 | } | ||
906 | |||
907 | void bdi_put(struct backing_dev_info *bdi) | ||
908 | { | ||
909 | kref_put(&bdi->refcnt, release_bdi); | ||
910 | } | ||
911 | |||
880 | void bdi_destroy(struct backing_dev_info *bdi) | 912 | void bdi_destroy(struct backing_dev_info *bdi) |
881 | { | 913 | { |
882 | bdi_unregister(bdi); | 914 | bdi_unregister(bdi); |