diff options
author | Tejun Heo <tj@kernel.org> | 2012-04-19 19:29:23 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2012-04-20 04:06:40 -0400 |
commit | 496fb7806d616185a46865a4f3a20ef19dc6c7e3 (patch) | |
tree | a200e6825be55f6d0ed411ec32dc16244f488fd9 /block | |
parent | aaf7c680682f1999ef2e574f743c45d1674a8b8a (diff) |
blkcg: fix blkcg->css ref leak in __blkg_lookup_create()
__blkg_lookup_create() leaked blkcg->css ref if blkg allocation
failed. Fix it.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-cgroup.c | 19 |
1 files changed, 9 insertions, 10 deletions
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 82283859727e..30a7a9c58b38 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c | |||
@@ -174,6 +174,7 @@ static struct blkcg_gq *__blkg_lookup_create(struct blkcg *blkcg, | |||
174 | __releases(q->queue_lock) __acquires(q->queue_lock) | 174 | __releases(q->queue_lock) __acquires(q->queue_lock) |
175 | { | 175 | { |
176 | struct blkcg_gq *blkg; | 176 | struct blkcg_gq *blkg; |
177 | int ret; | ||
177 | 178 | ||
178 | WARN_ON_ONCE(!rcu_read_lock_held()); | 179 | WARN_ON_ONCE(!rcu_read_lock_held()); |
179 | lockdep_assert_held(q->queue_lock); | 180 | lockdep_assert_held(q->queue_lock); |
@@ -186,24 +187,22 @@ static struct blkcg_gq *__blkg_lookup_create(struct blkcg *blkcg, | |||
186 | if (!css_tryget(&blkcg->css)) | 187 | if (!css_tryget(&blkcg->css)) |
187 | return ERR_PTR(-EINVAL); | 188 | return ERR_PTR(-EINVAL); |
188 | 189 | ||
189 | /* | 190 | /* allocate */ |
190 | * Allocate and initialize. | 191 | ret = -ENOMEM; |
191 | */ | ||
192 | blkg = blkg_alloc(blkcg, q); | 192 | blkg = blkg_alloc(blkcg, q); |
193 | 193 | if (unlikely(!blkg)) | |
194 | /* did alloc fail? */ | 194 | goto err_put; |
195 | if (unlikely(!blkg)) { | ||
196 | blkg = ERR_PTR(-ENOMEM); | ||
197 | goto out; | ||
198 | } | ||
199 | 195 | ||
200 | /* insert */ | 196 | /* insert */ |
201 | spin_lock(&blkcg->lock); | 197 | spin_lock(&blkcg->lock); |
202 | hlist_add_head_rcu(&blkg->blkcg_node, &blkcg->blkg_list); | 198 | hlist_add_head_rcu(&blkg->blkcg_node, &blkcg->blkg_list); |
203 | list_add(&blkg->q_node, &q->blkg_list); | 199 | list_add(&blkg->q_node, &q->blkg_list); |
204 | spin_unlock(&blkcg->lock); | 200 | spin_unlock(&blkcg->lock); |
205 | out: | ||
206 | return blkg; | 201 | return blkg; |
202 | |||
203 | err_put: | ||
204 | css_put(&blkcg->css); | ||
205 | return ERR_PTR(ret); | ||
207 | } | 206 | } |
208 | 207 | ||
209 | struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg, | 208 | struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg, |