aboutsummaryrefslogtreecommitdiffstats
path: root/mm/backing-dev.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2017-02-02 09:56:51 -0500
committerJens Axboe <axboe@fb.com>2017-02-02 10:20:50 -0500
commitd03f6cdc1fc422accb734c7c07a661a0018d8631 (patch)
treefe3500795df51b8ad11a0f76dddfa27d60fecf13 /mm/backing-dev.c
parentdc3b17cc8bf21307c7e076e7c778d5db756f7871 (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.c34
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}
242postcore_initcall(bdi_class_init); 243postcore_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}
792EXPORT_SYMBOL(bdi_init); 794EXPORT_SYMBOL(bdi_init);
793 795
796struct 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
794int bdi_register(struct backing_dev_info *bdi, struct device *parent, 812int 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
874void bdi_exit(struct backing_dev_info *bdi) 892static 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
898static 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
907void bdi_put(struct backing_dev_info *bdi)
908{
909 kref_put(&bdi->refcnt, release_bdi);
910}
911
880void bdi_destroy(struct backing_dev_info *bdi) 912void bdi_destroy(struct backing_dev_info *bdi)
881{ 913{
882 bdi_unregister(bdi); 914 bdi_unregister(bdi);