提交 ece84241 编写于 作者: T Tejun Heo 提交者: Jens Axboe

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: NTejun Heo <tj@kernel.org>
Signed-off-by: NJens Axboe <axboe@kernel.dk>
上级 523e1d39
...@@ -768,25 +768,14 @@ static uint64_t blkio_get_stat(struct blkio_group *blkg, ...@@ -768,25 +768,14 @@ static uint64_t blkio_get_stat(struct blkio_group *blkg,
return disk_total; return disk_total;
} }
static int blkio_check_dev_num(dev_t dev)
{
int part = 0;
struct gendisk *disk;
disk = get_gendisk(dev, &part);
if (!disk || part)
return -ENODEV;
return 0;
}
static int blkio_policy_parse_and_set(char *buf, static int blkio_policy_parse_and_set(char *buf,
struct blkio_policy_node *newpn, enum blkio_policy_id plid, int fileid) struct blkio_policy_node *newpn, enum blkio_policy_id plid, int fileid)
{ {
struct gendisk *disk = NULL;
char *s[4], *p, *major_s = NULL, *minor_s = NULL; char *s[4], *p, *major_s = NULL, *minor_s = NULL;
int ret;
unsigned long major, minor; unsigned long major, minor;
int i = 0; int i = 0, ret = -EINVAL;
int part;
dev_t dev; dev_t dev;
u64 temp; u64 temp;
...@@ -804,37 +793,36 @@ static int blkio_policy_parse_and_set(char *buf, ...@@ -804,37 +793,36 @@ static int blkio_policy_parse_and_set(char *buf,
} }
if (i != 2) if (i != 2)
return -EINVAL; goto out;
p = strsep(&s[0], ":"); p = strsep(&s[0], ":");
if (p != NULL) if (p != NULL)
major_s = p; major_s = p;
else else
return -EINVAL; goto out;
minor_s = s[0]; minor_s = s[0];
if (!minor_s) if (!minor_s)
return -EINVAL; goto out;
ret = strict_strtoul(major_s, 10, &major); if (strict_strtoul(major_s, 10, &major))
if (ret) goto out;
return -EINVAL;
ret = strict_strtoul(minor_s, 10, &minor); if (strict_strtoul(minor_s, 10, &minor))
if (ret) goto out;
return -EINVAL;
dev = MKDEV(major, minor); dev = MKDEV(major, minor);
ret = strict_strtoull(s[1], 10, &temp); if (strict_strtoull(s[1], 10, &temp))
if (ret) goto out;
return -EINVAL;
/* For rule removal, do not check for device presence. */ /* For rule removal, do not check for device presence. */
if (temp) { if (temp) {
ret = blkio_check_dev_num(dev); disk = get_gendisk(dev, &part);
if (ret) if (!disk || part) {
return ret; ret = -ENODEV;
goto out;
}
} }
newpn->dev = dev; newpn->dev = dev;
...@@ -843,7 +831,7 @@ static int blkio_policy_parse_and_set(char *buf, ...@@ -843,7 +831,7 @@ static int blkio_policy_parse_and_set(char *buf,
case BLKIO_POLICY_PROP: case BLKIO_POLICY_PROP:
if ((temp < BLKIO_WEIGHT_MIN && temp > 0) || if ((temp < BLKIO_WEIGHT_MIN && temp > 0) ||
temp > BLKIO_WEIGHT_MAX) temp > BLKIO_WEIGHT_MAX)
return -EINVAL; goto out;
newpn->plid = plid; newpn->plid = plid;
newpn->fileid = fileid; newpn->fileid = fileid;
...@@ -860,7 +848,7 @@ static int blkio_policy_parse_and_set(char *buf, ...@@ -860,7 +848,7 @@ static int blkio_policy_parse_and_set(char *buf,
case BLKIO_THROTL_read_iops_device: case BLKIO_THROTL_read_iops_device:
case BLKIO_THROTL_write_iops_device: case BLKIO_THROTL_write_iops_device:
if (temp > THROTL_IOPS_MAX) if (temp > THROTL_IOPS_MAX)
return -EINVAL; goto out;
newpn->plid = plid; newpn->plid = plid;
newpn->fileid = fileid; newpn->fileid = fileid;
...@@ -871,8 +859,10 @@ static int blkio_policy_parse_and_set(char *buf, ...@@ -871,8 +859,10 @@ static int blkio_policy_parse_and_set(char *buf,
default: default:
BUG(); BUG();
} }
ret = 0;
return 0; out:
put_disk(disk);
return ret;
} }
unsigned int blkcg_get_weight(struct blkio_cgroup *blkcg, unsigned int blkcg_get_weight(struct blkio_cgroup *blkcg,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册