diff options
author | Tejun Heo <tj@kernel.org> | 2011-10-19 08:31:15 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2011-10-19 08:31:15 -0400 |
commit | ece84241b93c4693bfe0a8ec9a043a16d216d0cd (patch) | |
tree | 4bddd724aaecaf391488d3194d59cef80ef0c9eb /block/blk-cgroup.c | |
parent | 523e1d399ce0e23bec562abe2b2f8d297af81161 (diff) |
block: fix genhd refcounting in blkio_policy_parse_and_set()
blkio_policy_parse_and_set() calls blkio_check_dev_num() to check
whether the given dev_t is valid. blkio_check_dev_num() uses
get_gendisk() for verification but never puts the returned genhd
leaking the reference.
This patch collapses blkio_check_dev_num() into its caller and updates
it such that the genhd is put before returning.
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/blk-cgroup.c')
-rw-r--r-- | block/blk-cgroup.c | 56 |
1 files changed, 23 insertions, 33 deletions
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index b596e54ddd71..d61ec5636ce0 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c | |||
@@ -768,25 +768,14 @@ static uint64_t blkio_get_stat(struct blkio_group *blkg, | |||
768 | return disk_total; | 768 | return disk_total; |
769 | } | 769 | } |
770 | 770 | ||
771 | static int blkio_check_dev_num(dev_t dev) | ||
772 | { | ||
773 | int part = 0; | ||
774 | struct gendisk *disk; | ||
775 | |||
776 | disk = get_gendisk(dev, &part); | ||
777 | if (!disk || part) | ||
778 | return -ENODEV; | ||
779 | |||
780 | return 0; | ||
781 | } | ||
782 | |||
783 | static int blkio_policy_parse_and_set(char *buf, | 771 | static int blkio_policy_parse_and_set(char *buf, |
784 | struct blkio_policy_node *newpn, enum blkio_policy_id plid, int fileid) | 772 | struct blkio_policy_node *newpn, enum blkio_policy_id plid, int fileid) |
785 | { | 773 | { |
774 | struct gendisk *disk = NULL; | ||
786 | char *s[4], *p, *major_s = NULL, *minor_s = NULL; | 775 | char *s[4], *p, *major_s = NULL, *minor_s = NULL; |
787 | int ret; | ||
788 | unsigned long major, minor; | 776 | unsigned long major, minor; |
789 | int i = 0; | 777 | int i = 0, ret = -EINVAL; |
778 | int part; | ||
790 | dev_t dev; | 779 | dev_t dev; |
791 | u64 temp; | 780 | u64 temp; |
792 | 781 | ||
@@ -804,37 +793,36 @@ static int blkio_policy_parse_and_set(char *buf, | |||
804 | } | 793 | } |
805 | 794 | ||
806 | if (i != 2) | 795 | if (i != 2) |
807 | return -EINVAL; | 796 | goto out; |
808 | 797 | ||
809 | p = strsep(&s[0], ":"); | 798 | p = strsep(&s[0], ":"); |
810 | if (p != NULL) | 799 | if (p != NULL) |
811 | major_s = p; | 800 | major_s = p; |
812 | else | 801 | else |
813 | return -EINVAL; | 802 | goto out; |
814 | 803 | ||
815 | minor_s = s[0]; | 804 | minor_s = s[0]; |
816 | if (!minor_s) | 805 | if (!minor_s) |
817 | return -EINVAL; | 806 | goto out; |
818 | 807 | ||
819 | ret = strict_strtoul(major_s, 10, &major); | 808 | if (strict_strtoul(major_s, 10, &major)) |
820 | if (ret) | 809 | goto out; |
821 | return -EINVAL; | ||
822 | 810 | ||
823 | ret = strict_strtoul(minor_s, 10, &minor); | 811 | if (strict_strtoul(minor_s, 10, &minor)) |
824 | if (ret) | 812 | goto out; |
825 | return -EINVAL; | ||
826 | 813 | ||
827 | dev = MKDEV(major, minor); | 814 | dev = MKDEV(major, minor); |
828 | 815 | ||
829 | ret = strict_strtoull(s[1], 10, &temp); | 816 | if (strict_strtoull(s[1], 10, &temp)) |
830 | if (ret) | 817 | goto out; |
831 | return -EINVAL; | ||
832 | 818 | ||
833 | /* For rule removal, do not check for device presence. */ | 819 | /* For rule removal, do not check for device presence. */ |
834 | if (temp) { | 820 | if (temp) { |
835 | ret = blkio_check_dev_num(dev); | 821 | disk = get_gendisk(dev, &part); |
836 | if (ret) | 822 | if (!disk || part) { |
837 | return ret; | 823 | ret = -ENODEV; |
824 | goto out; | ||
825 | } | ||
838 | } | 826 | } |
839 | 827 | ||
840 | newpn->dev = dev; | 828 | newpn->dev = dev; |
@@ -843,7 +831,7 @@ static int blkio_policy_parse_and_set(char *buf, | |||
843 | case BLKIO_POLICY_PROP: | 831 | case BLKIO_POLICY_PROP: |
844 | if ((temp < BLKIO_WEIGHT_MIN && temp > 0) || | 832 | if ((temp < BLKIO_WEIGHT_MIN && temp > 0) || |
845 | temp > BLKIO_WEIGHT_MAX) | 833 | temp > BLKIO_WEIGHT_MAX) |
846 | return -EINVAL; | 834 | goto out; |
847 | 835 | ||
848 | newpn->plid = plid; | 836 | newpn->plid = plid; |
849 | newpn->fileid = fileid; | 837 | newpn->fileid = fileid; |
@@ -860,7 +848,7 @@ static int blkio_policy_parse_and_set(char *buf, | |||
860 | case BLKIO_THROTL_read_iops_device: | 848 | case BLKIO_THROTL_read_iops_device: |
861 | case BLKIO_THROTL_write_iops_device: | 849 | case BLKIO_THROTL_write_iops_device: |
862 | if (temp > THROTL_IOPS_MAX) | 850 | if (temp > THROTL_IOPS_MAX) |
863 | return -EINVAL; | 851 | goto out; |
864 | 852 | ||
865 | newpn->plid = plid; | 853 | newpn->plid = plid; |
866 | newpn->fileid = fileid; | 854 | newpn->fileid = fileid; |
@@ -871,8 +859,10 @@ static int blkio_policy_parse_and_set(char *buf, | |||
871 | default: | 859 | default: |
872 | BUG(); | 860 | BUG(); |
873 | } | 861 | } |
874 | 862 | ret = 0; | |
875 | return 0; | 863 | out: |
864 | put_disk(disk); | ||
865 | return ret; | ||
876 | } | 866 | } |
877 | 867 | ||
878 | unsigned int blkcg_get_weight(struct blkio_cgroup *blkcg, | 868 | unsigned int blkcg_get_weight(struct blkio_cgroup *blkcg, |